fix: replace Helm-based cloud-provider-kind installer with Docker container approach #3565
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI - KSail | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| merge_group: | |
| concurrency: | |
| group: "ci-ksail-${{ github.workflow }}-${{ github.ref }}" | |
| cancel-in-progress: true | |
| permissions: {} | |
| jobs: | |
| # Detect which file categories changed to conditionally run jobs | |
| changes: | |
| name: 🔍 Detect Changes | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| outputs: | |
| code: ${{ steps.filter.outputs.code }} | |
| schema: ${{ steps.filter.outputs.schema }} | |
| cli: ${{ steps.filter.outputs.cli }} | |
| vsce: ${{ steps.filter.outputs.vsce }} | |
| docs-deps: ${{ steps.filter.outputs.docs-deps }} | |
| vsce-deps: ${{ steps.filter.outputs.vsce-deps }} | |
| steps: | |
| - name: 📄 Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: 🔍 Filter paths | |
| uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 | |
| id: filter | |
| with: | |
| filters: | | |
| code: | |
| - '**/*.go' | |
| - 'go.mod' | |
| - 'go.sum' | |
| - '.github/actions/**' | |
| schema: | |
| - 'pkg/apis/**/*.go' | |
| - 'go.mod' | |
| - '.github/scripts/generate-schema*' | |
| cli: | |
| - 'cmd/**/*.go' | |
| - 'pkg/**/*.go' | |
| - 'go.mod' | |
| - '.github/scripts/generate-cli-flags-docs.sh' | |
| vsce: | |
| - 'vsce/**' | |
| - '.github/workflows/ci.yaml' | |
| docs-deps: | |
| - 'docs/package*.json' | |
| - '.github/workflows/ci.yaml' | |
| vsce-deps: | |
| - 'vsce/package*.json' | |
| - '.github/workflows/ci.yaml' | |
| build-artifact: | |
| name: 🏗️ Build KSail Binary | |
| runs-on: ubuntu-latest | |
| needs: [changes] | |
| if: (github.event_name == 'pull_request' || github.event_name == 'merge_group') && (needs.changes.outputs.code == 'true' || needs.changes.outputs.cli == 'true') | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: 📄 Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: ⚙️ Setup Go | |
| id: setup-go | |
| uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 | |
| with: | |
| go-version-file: go.mod | |
| - name: 📦 Cache KSail Binary | |
| uses: ./.github/actions/cache-ksail-binary | |
| with: | |
| go-version: ${{ steps.setup-go.outputs.go-version }} | |
| source-hash: ${{ hashFiles('go.mod', 'go.sum', '**/*.go') }} | |
| output-path: /usr/local/bin/ksail | |
| generate-schema: | |
| name: 📝 Generate JSON Schema | |
| runs-on: ubuntu-latest | |
| needs: [changes] | |
| if: needs.changes.outputs.schema == 'true' | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: 🔑 Generate GitHub App Token | |
| uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # v2.1.0 | |
| id: generate-token | |
| with: | |
| app_id: ${{ vars.APP_ID }} | |
| private_key: ${{ secrets.APP_PRIVATE_KEY }} | |
| - name: 📄 Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: true | |
| token: ${{ steps.generate-token.outputs.token }} | |
| - name: ⚙️ Setup Go | |
| uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 | |
| with: | |
| go-version-file: go.mod | |
| - name: 📝 Generate JSON schema | |
| run: .github/scripts/generate-schema.sh | |
| - name: 📤 Commit and push schema changes | |
| if: github.event_name != 'merge_group' | |
| uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0 | |
| with: | |
| commit_message: "chore: update generated JSON schema" | |
| commit_user_name: generator-bot | |
| commit_user_email: [email protected] | |
| generate-cli-flags-docs: | |
| name: 📚 Generate CLI Flags Docs | |
| runs-on: ubuntu-latest | |
| needs: [changes, build-artifact] | |
| if: needs.changes.outputs.cli == 'true' | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: 🔑 Generate GitHub App Token | |
| uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # v2.1.0 | |
| id: generate-token | |
| with: | |
| app_id: ${{ vars.APP_ID }} | |
| private_key: ${{ secrets.APP_PRIVATE_KEY }} | |
| - name: 📄 Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: true | |
| token: ${{ steps.generate-token.outputs.token }} | |
| - name: ⚙️ Setup Go | |
| id: setup-go | |
| uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 | |
| with: | |
| go-version-file: go.mod | |
| - name: 📦 Cache KSail Binary | |
| uses: ./.github/actions/cache-ksail-binary | |
| with: | |
| go-version: ${{ steps.setup-go.outputs.go-version }} | |
| source-hash: ${{ hashFiles('go.mod', 'go.sum', '**/*.go') }} | |
| output-path: /usr/local/bin/ksail | |
| - name: 📚 Generate CLI flags documentation | |
| run: .github/scripts/generate-cli-flags-docs.sh | |
| - name: 📤 Commit and push CLI flags docs | |
| if: github.event_name != 'merge_group' | |
| uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0 | |
| with: | |
| commit_message: "chore: update generated CLI flags docs" | |
| commit_user_name: generator-bot | |
| commit_user_email: [email protected] | |
| coverage: | |
| name: 📊 Code Coverage | |
| runs-on: ubuntu-latest | |
| needs: [changes] | |
| # Only run on push to main, skip if no code files changed | |
| if: | | |
| github.event_name == 'push' | |
| && github.ref == 'refs/heads/main' | |
| && needs.changes.outputs.code == 'true' | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: 📑 Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: ⚙️ Setup Go | |
| uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 | |
| with: | |
| go-version-file: go.mod | |
| - name: 👨🏻🔧 Enable covdata (temp) see https://github.com/golang/go/issues/75031 | |
| run: go env -w GOTOOLCHAIN=go1.25.0+auto | |
| - name: 📄 Generate coverage | |
| run: | | |
| go test -race -coverprofile=coverage.txt -covermode=atomic ./... | |
| - name: 📄 Upload coverage to Codecov | |
| uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.5.2 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| system-test: | |
| name: 🧪 System Test | |
| runs-on: ubuntu-latest | |
| needs: [changes, build-artifact] | |
| if: github.event_name == 'merge_group' && needs.changes.outputs.code == 'true' | |
| permissions: | |
| contents: read | |
| packages: write | |
| strategy: | |
| matrix: | |
| distribution: [Vanilla, K3s, Talos] | |
| provider: [Docker] | |
| init: [true, false] | |
| args: | |
| - "" | |
| - "--name system-test-cluster" | |
| - "--cert-manager Enabled" | |
| - "--cni Cilium" | |
| - "--cni Calico" | |
| - "--csi Enabled" | |
| - "--csi Disabled" | |
| - "--gitops-engine Flux" | |
| - "--gitops-engine ArgoCD" | |
| - "--gitops-engine Flux --local-registry ghcr.io/devantler-tech/ksail/system-test-manifests" | |
| - "--gitops-engine ArgoCD --local-registry ghcr.io/devantler-tech/ksail/system-test-manifests" | |
| - "--mirror-registry ghcr.io=https://ghcr.io" | |
| - "--mirror-registry ghcr.io=https://ghcr.io --mirror-registry docker.io=https://registry-1.docker.io" | |
| - "--metrics-server Enabled" | |
| - "--metrics-server Disabled" | |
| - "--policy-engine Kyverno" | |
| - "--policy-engine Gatekeeper" | |
| - "--load-balancer Enabled" | |
| - "--load-balancer Disabled" | |
| # Exclude combinations where CSI flag matches distribution × provider default behavior | |
| # to avoid wasting GitHub Actions minutes on no-op tests | |
| exclude: | |
| # Vanilla has no default CSI, so --csi Disabled is a no-op | |
| - distribution: Vanilla | |
| args: "--csi Disabled" | |
| # K3s has default CSI (local-path), so --csi Enabled is a no-op | |
| - distribution: K3s | |
| args: "--csi Enabled" | |
| # Talos × Docker has no default CSI, so --csi Disabled is a no-op | |
| - distribution: Talos | |
| provider: Docker | |
| args: "--csi Disabled" | |
| # Vanilla has no default LoadBalancer, so --load-balancer Disabled is a no-op | |
| - distribution: Vanilla | |
| args: "--load-balancer Disabled" | |
| # K3s has default LoadBalancer (ServiceLB), so --load-balancer Enabled is a no-op | |
| - distribution: K3s | |
| args: "--load-balancer Enabled" | |
| # Talos × Docker has no default LoadBalancer, so --load-balancer Disabled is a no-op | |
| - distribution: Talos | |
| provider: Docker | |
| args: "--load-balancer Disabled" | |
| # Add Talos x Hetzner combination | |
| include: | |
| - distribution: Talos | |
| provider: Hetzner | |
| init: true | |
| args: "--name system-test-cluster-with-scaffolding" | |
| - distribution: Talos | |
| provider: Hetzner | |
| init: false | |
| args: "--name system-test-cluster-without-scaffolding" | |
| # Note: Talos × Hetzner has default CSI (Hetzner CSI), so --csi Enabled | |
| # would be a no-op. Similarly, Talos × Hetzner has default LoadBalancer | |
| # (hcloud-cloud-controller-manager), so --load-balancer Enabled would be | |
| # a no-op. We don't add these to the matrix to save CI minutes. | |
| steps: | |
| - name: 📄 Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: 🧹 Free disk space | |
| uses: ./.github/actions/free-disk-space | |
| - name: ⚙️ Setup Go | |
| id: setup-go | |
| uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6.2.0 | |
| with: | |
| go-version-file: go.mod | |
| - name: 📦 Cache KSail Binary | |
| uses: ./.github/actions/cache-ksail-binary | |
| with: | |
| go-version: ${{ steps.setup-go.outputs.go-version }} | |
| source-hash: ${{ hashFiles('go.mod', 'go.sum', '**/*.go') }} | |
| output-path: /usr/local/bin/ksail | |
| - name: 🧪 Run KSail System Test | |
| uses: ./.github/actions/ksail-system-test | |
| with: | |
| distribution: ${{ matrix.distribution }} | |
| provider: ${{ matrix.provider }} | |
| init: ${{ matrix.init }} | |
| args: ${{ matrix.args }} | |
| apply-overlay-path: ".github/fixtures/podinfo-overlay" | |
| hcloud-token: ${{ matrix.provider == 'Hetzner' && secrets.HCLOUD_TOKEN || '' }} | |
| ghcr-user: ${{ github.actor }} | |
| ghcr-token: ${{ secrets.GITHUB_TOKEN }} | |
| cleanup-hetzner: | |
| name: 🧹 Cleanup Hetzner Resources | |
| runs-on: ubuntu-latest | |
| needs: [system-test] | |
| if: ${{ always() && github.event_name == 'merge_group' && needs.system-test.result != 'skipped' }} | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: 📄 Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: 🧹 Cleanup all KSail-owned Hetzner resources | |
| uses: ./.github/actions/cleanup-hetzner | |
| with: | |
| hcloud-token: ${{ secrets.HCLOUD_TOKEN }} | |
| audit-docs: | |
| name: 🔍 Audit Docs Dependencies | |
| runs-on: ubuntu-latest | |
| needs: [changes] | |
| if: needs.changes.outputs.docs-deps == 'true' | |
| permissions: | |
| contents: write | |
| defaults: | |
| run: | |
| working-directory: docs | |
| steps: | |
| - name: 🔑 Generate GitHub App Token | |
| uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # v2.1.0 | |
| id: generate-token | |
| with: | |
| app_id: ${{ vars.APP_ID }} | |
| private_key: ${{ secrets.APP_PRIVATE_KEY }} | |
| - name: 📄 Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: true | |
| token: ${{ steps.generate-token.outputs.token }} | |
| - name: ⚙️ Setup Node.js | |
| uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 | |
| with: | |
| node-version: "22" | |
| cache: "npm" | |
| cache-dependency-path: docs/package-lock.json | |
| - name: 📦 Install dependencies | |
| run: npm ci | |
| - name: 🔍 Run npm audit | |
| id: audit | |
| run: npm audit --audit-level=moderate | |
| continue-on-error: true | |
| - name: 🔧 Attempt automatic fix (non-breaking) | |
| id: fix | |
| if: steps.audit.outcome == 'failure' && (github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main')) | |
| run: | | |
| # Only apply non-breaking fixes automatically | |
| npm audit fix --no-force | |
| if [ -n "$(git status --porcelain)" ]; then | |
| echo "changes_made=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "changes_made=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: 📤 Commit and push fixes | |
| if: steps.fix.outputs.changes_made == 'true' && github.event_name != 'merge_group' | |
| uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0 | |
| with: | |
| commit_message: "chore(docs): fix npm audit vulnerabilities" | |
| commit_user_name: security-bot | |
| commit_user_email: [email protected] | |
| file_pattern: "docs/package*.json" | |
| - name: 🔍 Re-audit after fix | |
| id: reaudit | |
| if: steps.fix.outputs.changes_made == 'true' | |
| run: npm audit --audit-level=moderate | |
| continue-on-error: true | |
| - name: ❌ Fail if vulnerabilities remain | |
| if: | | |
| github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| && ((steps.fix.outputs.changes_made != 'true' && steps.audit.outcome == 'failure') | |
| || (steps.fix.outputs.changes_made == 'true' && steps.reaudit.outcome == 'failure')) | |
| run: npm audit --audit-level=moderate | |
| audit-vsce: | |
| name: 🔍 Audit VSCode Extension Dependencies | |
| runs-on: ubuntu-latest | |
| needs: [changes] | |
| if: needs.changes.outputs.vsce-deps == 'true' | |
| permissions: | |
| contents: write | |
| defaults: | |
| run: | |
| working-directory: vsce | |
| steps: | |
| - name: 🔑 Generate GitHub App Token | |
| uses: tibdex/github-app-token@3beb63f4bd073e61482598c45c71c1019b59b73a # v2.1.0 | |
| id: generate-token | |
| with: | |
| app_id: ${{ vars.APP_ID }} | |
| private_key: ${{ secrets.APP_PRIVATE_KEY }} | |
| - name: 📄 Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: true | |
| token: ${{ steps.generate-token.outputs.token }} | |
| - name: ⚙️ Setup Node.js | |
| uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 | |
| with: | |
| node-version: "22" | |
| cache: "npm" | |
| cache-dependency-path: vsce/package-lock.json | |
| - name: 📦 Install dependencies | |
| run: npm ci | |
| - name: 🔍 Run npm audit | |
| id: audit | |
| run: npm audit --audit-level=moderate | |
| continue-on-error: true | |
| - name: 🔧 Attempt automatic fix (non-breaking) | |
| id: fix | |
| if: steps.audit.outcome == 'failure' && (github.event_name == 'pull_request' || (github.event_name == 'push' && github.ref == 'refs/heads/main')) | |
| run: | | |
| # Only apply non-breaking fixes automatically | |
| npm audit fix --no-force | |
| if [ -n "$(git status --porcelain)" ]; then | |
| echo "changes_made=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "changes_made=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: 📤 Commit and push fixes | |
| if: steps.fix.outputs.changes_made == 'true' && github.event_name != 'merge_group' | |
| uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0 | |
| with: | |
| commit_message: "chore(vsce): fix npm audit vulnerabilities" | |
| commit_user_name: security-bot | |
| commit_user_email: [email protected] | |
| file_pattern: "vsce/package*.json" | |
| - name: 🔍 Re-audit after fix | |
| id: reaudit | |
| if: steps.fix.outputs.changes_made == 'true' | |
| run: npm audit --audit-level=moderate | |
| continue-on-error: true | |
| - name: ❌ Fail if vulnerabilities remain | |
| if: | | |
| github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| && ((steps.fix.outputs.changes_made != 'true' && steps.audit.outcome == 'failure') | |
| || (steps.fix.outputs.changes_made == 'true' && steps.reaudit.outcome == 'failure')) | |
| run: npm audit --audit-level=moderate | |
| vscode-extension: | |
| name: 🧩 VSCode Extension | |
| runs-on: ubuntu-latest | |
| needs: [changes] | |
| if: needs.changes.outputs.vsce == 'true' | |
| permissions: | |
| contents: read | |
| defaults: | |
| run: | |
| working-directory: vsce | |
| steps: | |
| - name: 📄 Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: ⚙️ Setup Node.js | |
| uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0 | |
| with: | |
| node-version: "22" | |
| cache: "npm" | |
| cache-dependency-path: "vsce/package-lock.json" | |
| - name: 📦 Install dependencies | |
| run: npm ci | |
| - name: 🏗️ Compile | |
| run: npm run compile | |
| - name: 📦 Package extension | |
| run: npm run package | |
| - name: 📦 Create VSIX package | |
| if: github.event_name == 'pull_request' || github.event_name == 'merge_group' | |
| run: npx @vscode/vsce package --out ksail.vsix | |
| - name: 📤 Upload VSIX artifact | |
| if: github.event_name == 'pull_request' || github.event_name == 'merge_group' | |
| uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # 6.0.0 | |
| with: | |
| name: ksail-vsix | |
| path: ksail.vsix | |
| retention-days: 7 | |
| status: | |
| name: CI - KSail | |
| runs-on: ubuntu-latest | |
| needs: | |
| [ | |
| changes, | |
| build-artifact, | |
| generate-schema, | |
| generate-cli-flags-docs, | |
| coverage, | |
| system-test, | |
| cleanup-hetzner, | |
| audit-docs, | |
| audit-vsce, | |
| vscode-extension, | |
| ] | |
| if: ${{ always() }} | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - uses: ./.github/actions/summarize-workflow | |
| with: | |
| job-results: >- | |
| ${{ needs.changes.result }} | |
| ${{ needs.build-artifact.result }} | |
| ${{ needs.generate-schema.result }} | |
| ${{ needs.generate-cli-flags-docs.result }} | |
| ${{ needs.coverage.result }} | |
| ${{ needs.system-test.result }} | |
| ${{ needs.cleanup-hetzner.result }} | |
| ${{ needs.audit-docs.result }} | |
| ${{ needs.audit-vsce.result }} | |
| ${{ needs.vscode-extension.result }} |