diff --git a/.github/workflows/helm-lint.yaml b/.github/workflows/helm-lint.yaml new file mode 100644 index 0000000..8498f12 --- /dev/null +++ b/.github/workflows/helm-lint.yaml @@ -0,0 +1,44 @@ +# NOTE: This workflow can be run locally using https://github.com/nektos/act with: +# act -W .github/workflows/helm-lint.yaml workflow_call -s GITHUB_TOKEN=$(gh auth token) +name: Helm Lint +on: + workflow_call: + inputs: + ref: + type: string + description: The Git ref under test. + required: true + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref }} + fetch-depth: 0 + + - name: Set up Helm + uses: azure/setup-helm@v4 + with: + version: v3.15.3 + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2 + + - name: Run chart-testing (lint) + run: |- + ct lint \ + --target-branch ${{ github.event.repository.default_branch }} \ + --charts chart/ \ + --validate-maintainers=false + + - name: Run template validation + run: |- + helm template foo chart \ + | docker run -i --rm ghcr.io/yannh/kubeconform:latest \ + --strict --summary + + - name: Run manifest snapshot test + run: docker run -i --rm -v $(pwd):/apps helmunittest/helm-unittest chart diff --git a/.github/workflows/test-pr.yaml b/.github/workflows/test-pr.yaml index 72aa987..be2a1a6 100644 --- a/.github/workflows/test-pr.yaml +++ b/.github/workflows/test-pr.yaml @@ -31,15 +31,22 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} + # Run the chart linting on every PR, even from external repos + helm_lint: + uses: ./.github/workflows/helm-lint.yaml + with: + ref: ${{ github.event.pull_request.head.sha }} + # This job exists so that PRs from outside the main repo are rejected fail_on_remote: + needs: [unit_tests, helm_lint] runs-on: ubuntu-latest steps: - name: PR must be from a branch in the azimuth-cloud/cluster-api-addon-provider repo run: exit ${{ github.event.pull_request.head.repo.full_name == 'azimuth-cloud/cluster-api-addon-provider' && '0' || '1' }} publish_artifacts: - needs: [unit_tests,fail_on_remote] + needs: [fail_on_remote] uses: ./.github/workflows/build-push-artifacts.yaml with: ref: ${{ github.event.pull_request.head.sha }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..1e97e73 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,22 @@ +# Contributing + +We welcome contributions and suggestions for improvements to this code base. +Please check for relevant issues and PRs before opening a new one of your own. + +## Making a contribution + +### Helm template snapshots + +The CI in this repository uses the Helm +[unittest](https://github.com/helm-unittest/helm-unittest) plugin's +snapshotting functionality to check PRs for changes to the templated manifests. +Therefore, if your PR makes changes to the manifest templates or values, you +will need to update the saved snapshots to allow your changes to pass the +automated tests. The easiest way to do this is to run the `helm unittest` command +inside a docker container from the repo root. + +``` +docker run -i --rm -v $(pwd):/apps helmunittest/helm-unittest chart -u +``` + +where the `-u` option is used to update the existing snapshots. diff --git a/chart/.helmignore b/chart/.helmignore index 0e8a0eb..10a0506 100644 --- a/chart/.helmignore +++ b/chart/.helmignore @@ -21,3 +21,5 @@ .idea/ *.tmproj .vscode/ +# Helm unit test files +tests/ diff --git a/chart/tests/__snapshot__/snapshot_test.yaml.snap b/chart/tests/__snapshot__/snapshot_test.yaml.snap new file mode 100644 index 0000000..d863727 --- /dev/null +++ b/chart/tests/__snapshot__/snapshot_test.yaml.snap @@ -0,0 +1,179 @@ +templated manifests should match snapshot: + 1: | + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRole + metadata: + labels: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: cluster-api-addon-provider + app.kubernetes.io/version: main + helm.sh/chart: cluster-api-addon-provider-0.1.0 + name: RELEASE-NAME-cluster-api-addon-provider + rules: + - apiGroups: + - apiextensions.k8s.io + resources: + - customresourcedefinitions + verbs: + - list + - get + - watch + - create + - apiGroups: + - apiextensions.k8s.io + resourceNames: + - helmreleases.addons.stackhpc.com + - manifests.addons.stackhpc.com + resources: + - customresourcedefinitions + verbs: + - update + - patch + - apiGroups: + - "" + resources: + - namespaces + verbs: + - list + - watch + - apiGroups: + - "" + - events.k8s.io + resources: + - events + verbs: + - create + - apiGroups: + - addons.stackhpc.com + resources: + - '*' + verbs: + - '*' + - apiGroups: + - cluster.x-k8s.io + resources: + - clusters + verbs: + - list + - watch + - get + - apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - '*' + verbs: + - list + - watch + - get + - apiGroups: + - "" + resources: + - configmaps + - secrets + verbs: + - list + - watch + - get + - patch + 2: | + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + labels: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: cluster-api-addon-provider + app.kubernetes.io/version: main + helm.sh/chart: cluster-api-addon-provider-0.1.0 + name: RELEASE-NAME-cluster-api-addon-provider + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: RELEASE-NAME-cluster-api-addon-provider + subjects: + - kind: ServiceAccount + name: RELEASE-NAME-cluster-api-addon-provider + namespace: NAMESPACE + 3: | + apiVersion: v1 + data: + config.yaml: | + !include "/etc/capi-addon-provider/defaults.yaml,/etc/capi-addon-provider/user-config.yaml" + defaults.yaml: | + easykubeFieldManager: RELEASE-NAME-cluster-api-addon-provider + user-config.yaml: | + {} + kind: ConfigMap + metadata: + labels: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: cluster-api-addon-provider + app.kubernetes.io/version: main + helm.sh/chart: cluster-api-addon-provider-0.1.0 + name: RELEASE-NAME-cluster-api-addon-provider + 4: | + apiVersion: apps/v1 + kind: Deployment + metadata: + labels: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: cluster-api-addon-provider + app.kubernetes.io/version: main + helm.sh/chart: cluster-api-addon-provider-0.1.0 + name: RELEASE-NAME-cluster-api-addon-provider + spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/name: cluster-api-addon-provider + strategy: + type: Recreate + template: + metadata: + annotations: + addons.stackhpc.com/config-hash: ae07aeabb7cd21042b32369ecbc49a27c81ef80948939f1676d4ac9530ab60e4 + labels: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/name: cluster-api-addon-provider + spec: + containers: + - image: ghcr.io/azimuth-cloud/cluster-api-addon-provider:main + imagePullPolicy: IfNotPresent + name: cluster-api-addon-provider + resources: {} + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + readOnlyRootFilesystem: true + volumeMounts: + - mountPath: /etc/capi-addon-provider + name: etc-capi-addon-provider + readOnly: true + - mountPath: /tmp + name: tmp + securityContext: + runAsNonRoot: true + serviceAccountName: RELEASE-NAME-cluster-api-addon-provider + volumes: + - configMap: + name: RELEASE-NAME-cluster-api-addon-provider + name: etc-capi-addon-provider + - emptyDir: {} + name: tmp + 5: | + apiVersion: v1 + kind: ServiceAccount + metadata: + labels: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: cluster-api-addon-provider + app.kubernetes.io/version: main + helm.sh/chart: cluster-api-addon-provider-0.1.0 + name: RELEASE-NAME-cluster-api-addon-provider diff --git a/chart/tests/snapshot_test.yaml b/chart/tests/snapshot_test.yaml new file mode 100644 index 0000000..262562e --- /dev/null +++ b/chart/tests/snapshot_test.yaml @@ -0,0 +1,7 @@ +# To update manifest snapshots run helm unittest plugin with -u option: +# docker run -i --rm -v $(pwd):/apps helmunittest/helm-unittest -u chart +suite: Manifest snapshot tests +tests: + - it: templated manifests should match snapshot + asserts: + - matchSnapshot: {}