Skip to content

release

release #265

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
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-22.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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- 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 ${{ inputs.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 ${{ inputs.version }} is already published."
exit 1
fi
update-main:
name: Update main branch
runs-on: ubuntu-22.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 }}
steps:
- name: Checkout working branch
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ needs.process-inputs.outputs.WORKING_BRANCH }}
path: contrast-working
- name: Checkout main
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: main
path: contrast-main
- 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 "[email protected]"
- name: Create docs release
if: inputs.kind == 'minor'
working-directory: contrast-main/docs
run: |
nix run .#yarn install
nix run .#yarn docusaurus docs:version ${{ needs.process-inputs.outputs.MAJOR_MINOR }}
git add .
git commit -am "docs: release ${{ needs.process-inputs.outputs.MAJOR_MINOR }}"
# Clean up auxiliary files, so next steps run on a clean tree
git clean -fx :/
- name: Download image replacements file (from release branch)
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: image-replacements.txt
- name: Update release urls in docs with tags
working-directory: contrast-main
env:
MAJOR_MINOR: ${{ needs.process-inputs.outputs.MAJOR_MINOR }}
VERSION: ${{ inputs.version }}
run: nix run .#scripts.update-release-urls
- name: Commit updated docs
working-directory: contrast-main
run: |
git add docs/versioned_docs/version-${{ needs.process-inputs.outputs.MAJOR_MINOR }}
git commit -m "docs: update release download urls"
git clean -fx :/
- name: Download release artifacts (from release branch)
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: contrast-release-artifacts
path: ./contrast-main
- name: Update contrast-releases.json with new release
working-directory: contrast-main
env:
VERSION: ${{ inputs.version }}
run: nix run .#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 ${{ needs.process-inputs.outputs.MAJOR_MINOR_PATCH }}"
git clean -fx :/
- 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@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
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 <[email protected]>
author: edgelessci <[email protected]>
token: ${{ secrets.NUNKI_CI_COMMIT_PUSH_PR }}
path: ./contrast-main
release:
name: Build and push artifacts, create release
runs-on: ubuntu-22.04
needs: process-inputs
permissions:
contents: write
packages: write
env:
RELEASE_BRANCH: ${{ needs.process-inputs.outputs.RELEASE_BRANCH }}
WORKING_BRANCH: ${{ needs.process-inputs.outputs.WORKING_BRANCH }}
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ needs.process-inputs.outputs.WORKING_BRANCH }}
- 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@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.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: |
coordinatorImg=$(nix run .#containers.push-coordinator -- "$container_registry/contrast/coordinator")
nodeInstallerMsftImg=$(nix run .#containers.push-node-installer-microsoft -- "$container_registry/contrast/node-installer-microsoft")
nodeInstallerKataImg=$(nix run .#containers.push-node-installer-kata -- "$container_registry/contrast/node-installer-kata")
initializerImg=$(nix run .#containers.push-initializer -- "$container_registry/contrast/initializer")
serviceMeshImg=$(nix run .#containers.push-service-mesh-proxy -- "$container_registry/contrast/service-mesh-proxy")
tardevSnapshotterImg=$(nix run .#containers.push-tardev-snapshotter -- "$container_registry/contrast/tardev-snapshotter")
nydusSnapshotterImg=$(nix run .#containers.push-nydus-snapshotter -- "$container_registry/contrast/nydus-snapshotter")
cryptsetupImg=$(nix run .#containers.push-cryptsetup -- "$container_registry/contrast/cryptsetup")
echo "coordinatorImg=$coordinatorImg" | tee -a "$GITHUB_ENV"
echo "nodeInstallerMsftImg=$nodeInstallerMsftImg" | tee -a "$GITHUB_ENV"
echo "nodeInstallerKataImg=$nodeInstallerKataImg" | tee -a "$GITHUB_ENV"
echo "initializerImg=$initializerImg" | tee -a "$GITHUB_ENV"
echo "serviceMeshImg=$serviceMeshImg" | tee -a "$GITHUB_ENV"
echo "tardevSnapshotterImg=$tardevSnapshotterImg" | tee -a "$GITHUB_ENV"
echo "nydusSnapshotterImg=$nydusSnapshotterImg" | tee -a "$GITHUB_ENV"
echo "cryptsetupImg=$cryptsetupImg" | tee -a "$GITHUB_ENV"
- name: Add tag to Coordinator image
run: |
tag() {
front=${1%@*}
back=${1#*@}
printf "%s:%s@%s" "$front" "${{ inputs.version }}" "$back"
}
echo "coordinatorImgTagged=$(tag "$coordinatorImg")" | tee -a "$GITHUB_ENV"
echo "nodeInstallerMsftImgTagged=$(tag "$nodeInstallerMsftImg")" | tee -a "$GITHUB_ENV"
echo "nodeInstallerKataImgTagged=$(tag "$nodeInstallerKataImg")" | tee -a "$GITHUB_ENV"
echo "initializerImgTagged=$(tag "$initializerImg")" | tee -a "$GITHUB_ENV"
echo "serviceMeshImgTagged=$(tag "$serviceMeshImg")" | tee -a "$GITHUB_ENV"
echo "cryptsetupImgTagged=$(tag "$cryptsetupImg")" | tee -a "$GITHUB_ENV"
tardevVer=$(nix eval --impure --raw --expr "(builtins.getFlake \"git+file://$(pwd)?shallow=1\").outputs.legacyPackages.x86_64-linux.microsoft.tardev-snapshotter.version")
front=${tardevSnapshotterImg%@*}
back=${tardevSnapshotterImg#*@}
echo "tardevSnapshotterImgTagged=$(printf "%s:%s@%s" "$front" "$tardevVer" "$back")" | tee -a "$GITHUB_ENV"
nydusVer=$(nix eval --impure --raw --expr "(builtins.getFlake \"git+file://$(pwd)?shallow=1\").outputs.legacyPackages.x86_64-linux.nydus-snapshotter.version")
front=${nydusSnapshotterImg%@*}
back=${nydusSnapshotterImg#*@}
echo "nydusSnapshotterImgTagged=$(printf "%s:%s@%s" "$front" "$nydusVer" "$back")" | tee -a "$GITHUB_ENV"
- name: Create file with image replacements
run: |
{
echo "ghcr.io/edgelesssys/contrast/coordinator:latest=$coordinatorImgTagged"
echo "ghcr.io/edgelesssys/contrast/initializer:latest=$initializerImgTagged"
echo "ghcr.io/edgelesssys/contrast/service-mesh-proxy:latest=$serviceMeshImgTagged"
echo "ghcr.io/edgelesssys/contrast/node-installer-microsoft:latest=$nodeInstallerMsftImgTagged"
echo "ghcr.io/edgelesssys/contrast/node-installer-kata:latest=$nodeInstallerKataImgTagged"
echo "ghcr.io/edgelesssys/contrast/tardev-snapshotter:latest=$tardevSnapshotterImgTagged"
echo "ghcr.io/edgelesssys/contrast/nydus-snapshotter:latest=$nydusSnapshotterImgTagged"
echo "ghcr.io/edgelesssys/contrast/cryptsetup:latest=$cryptsetupImgTagged"
} > image-replacements.txt
- name: Upload image replacements file (for main branch PR)
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: image-replacements.txt
path: ./image-replacements.txt
- name: Create coordinator resource definitions
run: |
mkdir -p workspace
for platform in aks-clh-snp k3s-qemu-tdx k3s-qemu-snp rke2-qemu-tdx; do
nix run .#scripts.write-coordinator-yaml -- "${coordinatorImgTagged}" "${platform}" > workspace/coordinator-$platform.yml
echo -n "${platform} " >> workspace/coordinator-policy.hash
yq < workspace/coordinator-$platform.yml \
'select(.kind == "StatefulSet") | .spec.template.metadata.annotations["io.katacontainers.config.agent.policy"]' |
base64 -d | sha256sum | cut -d " " -f1 >> workspace/coordinator-policy.hash
nix shell .#contrast --command resourcegen --image-replacements ./image-replacements.txt --platform $platform \
--namespace kube-system runtime > workspace/runtime-$platform.yml
done
nix shell .#contrast --command resourcegen --image-replacements ./image-replacements.txt \
--add-load-balancers emojivoto-sm-ingress > workspace/emojivoto-demo.yml
nix shell .#contrast --command resourcegen --image-replacements ./image-replacements.txt \
--add-load-balancers mysql > workspace/mysql-demo.yml
- name: Update coordinator policy hash
run: |
yq < workspace/coordinator-aks-clh-snp.yml \
'select(.kind == "StatefulSet") | .spec.template.metadata.annotations["io.katacontainers.config.agent.policy"]' |
base64 -d | sha256sum | cut -d " " -f1 > cli/cmd/assets/coordinator-policy-hash
cp image-replacements.txt cli/cmd/assets/image-replacements.txt
git config --global user.name "edgelessci"
git config --global user.email "[email protected]"
git add cli/cmd/assets/coordinator-policy-hash
git add cli/cmd/assets/image-replacements.txt
git diff --staged --quiet || git commit -m "release: update cli assets"
- name: Build CLI
run: |
nix build -L .#cli-release
- name: Upload release artifacts (for main branch PR)
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
with:
name: contrast-release-artifacts
path: |
result-cli/bin/contrast
workspace/coordinator-*.yml
workspace/runtime-*.yml
workspace/emojivoto-demo.yml
workspace/mysql-demo.yml
- name: Create draft release
uses: softprops/action-gh-release@01570a1f39cb168c169c802c3bceb9e93fb10974 # v2.1.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: |
result-cli/bin/contrast
workspace/coordinator-*.yml
workspace/coordinator-policy.hash
workspace/runtime-*.yml
workspace/emojivoto-demo.yml
workspace/mysql-demo.yml
- name: Reset temporary changes
run: |
git reset --hard ${{ needs.process-inputs.outputs.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: AKS-CLH-SNP
runner: ubuntu-22.04
self-hosted: false
- name: K3s-QEMU-SNP
runner: SNP
self-hosted: true
- name: K3s-QEMU-TDX
runner: TDX
self-hosted: true
fail-fast: false
name: "Test on ${{ matrix.platform.name }}"
runs-on: ${{ matrix.platform.runner }}
permissions:
# Job needs content:write to see draft releases.
contents: write
packages: read
needs: release
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- if: ${{ !matrix.platform.self-hosted }}
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@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Azure
if: ${{ !matrix.platform.self-hosted }}
uses: azure/login@a65d910e8af852a8061c627c456678983e180302 # v2.2.0
with:
creds: ${{ secrets.CONTRAST_CI_INFRA_AZURE }}
- if: ${{ !matrix.platform.self-hosted }}
uses: nicknovitski/nix-develop@9be7cfb4b10451d3390a75dc18ad0465bed4932a # v1.2.1
- 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: E2E Test
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
nix shell -L .#contrast.e2e --command release.test -test.v --tag ${{ inputs.version }} --platform ${{ matrix.platform.name }}
create-github-stuff:
name: Create backport label and milestone
if: inputs.kind == 'minor'
needs: process-inputs
runs-on: ubuntu-22.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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ needs.process-inputs.outputs.WORKING_BRANCH }}
- 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'