From 7cff47f30fada5920da2077d33b3057a70fb16f6 Mon Sep 17 00:00:00 2001 From: Malte Poll <1780588+malt3@users.noreply.github.com> Date: Thu, 25 May 2023 10:14:42 +0200 Subject: [PATCH] ci: run release workflow on temporary branch (#1628) --- .github/workflows/on-release.yml | 72 +++++++++++++++++++++++++++++++- .github/workflows/release.yml | 56 +++++++++++++++++-------- dev-docs/workflows/release.md | 32 ++++++++++---- 3 files changed, 132 insertions(+), 28 deletions(-) diff --git a/.github/workflows/on-release.yml b/.github/workflows/on-release.yml index e7c28a3b6..c82270e00 100644 --- a/.github/workflows/on-release.yml +++ b/.github/workflows/on-release.yml @@ -14,6 +14,58 @@ on: default: false jobs: + complete-release-branch-transaction: + runs-on: ubuntu-22.04 + permissions: + id-token: write + contents: read + env: + FULL_VERSION: ${{ github.event.release.tag_name }}${{ github.event.inputs.tag }} + outputs: + RELEASE_BRANCH: ${{ env.RELEASE_BRANCH }} + WORKING_BRANCH: ${{ env.WORKING_BRANCH }} + steps: + - name: Checkout + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + + - name: Determine branch names + run: | + WITHOUT_V=${FULL_VERSION#v} + PART_MAJOR=${WITHOUT_V%%.*} + PART_MINOR=${WITHOUT_V#*.} + MAJOR_MINOR=${PART_MAJOR}.${PART_MINOR} + RELEASE_BRANCH="release/v${MAJOR_MINOR}" + WORKING_BRANCH_PREFIX="tmp/${FULL_VERSION}" + echo "RELEASE_BRANCH=${RELEASE_BRANCH}" | tee -a "$GITHUB_ENV" + echo "WORKING_BRANCH_PREFIX=${WORKING_BRANCH_PREFIX}" | tee -a "$GITHUB_ENV" + + - name: Find temporary branch + id: find-temporary-branch + run: | + working_branch_count=$(git branch --list "${WORKING_BRANCH_PREFIX}*" | wc -l) + if [[ "${working_branch_count}" -ne 1 ]]; then + echo "More than one (or zero) temporary branches found. Cannot finish transaction." + git branch --list "${WORKING_BRANCH_PREFIX}*" + exit 1 + fi + WORKING_BRANCH=$(git branch --list "${WORKING_BRANCH_PREFIX}*" | head -n 1 | sed -e 's/^[[:space:]]*//') + echo "WORKING_BRANCH=${WORKING_BRANCH}" | tee -a "$GITHUB_ENV" + + - name: Check if we are strictly ahead of the release branch (if it exists) + run: | + git fetch + git pull + git checkout "${RELEASE_BRANCH}" || exit 0 + git checkout "${WORKING_BRANCH}" + ahead=$(git rev-list HEAD --not "${RELEASE_BRANCH}" | wc -l) + if [[ "${ahead}" -gt 0 ]]; then + echo "The current branch is not strictly ahead of the release branch. Cannot finish transaction without touching release branch history." + exit 1 + fi + + - name: Create or update release branch + run: git push origin "${WORKING_BRANCH}":"${RELEASE_BRANCH}" + update: runs-on: ubuntu-22.04 outputs: @@ -21,8 +73,6 @@ jobs: steps: - name: Checkout uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 - with: - ref: ${{ !github.event.pull_request.head.repo.fork && github.head_ref || '' }} - name: Override latest if: github.event.inputs.latest == 'true' @@ -82,3 +132,21 @@ jobs: version: ${{ github.event.release.tag_name }}${{ github.event.inputs.tag }} kind: cli add_latest: ${{ needs.update.outputs.latest == 'true' }} + + remove-temporary-branch: + needs: + [ + complete-release-branch-transaction, + add-image-version-to-versionsapi, + add-cli-version-to-versionsapi, + ] + runs-on: ubuntu-22.04 + permissions: + id-token: write + contents: read + steps: + - name: Checkout + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + + - name: Remove temporary branch + run: git push origin --delete "${WORKING_BRANCH}" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d8571d493..27f0237c0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,7 +28,13 @@ jobs: MAJOR_MINOR: ${{ steps.version-info.outputs.MAJOR_MINOR }} MAJOR_MINOR_PATCH: ${{ steps.version-info.outputs.MAJOR_MINOR_PATCH }} RELEASE_BRANCH: ${{ steps.version-info.outputs.RELEASE_BRANCH }} + WORKING_BRANCH: ${{ steps.version-info.outputs.WORKING_BRANCH }} steps: + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + + - name: Working branch + run: echo "WORKING_BRANCH=$(git branch --show-current)" | tee -a "$GITHUB_ENV" + - name: Verify version run: | if [[ ! "${FULL_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then @@ -36,6 +42,13 @@ jobs: exit 1 fi + - name: Verify temporary branch + run: | + if [[ ! "${WORKING_BRANCH}" =~ ^tmp/v[0-9]+\.[0-9]+\.[0-9]+(/.+)? ]]; then + echo "Workflow can only be triggered from a temporary branch in the form of tmp/vX.Y.Z/..." + exit 1 + fi + - name: Extract version info id: version-info run: | @@ -53,10 +66,11 @@ jobs: echo "MAJOR_MINOR=${PART_MAJOR}.${PART_MINOR}" echo "MAJOR_MINOR_PATCH=${PART_MAJOR}.${PART_MINOR}.${PART_PATCH}" echo "RELEASE_BRANCH=release/v${PART_MAJOR}.${PART_MINOR}" + echo "WORKING_BRANCH=${WORKING_BRANCH}" } | tee -a "$GITHUB_OUTPUT" docs: - name: Create docs release + name: Create docs release (from main) runs-on: ubuntu-22.04 if: inputs.kind == 'minor' needs: verify-inputs @@ -70,7 +84,7 @@ jobs: steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 with: - ref: ${{ github.head_ref }} + ref: main - name: Create docs release working-directory: docs @@ -95,40 +109,46 @@ jobs: # We need to push changes using a token, otherwise triggers like on:push and on:pull_request won't work. token: ${{ !github.event.pull_request.head.repo.fork && secrets.CI_COMMIT_PUSH_PR || '' }} - prepare-release-branch: - name: Prepare release branch + check-working-branch: + name: Check temporary working branch runs-on: ubuntu-22.04 needs: verify-inputs permissions: contents: write env: - BRANCH: ${{ needs.verify-inputs.outputs.RELEASE_BRANCH }} + RELEASE_BRANCH: ${{ needs.verify-inputs.outputs.RELEASE_BRANCH }} + WORKING_BRANCH: ${{ needs.verify-inputs.outputs.WORKING_BRANCH }} steps: - name: Checkout uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 with: - ref: ${{ github.head_ref }} + ref: ${{ needs.verify-inputs.outputs.WORKING_BRANCH }} - - name: Create release branch - if: inputs.kind == 'minor' + - name: Check if we are strictly ahead of the release branch (if it exists) run: | git fetch git pull - git checkout "${BRANCH}" || git checkout -B "${BRANCH}" - git push origin "${BRANCH}" + git checkout "${RELEASE_BRANCH}" || exit 0 + git checkout "${WORKING_BRANCH}" + ahead=$(git rev-list HEAD --not "${RELEASE_BRANCH}" | wc -l) + if [[ "${ahead}" -gt 0 ]]; then + echo "The current branch is not strictly ahead of the release branch. Please rebase." + exit 1 + fi - name: Write version to version.txt run: | + git checkout "${WORKING_BRANCH}" echo "${{ inputs.version }}" > version.txt git config --global user.name "edgelessci" git config --global user.email "edgelessci@users.noreply.github.com" git add version.txt git diff --staged --quiet || git commit -m "chore: update version.txt to ${{ inputs.version }}" - git push origin "${BRANCH}" + git push origin "${WORKING_BRANCH}" update-versions: name: Update container image versions - needs: [verify-inputs, prepare-release-branch] + needs: [verify-inputs, check-working-branch] runs-on: ubuntu-22.04 permissions: contents: write @@ -140,7 +160,7 @@ jobs: - name: Checkout uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 with: - ref: ${{ needs.verify-inputs.outputs.RELEASE_BRANCH }} + ref: ${{ needs.verify-inputs.outputs.WORKING_BRANCH }} - name: Update enterprise image version run: | @@ -172,7 +192,7 @@ jobs: imageVersion: ${{ inputs.version }} isRelease: true stream: "stable" - ref: ${{ needs.verify-inputs.outputs.RELEASE_BRANCH }} + ref: ${{ needs.verify-inputs.outputs.WORKING_BRANCH }} update-hardcoded-measurements: name: Update hardcoded measurements (in the CLI) @@ -187,7 +207,7 @@ jobs: - name: Checkout uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 with: - ref: ${{ needs.verify-inputs.outputs.RELEASE_BRANCH }} + ref: ${{ needs.verify-inputs.outputs.WORKING_BRANCH }} - name: Setup Go environment uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0 @@ -224,7 +244,7 @@ jobs: - name: Checkout uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 with: - ref: ${{ needs.verify-inputs.outputs.RELEASE_BRANCH }} + ref: ${{ needs.verify-inputs.outputs.WORKING_BRANCH }} - name: Tag release run: | @@ -258,7 +278,7 @@ jobs: contents: read secrets: inherit with: - ref: ${{ needs.verify-inputs.outputs.RELEASE_BRANCH }} + ref: ${{ needs.verify-inputs.outputs.WORKING_BRANCH }} mini-e2e: name: Run mini E2E tests @@ -271,4 +291,4 @@ jobs: contents: read secrets: inherit with: - ref: ${{ needs.verify-inputs.outputs.RELEASE_BRANCH }} + ref: ${{ needs.verify-inputs.outputs.WORKING_BRANCH }} diff --git a/dev-docs/workflows/release.md b/dev-docs/workflows/release.md index 5b0f72f0a..cc1c8afa5 100644 --- a/dev-docs/workflows/release.md +++ b/dev-docs/workflows/release.md @@ -12,15 +12,32 @@ This checklist will prepare `v1.3.0` from `v1.2.0` (minor release) or `v1.3.1` f Releases should be performed using [the automated release pipeline](https://github.com/edgelesssys/constellation/actions/workflows/release.yml). +### Prepare temporary working branch + +1. Create a temporary working branch to prepare the release. This branch should be based on main if preparing a minor release or be based on the existing release branch if it is a patch release. + ```sh + ver=v1.3.1 # replace me + minor=$(echo ${ver} | cut -d '.' -f 1,2) + # optional suffix to add to the temporary branch name. Can be empty: suffix= + suffix=/foo + # if preparing a patch release, checkout existing release branch as base + git checkout release/${minor} + # if preparing a minor release, branch out from main instead + git checkout main + git pull + working_branch=tmp/${ver}${suffix} + git checkout -b ${working_branch} + git push origin ${working_branch} + ``` + + ### Patch release 1. `cherry-pick` (only) the required commits from `main` * Check PRs with label [needs-backport](https://github.com/edgelesssys/constellation/pulls?q=is%3Apr+is%3Aclosed+label%3A%22needs+backport%22) to find candidates that should be included in a patch release. -2. trigger the automated release pipeline from the existing minor version branch: +2. trigger the automated release pipeline from the working branch created above: ```sh - ver=v1.3.1 # replace me - minor=$(echo $ver | cut -d '.' -f 1,2) - gh workflow run release.yml --ref release/v$minor -F version=$ver -F kind=patch + gh workflow run release.yml --ref ${working_branch} -F version=${ver} -F kind=patch ``` 3. wait for the pipeline to finish 4. while in editing mode for the release, clear the textbox, select the last patch release for the current release branch and click "Generate release notes". @@ -29,11 +46,9 @@ Releases should be performed using [the automated release pipeline](https://gith ### Minor release 1. Merge ready PRs -2. trigger the automated release pipeline from `main`: +2. trigger the automated release pipeline from the working branch created above: ```sh - ver=v1.3.0 # replace me - minor=$(echo $ver | cut -d '.' -f 1,2) - gh workflow run release.yml --ref main -F version=$ver -F kind=minor + gh workflow run release.yml --ref ${working_branch} -F version=${ver} -F kind=minor ``` 3. wait for the pipeline to finish 4. while in editing mode for the release, clear the textbox, select the last minor release and click "Generate release notes". @@ -59,6 +74,7 @@ These are the necessary steps. ### General Depending on how far the pipeline ran we need to delete: +- the working branch (remove automated commits made by the process, keep any cherry picks) - the release tag create by the pipeline: `v1.3.0`/`v1.3.1` - (only minor releases) the branch to merge changes back to main: `feat/release/v1.3.0` - invalidate the CDN caches. This may become necessary if e.g. during measurement updating the measurements of a previous run are still in the cache