From 2c3dbd87ce6dc72a391fd929adc8387da2b48ad2 Mon Sep 17 00:00:00 2001 From: Matt Trachier Date: Fri, 3 Oct 2025 18:23:17 -0500 Subject: [PATCH] fix: fix release and release candidate race (#221) Signed-off-by: matttrach --- .github/workflows/release-candidate.yml | 81 ------------------------- .github/workflows/release.yml | 68 +++++++++++++++++++++ 2 files changed, 68 insertions(+), 81 deletions(-) delete mode 100644 .github/workflows/release-candidate.yml diff --git a/.github/workflows/release-candidate.yml b/.github/workflows/release-candidate.yml deleted file mode 100644 index ad4e586..0000000 --- a/.github/workflows/release-candidate.yml +++ /dev/null @@ -1,81 +0,0 @@ -name: release-candidate - -on: - push: - branches: - - release/v* - -jobs: - release: - runs-on: ubuntu-latest - permissions: - contents: write - id-token: write - steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 https://github.com/actions/checkout - with: - fetch-depth: 0 - - name: Create and Push RC Tag with Git - run: | - BASE_VERSION=$(echo "$GITHUB_REF" | sed 's/refs\/heads\/release\///') - echo "Base version is: $BASE_VERSION" # gets v0 from release/v0 in branch name - git fetch --tags - LATEST_MINOR_NUM=$(git tag | grep "^${BASE_VERSION}\." | awk -F. '{print $2}' | sort -n | tail -1) - echo "Latest minor num: $LATEST_MINOR_NUM" - LATEST_PATCH_NUM=$(git tag | grep "^${BASE_VERSION}\.${LATEST_MINOR_NUM}\." | awk -F- '{print $1}' | awk -F. '{print $3}' | sort -n | tail -1) - echo "Latest patch num: $LATEST_PATCH_NUM" - LATEST_RC_NUM=$(git tag | grep "^${BASE_VERSION}\.${LATEST_MINOR_NUM}\.${LATEST_PATCH_NUM}-rc\." | awk -F. '{print $4}' | grep -v '^$' | sort -n | tail -1) - echo "Latest rc num: $LATEST_RC_NUM" - if [ -z "$LATEST_RC_NUM" ]; then - # the last minor was a full release, we need to start the next minor release candidate - # this sort of assumes there wont be a patch release - LATEST_MINOR_NUM=$((LATEST_MINOR_NUM + 1)) - LATEST_PATCH_NUM=0 - NEXT_RC_NUM=0 - else - NEXT_RC_NUM=$((LATEST_RC_NUM + 1)) - fi - NEXT_RC_TAG="${BASE_VERSION}.${LATEST_MINOR_NUM}.${LATEST_PATCH_NUM}-rc.${NEXT_RC_NUM}" - echo "Calculated next RC tag: $NEXT_RC_TAG" - - # Configure git user - git config user.name "${{ github.actor }}" - git config user.email "${{ github.actor }}@users.noreply.github.com" - - # Create and push the new tag - git tag "$NEXT_RC_TAG" -m "Release Candidate $NEXT_RC_TAG" - git push origin "$NEXT_RC_TAG" - - name: retrieve GPG Credentials - uses: rancher-eio/read-vault-secrets@main - with: - secrets: | - secret/data/github/repo/${{ github.repository }}/signing/gpg passphrase | GPG_PASSPHRASE ; - secret/data/github/repo/${{ github.repository }}/signing/gpg privateKeyId | GPG_KEY_ID ; - secret/data/github/repo/${{ github.repository }}/signing/gpg privateKey | GPG_KEY - - name: import_gpg_key - env: - GPG_PASSPHRASE: ${{ env.GPG_PASSPHRASE }} - GPG_KEY_ID: ${{ env.GPG_KEY_ID }} - GPG_KEY: ${{ env.GPG_KEY }} - run: | - cleanup() { - # clear history just in case - history -c - } - trap cleanup EXIT TERM - - # sanitize variables - if [ -z "${GPG_PASSPHRASE}" ]; then echo "gpg passphrase empty"; exit 1; fi - if [ -z "${GPG_KEY_ID}" ]; then echo "key id empty"; exit 1; fi - if [ -z "${GPG_KEY}" ]; then echo "key contents empty"; exit 1; fi - - echo "Importing gpg key" - echo "${GPG_KEY}" | gpg --import --batch > /dev/null || { echo "Failed to import GPG key"; exit 1; } - - name: Run GoReleaser - uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0 https://github.com/goreleaser/goreleaser-action - with: - args: release --clean --config .goreleaser_rc.yml - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - GPG_KEY_ID: ${{ env.GPG_KEY_ID }} - GPG_PASSPHRASE: ${{ env.GPG_PASSPHRASE }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1b34133..560198f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -89,6 +89,74 @@ jobs: body: "Tests Failed!" }) + # If the e2e tests pass we automatically generate an RC release + # this shouldn't happen when the release PR is merged, only when it's opened or updated + - name: Create and Push RC Tag with Git + if: steps.release-please.outputs.pr && always() && (steps.run-unit-tests.conclusion == 'success') && (steps.run-acc-tests.conclusion == 'success') + run: | + BASE_VERSION=$(echo "$GITHUB_REF" | sed 's/refs\/heads\/release\///') + echo "Base version is: $BASE_VERSION" # gets v0 from release/v0 in branch name + git fetch --tags + LATEST_MINOR_NUM=$(git tag | grep "^${BASE_VERSION}\." | awk -F. '{print $2}' | sort -n | tail -1) + echo "Latest minor num: $LATEST_MINOR_NUM" + LATEST_PATCH_NUM=$(git tag | grep "^${BASE_VERSION}\.${LATEST_MINOR_NUM}\." | awk -F- '{print $1}' | awk -F. '{print $3}' | sort -n | tail -1) + echo "Latest patch num: $LATEST_PATCH_NUM" + LATEST_RC_NUM=$(git tag | grep "^${BASE_VERSION}\.${LATEST_MINOR_NUM}\.${LATEST_PATCH_NUM}-rc\." | awk -F. '{print $4}' | grep -v '^$' | sort -n | tail -1) + echo "Latest rc num: $LATEST_RC_NUM" + if [ -z "$LATEST_RC_NUM" ]; then + # the last minor was a full release, we need to start the next minor release candidate + # this sort of assumes there wont be a patch release + LATEST_MINOR_NUM=$((LATEST_MINOR_NUM + 1)) + LATEST_PATCH_NUM=0 + NEXT_RC_NUM=0 + else + NEXT_RC_NUM=$((LATEST_RC_NUM + 1)) + fi + NEXT_RC_TAG="${BASE_VERSION}.${LATEST_MINOR_NUM}.${LATEST_PATCH_NUM}-rc.${NEXT_RC_NUM}" + echo "Calculated next RC tag: $NEXT_RC_TAG" + + # Configure git user + git config user.name "${{ github.actor }}" + git config user.email "${{ github.actor }}@users.noreply.github.com" + + # Create and push the new tag + git tag "$NEXT_RC_TAG" -m "Release Candidate $NEXT_RC_TAG" + git push origin "$NEXT_RC_TAG" + - name: retrieve GPG Credentials + uses: rancher-eio/read-vault-secrets@main + with: + secrets: | + secret/data/github/repo/${{ github.repository }}/signing/gpg passphrase | GPG_PASSPHRASE ; + secret/data/github/repo/${{ github.repository }}/signing/gpg privateKeyId | GPG_KEY_ID ; + secret/data/github/repo/${{ github.repository }}/signing/gpg privateKey | GPG_KEY + - name: import_gpg_key + env: + GPG_PASSPHRASE: ${{ env.GPG_PASSPHRASE }} + GPG_KEY_ID: ${{ env.GPG_KEY_ID }} + GPG_KEY: ${{ env.GPG_KEY }} + run: | + cleanup() { + # clear history just in case + history -c + } + trap cleanup EXIT TERM + + # sanitize variables + if [ -z "${GPG_PASSPHRASE}" ]; then echo "gpg passphrase empty"; exit 1; fi + if [ -z "${GPG_KEY_ID}" ]; then echo "key id empty"; exit 1; fi + if [ -z "${GPG_KEY}" ]; then echo "key contents empty"; exit 1; fi + + echo "Importing gpg key" + echo "${GPG_KEY}" | gpg --import --batch > /dev/null || { echo "Failed to import GPG key"; exit 1; } + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0 https://github.com/goreleaser/goreleaser-action + with: + args: release --clean --config .goreleaser_rc.yml + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GPG_KEY_ID: ${{ env.GPG_KEY_ID }} + GPG_PASSPHRASE: ${{ env.GPG_PASSPHRASE }} + # These run after release-please generates a release, so when the release PR is merged - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 https://github.com/actions/checkout if: steps.release-please.outputs.version