-
Notifications
You must be signed in to change notification settings - Fork 318
feat: publish container images and Helm chart to GHCR #1126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
andyzhangx
wants to merge
12
commits into
kubernetes-csi:master
Choose a base branch
from
andyzhangx:publish-helm-oci
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+297
−0
Open
Changes from 4 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
ca9977e
feat: publish container images and Helm chart to GHCR
andyzhangx eee43ea
fix: align arm/v7 build path and flags with Makefile conventions
andyzhangx 918b072
fix: update Go version to 1.25.10
andyzhangx 5b6fc58
fix: add --pull to docker buildx build to match Makefile
andyzhangx 97cbc84
fix: use step output instead of env for helm chart version verification
andyzhangx b4fdb64
fix: use step outputs instead of GITHUB_ENV for chart_dir
andyzhangx bff138a
fix: rename step id verify-version to verify_version for dot notation
andyzhangx 35fe48f
fix: use make nfs/nfs-armv7 targets instead of inline go build
andyzhangx 658d8e1
fix: set PUBLISH=true to prevent CI IMAGE_VERSION override
andyzhangx c567c01
fix: add DOCKER_CLI_EXPERIMENTAL, use helm for version parse, conditi…
andyzhangx 3c14b8e
fix: use go-version-file instead of hardcoded GO_VERSION, add chart d…
andyzhangx 20b33c7
feat: auto-set GHCR package visibility to public after publish
andyzhangx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,263 @@ | ||
| # Publish csi-driver-nfs container images and Helm chart to GHCR. | ||
| # | ||
| # Triggers: | ||
| # - Automatically on GitHub Release publish (tag must match v*) | ||
| # - Manually via workflow_dispatch with a version input | ||
| # | ||
| # Publishes: | ||
| # - Multi-arch container image: ghcr.io/kubernetes-csi/nfsplugin:<version> | ||
| # (linux/amd64, linux/arm64, linux/arm/v7, linux/ppc64le) | ||
| # - Helm chart (OCI): oci://ghcr.io/kubernetes-csi/csi-driver-nfs | ||
|
andyzhangx marked this conversation as resolved.
|
||
| # | ||
| name: Publish to GHCR | ||
|
andyzhangx marked this conversation as resolved.
|
||
|
|
||
| on: | ||
| release: | ||
| types: [published] | ||
| workflow_dispatch: | ||
| inputs: | ||
| version: | ||
| description: 'Version to publish (e.g., v4.13.2)' | ||
| required: true | ||
| type: string | ||
|
|
||
| permissions: | ||
| contents: read | ||
| packages: write | ||
|
|
||
| env: | ||
| REGISTRY: ghcr.io/kubernetes-csi | ||
| IMAGE_NAME: nfsplugin | ||
| CHART_NAME: csi-driver-nfs | ||
| GO_VERSION: '1.25.10' | ||
|
andyzhangx marked this conversation as resolved.
Outdated
andyzhangx marked this conversation as resolved.
Outdated
andyzhangx marked this conversation as resolved.
Outdated
|
||
|
|
||
| jobs: | ||
| # ── Validate version format early ────────────────────────────────────────── | ||
| validate: | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| version: ${{ steps.version.outputs.version }} | ||
| chart_version: ${{ steps.version.outputs.chart_version }} | ||
| steps: | ||
| - name: Determine and validate version | ||
| id: version | ||
| run: | | ||
| if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then | ||
| VERSION="${{ github.event.inputs.version }}" | ||
| else | ||
| VERSION="${{ github.event.release.tag_name }}" | ||
| fi | ||
|
|
||
| if [[ ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | ||
| echo "::error::Invalid version format: '${VERSION}'. Expected: v<major>.<minor>.<patch> (e.g., v4.13.2)" | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "version=${VERSION}" >> "$GITHUB_OUTPUT" | ||
| echo "chart_version=${VERSION#v}" >> "$GITHUB_OUTPUT" | ||
| echo "Version: ${VERSION}" | ||
|
|
||
| # ── Build & push container images ────────────────────────────────────────── | ||
| build-linux: | ||
| runs-on: ubuntu-latest | ||
| needs: [validate] | ||
| strategy: | ||
| matrix: | ||
| include: | ||
| - goarch: amd64 | ||
| platform: linux/amd64 | ||
| suffix: linux-amd64 | ||
| - goarch: arm64 | ||
| platform: linux/arm64 | ||
| suffix: linux-arm64 | ||
| - goarch: ppc64le | ||
| platform: linux/ppc64le | ||
| suffix: linux-ppc64le | ||
| - goarch: arm | ||
| goarm: '7' | ||
| platform: linux/arm/v7 | ||
| suffix: linux-arm-v7 | ||
| steps: | ||
| - name: Checkout at version tag | ||
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | ||
| with: | ||
| ref: ${{ needs.validate.outputs.version }} | ||
|
|
||
| - name: Set up Go | ||
| uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6 | ||
| with: | ||
| go-version: ${{ env.GO_VERSION }} | ||
|
|
||
| - name: Build binary | ||
| env: | ||
| GOARCH: ${{ matrix.goarch }} | ||
| GOARM: ${{ matrix.goarm }} | ||
| CGO_ENABLED: '0' | ||
| GOOS: linux | ||
| run: | | ||
| # Use the same output path convention as Makefile: | ||
| # bin/<goarch>/nfsplugin for most arches, bin/arm/v7/nfsplugin for armv7 | ||
| if [[ "${{ matrix.goarch }}" == "arm" ]]; then | ||
| OUT_DIR="bin/arm/v7" | ||
| else | ||
| OUT_DIR="bin/${{ matrix.goarch }}" | ||
| fi | ||
| GIT_COMMIT=$(git rev-parse HEAD) | ||
| mkdir -p "${OUT_DIR}" | ||
| go build -a -ldflags "-s -w \ | ||
| -X github.com/kubernetes-csi/csi-driver-nfs/pkg/nfs.driverVersion=${{ needs.validate.outputs.version }} \ | ||
| -X github.com/kubernetes-csi/csi-driver-nfs/pkg/nfs.gitCommit=${GIT_COMMIT} \ | ||
| -X github.com/kubernetes-csi/csi-driver-nfs/pkg/nfs.buildDate=$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ | ||
| -mod vendor -o "${OUT_DIR}/nfsplugin" ./cmd/nfsplugin | ||
|
andyzhangx marked this conversation as resolved.
Outdated
|
||
|
|
||
| - name: Set up QEMU | ||
| uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3 | ||
|
|
||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3 | ||
|
|
||
| - name: Login to GHCR | ||
| uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Build and push ${{ matrix.platform }} | ||
| run: | | ||
| VERSION="${{ needs.validate.outputs.version }}" | ||
| # Match Makefile convention: --build-arg ARCH=arm/v7 for armv7 | ||
| if [[ "${{ matrix.goarch }}" == "arm" ]]; then | ||
| DOCKER_ARCH="arm/v7" | ||
| else | ||
| DOCKER_ARCH="${{ matrix.goarch }}" | ||
| fi | ||
| GIT_COMMIT=$(git rev-parse HEAD) | ||
| docker buildx build --pull --push \ | ||
| --platform=${{ matrix.platform }} \ | ||
| --build-arg ARCH=${DOCKER_ARCH} \ | ||
| --provenance=false --sbom=false \ | ||
| --tag ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}-${{ matrix.suffix }} \ | ||
| --label org.opencontainers.image.revision=${GIT_COMMIT} \ | ||
| --label org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} \ | ||
| . | ||
|
|
||
| # ── Create multi-arch manifest ───────────────────────────────────────────── | ||
| manifest: | ||
| runs-on: ubuntu-latest | ||
| needs: [validate, build-linux] | ||
| steps: | ||
| - name: Login to GHCR | ||
| uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Create and push multi-arch manifest | ||
| run: | | ||
| VERSION="${{ needs.validate.outputs.version }}" | ||
| IMAGE="${REGISTRY}/${IMAGE_NAME}" | ||
|
|
||
| docker manifest create --amend "${IMAGE}:${VERSION}" \ | ||
| "${IMAGE}:${VERSION}-linux-amd64" \ | ||
| "${IMAGE}:${VERSION}-linux-arm64" \ | ||
| "${IMAGE}:${VERSION}-linux-arm-v7" \ | ||
|
andyzhangx marked this conversation as resolved.
|
||
| "${IMAGE}:${VERSION}-linux-ppc64le" | ||
|
|
||
| docker manifest push -p "${IMAGE}:${VERSION}" | ||
| echo "Pushed manifest: ${IMAGE}:${VERSION}" | ||
|
andyzhangx marked this conversation as resolved.
|
||
|
|
||
| # ── Publish Helm chart as OCI (independent of image builds) ──────────────── | ||
| publish-helm: | ||
| runs-on: ubuntu-latest | ||
| needs: [validate] | ||
| outputs: | ||
| helm_chart_version: ${{ steps.verify-version.outputs.helm_chart_version }} | ||
| steps: | ||
| - name: Checkout at version tag | ||
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | ||
|
andyzhangx marked this conversation as resolved.
|
||
| with: | ||
| ref: ${{ needs.validate.outputs.version }} | ||
|
|
||
| - name: Validate chart directory | ||
| run: | | ||
| CHART_DIR="charts/${{ needs.validate.outputs.version }}/${CHART_NAME}" | ||
| if [[ ! -f "${CHART_DIR}/Chart.yaml" ]]; then | ||
| echo "::error::Chart not found at ${CHART_DIR}/Chart.yaml" | ||
| echo "Available chart versions:" | ||
| ls -1 charts/ | grep '^v' || echo " (none)" | ||
|
andyzhangx marked this conversation as resolved.
Outdated
|
||
| exit 1 | ||
| fi | ||
| echo "chart_dir=${CHART_DIR}" >> "$GITHUB_ENV" | ||
|
|
||
| - name: Setup Helm | ||
| uses: azure/setup-helm@b9e51907a09c216f16ebe8536097933489208112 # v4 | ||
| with: | ||
| version: v3.17.0 | ||
|
|
||
| - name: Lint chart | ||
| run: helm lint "${{ env.chart_dir }}" | ||
|
|
||
| - name: Verify chart version matches | ||
| id: verify-version | ||
|
andyzhangx marked this conversation as resolved.
Outdated
|
||
| run: | | ||
| YAML_VERSION=$(grep '^version:' "${{ env.chart_dir }}/Chart.yaml" | awk '{print $2}') | ||
| EXPECTED="${{ needs.validate.outputs.chart_version }}" | ||
| # Handle older charts that may have leading 'v' in Chart.yaml version | ||
| YAML_VERSION_STRIPPED="${YAML_VERSION#v}" | ||
| if [[ "$YAML_VERSION_STRIPPED" != "$EXPECTED" ]]; then | ||
| echo "::error::Chart.yaml version ($YAML_VERSION) != expected ($EXPECTED)" | ||
| exit 1 | ||
| fi | ||
| # Use the actual Chart.yaml version for helm commands | ||
| echo "helm_chart_version=${YAML_VERSION}" >> "$GITHUB_ENV" | ||
| echo "helm_chart_version=${YAML_VERSION}" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Login to GHCR (Helm) | ||
| run: | | ||
| echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io \ | ||
| --username "${{ github.actor }}" --password-stdin | ||
|
|
||
| - name: Package and push chart | ||
| run: | | ||
| helm package "${{ env.chart_dir }}" --destination /tmp/helm-pkg | ||
| PACKAGE=$(ls /tmp/helm-pkg/${CHART_NAME}-*.tgz) | ||
| helm push "${PACKAGE}" "oci://${REGISTRY}" | ||
|
andyzhangx marked this conversation as resolved.
|
||
|
|
||
| - name: Verify published chart | ||
| run: | | ||
| helm show chart "oci://${REGISTRY}/${CHART_NAME}" \ | ||
| --version "${{ env.helm_chart_version }}" | ||
|
andyzhangx marked this conversation as resolved.
Outdated
andyzhangx marked this conversation as resolved.
Outdated
|
||
|
|
||
| # ── Summary ──────────────────────────────────────────────────────────────── | ||
| summary: | ||
| runs-on: ubuntu-latest | ||
| needs: [validate, manifest, publish-helm] | ||
| if: always() | ||
| steps: | ||
| - name: Job summary | ||
| env: | ||
| VERSION: ${{ needs.validate.outputs.version }} | ||
| CHART_VERSION: ${{ needs.publish-helm.outputs.helm_chart_version || needs.validate.outputs.chart_version }} | ||
| shell: bash | ||
| run: | | ||
| FENCE='```' | ||
| cat >> "$GITHUB_STEP_SUMMARY" << EOF | ||
| ## Published to GHCR | ||
|
|
||
| ### Container Image | ||
| | Image | Tag | | ||
| |-------|-----| | ||
| | ${REGISTRY}/${IMAGE_NAME} | ${VERSION} (linux/amd64, arm64, arm/v7, ppc64le) | | ||
|
|
||
| ${FENCE}bash | ||
| docker pull ${REGISTRY}/${IMAGE_NAME}:${VERSION} | ||
| ${FENCE} | ||
|
|
||
| ### Helm Chart (OCI) | ||
| ${FENCE}bash | ||
| helm install csi-driver-nfs oci://${REGISTRY}/${CHART_NAME} --version ${CHART_VERSION} -n kube-system | ||
| ${FENCE} | ||
|
andyzhangx marked this conversation as resolved.
Outdated
|
||
| EOF | ||
| sed -i 's/^ //' "$GITHUB_STEP_SUMMARY" | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.