Skip to content

release

release #379

Workflow file for this run

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
overwrite_published_release:
description: Tick this box if you want to overwrite a published release and have a good reason for doing so.
type: boolean
required: false
default: false
checkout_main_ref:
description: Checkout this git ref as main branch (some workflows run on this state)
type: string
required: false
default: main
env:
container_registry: ghcr.io/edgelesssys
azure_resource_group: contrast-ci
DO_NOT_TRACK: 1
concurrency:
group: ${{ github.ref }}
cancel-in-progress: true
jobs:
process-inputs:
name: Process inputs
runs-on: ubuntu-24.04
permissions:
contents: write
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: ${{ steps.version-info.outputs.NEXT_MINOR }}
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- 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=${PART_MAJOR}.$((PART_MINOR + 1)).0
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=${NEXT_MINOR}"
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=${RELEASE_BRANCH}" | tee -a "$GITHUB_ENV"
- name: Don't overwrite published releases
if: (! inputs.overwrite_published_release)
env:
GH_TOKEN: ${{ github.token }}
run: |
is_draft=$(gh release view "${FULL_VERSION}" --json isDraft -q .isDraft || true)
# If the release is not yet published, is_draft will either be "true" or empty.
if [[ "${is_draft}" == "false" ]]; then
echo "::error::Release ${FULL_VERSION} is already published."
exit 1
fi
update-main:
name: Update main branch
runs-on: ubuntu-24.04
needs: [process-inputs, release]
permissions:
contents: write
env:
RELEASE_BRANCH: ${{ needs.process-inputs.outputs.RELEASE_BRANCH }}
WORKING_BRANCH: ${{ needs.process-inputs.outputs.WORKING_BRANCH }}
VERSION: ${{ inputs.version }}
MAJOR_MINOR: ${{ needs.process-inputs.outputs.MAJOR_MINOR }}
MAJOR_MINOR_PATCH: ${{ needs.process-inputs.outputs.MAJOR_MINOR_PATCH }}
SET: base
steps:
- name: Checkout working branch
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ needs.process-inputs.outputs.WORKING_BRANCH }}
path: contrast-working
persist-credentials: false
- name: Checkout main
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ inputs.checkout_main_ref }}
path: contrast-main
persist-credentials: false
- uses: ./contrast-working/.github/actions/setup_nix
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
cachixToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Configure git
run: |
git config --global user.name "edgelessci"
git config --global user.email "edgelessci@users.noreply.github.com"
- name: Create docs release
if: inputs.kind == 'minor'
working-directory: contrast-main/docs
run: |
nix run ".#${SET}.nixpkgs.yarn install"
nix run ".#${SET}.nixpkgs.yarn" docusaurus docs:version "${MAJOR_MINOR}"
git add .
git commit -am "docs: release ${MAJOR_MINOR}"
# Clean up auxiliary files, so next steps run on a clean tree
git clean -fx :/
git reset --hard HEAD
- name: Download image replacements file (from release branch)
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: image-replacements
- name: Update release urls in docs with tags
working-directory: contrast-main
run: nix run ".#${SET}.scripts.update-release-urls"
- name: Commit updated docs
working-directory: contrast-main
run: |
git add "docs/versioned_docs/version-${MAJOR_MINOR}"
git commit -m "docs: update release download urls"
git clean -fx :/
git reset --hard HEAD
- name: Download release artifacts (from release branch)
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: contrast-release-artifacts
path: ./contrast-main
- name: Update contrast-releases.json with new release
working-directory: contrast-main
run: nix run ".#${SET}.scripts.update-contrast-releases"
- name: Commit updated contrast-releases.json
working-directory: contrast-main
run: |
git add ./packages/contrast-releases.json
git commit -m "packages/contrast-releases: add ${MAJOR_MINOR_PATCH}"
git clean -fx :/
git reset --hard HEAD
- name: Bump flake version to post release patch pre-version
if: inputs.kind == 'minor'
id: bump
uses: ./contrast-working/.github/actions/bump_version # Run action from working branch!
with:
version: ${{ needs.process-inputs.outputs.NEXT_MINOR_PRE_WITHOUT_V }}
working-directory: contrast-main
commit: false
- name: Create PR
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
with:
title: Post ${{ needs.process-inputs.outputs.WITHOUT_V }} release updates to main
body: |
Updating main as part of the ${{ needs.process-inputs.outputs.WITHOUT_V }} release.
Only merge after the release is published.
commit-message: ${{ steps.bump.outputs.commit-msg }}
base: main
draft: false
labels: "no changelog"
branch: automated/update-main-after-${{ needs.process-inputs.outputs.WORKING_BRANCH }}
committer: edgelessci <edgelessci@users.noreply.github.com>
author: edgelessci <edgelessci@users.noreply.github.com>
token: ${{ secrets.NUNKI_CI_COMMIT_PUSH_PR }}
path: ./contrast-main
release:
name: Build and push artifacts, create release
runs-on: ubuntu-24.04
needs: process-inputs
permissions:
contents: write
packages: write
id-token: write
env:
RELEASE_BRANCH: ${{ needs.process-inputs.outputs.RELEASE_BRANCH }}
WORKING_BRANCH: ${{ needs.process-inputs.outputs.WORKING_BRANCH }}
VERSION: ${{ inputs.version }}
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ needs.process-inputs.outputs.WORKING_BRANCH }}
persist-credentials: true
- uses: ./.github/actions/setup_nix
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
cachixToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- name: Log in to ghcr.io Container registry
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Configure git
run: |
git config --global user.name "edgelessci"
git config --global user.email "edgelessci@users.noreply.github.com"
- name: Bump flake version to release version
uses: ./.github/actions/bump_version
with:
version: ${{ needs.process-inputs.outputs.WITHOUT_V }}
commit: true
- name: Create release artifacts
id: create-artifacts
uses: ./.github/actions/release_artifacts
with:
version: ${{ inputs.version }}
container_registry: ${{ env.container_registry }}
s3-bucket-path: "pre-releases/${{ inputs.version }}"
- name: Upload release artifacts (for main branch PR)
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: contrast-release-artifacts
# Keep the LICENSE file! It isn't used, but ensures the paths of the other artifacts aren't stripped, see
# https://github.com/actions/upload-artifact/blob/6027e3dd177782cd8ab9af838c04fd81a07f1d47/README.md?plain=1#L187
path: |
LICENSE
${{ steps.create-artifacts.outputs.paths }}
- name: Create draft release
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
with:
draft: true
generate_release_notes: true
tag_name: ${{ inputs.version }}
target_commitish: ${{ needs.process-inputs.outputs.WORKING_BRANCH }}
fail_on_unmatched_files: true
files: ${{ steps.create-artifacts.outputs.paths }}
- name: Reset temporary changes
run: |
git reset --hard "${WORKING_BRANCH}"
- 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
test:
strategy:
matrix:
platform:
- name: Metal-QEMU-SNP
node-installer-target-conf: none
runner: SNP
self-hosted: true
- name: Metal-QEMU-SNP-GPU
node-installer-target-conf: k3s
runner: SNP-GPU
self-hosted: true
- name: Metal-QEMU-TDX
node-installer-target-conf: k3s
runner: TDX
self-hosted: true
- name: Metal-QEMU-TDX-GPU
node-installer-target-conf: k3s
runner: TDX-GPU
self-hosted: true
fail-fast: false
name: "e2e release on ${{ matrix.platform.name }}"
runs-on: ${{ matrix.platform.runner }}
permissions:
# Job needs content:write to see draft releases.
contents: write
packages: read
needs: [process-inputs, release, nightly]
env:
VERSION: ${{ inputs.version }}
SET: base
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ needs.process-inputs.outputs.WORKING_BRANCH }}
persist-credentials: false
- uses: ./.github/actions/setup_nix
if: (!matrix.platform.self-hosted)
with:
githubToken: ${{ secrets.GITHUB_TOKEN }}
cachixToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
- uses: nicknovitski/nix-develop@9be7cfb4b10451d3390a75dc18ad0465bed4932a # v1.2.1
- name: Log in to ghcr.io Container registry
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create justfile.env
run: |
cat <<EOF > justfile.env
container_registry=${{ env.container_registry }}
azure_resource_group=${{ env.azure_resource_group }}
default_platform=${{ matrix.platform.name }}
EOF
- name: Get credentials for CI cluster
if: (!matrix.platform.self-hosted)
run: |
just get-credentials
- name: Request fifo ticket
if: (!matrix.platform.self-hosted || matrix.platform.name == 'Metal-QEMU-SNP-GPU' || matrix.platform.name == 'Metal-QEMU-TDX-GPU')
run: |
just request-fifo-ticket
- name: E2E Test
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
mkdir -p workspace
nix build ".#${SET}.scripts.get-logs"
nix run ".#${SET}.scripts.get-logs start" workspace/just.namespace &
nix shell -L ".#${SET}.contrast.e2e" --command release.test \
-test.v \
--tag "${VERSION}" \
--platform ${{ matrix.platform.name }} \
--node-installer-target-conf ${{ matrix.platform.node-installer-target-conf }} \
--namespace-file workspace/just.namespace
- name: Download logs
if: always()
run: |
nix run ".#${SET}.scripts.get-logs download" workspace/just.namespace
- name: Cleanup
if: always()
run: |
kubectl delete -f workspace/log-collector.yaml
rm -f workspace/just.namespace
- name: Upload logs
if: always()
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with:
name: e2e_pod_logs-${{ matrix.platform.name }}-release
path: workspace/logs
if-no-files-found: error
- name: Release fifo ticket
if: always() && (!matrix.platform.self-hosted || matrix.platform.name == 'Metal-QEMU-SNP-GPU' || matrix.platform.name == 'Metal-QEMU-TDX-GPU')
run: |
just release-fifo-ticket
nightly:
name: e2e nightly
needs: release
uses: ./.github/workflows/e2e_nightly.yml
secrets:
GITHUB_TOKEN_IN: ${{ secrets.GITHUB_TOKEN }}
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
NUNKI_CI_COMMIT_PUSH_PR: ${{ secrets.NUNKI_CI_COMMIT_PUSH_PR }}
TEAMS_CI_WEBHOOK: ${{ secrets.TEAMS_CI_WEBHOOK }}
CONTRAST_GHCR_READ: ${{ secrets.CONTRAST_GHCR_READ }}
permissions:
contents: read
packages: write
publish:
name: Publish release
needs: [process-inputs, release, test]
runs-on: ubuntu-24.04
environment: release-publish
permissions:
contents: write
steps:
- name: Publish release
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ inputs.version }}
run: |
gh release edit "${VERSION}" --draft=false --repo "${{ github.repository }}"
create-github-stuff:
name: Create backport label and milestone
if: inputs.kind == 'minor'
needs: process-inputs
runs-on: ubuntu-24.04
permissions:
issues: write
contents: read
env:
RELEASE_BRANCH: ${{ needs.process-inputs.outputs.RELEASE_BRANCH }}
NEXT_MINOR: ${{ needs.process-inputs.outputs.NEXT_MINOR }}
GH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ needs.process-inputs.outputs.WORKING_BRANCH }}
persist-credentials: false
- name: Create backport label
run: |
gh label create "backport ${RELEASE_BRANCH}" --color 576F61 --force
- name: Create milestone
run: |
gh api \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/edgelesssys/contrast/milestones |
jq -r '.[] | .title' | \
grep -xqF "v${NEXT_MINOR}" && exit 0
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/edgelesssys/contrast/milestones \
-f title="v${NEXT_MINOR}" \
-f state='open'