diff --git a/.github/workflows/test-helm-lint.yml b/.github/workflows/test-helm-lint.yml index 9a829789..724cec6e 100644 --- a/.github/workflows/test-helm-lint.yml +++ b/.github/workflows/test-helm-lint.yml @@ -4,6 +4,7 @@ on: pull_request: paths: - "actions/helm-lint/**" + - "test/helm/**" permissions: contents: write @@ -18,13 +19,21 @@ jobs: with: fetch-depth: 0 + # The action lints only charts changed vs the base branch. + - name: Touch test chart so list-changed picks it up + run: | + echo "# touched by CI" >> test/helm/values.yaml + git -c user.name=ci -c user.email=ci@example.com commit -qam "test: touch chart" + - name: helm lint uses: ./actions/helm-lint id: helm-lint with: - repository: ${{ github.repository }} - chartPaths: "./test/helm" + chartPaths: "test" + registry: ${{ secrets.ACR_URL }} + username: ${{ secrets.ACR_PUSH_USER }} + password: ${{ secrets.ACR_PUSH_TOKEN }} - name: Print on chart change if: steps.helm-lint.outputs.changed == 'true' - run: echo "Charts were changed and linted." + run: echo "Charts were changed." diff --git a/.prettierignore b/.prettierignore index 240b5c48..f5546ad0 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,6 @@ # Changelogs that are generated by release-please **/CHANGELOG.md .release-please-manifest.json + +# Helm templates are not valid YAML; prettier mangles {{ }} +test/helm/templates/ diff --git a/actions/helm-lint/README.md b/actions/helm-lint/README.md index 8c9e1789..5a1b9679 100644 --- a/actions/helm-lint/README.md +++ b/actions/helm-lint/README.md @@ -7,9 +7,19 @@ It detects which charts have changed and only tests those. ## 🛠 Inputs -| Name | Description | Required | -|--------------|--------------------------------------------------------------|----------| -| `chartPaths` | Comma-separated list of root directories with Helm charts. | No | +| Name | Description | Required | +|--------------|-----------------------------------------------------------------------------|----------| +| `chartPaths` | Comma-separated list of root directories with Helm charts. | No | +| `registry` | OCI registry to log in to before building chart dependencies. | No | +| `username` | Registry username. | No | +| `password` | Registry password. | No | +| `install` | `true` to also install the changed charts in a kind cluster. Default `false`. | No | + +Lint (and install) run only when `registry`, `username` and `password` are all set, since +`ct lint` builds chart dependencies and most charts depend on charts in the OCI registry. + +Lint uses the action's `ct.yaml` (no version-bump or maintainers check) and `lintconf.yaml` +(ct's default, except `brackets`, `comments` and `trailing-spaces` only warn). ## 📤 Outputs @@ -26,5 +36,8 @@ It detects which charts have changed and only tests those. uses: MapColonies/shared-workflows/actions/helm-lint@helm-lint-v1.1.0 with: chartPaths: infra/monitoring,infra/sftpgo + registry: ${{ secrets.ACR_URL }} + username: ${{ secrets.ACR_PUSH_USER }} + password: ${{ secrets.ACR_PUSH_TOKEN }} ``` diff --git a/actions/helm-lint/action.yaml b/actions/helm-lint/action.yaml index 47160c67..6f61ee0b 100644 --- a/actions/helm-lint/action.yaml +++ b/actions/helm-lint/action.yaml @@ -5,6 +5,22 @@ inputs: description: "Comma-separated list of root directories containing Helm charts." required: false default: "." + registry: + description: "OCI registry to log in to before building chart dependencies. Lint and install run only when registry, username and password are all set." + required: false + default: "" + username: + description: "Registry username." + required: false + default: "" + password: + description: "Registry password." + required: false + default: "" + install: + description: "Also install the changed charts in a kind cluster." + required: false + default: "false" outputs: changed: description: "Indicates if there are changed charts." @@ -27,24 +43,56 @@ runs: uses: helm/chart-testing-action@v2 - name: Run chart-testing (list-changed) - id: list_changed + id: list-changed + env: + CHART_DIRS: ${{ inputs.chartPaths }} + TARGET_BRANCH: ${{ github.base_ref || github.event.repository.default_branch }} run: | - changed=$(ct list-changed --chart-dirs "${{ inputs.chartPaths }}" --target-branch "${{ github.base_ref || github.event.repository.default_branch }}") + changed=$(ct list-changed --config "$GITHUB_ACTION_PATH/ct.yaml" --chart-dirs "$CHART_DIRS" --target-branch "$TARGET_BRANCH") if [[ -n "$changed" ]]; then echo "changed=true" >> "$GITHUB_OUTPUT" fi shell: bash + - name: Log in to the registry + id: login + if: steps.list-changed.outputs.changed == 'true' && inputs.registry != '' && inputs.username != '' && inputs.password != '' + env: + REGISTRY: ${{ inputs.registry }} + USERNAME: ${{ inputs.username }} + PASSWORD: ${{ inputs.password }} + run: printf '%s' "$PASSWORD" | helm registry login "$REGISTRY" --username "$USERNAME" --password-stdin + shell: bash + + - name: Warn that lint is skipped + if: steps.list-changed.outputs.changed == 'true' && steps.login.outcome == 'skipped' + run: echo "::warning::Charts changed but were not linted. Pass registry, username and password to lint them." + shell: bash + - name: Run chart-testing (lint) - if: steps.list-changed.outputs.changed == 'true' - run: ct lint --chart-dirs "${{ inputs.chartPaths }}" --target-branch "${{ github.base_ref || github.event.repository.default_branch }}" + if: steps.login.outcome == 'success' + env: + CHART_DIRS: ${{ inputs.chartPaths }} + TARGET_BRANCH: ${{ github.base_ref || github.event.repository.default_branch }} + run: ct lint --config "$GITHUB_ACTION_PATH/ct.yaml" --lint-conf "$GITHUB_ACTION_PATH/lintconf.yaml" --chart-dirs "$CHART_DIRS" --target-branch "$TARGET_BRANCH" shell: bash - name: Create kind cluster - if: steps.list-changed.outputs.changed == 'true' + if: inputs.install == 'true' && steps.login.outcome == 'success' uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0 - name: Run chart-testing (install) - if: steps.list-changed.outputs.changed == 'true' - run: ct install --chart-dirs "${{ inputs.chartPaths }}" --target-branch "${{ github.base_ref || github.event.repository.default_branch }}" + if: inputs.install == 'true' && steps.login.outcome == 'success' + env: + CHART_DIRS: ${{ inputs.chartPaths }} + TARGET_BRANCH: ${{ github.base_ref || github.event.repository.default_branch }} + run: ct install --config "$GITHUB_ACTION_PATH/ct.yaml" --chart-dirs "$CHART_DIRS" --target-branch "$TARGET_BRANCH" + shell: bash + + # Self-hosted runners keep the login in ~/.config/helm/registry/config.json. + - name: Log out of the registry + if: always() && steps.login.outcome == 'success' + env: + REGISTRY: ${{ inputs.registry }} + run: helm registry logout "$REGISTRY" shell: bash diff --git a/actions/helm-lint/ct.yaml b/actions/helm-lint/ct.yaml new file mode 100644 index 00000000..ae7173a4 --- /dev/null +++ b/actions/helm-lint/ct.yaml @@ -0,0 +1,2 @@ +check-version-increment: false +validate-maintainers: false diff --git a/actions/helm-lint/lintconf.yaml b/actions/helm-lint/lintconf.yaml new file mode 100644 index 00000000..ff1d1a84 --- /dev/null +++ b/actions/helm-lint/lintconf.yaml @@ -0,0 +1,46 @@ +--- +# ct's etc/lintconf.yaml, except brackets, comments and trailing-spaces warn: most consumer charts violate them today. +rules: + braces: + min-spaces-inside: 0 + max-spaces-inside: 0 + min-spaces-inside-empty: -1 + max-spaces-inside-empty: -1 + brackets: + level: warning + min-spaces-inside: 0 + max-spaces-inside: 0 + min-spaces-inside-empty: -1 + max-spaces-inside-empty: -1 + colons: + max-spaces-before: 0 + max-spaces-after: 1 + commas: + max-spaces-before: 0 + min-spaces-after: 1 + max-spaces-after: 1 + comments: + level: warning + require-starting-space: true + min-spaces-from-content: 2 + document-end: disable + document-start: disable # No --- to start a file + empty-lines: + max: 2 + max-start: 0 + max-end: 0 + hyphens: + max-spaces-after: 1 + indentation: + spaces: consistent + indent-sequences: whatever # - list indentation will handle both indentation and without + check-multi-line-strings: false + key-duplicates: enable + line-length: disable # Lines can be any length + new-line-at-end-of-file: enable + new-lines: + type: unix + trailing-spaces: + level: warning + truthy: + level: warning diff --git a/test/helm/templates/deployment.yaml b/test/helm/templates/deployment.yaml index 313ad712..24bd54b7 100644 --- a/test/helm/templates/deployment.yaml +++ b/test/helm/templates/deployment.yaml @@ -1,28 +1,26 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: { { include "hello-world-chart.fullname" . } } - labels: { { - include "hello-world-chart.labels" . | nindent 4 } } + name: {{ include "hello-world-chart.fullname" . }} + labels: + {{- include "hello-world-chart.labels" . | nindent 4 }} spec: - replicas: { { .Values.replicaCount } } + replicas: {{ .Values.replicaCount }} selector: matchLabels: - app: { { include "hello-world-chart.name" . } } - release: { { .Release.Name } } + app: {{ include "hello-world-chart.name" . }} + release: {{ .Release.Name }} template: metadata: labels: - app: { { include "hello-world-chart.name" . } } - release: { { .Release.Name } } + app: {{ include "hello-world-chart.name" . }} + release: {{ .Release.Name }} spec: containers: - - name: { { .Chart.Name } } + - name: {{ .Chart.Name }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" - imagePullPolicy: { { .Values.image.pullPolicy } } - command: ["echo"] - args: ["hello world"] + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ["sleep", "infinity"] ports: - containerPort: 80 name: http - invalidField: true - restartPolicy: Never diff --git a/test/helm/templates/secret.yaml b/test/helm/templates/secret.yaml index f2c230cd..85348b21 100644 --- a/test/helm/templates/secret.yaml +++ b/test/helm/templates/secret.yaml @@ -4,5 +4,5 @@ metadata: name: sftpgo-admin-creds type: Opaque data: - username: { { .Values.secret.username | b64enc } } - password: { { .Values.secret.password | b64enc } } + username: {{ .Values.secret.username | b64enc }} + password: {{ .Values.secret.password | b64enc }} diff --git a/test/helm/values.yaml b/test/helm/values.yaml index 8fab8768..a1657ed5 100644 --- a/test/helm/values.yaml +++ b/test/helm/values.yaml @@ -26,3 +26,7 @@ nodeSelector: {} tolerations: [] affinity: {} + +secret: + username: admin + password: admin