From 756bd33df8e7f08baed7fbd7aa965ba67f2a7520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Skyler=20M=C3=A4ntysaari?= Date: Thu, 3 Apr 2025 16:57:23 +0300 Subject: [PATCH] feat: Add reusable charts test workflow and enhance PR validation process --- .github/workflows/charts-lint.yaml | 2 +- .github/workflows/charts-test.yaml | 146 +++++++++++++++++++++++++++++ .github/workflows/pr-metadata.yaml | 77 --------------- .github/workflows/pr-validate.yaml | 98 +++++++++++++++++-- 4 files changed, 237 insertions(+), 86 deletions(-) create mode 100644 .github/workflows/charts-test.yaml delete mode 100644 .github/workflows/pr-metadata.yaml diff --git a/.github/workflows/charts-lint.yaml b/.github/workflows/charts-lint.yaml index 0c84aaa..f5588b1 100644 --- a/.github/workflows/charts-lint.yaml +++ b/.github/workflows/charts-lint.yaml @@ -58,7 +58,7 @@ jobs: - name: Set up chart-testing uses: helm/chart-testing-action@v2.7.0 - - name: Run chart-testing (install) + - name: Run chart-testing run: ct lint --config .ci/ct/ct.yaml --charts "charts/${{ matrix.chart }}" # Summarize matrix https://github.community/t/status-check-for-a-matrix-jobs/127354/7 diff --git a/.github/workflows/charts-test.yaml b/.github/workflows/charts-test.yaml new file mode 100644 index 0000000..ce411c8 --- /dev/null +++ b/.github/workflows/charts-test.yaml @@ -0,0 +1,146 @@ +name: "Charts: Test (Reusable)" + +on: + workflow_call: + inputs: + charts: + description: > + Json encoded list of Helm charts to release. + Defaults to releasing everything. + default: "[]" + required: true + type: string + helmVersion: + description: > + Helm version to use. + default: "latest" + required: false + type: string + +jobs: + install-chart: + name: Install chart + runs-on: ubuntu-22.04 + if: ${{ inputs.charts != '[]' && inputs.charts != '' }} + strategy: + matrix: + chart: ${{ fromJSON(inputs.charts) }} + k8s_version: + [ + "v1.29.13", + "v1.30.9", + "v1.31.5", + "v1.32.1", + ] + fail-fast: false + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Validate prerequisite folders + working-directory: "charts/${{ matrix.chart }}" + run: | + CHART_TYPE=$(yq '.type // "application"' Chart.yaml) + + - name: Install Kubernetes tools + uses: yokawasa/action-setup-kube-tools@v0.11.2 + with: + setup-tools: | + helmv3 + kubectl + helm: "${{ inputs.helmVersion }}" + kubectl: "${{ matrix.k8s_version }}" + + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2.6.1 + + - name: Create k3d cluster + uses: nolar/setup-k3d-k3s@v1 + with: + version: ${{ matrix.k8s_version }} + + - name: Remove node taints + run: | + kubectl taint --all=true nodes node.cloudprovider.kubernetes.io/uninitialized- || true + + - name: Run chart-testing (install) + working-directory: "charts/${{ matrix.chart }}" + run: | + ct install --config "$GITHUB_WORKSPACE/.ci/ct/ct.yaml" --charts . + + install_success: + needs: + - install-chart + if: ${{ !cancelled() }} + name: Install successful + runs-on: ubuntu-latest + steps: + - name: Check matrix status + if: >- + ${{ + (inputs.chartsToTest != '' && inputs.chartsToTest != '[]') && + contains(needs.*.result, 'failure') + }} + run: exit 1 + + unittest-chart: + name: Unit-test chart + runs-on: ubuntu-22.04 + if: ${{ inputs.charts != '[]' && inputs.charts != '' }} + strategy: + matrix: + chart: ${{ fromJSON(inputs.charts) }} + fail-fast: false + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Validate prerequisite folders + working-directory: "charts/${{ matrix.chart }}" + run: | + CHART_TYPE=$(yq '.type // "application"' Chart.yaml) + + - name: Install Kubernetes tools + uses: yokawasa/action-setup-kube-tools@v0.11.2 + with: + setup-tools: | + helmv3 + helm: "${{ inputs.helmVersion }}" + +# - name: Dereference JSON schema +# uses: bjw-s/helm-charts-actions/dereference-json-schema@main +# with: +# schemaFile: "charts/${{ matrix.chart }}/values.schema.json" +# outputFile: "charts/${{ matrix.chart }}/values.schema.json" +# allowFileNotFound: true + + - name: Run tests + working-directory: "charts/${{ matrix.chart }}" + run: | + if [[ ! -d "unittests" ]]; then + echo "No unit tests found for chart ${{ matrix.chart }}" + exit 0 + fi + + helm plugin install https://github.com/helm-unittest/helm-unittest.git + helm dep update + helm unittest -f "unittests/**/*_test.yaml" . + + unittest_success: + needs: + - unittest-chart + if: ${{ !cancelled() }} + name: Unittest successful + runs-on: ubuntu-latest + steps: + - name: Check matrix status + if: >- + ${{ + (inputs.chartsToTest != '' && inputs.chartsToTest != '[]') && + contains(needs.*.result, 'failure') + }} + run: exit 1 \ No newline at end of file diff --git a/.github/workflows/pr-metadata.yaml b/.github/workflows/pr-metadata.yaml deleted file mode 100644 index a40b40b..0000000 --- a/.github/workflows/pr-metadata.yaml +++ /dev/null @@ -1,77 +0,0 @@ -name: "Pull Request: Get metadata" - -on: - workflow_call: - outputs: - isRenovatePR: - description: "Is the PR coming from Renovate?" - value: ${{ jobs.pr-metadata.outputs.isRenovatePR }} - isFork: - description: "Is the PR coming from a forked repo?" - value: ${{ jobs.pr-metadata.outputs.isFork }} - addedOrModifiedFilesDetected: - description: "Does the PR contain any changes?" - value: ${{ jobs.pr-changes.outputs.addedOrModifiedFilesDetected }} - addedOrModifiedFiles: - description: "A list of the files changed in this PR" - value: ${{ jobs.pr-changes.outputs.addedOrModifiedFiles }} - addedOrModifiedCharts: - description: "A list of the charts changed in this PR" - value: ${{ jobs.pr-changes.outputs.addedOrModifiedCharts }} - chartsToLint: - value: ${{ jobs.pr-changes.outputs.chartsToLint }} - chartsToInstall: - value: ${{ jobs.pr-changes.outputs.chartsToInstall }} - -jobs: - pr-metadata: - name: Collect PR metadata - runs-on: ubuntu-latest - outputs: - isRenovatePR: ${{ startsWith(steps.branch-name.outputs.current_branch, 'renovate/') }} - isFork: ${{ github.event.pull_request.head.repo.full_name != github.repository }} - steps: - - name: Get branch name - id: branch-name - uses: tj-actions/branch-names@v6.5 - - - name: Save PR data to file - env: - PR_NUMBER: ${{ github.event.number }} - run: | - echo $PR_NUMBER > pr_number.txt - - - name: Store pr data in artifact - uses: actions/upload-artifact@v4 - with: - name: pr_metadata - path: ./pr_number.txt - retention-days: 5 - - pr-changes: - name: Collect PR changes - runs-on: ubuntu-latest - outputs: - addedOrModifiedFilesDetected: ${{ steps.changed-files.outputs.allAddedOrModified }} - addedOrModifiedFiles: ${{ steps.changed-files.outputs.allAddedOrModified_files }} - addedOrModifiedCharts: ${{ steps.changed-charts.outputs.charts }} - chartsToLint: ${{ steps.changed-charts.outputs.chartsToLint }} - chartsToInstall: ${{ steps.changed-charts.outputs.chartsToInstall }} - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - - name: Collect changed files - uses: dorny/paths-filter@v3 - id: changed-files - with: - list-files: json - filters: | - allAddedOrModified: - - added|modified: '**' - - - name: Collect changed charts - uses: bjw-s-labs/helm-charts-actions/collect-charts@2025.2.0 - id: changed-charts diff --git a/.github/workflows/pr-validate.yaml b/.github/workflows/pr-validate.yaml index 7e9f1a1..07aa539 100644 --- a/.github/workflows/pr-validate.yaml +++ b/.github/workflows/pr-validate.yaml @@ -2,6 +2,11 @@ name: "Pull Request: Validate" on: pull_request: + types: + - opened + - reopened + - ready_for_review + - synchronize workflow_dispatch: concurrency: @@ -9,23 +14,100 @@ concurrency: cancel-in-progress: true jobs: - pr-metadata: - uses: ./.github/workflows/pr-metadata.yaml + prepare: + name: Prepare data required for workflow + runs-on: ubuntu-22.04 + outputs: + isRenovatePR: ${{ startsWith(steps.branch-name.outputs.current_branch, 'renovate/') }} + repoConfiguration: ${{ steps.repo-config.outputs.config }} + addedOrModifiedFiles: ${{ steps.added-modified-files.outputs.all_changed_files }} + chartsToLint: ${{ steps.charts-to-lint.outputs.filteredCharts }} + chartsToInstall: ${{ steps.charts-to-install.outputs.filteredCharts }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Grab repository configuration + id: repo-config + shell: bash + run: | + echo "config=$(yq '.' '.ci/repo-config.yaml' -o json -I=0)" >> "$GITHUB_OUTPUT" + + - name: Get branch name + id: branch-name + uses: tj-actions/branch-names@v6.5 + + - name: Get all added or modified files + id: added-modified-files + uses: tj-actions/changed-files@v45 + + - name: Get changed charts + id: changed-charts + uses: tj-actions/changed-files@v45 + with: + matrix: true + path: charts + dir_names: true + dir_names_max_depth: 2 + + - name: Determine charts to lint + id: charts-to-lint + uses: actions/github-script@v7 + with: + script: | + var changedCharts = ${{ steps.changed-charts.outputs.all_changed_files }}; + var chartsToFilter = ${{ toJSON(fromJSON(steps.repo-config.outputs.config).excluded-charts-lint) }}; + let filteredCharts = changedCharts.filter(item => chartsToFilter.indexOf(item) < 0); + core.setOutput("filteredCharts", filteredCharts); + + - name: Determine charts to install + id: charts-to-install + uses: actions/github-script@v7 + with: + script: | + var changedCharts = ${{ steps.changed-charts.outputs.all_changed_files }}; + var chartsToFilter = ${{ toJSON(fromJSON(steps.repo-config.outputs.config).excluded-charts-install) }}; + let filteredCharts = changedCharts.filter(item => chartsToFilter.indexOf(item) < 0); + core.setOutput("filteredCharts", filteredCharts); + + pre-commit-check: + name: Perform Pre-Commit check + runs-on: ubuntu-22.04 + needs: + - prepare + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Run against changes + uses: pre-commit/action@v3.0.1 + with: + extra_args: --files ${{ needs.prepare.outputs.addedOrModifiedFiles }} --config .ci/pre-commit/config.yaml charts-changelog: uses: ./.github/workflows/charts-changelog.yaml needs: - - pr-metadata + - prepare with: - isRenovatePR: ${{ needs.pr-metadata.outputs.isRenovatePR }} - modifiedCharts: ${{ needs.pr-metadata.outputs.addedOrModifiedCharts }} + isRenovatePR: ${{ needs.prepare.outputs.isRenovatePR }} + modifiedCharts: ${{ needs.prepare.outputs.addedOrModifiedCharts }} charts-lint: uses: ./.github/workflows/charts-lint.yaml needs: - - pr-metadata + - prepare - charts-changelog with: checkoutCommit: ${{ github.sha }} - chartsToLint: ${{ needs.pr-metadata.outputs.chartsToLint }} - isRenovatePR: ${{ needs.pr-metadata.outputs.isRenovatePR }} + chartsToLint: ${{ needs.prepare.outputs.chartsToLint }} + isRenovatePR: ${{ needs.prepare.outputs.isRenovatePR }} + + charts-test: + name: Test charts + uses: ./.github/workflows/charts-test.yaml + needs: + - prepare + with: + charts: ${{ needs.prepare.outputs.chartsToInstall }}