Repository navigation
feat(workflows): add chart-only mode to shared-release and three new release workflows #69
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
onuryilmaz
wants to merge
7
commits into
main
Choose a base branch
from
feat/phase1-shared-release-helm-docker-goreleaser
base: main
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.
Open
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
288c0be
feat(workflows): add chart-only mode to shared-release and three new …
onuryilmaz fb19184
docs: add RELEASING.md with usage guide for shared release workflows
onuryilmaz 9e87124
fix(workflows): address Copilot review comments on shared release wor…
onuryilmaz 7f4d091
docs: clarify GITHUB_TOKEN limitation and separate app/chart release …
d5a5993
chore: trigger Copilot re-review
9630026
fix(workflows): harden helm pull error handling and add v-prefixed do…
ab36cb6
chore: trigger Copilot re-review
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
Some comments aren't visible on the classic Files Changed page.
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,100 @@ | ||
| name: Shared Docker Release | ||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| runs-on: | ||
| description: "The runner to use for the job (must be a Linux runner; this workflow uses Docker buildx)" | ||
| required: false | ||
| default: "ubuntu-latest" | ||
| type: string | ||
| image-name: | ||
| description: "Full GHCR image name, e.g. ghcr.io/cloudoperators/myapp" | ||
| required: true | ||
| type: string | ||
| dockerfile: | ||
| description: "Path to the Dockerfile" | ||
| required: false | ||
| default: "Dockerfile" | ||
| type: string | ||
| context: | ||
| description: "Docker build context path" | ||
| required: false | ||
| default: "." | ||
| type: string | ||
| platforms: | ||
| description: "Comma-separated list of target platforms" | ||
| required: false | ||
| default: "linux/amd64,linux/arm64" | ||
| type: string | ||
| environment: | ||
| description: "GitHub environment name to use for this job (e.g. release), for environment protection rules and scoped secrets" | ||
| required: false | ||
| default: "" | ||
| type: string | ||
| secrets: | ||
| registry-token: | ||
| description: "Token to authenticate to GHCR; falls back to GITHUB_TOKEN if not provided" | ||
| required: false | ||
|
|
||
| jobs: | ||
| docker-release: | ||
| runs-on: ${{ inputs.runs-on }} | ||
| environment: ${{ inputs.environment != '' && inputs.environment || null }} | ||
| permissions: | ||
| contents: read | ||
| packages: write | ||
| steps: | ||
| - name: Validate inputs | ||
| env: | ||
| IMAGE_NAME: ${{ inputs.image-name }} | ||
| run: | | ||
| if [ "$RUNNER_OS" != "Linux" ]; then | ||
| echo "ERROR: this workflow requires a Linux runner (uses Docker buildx); got: $RUNNER_OS" | ||
| exit 1 | ||
| fi | ||
| case "$IMAGE_NAME" in | ||
| ghcr.io/*) ;; | ||
| *) echo "ERROR: image-name must start with 'ghcr.io/' (got: '$IMAGE_NAME')"; exit 1 ;; | ||
| esac | ||
|
|
||
| - name: Checkout repository | ||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 | ||
|
|
||
| - name: Set up QEMU | ||
| uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3 | ||
|
|
||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v3 | ||
|
|
||
| - name: Log in to container registry | ||
| uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3 | ||
| with: | ||
| registry: ghcr.io | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.registry-token != '' && secrets.registry-token || secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Extract Docker metadata | ||
| id: meta | ||
| uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v5 | ||
| with: | ||
| images: ${{ inputs.image-name }} | ||
| flavor: | | ||
| latest=false | ||
| tags: | | ||
| type=semver,pattern={{version}} | ||
| type=semver,pattern=v{{version}} | ||
| type=semver,pattern=v{{major}}.{{minor}} | ||
| type=semver,pattern=v{{major}} | ||
| type=raw,value=latest,enable={{is_default_branch}} | ||
| type=sha,format=long | ||
|
|
||
| - name: Build and push Docker image | ||
| uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6 | ||
| with: | ||
| context: ${{ inputs.context }} | ||
| file: ${{ inputs.dockerfile }} | ||
| platforms: ${{ inputs.platforms }} | ||
| push: true | ||
| tags: ${{ steps.meta.outputs.tags }} | ||
| labels: ${{ steps.meta.outputs.labels }} |
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,71 @@ | ||
| name: Shared GoReleaser | ||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| runs-on: | ||
| description: "The runner to use for the job (must be a Linux runner)" | ||
| required: false | ||
| default: "ubuntu-latest" | ||
| type: string | ||
| goreleaser-version: | ||
| description: "GoReleaser version constraint passed to goreleaser-action (e.g. '~> v2')" | ||
| required: false | ||
| default: "~> v2" | ||
| type: string | ||
| goreleaser-config: | ||
| description: "Path to .goreleaser.yaml config file; leave empty to use GoReleaser's default discovery" | ||
| required: false | ||
| default: "" | ||
| type: string | ||
| go-version-file: | ||
| description: "Path to the go.mod file used by setup-go" | ||
| required: false | ||
| default: "go.mod" | ||
| type: string | ||
| environment: | ||
| description: "GitHub environment name to use for this job (e.g. release), for environment protection rules and scoped secrets" | ||
| required: false | ||
| default: "" | ||
| type: string | ||
| secrets: | ||
| release-token: | ||
| description: "Token used for GoReleaser GitHub Release creation; falls back to GITHUB_TOKEN if not provided" | ||
| required: false | ||
|
|
||
| jobs: | ||
| goreleaser: | ||
| runs-on: ${{ inputs.runs-on }} | ||
| environment: ${{ inputs.environment != '' && inputs.environment || null }} | ||
| concurrency: | ||
| group: goreleaser-${{ github.repository }}-${{ github.ref }} | ||
| cancel-in-progress: false | ||
| permissions: | ||
| contents: write | ||
| steps: | ||
| - name: Validate inputs | ||
| run: | | ||
| if [ "$RUNNER_OS" != "Linux" ]; then | ||
| echo "ERROR: this workflow requires a Linux runner; got: $RUNNER_OS" | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Checkout repository | ||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 | ||
| with: | ||
| fetch-depth: 0 | ||
|
|
||
| - name: Set up Go | ||
| uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5 # v5 | ||
| with: | ||
| go-version-file: ${{ inputs.go-version-file }} | ||
| cache: true | ||
|
|
||
| - name: Run GoReleaser | ||
| uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6 | ||
| with: | ||
| distribution: goreleaser | ||
| version: ${{ inputs.goreleaser-version }} | ||
| args: release --clean${{ inputs.goreleaser-config != '' && format(' --config {0}', inputs.goreleaser-config) || '' }} | ||
| env: | ||
| GITHUB_TOKEN: ${{ secrets.release-token != '' && secrets.release-token || secrets.GITHUB_TOKEN }} |
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,138 @@ | ||
| name: Shared Helm Release | ||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| runs-on: | ||
| description: "The runner to use for the job (must be a Linux runner)" | ||
| required: false | ||
| default: "ubuntu-latest" | ||
| type: string | ||
| registry: | ||
| description: "Container registry hostname" | ||
| required: false | ||
| default: "ghcr.io" | ||
| type: string | ||
| chart-dir: | ||
| description: "Path to the chart directory containing Chart.yaml (e.g. charts/myapp)" | ||
| required: true | ||
| type: string | ||
| chart-name: | ||
| description: "Chart name used for the OCI duplicate-version check (must match the name field in Chart.yaml)" | ||
| required: true | ||
| type: string | ||
| helm-version: | ||
| description: "Helm CLI version to install" | ||
| required: false | ||
| default: "v3.17.0" | ||
| type: string | ||
| run-dependency-update: | ||
| description: "Run helm dependency update before packaging" | ||
| required: false | ||
| default: false | ||
| type: boolean | ||
| allow-existing: | ||
| description: "When true, exit 0 instead of failing if the chart version already exists in the registry. Useful when not all charts in a batch have changed." | ||
| required: false | ||
| default: false | ||
| type: boolean | ||
| environment: | ||
| description: "GitHub environment name to use for this job (e.g. release), for environment protection rules and scoped secrets" | ||
| required: false | ||
| default: "" | ||
| type: string | ||
| secrets: | ||
| registry-token: | ||
| description: "Token to authenticate to the container registry; falls back to GITHUB_TOKEN if not provided" | ||
| required: false | ||
|
|
||
| jobs: | ||
| helm-release: | ||
| runs-on: ${{ inputs.runs-on }} | ||
| environment: ${{ inputs.environment != '' && inputs.environment || null }} | ||
| concurrency: | ||
| group: helm-release-${{ github.repository }}-${{ inputs.chart-name }}-${{ github.ref }} | ||
| cancel-in-progress: false | ||
| permissions: | ||
| contents: read | ||
| packages: write | ||
| steps: | ||
| - name: Validate inputs | ||
| env: | ||
| CHART_DIR: ${{ inputs.chart-dir }} | ||
| run: | | ||
| if [ "$RUNNER_OS" != "Linux" ]; then | ||
| echo "ERROR: this workflow requires a Linux runner; got: $RUNNER_OS" | ||
| exit 1 | ||
| fi | ||
| if [ -z "$CHART_DIR" ]; then | ||
| echo "ERROR: chart-dir is required" | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Checkout repository | ||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 | ||
|
|
||
| - name: Set up Helm | ||
| uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1 | ||
| with: | ||
| version: ${{ inputs.helm-version }} | ||
|
|
||
| - name: Log in to container registry | ||
| uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3 | ||
| with: | ||
| registry: ${{ inputs.registry }} | ||
| username: ${{ github.actor }} | ||
| password: ${{ secrets.registry-token != '' && secrets.registry-token || secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Validate chart and check for duplicate version | ||
| id: chart-check | ||
| env: | ||
| CHART_DIR: ${{ inputs.chart-dir }} | ||
| CHART_NAME: ${{ inputs.chart-name }} | ||
| REGISTRY: ${{ inputs.registry }} | ||
| ALLOW_EXISTING: ${{ inputs.allow-existing }} | ||
| run: | | ||
| if [ ! -f "${CHART_DIR}/Chart.yaml" ]; then | ||
| echo "ERROR: chart-dir '${CHART_DIR}' does not contain Chart.yaml" | ||
| exit 1 | ||
| fi | ||
| CHART_VERSION=$(helm show chart "${CHART_DIR}" | grep -E '^version:' | head -1 | sed 's/^version:[[:space:]]*//' | tr -d '[:space:]') | ||
| if ! echo "$CHART_VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+'; then | ||
| echo "ERROR: could not parse semver from chart metadata (got: '$CHART_VERSION')" | ||
| exit 1 | ||
| fi | ||
| echo "chart_version=${CHART_VERSION}" >> "$GITHUB_OUTPUT" | ||
| PULL_STDERR=$(helm pull "oci://${REGISTRY}/${{ github.repository }}/charts/${CHART_NAME}" --version "${CHART_VERSION}" 2>&1 >/dev/null) && PULL_EXIT=0 || PULL_EXIT=$? | ||
| if [ "$PULL_EXIT" -eq 0 ]; then | ||
| if [ "$ALLOW_EXISTING" = "true" ]; then | ||
| echo "Chart ${CHART_NAME}:${CHART_VERSION} already exists in OCI registry — skipping (allow-existing=true)" | ||
| echo "skip=true" >> "$GITHUB_OUTPUT" | ||
| else | ||
| echo "ERROR: chart ${CHART_NAME}:${CHART_VERSION} already exists in OCI registry — bump Chart.yaml version before pushing" | ||
| exit 1 | ||
| fi | ||
| elif echo "$PULL_STDERR" | grep -qiE 'not found|does not exist|manifest unknown|tag does not exist'; then | ||
| : # version absent — proceed with push | ||
| else | ||
| echo "ERROR: helm pull failed with an unexpected error (auth/network/transport issue):" | ||
| echo "$PULL_STDERR" | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Run helm dependency update | ||
| if: inputs.run-dependency-update == true && steps.chart-check.outputs.skip != 'true' | ||
| env: | ||
| CHART_DIR: ${{ inputs.chart-dir }} | ||
| run: helm dependency update "$CHART_DIR" | ||
|
|
||
| - name: Package and push Helm chart | ||
| if: steps.chart-check.outputs.skip != 'true' | ||
| env: | ||
| CHART_DIR: ${{ inputs.chart-dir }} | ||
| CHART_NAME: ${{ inputs.chart-name }} | ||
| CHART_VERSION: ${{ steps.chart-check.outputs.chart_version }} | ||
| REGISTRY: ${{ inputs.registry }} | ||
| run: | | ||
| helm package "$CHART_DIR" | ||
| helm push "${CHART_NAME}-${CHART_VERSION}.tgz" "oci://${REGISTRY}/${{ github.repository }}/charts/" |
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
Oops, something went wrong.
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.