diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..a4a06fb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,22 @@ +--- +name: Bug report 🐞 +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior e.g. provide example action definition. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Additional context** +Add any other context about the problem here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..c270842 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,17 @@ +--- +name: Feature Request 💡 +about: Suggest a new idea for the project. +labels: enhancement +--- + +# Summary + +Brief explanation of the feature. + +## Basic example + +If the proposal involves a new or changed API, include a basic code example. Omit this section if it's not applicable. + +## Motivation + +Why are we doing this? What use cases does it support? What is the expected outcome? \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md new file mode 100644 index 0000000..609870c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.md @@ -0,0 +1,7 @@ +--- +name: Question ❓ +about: Is something unclear? +labels: question +--- + +# Question? \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..f653875 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,26 @@ +--- +version: 2 +updates: + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "weekly" + # Ignore K8 packages as these are done manually + ignore: + - dependency-name: "k8s.io/api" + - dependency-name: "k8s.io/apiextensions-apiserver" + - dependency-name: "k8s.io/apimachinery" + - dependency-name: "k8s.io/apiserver" + - dependency-name: "k8s.io/client-go" + - dependency-name: "k8s.io/component-base" + - dependency-name: "k8s.io/kube-aggregator" + - dependency-name: "k8s.io/kubectl" + - dependency-name: "sigs.k8s.io/controller-runtime" + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "weekly" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..4ba787f --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,7 @@ +# Proposed Changes + +- +- +- + +Fixes # \ No newline at end of file diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml new file mode 100644 index 0000000..c2dc12d --- /dev/null +++ b/.github/release-drafter.yml @@ -0,0 +1,64 @@ +name-template: 'v$RESOLVED_VERSION' +tag-template: 'v$RESOLVED_VERSION' +categories: + - title: '⚠️ Breaking' + labels: + - 'breaking' + - title: '🚀 Features' + labels: + - 'feature' + - 'enhancement' + - 'api-change' + - title: '🐛 Bug Fixes' + labels: + - 'fix' + - 'bugfix' + - 'bug' + - title: '🧰 Maintenance' + labels: + - 'chore' + - 'dependencies' + - 'marketing' +change-template: '- $TITLE @$AUTHOR (#$NUMBER)' +change-title-escapes: '\<*_&' # You can add # and @ to disable mentions, and add ` to disable code blocks. +version-resolver: + major: + labels: + - 'major' + minor: + labels: + - 'minor' + patch: + labels: + - 'patch' + default: patch +exclude-labels: + - 'skip-changelog' +autolabeler: + - label: 'api-change' + files: + - '/api/*' + - label: 'documentation' + files: + - '*.md' + branch: + - '/docs{0,1}\/.+/' + - label: 'bug' + branch: + - '/fix\/.+/' + title: + - '/fix/i' + - label: 'enhancement' + branch: + - '/feature\/.+/' + body: + - '/JIRA-[0-9]{1,4}/' + - label: 'enhancement' + branch: + - '/enh\/.+/' + - label: 'chore' + branch: + - '/chore\/.+/' +template: | + ## Changes + $CHANGES diff --git a/.github/workflows/check-codegen.yml b/.github/workflows/check-codegen.yml new file mode 100644 index 0000000..7d97534 --- /dev/null +++ b/.github/workflows/check-codegen.yml @@ -0,0 +1,28 @@ +name: Check Codegen + +on: + pull_request: + paths-ignore: + - 'docs/**' + - '**/*.md' + +jobs: + check-codegen: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + - name: Run make generate + run: make generate + - name: Run make docs + run: make docs + - name: Compare the expected and actual generated/* directories + run: | + if [ "$(git diff --ignore-space-at-eol client-go/ | wc -l)" -gt "0" ]; then + echo "Detected uncommitted changes after build. Consider running 'make generate && make docs'." + echo "See status below:" + git diff + exit 1 + fi diff --git a/.github/workflows/clean-cache.yml b/.github/workflows/clean-cache.yml new file mode 100644 index 0000000..2fd77bf --- /dev/null +++ b/.github/workflows/clean-cache.yml @@ -0,0 +1,31 @@ +name: cleanup caches by a branch +on: + pull_request: + types: + - closed + +jobs: + cleanup: + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Cleanup + run: | + gh extension install actions/gh-actions-cache + + REPO=${{ github.repository }} + BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge" + echo "Fetching list of cache key" + cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 ) + ## Setting this to not fail the workflow while deleting cache keys. + set +e + echo "Deleting caches..." + for cacheKey in $cacheKeysForPR + do + gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm + done + echo "Done" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/kustomize-validation.yml b/.github/workflows/kustomize-validation.yml new file mode 100644 index 0000000..c381bc8 --- /dev/null +++ b/.github/workflows/kustomize-validation.yml @@ -0,0 +1,20 @@ +name: Kustomize Validation + +on: + pull_request: + types: [ assigned, opened, synchronize, reopened ] + paths-ignore: + - 'docs/**' + - '**/*.md' + +jobs: + kustomize-validation: + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v4 + - uses: imranismail/setup-kustomize@v2 + with: + kustomize-version: '5.0.0' + - run: | + ./hack/validate-kustomize.sh diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..da677b8 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,20 @@ +name: Lint + +on: + pull_request: + paths-ignore: + - 'docs/**' + - '**/*.md' +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + - name: golangci-lint + uses: golangci/golangci-lint-action@v6 + with: + version: v1.59 diff --git a/.github/workflows/publish-docker.yml b/.github/workflows/publish-docker.yml new file mode 100644 index 0000000..5977d06 --- /dev/null +++ b/.github/workflows/publish-docker.yml @@ -0,0 +1,82 @@ +name: Build and Publish Docker Image + +on: + release: + types: + - published + push: + branches: + - main + tags: + - v* + paths-ignore: + - 'docs/**' + - '**/*.md' + pull_request: + types: + - labeled + paths-ignore: + - 'docs/**' + - '**/*.md' + +jobs: + buildAndPush: + strategy: + matrix: + image: + - name: cluster-api-provider-metal + target: manager + permissions: + contents: read + packages: write + if: ${{ github.event.label.name == 'ok-to-image' }} || ${{ github.event.label.name == 'ok-to-🐳' }} || ${{ github.ref == 'refs/heads/main' }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: docker/metadata-action@v5 + id: meta + with: + images: | + ghcr.io/${{ github.repository_owner }}/${{ matrix.image.name }} + tags: | + type=semver,pattern={{version}} + type=schedule + type=ref,event=branch + type=ref,event=tag + type=ref,event=pr + type=sha + flavor: | + latest=${{ github.ref == 'refs/heads/main' }} + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: all + # workaround for self-hosted runner + # https://github.com/mumoshu/actions-runner-controller-ci/commit/e91c8c0f6ca82aa7618010c6d2f417aa46c4a4bf + - name: Set up Docker Context for Buildx + id: buildx-context + run: | + docker context create builders + - name: Set up Docker Buildx + timeout-minutes: 5 + uses: docker/setup-buildx-action@v3 + with: + version: latest + endpoint: builders # self-hosted + - name: Login to GHCR + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Build and push + timeout-minutes: 40 + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + target: ${{ matrix.image.target }} diff --git a/.github/workflows/release-drafter.yml b/.github/workflows/release-drafter.yml new file mode 100644 index 0000000..327c5ab --- /dev/null +++ b/.github/workflows/release-drafter.yml @@ -0,0 +1,26 @@ +name: Release Drafter + +on: + push: + branches: + - main + pull_request_target: + types: [ opened, reopened, synchronize ] + workflow_dispatch: + +jobs: + update_release_draft: + permissions: + # write permission is required to create a github release + contents: write + # write permission is required for autolabeler + # otherwise, read permission is required at least + pull-requests: write + runs-on: ubuntu-latest + steps: + # Drafts your next Release notes as Pull Requests are merged into "main" + - uses: release-drafter/release-drafter@v6 + with: + config-name: release-drafter.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/reuse.yml b/.github/workflows/reuse.yml new file mode 100644 index 0000000..81fddbc --- /dev/null +++ b/.github/workflows/reuse.yml @@ -0,0 +1,12 @@ +name: REUSE Compliance Check + +on: pull_request + +jobs: + test: + name: reuse + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: REUSE Compliance Check + uses: fsfe/reuse-action@v4 diff --git a/.github/workflows/size-label.yml b/.github/workflows/size-label.yml new file mode 100644 index 0000000..992a382 --- /dev/null +++ b/.github/workflows/size-label.yml @@ -0,0 +1,20 @@ +name: Size Label + +on: + pull_request_target: + types: + - opened + - edited + - synchronize + +jobs: + size-label: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - name: size-label + uses: pascalgn/size-label-action@v0.5.2 + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..93b84db --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,19 @@ +name: Pull Request Code test + +on: + pull_request: + types: [ assigned, opened, synchronize, reopened ] + paths-ignore: + - 'docs/**' + - '**/*.md' + +jobs: + checks: + name: test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-go@v5 + with: + go-version-file: 'go.mod' + - run: make test diff --git a/.golangci.yml b/.golangci.yml index aac8a13..a2524e3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,5 +1,5 @@ run: - timeout: 5m + timeout: 10m allow-parallel-runners: true issues: @@ -22,7 +22,6 @@ linters: - dupl - errcheck - exportloopref - - ginkgolinter - goconst - gocyclo - gofmt @@ -30,18 +29,13 @@ linters: - gosimple - govet - ineffassign + - ginkgolinter - lll - misspell - nakedret - prealloc - - revive - staticcheck - typecheck - unconvert - unparam - - unused - -linters-settings: - revive: - rules: - - name: comment-spacings + - unused \ No newline at end of file diff --git a/.reuse/dep5 b/.reuse/dep5 index 8bf3f5d..1e06a06 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -19,6 +19,10 @@ Files: go.mod go.sum hack/* + scripts/* + Tiltfile + tilt-provider.json + templates/* Copyright: 2024 SAP SE or an SAP affiliate company and IronCore contributors License: Apache-2.0 diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 8cbc054..62b7abb 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1,20 +1,7 @@ //go:build !ignore_autogenerated -/* -Copyright 2024. - -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. -*/ +// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors +// SPDX-License-Identifier: Apache-2.0 // Code generated by controller-gen. DO NOT EDIT. diff --git a/internal/controller/metalcluster_controller.go b/internal/controller/metalcluster_controller.go index d760a79..dc04911 100644 --- a/internal/controller/metalcluster_controller.go +++ b/internal/controller/metalcluster_controller.go @@ -125,6 +125,7 @@ func (r *MetalClusterReconciler) reconcileDelete(ctx context.Context, clusterSco return ctrl.Result{}, nil } +//nolint:unparam func (r *MetalClusterReconciler) reconcileNormal(_ context.Context, clusterScope *scope.ClusterScope) (reconcile.Result, error) { clusterScope.Logger.Info("Reconciling MetalCluster") diff --git a/scripts/kind-with-registry.sh b/scripts/kind-with-registry.sh index ce80257..e737680 100755 --- a/scripts/kind-with-registry.sh +++ b/scripts/kind-with-registry.sh @@ -1,17 +1,7 @@ + #!/usr/bin/env bash -# Copyright 2021 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. +#// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors +#// SPDX-License-Identifier: Apache-2.0 set -o errexit set -o nounset diff --git a/test/e2e/e2e_suite_test.go b/test/e2e/e2e_suite_test.go index 726d5cb..76cd08a 100644 --- a/test/e2e/e2e_suite_test.go +++ b/test/e2e/e2e_suite_test.go @@ -1,18 +1,5 @@ -/* -Copyright 2024. - -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. -*/ +// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors +// SPDX-License-Identifier: Apache-2.0 package e2e @@ -27,6 +14,6 @@ import ( // Run e2e tests using the Ginkgo runner. func TestE2E(t *testing.T) { RegisterFailHandler(Fail) - fmt.Fprintf(GinkgoWriter, "Starting cluster-api-provider-metal suite\n") + _, _ = fmt.Fprintf(GinkgoWriter, "Starting cluster-api-provider-metal suite\n") RunSpecs(t, "e2e suite") } diff --git a/test/e2e/e2e_test.go b/test/e2e/e2e_test.go index 53cf0e1..325f5df 100644 --- a/test/e2e/e2e_test.go +++ b/test/e2e/e2e_test.go @@ -1,18 +1,5 @@ -/* -Copyright 2024. - -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. -*/ +// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors +// SPDX-License-Identifier: Apache-2.0 package e2e diff --git a/test/utils/utils.go b/test/utils/utils.go index e3eb79b..6e7afb5 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -1,18 +1,5 @@ -/* -Copyright 2024. - -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. -*/ +// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and IronCore contributors +// SPDX-License-Identifier: Apache-2.0 package utils @@ -35,7 +22,7 @@ const ( ) func warnError(err error) { - fmt.Fprintf(GinkgoWriter, "warning: %v\n", err) + _, _ = fmt.Fprintf(GinkgoWriter, "warning: %v\n", err) } // InstallPrometheusOperator installs the prometheus Operator to be used to export the enabled metrics. @@ -52,12 +39,16 @@ func Run(cmd *exec.Cmd) ([]byte, error) { cmd.Dir = dir if err := os.Chdir(cmd.Dir); err != nil { - fmt.Fprintf(GinkgoWriter, "chdir dir: %s\n", err) + if _, err := fmt.Fprintf(GinkgoWriter, "chdir dir: %s\n", err); err != nil { + return nil, fmt.Errorf("%w", err) + } } cmd.Env = append(os.Environ(), "GO111MODULE=on") command := strings.Join(cmd.Args, " ") - fmt.Fprintf(GinkgoWriter, "running: %s\n", command) + if _, err := fmt.Fprintf(GinkgoWriter, "running: %s\n", command); err != nil { + return nil, fmt.Errorf("%w", err) + } output, err := cmd.CombinedOutput() if err != nil { return output, fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output))