Create release (manually) #5
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: Create release (manually) | |
| # Single manual entry point for releasing production-stack. Orchestrates: | |
| # 1. publish-image.yaml — create tag, build & push multi-arch image, scan | |
| # 2. publish-helm-chart.yaml — push releasable charts to gh-pages | |
| # 3. create-gh-release — create the GitHub Release with auto-generated notes | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| release_version: | |
| description: 'Release version (e.g., v0.1.0)' | |
| required: true | |
| type: string | |
| permissions: | |
| id-token: write | |
| contents: write | |
| packages: write | |
| actions: read | |
| deployments: read | |
| pull-requests: read | |
| jobs: | |
| validate: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Validate version format | |
| run: | | |
| if [[ ! "${{ github.event.inputs.release_version }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | |
| echo "Error: Release version must follow format vX.Y.Z (got '${{ github.event.inputs.release_version }}')" | |
| exit 1 | |
| fi | |
| publish-image: | |
| needs: [validate] | |
| uses: ./.github/workflows/publish-image.yaml | |
| with: | |
| release_version: ${{ github.event.inputs.release_version }} | |
| secrets: inherit | |
| publish-helm-charts: | |
| needs: [publish-image] | |
| uses: ./.github/workflows/publish-helm-chart.yaml | |
| with: | |
| release_version: ${{ github.event.inputs.release_version }} | |
| secrets: inherit | |
| create-gh-release: | |
| needs: [publish-image, publish-helm-charts] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Harden Runner | |
| uses: step-security/harden-runner@a5ad31d6a139d249332a2605b85202e8c0b78450 # v2.19.1 | |
| with: | |
| egress-policy: audit | |
| disable-sudo: true | |
| disable-telemetry: true | |
| - name: Checkout the repository at the release tag | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| submodules: true | |
| fetch-depth: 0 | |
| ref: ${{ github.event.inputs.release_version }} | |
| - name: Check if release already exists | |
| id: check-release | |
| run: | | |
| TAG="${{ github.event.inputs.release_version }}" | |
| if gh release view "$TAG" >/dev/null 2>&1; then | |
| echo "exists=true" >> $GITHUB_OUTPUT | |
| echo "Release $TAG already exists, skipping creation" | |
| else | |
| echo "exists=false" >> $GITHUB_OUTPUT | |
| echo "Release $TAG does not exist, proceeding with creation" | |
| fi | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Create GitHub release | |
| if: steps.check-release.outputs.exists == 'false' | |
| run: | | |
| set -euo pipefail | |
| TAG="${{ github.event.inputs.release_version }}" | |
| IMG_TAG="${TAG#v}" | |
| # Generate changelog notes via the GitHub API. We do this manually | |
| # (instead of `gh release create --generate-notes`) so we can | |
| # prepend our own header in --notes-file (the two flags are | |
| # mutually exclusive in `gh release create`). | |
| GENERATED_NOTES=$(gh api \ | |
| -H "Accept: application/vnd.github+json" \ | |
| -X POST "repos/${GITHUB_REPOSITORY}/releases/generate-notes" \ | |
| -f tag_name="${TAG}" \ | |
| --jq '.body') | |
| NOTES_FILE=$(mktemp) | |
| cat > "${NOTES_FILE}" <<EOF | |
| ## Production Stack ${TAG} | |
| ### Container image | |
| \`\`\` | |
| ghcr.io/kaito-project/gpu-node-mocker:${IMG_TAG} | |
| \`\`\` | |
| ### Helm charts | |
| Add the chart repository (once): | |
| \`\`\` | |
| helm repo add production-stack https://kaito-project.github.io/production-stack/charts/kaito-project | |
| helm repo update production-stack | |
| \`\`\` | |
| The following charts are published from this release (versions taken | |
| from each chart's \`Chart.yaml\` at this tag): | |
| - \`production-stack/gpu-node-mocker\` | |
| - \`production-stack/modeldeployment\` | |
| - \`production-stack/modelharness\` | |
| See [README.md](https://github.com/kaito-project/production-stack/blob/${TAG}/README.md) for installation steps. | |
| --- | |
| ${GENERATED_NOTES} | |
| EOF | |
| # Note: do NOT pass --target — it expects a branch or commit SHA, | |
| # not a tag. The tag was already created by publish-image.yaml, | |
| # so `gh release create TAG` will use the tag's existing commit. | |
| gh release create "${TAG}" \ | |
| --title "${TAG}" \ | |
| --notes-file "${NOTES_FILE}" | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| GITHUB_REPOSITORY: ${{ github.repository }} | |
| - name: Release already exists | |
| if: steps.check-release.outputs.exists == 'true' | |
| run: | | |
| echo "Release ${{ github.event.inputs.release_version }} already exists." |