From b024fa99a10b1b8b959066c83c0d5e0943de4db4 Mon Sep 17 00:00:00 2001 From: Paul Meyer <49727155+katexochen@users.noreply.github.com> Date: Mon, 29 Jan 2024 15:56:19 +0100 Subject: [PATCH] ci: add release workflow Signed-off-by: Paul Meyer <49727155+katexochen@users.noreply.github.com> --- .github/actions/bump_version/action.yml | 32 +++++ .github/workflows/release.yml | 176 ++++++++++++++++++++++++ .github/workflows/release_publish.yml | 86 ++++++++++++ 3 files changed, 294 insertions(+) create mode 100644 .github/actions/bump_version/action.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/release_publish.yml diff --git a/.github/actions/bump_version/action.yml b/.github/actions/bump_version/action.yml new file mode 100644 index 0000000000..b9628935d0 --- /dev/null +++ b/.github/actions/bump_version/action.yml @@ -0,0 +1,32 @@ +name: bump version +description: Bump the projects main version and commit the change + +inputs: + version: + description: "Version to bump to" + required: true + commit: + description: Whether to commit the change + required: false + +runs: + using: "composite" + steps: + - name: Bump version + shell: bash + run: | + current=$(s + grep -E '^\s*version = "[^"]*";$' flake.nix | + sed -E 's/\s*version = "([^"]*)";/\1/' + ) + sed -i 's/version = "[^"]*";$/version = "${{ inputs.version }}";/' flake.nix + + if [[ "${{ inputs.commit }}" == "false" ]]; then + exit 0 + fi + + git config --global user.name "edgelessci" + git config --global user.email "edgelessci@users.noreply.github.com" + git add flake.nix + git diff --staged --quiet || git commit -m "flake: ${current} -> ${{ inputs.version }}" + git push origin "$(git rev-parse --abbrev-ref HEAD)" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..506fd5387b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,176 @@ +name: release + +on: + workflow_dispatch: + inputs: + version: + description: Version to release (e.g. v1.2.3) + required: true + kind: + description: Release kind + type: choice + options: [minor, patch] + required: true + default: minor + +env: + container_registry: ghcr.io/edgelesssys + +concurrency: + group: ${{ github.ref }} + cancel-in-progress: true + +jobs: + process-inputs: + name: Process inputs + runs-on: ubuntu-22.04 + env: + FULL_VERSION: ${{ inputs.version }} + outputs: + WITHOUT_V: ${{ steps.version-info.outputs.WITHOUT_V }} + PART_MAJOR: ${{ steps.version-info.outputs.PART_MAJOR }} + PART_MINOR: ${{ steps.version-info.outputs.PART_MINOR }} + PART_PATCH: ${{ steps.version-info.outputs.PART_PATCH }} + MAJOR: ${{ steps.version-info.outputs.MAJOR }} + 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 }} + NEXT_MINOR_PRE_WITHOUT_V: ${{ steps.version-info.outputs.NEXT_MINOR_PRE_WITHOUT_V }} + NEXT_PATCH_PRE_WITHOUT_V: ${{ steps.version-info.outputs.NEXT_PATCH_PRE_WITHOUT_V }} + steps: + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Working branch + run: | + echo "WORKING_BRANCH=$(git branch --show-current)" | tee -a "$GITHUB_ENV" + - name: Verify minor version bump + if: ${{ inputs.kind == 'minor' }} + run: | + if [[ ! "${FULL_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Version must be in the form of vX.Y.Z" + exit 1 + fi + - name: Verify patch version bump + if: ${{ inputs.kind == 'patch' }} + run: | + if [[ ! "${FULL_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[1-9]+$ ]]; then + echo "Version must be in the form of vX.Y.Z, where Z > 0" + exit 1 + fi + - name: Verify temporary branch for minor release + 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: | + WITHOUT_V=${FULL_VERSION#v} + PART_MAJOR=${WITHOUT_V%%.*} + PART_MINOR=${WITHOUT_V#*.} + PART_MINOR=${PART_MINOR%%.*} + PART_PATCH=${WITHOUT_V##*.} + RELEASE_BRANCH=release/v${PART_MAJOR}.${PART_MINOR} + NEXT_MINOR_PRE_WITHOUT_V=${PART_MAJOR}.$((PART_MINOR + 1)).0-pre + NEXT_PATCH_PRE_WITHOUT_V=${PART_MAJOR}.${PART_MINOR}.$((PART_PATCH + 1))-pre + { + echo "WITHOUT_V=${WITHOUT_V}" + echo "PART_MAJOR=${PART_MAJOR}" + echo "PART_MINOR=${PART_MINOR}" + echo "PART_PATCH=${PART_PATCH}" + echo "MAJOR=${PART_MAJOR}" + echo "MAJOR_MINOR=${PART_MAJOR}.${PART_MINOR}" + echo "MAJOR_MINOR_PATCH=${PART_MAJOR}.${PART_MINOR}.${PART_PATCH}" + echo "RELEASE_BRANCH=${RELEASE_BRANCH}" + echo "WORKING_BRANCH=${WORKING_BRANCH}" + echo "NEXT_MINOR_PRE_WITHOUT_V=${NEXT_MINOR_PRE_WITHOUT_V}" + echo "NEXT_PATCH_PRE_WITHOUT_V=${NEXT_PATCH_PRE_WITHOUT_V}" + } | tee -a "$GITHUB_OUTPUT" + echo $RELEASE_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}" -eq 0 ]]; then + echo "The current branch is not strictly ahead of the release branch. Please rebase." + exit 1 + fi + + update-main: + name: Update main branch + if: ${{ inputs.kind == 'minor' }} + runs-on: ubuntu-22.04 + needs: process-inputs + permissions: + contents: write + env: + RELEASE_BRANCH: ${{ needs.process-inputs.outputs.RELEASE_BRANCH }} + WORKING_BRANCH: ${{ needs.process-inputs.outputs.WORKING_BRANCH }} + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: main + - name: Bump flake version to post release patch pre-version + uses: ./.github/actions/bump_version + with: + version: ${{ needs.process-inputs.outputs.NEXT_MINOR_PRE_WITHOUT_V }} + commit: true + + release: + name: Build and push artifacts, create release + runs-on: ubuntu-22.04 + needs: process-inputs + permissions: + contents: write + env: + RELEASE_BRANCH: ${{ needs.process-inputs.outputs.RELEASE_BRANCH }} + WORKING_BRANCH: ${{ needs.process-inputs.outputs.WORKING_BRANCH }} + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + ref: ${{ needs.process-inputs.outputs.WORKING_BRANCH }} + - uses: cachix/install-nix-action@6004951b182f8860210c8d6f0d808ec5b1a33d28 # v25 + with: + github_access_token: ${{ secrets.GITHUB_TOKEN }} + - uses: cachix/cachix-action@18cf96c7c98e048e10a83abd92116114cd8504be # v14 + with: + name: edgelesssys + authToken: ${{ secrets.CACHIX_AUTH_TOKEN }} + - name: Log in to ghcr.io Container registry + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Bump flake version temporarily to release version + uses: ./.github/actions/bump_version + with: + version: ${{ needs.process-inputs.outputs.WITHOUT_V }} + commit: false + - name: Push containers with release tag + run: | + nix run .#push-coordinator -- "$container_registry/nunki/coordinator" + nix run .#push-initializer -- "$container_registry/nunki/initializer" + - name: Build CLI + run: | + nix build .#cli + - name: Create draft release + uses: softprops/action-gh-release@de2c0eb89ae2a093876385947365aca7b0e5f844 # v0.1.15 + with: + draft: true + generate_release_notes: true + tag_name: ${{ inputs.version }} + target_commitish: ${{ needs.process-inputs.outputs.WORKING_BRANCH }} + files: | + - result-cli/bin/nunki + - name: Bump flake version to post release patch pre-version + uses: ./.github/actions/bump_version + with: + version: ${{ needs.process-inputs.outputs.NEXT_PATCH_PRE_WITHOUT_V }} + commit: true diff --git a/.github/workflows/release_publish.yml b/.github/workflows/release_publish.yml new file mode 100644 index 0000000000..d32e57b4f8 --- /dev/null +++ b/.github/workflows/release_publish.yml @@ -0,0 +1,86 @@ +name: Make updated OS images available on release + +on: + release: + types: + - published + workflow_dispatch: + inputs: + tag: + description: "Semantic version tag of the release (vX.Y.Z)." + required: true + latest: + description: "Whether to update the latest tag." + type: boolean + default: false + +jobs: + complete-release-branch-transaction: + runs-on: ubuntu-22.04 + permissions: + id-token: write + contents: write + 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@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + fetch-depth: 0 # fetch all history + - name: Determine branch names + run: | + RELEASE_BRANCH="release/${FULL_VERSION%.*}" + WORKING_BRANCH="tmp/${FULL_VERSION}" + { + echo "RELEASE_BRANCH=${RELEASE_BRANCH}" + echo "WORKING_BRANCH=${WORKING_BRANCH}" + } | tee -a "$GITHUB_ENV" + - name: Create or update release branch + run: | + git fetch + git checkout "${WORKING_BRANCH}" # ensure branch exists locally + git push origin "${WORKING_BRANCH}":"${RELEASE_BRANCH}" + + update: + runs-on: ubuntu-22.04 + needs: + - complete-release-branch-transaction + outputs: + latest: ${{ steps.input-passthrough.outputs.latest }}${{ steps.check-last-release.outputs.latest }} + steps: + - name: Checkout + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + - name: Override latest + if: github.event.inputs.latest == 'true' + id: input-passthrough + run: | + echo "latest=true" | tee -a "$GITHUB_OUTPUT" + - name: Check if should mark latest + if: github.event.inputs.latest != 'true' + id: check-last-release + env: + REPO: edgelesssys/constellation + GH_TOKEN: ${{ github.token }} + run: | + latest_release_tag=$( + gh api \ + -H "Accept: application/vnd.github+json" \ + "/repos/${REPO}/releases/latest" \ + | jq -r '.tag_name' + ) + + current_tag=${{ github.event.release.tag_name }}${{ github.event.inputs.tag }} + echo "Latest release tag: ${latest_release_tag}" + echo "Current tag: ${current_tag}" + + if [[ "${latest_release_tag}" == "${current_tag}" ]]; then + echo "latest=true" | tee -a "$GITHUB_OUTPUT" + else + echo "latest=false" | tee -a "$GITHUB_OUTPUT" + fi + - name: Remove temporary branch + run: | + git push origin --delete "${{needs.complete-release-branch-transaction.outputs.WORKING_BRANCH}}"