Skip to content

fix: replace Helm-based cloud-provider-kind installer with Docker container approach #3565

fix: replace Helm-based cloud-provider-kind installer with Docker container approach

fix: replace Helm-based cloud-provider-kind installer with Docker container approach #3565

Workflow file for this run

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 }}