From 7dbb8a1d754973c41d666c0eb1e3f7969e38b6b8 Mon Sep 17 00:00:00 2001 From: Andrei Kvapil Date: Wed, 16 Apr 2025 12:06:13 +0200 Subject: [PATCH] [ci] Update pipeline for patch releases Signed-off-by: Andrei Kvapil Co-authored-by: Nick Volynkin --- .github/workflows/pull-requests-release.yaml | 4 +- .github/workflows/tags.yaml | 68 ++++++++++++++------ 2 files changed, 52 insertions(+), 20 deletions(-) diff --git a/.github/workflows/pull-requests-release.yaml b/.github/workflows/pull-requests-release.yaml index 49edbba3..790c9188 100644 --- a/.github/workflows/pull-requests-release.yaml +++ b/.github/workflows/pull-requests-release.yaml @@ -68,8 +68,8 @@ jobs: - name: Create tag on merged commit run: | - git tag ${{ steps.get_tag.outputs.tag }} ${{ github.sha }} - git push origin ${{ steps.get_tag.outputs.tag }} + git tag ${{ steps.get_tag.outputs.tag }} ${{ github.sha }} --force + git push origin ${{ steps.get_tag.outputs.tag }} --force - name: Publish draft release uses: actions/github-script@v7 diff --git a/.github/workflows/tags.yaml b/.github/workflows/tags.yaml index 53992c61..44bc8479 100644 --- a/.github/workflows/tags.yaml +++ b/.github/workflows/tags.yaml @@ -1,6 +1,7 @@ name: Versioned Tag on: + # Trigger on push if it includes a tag like vX.Y.Z push: tags: - 'v*.*.*' @@ -15,6 +16,7 @@ jobs: pull-requests: write steps: + # 1) Check if a non-draft release with this tag already exists - name: Check if release already exists id: check_release uses: actions/github-script@v7 @@ -25,7 +27,6 @@ jobs: owner: context.repo.owner, repo: context.repo.repo }); - const existing = releases.data.find(r => r.tag_name === tag && !r.draft); if (existing) { core.setOutput('skip', 'true'); @@ -33,10 +34,39 @@ jobs: core.setOutput('skip', 'false'); } + # If a published release already exists, skip the rest of the workflow - name: Skip if release already exists if: steps.check_release.outputs.skip == 'true' run: echo "Release already exists, skipping workflow." + # 2) Determine the base branch from which the tag was pushed + - name: Get base branch + if: steps.check_release.outputs.skip == 'false' + id: get_base + uses: actions/github-script@v7 + with: + script: | + /* + For a push event with a tag, GitHub sets context.payload.base_ref + if the tag was pushed from a branch. + If it's empty, we can't determine the correct base branch and must fail. + */ + const baseRef = context.payload.base_ref; + if (!baseRef) { + core.setFailed(`❌ base_ref is empty. Make sure you push the tag from a branch (e.g. 'git push origin HEAD:refs/tags/vX.Y.Z').`); + return; + } + + const shortBranch = baseRef.replace("refs/heads/", ""); + const releasePattern = /^release-\d+\.\d+$/; + if (shortBranch !== "main" && !releasePattern.test(shortBranch)) { + core.setFailed(`❌ Tagged commit must belong to branch 'main' or 'release-X.Y'. Got '${shortBranch}'`); + return; + } + + core.setOutput('branch', shortBranch); + + # 3) Checkout full git history and tags - name: Checkout code if: steps.check_release.outputs.skip == 'false' uses: actions/checkout@v4 @@ -44,6 +74,7 @@ jobs: fetch-depth: 0 fetch-tags: true + # 4) Login to GitHub Container Registry - name: Login to GitHub Container Registry if: steps.check_release.outputs.skip == 'false' uses: docker/login-action@v3 @@ -52,10 +83,12 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} registry: ghcr.io + # 5) Build project artifacts - name: Build if: steps.check_release.outputs.skip == 'false' run: make build + # 6) Optionally commit built artifacts to the repository - name: Commit release artifacts if: steps.check_release.outputs.skip == 'false' env: @@ -67,6 +100,7 @@ jobs: git add . git commit -m "Prepare release ${GITHUB_REF#refs/tags/}" -s || echo "No changes to commit" + # 7) Create a release branch like release-X.Y.Z - name: Create release branch if: steps.check_release.outputs.skip == 'false' run: | @@ -74,48 +108,48 @@ jobs: git branch -f "$BRANCH_NAME" git push origin "$BRANCH_NAME" --force + # 8) Create a pull request from release-X.Y.Z to the original base branch - name: Create pull request if not exists if: steps.check_release.outputs.skip == 'false' uses: actions/github-script@v7 with: script: | const version = context.ref.replace('refs/tags/v', ''); - const branch = `release-${version}`; - const base = 'main'; - + const base = '${{ steps.get_base.outputs.branch }}'; + const head = `release-${version}`; + const prs = await github.rest.pulls.list({ owner: context.repo.owner, repo: context.repo.repo, - head: `${context.repo.owner}:${branch}`, + head: `${context.repo.owner}:${head}`, base }); - + if (prs.data.length === 0) { const newPr = await github.rest.pulls.create({ owner: context.repo.owner, repo: context.repo.repo, - head: branch, - base: base, + head, + base, title: `Release v${version}`, body: `This PR prepares the release \`v${version}\`.\n` + `(Please merge it before releasing draft)`, draft: false }); - - console.log(`Created pull request #${newPr.data.number} from ${branch} to ${base}`); - + + console.log(`Created pull request #${newPr.data.number} from ${head} to ${base}`); await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: newPr.data.number, labels: ['release'] }); - } else { - console.log(`Pull request already exists from ${branch} to ${base}`); + console.log(`Pull request already exists from ${head} to ${base}`); } + # 9) Create or reuse an existing draft GitHub release for this tag - name: Create or reuse draft release if: steps.check_release.outputs.skip == 'false' id: create_release @@ -141,22 +175,20 @@ jobs: } core.setOutput('upload_url', release.upload_url); + # 10) Build additional assets for the release (if needed) - name: Build assets if: steps.check_release.outputs.skip == 'false' run: make assets env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # 11) Upload assets to the draft release - name: Upload assets if: steps.check_release.outputs.skip == 'false' run: make upload_assets VERSION=${GITHUB_REF#refs/tags/} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Delete pushed tag - if: steps.check_release.outputs.skip == 'false' - run: | - git push --delete origin ${GITHUB_REF#refs/tags/} - + # 12) Run tests - name: Run tests run: make test