ci(release): align image tags and manifests with git tags #9
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
| # Create a GitHub release whenever a SemVer tag is pushed and build/push the image. | |
| name: Create Release from Tag | |
| permissions: | |
| contents: write | |
| packages: write | |
| on: | |
| push: | |
| tags: | |
| - "*" | |
| jobs: | |
| ci-checks: | |
| uses: ./.github/workflows/ci.yaml | |
| secrets: inherit | |
| create-release: | |
| needs: ci-checks | |
| runs-on: ubuntu-latest | |
| outputs: | |
| tag: ${{ steps.semver.outputs.tag }} | |
| version: ${{ steps.semver.outputs.version }} | |
| steps: | |
| - name: Validate SemVer tag | |
| id: semver | |
| env: | |
| TAG_NAME: ${{ github.ref_name }} | |
| run: | | |
| TAG="${TAG_NAME}" | |
| REGEX='^v?[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$' | |
| if echo "${TAG}" | grep -Eq "${REGEX}"; then | |
| echo "valid=true" >> "${GITHUB_OUTPUT}" | |
| echo "tag=${TAG}" >> "${GITHUB_OUTPUT}" | |
| echo "version=${TAG#v}" >> "${GITHUB_OUTPUT}" | |
| exit 0 | |
| fi | |
| echo "Tag '${TAG}' is not a valid SemVer (with optional leading 'v')." >&2 | |
| exit 1 | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Ensure manifests image tag matches release tag | |
| run: | | |
| EXPECTED_TAG='${{ steps.semver.outputs.tag }}' | |
| IMAGE_TAG=$(grep -A2 'name: ghcr.io/klustrefs/klustre-csi-plugin' manifests/kustomization.yaml | grep 'newTag:' | awk '{print $2}') | |
| if [ -z "${IMAGE_TAG}" ]; then | |
| echo "Could not determine image tag from manifests/kustomization.yaml" >&2 | |
| exit 1 | |
| fi | |
| if [ "${IMAGE_TAG}" != "${EXPECTED_TAG}" ]; then | |
| echo "Image tag in manifests/kustomization.yaml (${IMAGE_TAG}) does not match release tag (${EXPECTED_TAG})." >&2 | |
| echo "Update manifests/kustomization.yaml images.newTag before tagging a release." >&2 | |
| exit 1 | |
| fi | |
| - name: Generate release notes | |
| id: cliff | |
| uses: orhun/git-cliff-action@v4 | |
| with: | |
| config: cliff.toml | |
| args: --tag ${{ steps.semver.outputs.tag }} | |
| env: | |
| OUTPUT: RELEASE_NOTES.md | |
| GITHUB_REPO: ${{ github.repository }} | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Load release notes | |
| id: notes | |
| run: | | |
| echo "RELEASE_NOTES<<EOF" >> "${GITHUB_OUTPUT}" | |
| cat RELEASE_NOTES.md >> "${GITHUB_OUTPUT}" | |
| echo "EOF" >> "${GITHUB_OUTPUT}" | |
| - name: Create GitHub release | |
| uses: actions/github-script@v7 | |
| env: | |
| RELEASE_NOTES: ${{ steps.notes.outputs.RELEASE_NOTES }} | |
| with: | |
| script: | | |
| const tag = '${{ steps.semver.outputs.tag }}'; | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const body = process.env.RELEASE_NOTES ?? ''; | |
| try { | |
| const release = await github.rest.repos.createRelease({ | |
| owner, | |
| repo, | |
| tag_name: tag, | |
| name: tag, | |
| body | |
| }); | |
| core.info(`Created release ${release.data.html_url}`); | |
| } catch (error) { | |
| const errors = error.response?.data?.errors ?? []; | |
| const alreadyExists = errors.some((item) => item.code === 'already_exists'); | |
| if (error.status === 422 && alreadyExists) { | |
| core.info(`Release for ${tag} already exists, skipping creation.`); | |
| } else { | |
| throw error; | |
| } | |
| } | |
| build-and-push-image: | |
| needs: create-release | |
| uses: ./.github/workflows/build-and-push.yaml | |
| secrets: inherit | |
| with: | |
| image_tag: ${{ needs.create-release.outputs.tag }} |