diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000000..5457b20edbc --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,35 @@ +name: Docs verification + +# Trigger the workflow on pull requests and direct pushes to any branch +on: + push: + pull_request: + +jobs: + testdata: + name: Verify Docs update + runs-on: ubuntu-latest + # Pull requests from the same repository won't trigger this checks as they were already triggered by the push + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + steps: + - name: Clone the code + uses: actions/checkout@v3 + - name: Setup Go + uses: actions/setup-go@v3 + with: + go-version: "1.19" + - name: Remove pre-installed kustomize + # This step is needed as the following one tries to remove + # kustomize for each test but has no permission to do so + run: sudo rm -f /usr/local/bin/kustomize + - name: Verify docs + run: | + make generate-docs + if [[ $(git status --porcelain) ]]; then + git diff + echo "Generate Docs failed!" + echo "Please, if you have changed the scaffolding make sure you have run: make generate-docs" + exit 1 + else + echo "Generate Docs passed!" + fi diff --git a/Makefile b/Makefile index 62c570f61aa..1fe747f051b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# Copyright 2019 The Kubernetes Authors. +# Copyright 2023 The Kubernetes Authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -71,6 +71,10 @@ generate-testdata: ## Update/generate the testdata in $GOPATH/src/sigs.k8s.io/ku rm -rf testdata/ ./test/testdata/generate.sh +.PHONY: generate-docs +generate-docs: ## Update/generate the docs in $GOPATH/src/sigs.k8s.io/kubebuilder + go run hack/docs/generate_samples.go + .PHONY: lint lint: golangci-lint yamllint ## Run golangci-lint linter & yamllint $(GOLANGCI_LINT) run diff --git a/docs/book/src/component-config-tutorial/testdata/generate_componentconfig.sh b/docs/book/src/component-config-tutorial/testdata/generate_componentconfig.sh deleted file mode 100755 index 48848190407..00000000000 --- a/docs/book/src/component-config-tutorial/testdata/generate_componentconfig.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2020 The Kubernetes Authors -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -# This script is a helper which has just the commands -# to generate the conjob tutorial to let us know update manually the testdata dir -# It allows us run ./generate_cronjob.sh and git diff with to check what requires updates -# NOTE: run make install from the project root before execute it. -# - -set -o errexit -set -o pipefail - -# Turn colors in this script off by setting the NO_COLOR variable in your -# environment to any value: -# -# $ NO_COLOR=1 test.sh -NO_COLOR=${NO_COLOR:-""} -if [ -z "$NO_COLOR" ]; then - header=$'\e[1;33m' - reset=$'\e[0m' -else - header='' - reset='' -fi - -build_kb() { - go build -o ./bin/kubebuilder sigs.k8s.io/kubebuilder/cmd -} - -function header_text { - echo "$header$*$reset" -} - -function gen_component_config_tutorial { - header_text "removing project ..." - rm -rf project - header_text "starting to generate the component config ..." - mkdir project - cd project - header_text "creating tutorial.kubebuilder.io base ..." - kubebuilder init --domain tutorial.kubebuilder.io --repo tutorial.kubebuilder.io/project --component-config --license apache2 --owner "The Kubernetes authors" - kubebuilder create api --group config --version v2 --kind ProjectConfig --resource --controller=false --make=false - go mod tidy - make -} - -gen_component_config_tutorial diff --git a/docs/book/src/component-config-tutorial/testdata/project/README.md b/docs/book/src/component-config-tutorial/testdata/project/README.md index 4e55b988a3b..3a778e70fb1 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/README.md +++ b/docs/book/src/component-config-tutorial/testdata/project/README.md @@ -78,7 +78,7 @@ More information can be found via the [Kubebuilder Documentation](https://book.k ## License -Copyright 2023. +Copyright 2023 The Kubernetes authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/docs/book/src/component-config-tutorial/testdata/project/api/v2/groupversion_info.go b/docs/book/src/component-config-tutorial/testdata/project/api/v2/groupversion_info.go index 8d87debb460..12badc8da4e 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/api/v2/groupversion_info.go +++ b/docs/book/src/component-config-tutorial/testdata/project/api/v2/groupversion_info.go @@ -1,5 +1,5 @@ /* -Copyright 2023. +Copyright 2023 The Kubernetes authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/docs/book/src/component-config-tutorial/testdata/project/api/v2/projectconfig_types.go b/docs/book/src/component-config-tutorial/testdata/project/api/v2/projectconfig_types.go index 224fa7ec4eb..85e058ae086 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/api/v2/projectconfig_types.go +++ b/docs/book/src/component-config-tutorial/testdata/project/api/v2/projectconfig_types.go @@ -1,5 +1,5 @@ /* -Copyright 2023. +Copyright 2023 The Kubernetes authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -49,7 +49,6 @@ type ProjectConfig struct { Spec ProjectConfigSpec `json:"spec,omitempty"` Status ProjectConfigStatus `json:"status,omitempty"` - // ControllerManagerConfigurationSpec returns the configurations for controllers cfg.ControllerManagerConfigurationSpec `json:",inline"` diff --git a/docs/book/src/component-config-tutorial/testdata/project/api/v2/zz_generated.deepcopy.go b/docs/book/src/component-config-tutorial/testdata/project/api/v2/zz_generated.deepcopy.go index 715af21c786..ed6397b49b3 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/api/v2/zz_generated.deepcopy.go +++ b/docs/book/src/component-config-tutorial/testdata/project/api/v2/zz_generated.deepcopy.go @@ -2,7 +2,7 @@ // +build !ignore_autogenerated /* -Copyright 2023. +Copyright 2023 The Kubernetes authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/docs/book/src/component-config-tutorial/testdata/project/hack/boilerplate.go.txt b/docs/book/src/component-config-tutorial/testdata/project/hack/boilerplate.go.txt index 65b86227183..8c36d12450d 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/hack/boilerplate.go.txt +++ b/docs/book/src/component-config-tutorial/testdata/project/hack/boilerplate.go.txt @@ -1,5 +1,5 @@ /* -Copyright 2023. +Copyright 2023 The Kubernetes authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/docs/book/src/component-config-tutorial/testdata/project/main.go b/docs/book/src/component-config-tutorial/testdata/project/main.go index 07d4ad17849..6dee9d72d9d 100644 --- a/docs/book/src/component-config-tutorial/testdata/project/main.go +++ b/docs/book/src/component-config-tutorial/testdata/project/main.go @@ -1,5 +1,5 @@ /* -Copyright 2023. +Copyright 2023 The Kubernetes authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/hack/docs/generate_samples.go b/hack/docs/generate_samples.go new file mode 100644 index 00000000000..4dc41aead27 --- /dev/null +++ b/hack/docs/generate_samples.go @@ -0,0 +1,49 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "fmt" + + componentconfig "sigs.k8s.io/kubebuilder/v3/hack/docs/internal" +) + +func main() { + fmt.Println("Generating documents...") + + fmt.Println("Generating component-config tutorial...") + UpdateComponentConfigTutorial() + + // TODO: Generate cronjob-tutorial + + // TODO: Generate multiversion-tutorial +} + +func UpdateComponentConfigTutorial() { + binaryPath := "/tmp/kubebuilder/bin/kubebuilder" + samplePath := "docs/book/src/component-config-tutorial/testdata/project/" + + sp := componentconfig.NewSample(binaryPath, samplePath) + + sp.Prepare() + + sp.GenerateSampleProject() + + sp.UpdateTutorial() + + sp.CodeGen() +} diff --git a/hack/docs/internal/generate_component_config.go b/hack/docs/internal/generate_component_config.go new file mode 100644 index 00000000000..e0b72c179b0 --- /dev/null +++ b/hack/docs/internal/generate_component_config.go @@ -0,0 +1,165 @@ +/* +Copyright 2023 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package componentconfig + +import ( + "os" + "os/exec" + "path/filepath" + + log "github.com/sirupsen/logrus" + + "github.com/spf13/afero" + pluginutil "sigs.k8s.io/kubebuilder/v3/pkg/plugin/util" + "sigs.k8s.io/kubebuilder/v3/test/e2e/utils" +) + +type Sample struct { + ctx *utils.TestContext +} + +func NewSample(binaryPath, samplePath string) Sample { + log.Infof("Generating the sample context of component-config...") + + ctx := newSampleContext(binaryPath, samplePath, "GO111MODULE=on") + + return Sample{&ctx} +} + +func newSampleContext(binaryPath string, samplePath string, env ...string) utils.TestContext { + cmdContext := &utils.CmdContext{ + Env: env, + Dir: samplePath, + } + + testContext := utils.TestContext{ + CmdContext: cmdContext, + BinaryName: binaryPath, + } + + return testContext +} + +// Prepare the Context for the sample project +func (sp *Sample) Prepare() { + log.Infof("destroying directory for sample project") + sp.ctx.Destroy() + + log.Infof("refreshing tools and creating directory...") + err := sp.ctx.Prepare() + + CheckError("creating directory for sample project", err) +} + +func (sp *Sample) GenerateSampleProject() { + log.Infof("Initializing the project") + err := sp.ctx.Init( + "--domain", "tutorial.kubebuilder.io", + "--repo", "tutorial.kubebuilder.io/project", + "--license", "apache2", + "--owner", "The Kubernetes authors", + "--component-config", + ) + CheckError("Initializing the project", err) + + log.Infof("Adding a new config type") + err = sp.ctx.CreateAPI( + "--group", "config", + "--version", "v2", + "--kind", "ProjectConfig", + "--resource", "--controller=false", + "--make=false", + ) + CheckError("Creating the API", err) +} + +func (sp *Sample) UpdateTutorial() { + // 1. generate controller_manager_config.yaml + var fs = afero.NewOsFs() + err := afero.WriteFile(fs, filepath.Join(sp.ctx.Dir, "config/manager/controller_manager_config.yaml"), + []byte(`apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 +kind: ControllerManagerConfig +metadata: + labels: + app.kubernetes.io/name: controllermanagerconfig + app.kubernetes.io/instance: controller-manager-configuration + app.kubernetes.io/component: manager + app.kubernetes.io/created-by: project + app.kubernetes.io/part-of: project + app.kubernetes.io/managed-by: kustomize +health: + healthProbeBindAddress: :8081 +metrics: + bindAddress: 127.0.0.1:8080 +webhook: + port: 9443 +leaderElection: + leaderElect: true + resourceName: 80807133.tutorial.kubebuilder.io +clusterName: example-test +`), 0600) + CheckError("fixing controller_manager_config", err) + + // 2. fix projectconfig_types.go + err = pluginutil.InsertCode( + filepath.Join(sp.ctx.Dir, "api/v2/projectconfig_types.go"), + `metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"`, + ` + cfg "sigs.k8s.io/controller-runtime/pkg/config/v1alpha1"`) + CheckError("fixing projectconfig_types", err) + + err = pluginutil.InsertCode( + filepath.Join(sp.ctx.Dir, "api/v2/projectconfig_types.go"), + `Status ProjectConfigStatus `+"`"+`json:"status,omitempty"`+"`", + ` + // ControllerManagerConfigurationSpec returns the configurations for controllers + cfg.ControllerManagerConfigurationSpec `+"`"+`json:",inline"`+"`"+` + + ClusterName string `+"`"+`json:"clusterName,omitempty"`+"`", + ) + + CheckError("fixing projectconfig_types", err) + + // 3. fix main + err = pluginutil.InsertCode( + filepath.Join(sp.ctx.Dir, "main.go"), + `var err error`, + ` + ctrlConfig := configv2.ProjectConfig{}`) + CheckError("fixing main.go", err) + + err = pluginutil.InsertCode( + filepath.Join(sp.ctx.Dir, "main.go"), + `AtPath(configFile)`, + `.OfKind(&ctrlConfig)`) + CheckError("fixing main.go", err) +} + +func (sp *Sample) CodeGen() { + cmd := exec.Command("make", "build") + _, err := sp.ctx.Run(cmd) + + CheckError("Failed to generate code in componentconfig tutorial", err) +} + +// CheckError will exit with exit code 1 when err is not nil. +func CheckError(msg string, err error) { + if err != nil { + log.Errorf("error %s: %s", msg, err) + os.Exit(1) + } +}