Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 101 additions & 36 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,61 +2,133 @@ name: Release

on:
push:
branches: [main]
tags: ['v*']
pull_request:
branches: [main]

permissions:
contents: write
packages: write
id-token: write
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false

env:
REGISTRY: ghcr.io
IMAGE: ghcr.io/polarsquad/uck

jobs:
release:
name: Build, sign, publish
runs-on: ubuntu-latest
build:
name: Build ${{ matrix.arch }} (native)
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
- arch: amd64
runner: ubuntu-24.04
- arch: arm64
runner: ubuntu-24.04-arm
permissions:
contents: read
packages: write
steps:
- name: Clone the code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Setup Go
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version-file: go.mod
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@594f3bf4285d9ea8dc53c9a0c9c4092420091003 # v4.4.0

- name: Set up QEMU
uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 # v4.4.0
- name: Log in to the GitHub Container Registry
if: github.ref_type == 'tag'
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
platforms: amd64,arm64
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@594f3bf4285d9ea8dc53c9a0c9c4092420091003 # v4.4.0
- name: Build and push arch image
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
with:
context: .
file: Dockerfile
platforms: linux/${{ matrix.arch }}
push: ${{ github.ref_type == 'tag' }}
provenance: false
sbom: false
tags: ${{ env.IMAGE }}:${{ github.ref_type == 'tag' && format('{0}-linux-{1}', github.ref_name, matrix.arch) || format('{0}-linux-{1}', github.sha, matrix.arch) }}

merge:
name: Merge manifest list
needs: build
if: github.ref_type == 'tag'
runs-on: ubuntu-24.04
permissions:
contents: read
packages: write
outputs:
digest: ${{ steps.publish.outputs.digest }}
steps:
- name: Log in to the GitHub Container Registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push the multi-arch image
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@594f3bf4285d9ea8dc53c9a0c9c4092420091003 # v4.4.0

- name: Create and verify manifest list
id: publish
env:
TAG: ${{ github.ref_name }}
run: |
make docker-buildx IMG=${{ env.IMAGE }}:${TAG} PLATFORMS=linux/amd64,linux/arm64
set -euo pipefail
docker buildx imagetools create \
-t "$IMAGE:$TAG" \
"$IMAGE:$TAG-linux-amd64" \
"$IMAGE:$TAG-linux-arm64"
platforms=$(docker buildx imagetools inspect "$IMAGE:$TAG" \
--format '{{range .Manifest.Manifests}}{{.Platform.OS}}/{{.Platform.Architecture}} {{end}}')
for want in linux/amd64 linux/arm64; do
[[ " $platforms " == *" $want "* ]] || {
echo "::error::missing $want (got: $platforms)"
exit 1
}
done
digest=$(docker buildx imagetools inspect "$IMAGE:$TAG" \
--format '{{.Manifest.Digest}}')
[ -n "$digest" ] || { echo "::error::empty index digest"; exit 1; }
echo "digest=$digest" >> "$GITHUB_OUTPUT"

- name: Capture the image digest
id: digest
run: |
# Top-level (multi-arch) digest, for precise digest-based signing.
# Fallback: if the template yields nothing, we sign by tag below
# (cosign resolves the tag to its digest).
d=$(docker buildx imagetools inspect ${{ env.IMAGE }}:${{ github.ref_name }} --format '{{.Manifest.Digest}}' 2>/dev/null | tail -1 || true)
echo "digest=${d}" >> "$GITHUB_OUTPUT"
release:
name: Sign and publish
needs: merge
if: github.ref_type == 'tag'
runs-on: ubuntu-24.04
permissions:
contents: write
packages: write
id-token: write
steps:
- name: Clone the code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

- name: Setup Go
uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6.3.0
with:
go-version-file: go.mod

- name: Log in to the GitHub Container Registry
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build the consolidated installer
run: make build-installer IMG=${{ env.IMAGE }}:${{ github.ref_name }}
Expand All @@ -65,25 +137,18 @@ jobs:
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2

- name: Sign the image (keyless via GitHub OIDC)
run: |
if [ -n "${{ steps.digest.outputs.digest }}" ]; then
cosign sign --yes ${{ env.IMAGE }}@${{ steps.digest.outputs.digest }}
else
# Fall back to the tag; cosign resolves it to the manifest list.
cosign sign --yes ${{ env.IMAGE }}:${{ github.ref_name }}
fi
env:
DIGEST: ${{ needs.merge.outputs.digest }}
run: cosign sign --yes "$IMAGE@$DIGEST"

- name: Create or update the GitHub release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Re-pointing a tag re-triggers this workflow; in that case the
# release already exists, so attach/replace the asset instead.
if gh release view "${{ github.ref_name }}" >/dev/null 2>&1; then
gh release upload "${{ github.ref_name }}" dist/install.yaml --clobber
else
args=(--generate-notes)
# rc/alpha/beta tags become pre-releases; plain vX.Y.Z are final.
case "${{ github.ref_name }}" in
*rc*|*alpha*|*beta*) args+=(--prerelease) ;;
esac
Expand Down
12 changes: 1 addition & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ run: manifests generate fmt vet ## Run a controller from your host.
# If you wish to build the manager image targeting other platforms you can use the --platform flag.
# (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it.
# More info: https://docs.docker.com/develop/develop-images/build_enhancements/
# Tagged releases are built per architecture on native runners by .github/workflows/release.yml.
.PHONY: docker-build
docker-build: ## Build docker image with the manager.
$(CONTAINER_TOOL) build -t ${IMG} .
Expand All @@ -153,17 +154,6 @@ docker-build: ## Build docker image with the manager.
docker-push: ## Push docker image with the manager.
$(CONTAINER_TOOL) push ${IMG}

# PLATFORMS defines the target platforms for the manager image be built to provide support to multiple
# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to:
# - be able to use docker buildx. More info: https://docs.docker.com/build/buildx/
# - have enabled BuildKit. More info: https://docs.docker.com/develop/develop-images/build_enhancements/
# - be able to push the image to your registry (i.e. if you do not set a valid value via IMG=<myregistry/image:<tag>> then the export will fail)
# To adequately provide solutions that are compatible with multiple platforms, you should consider using this option.
PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le
.PHONY: docker-buildx
docker-buildx: ## Build and push docker image for the manager for cross-platform support
CONTAINER_TOOL="$(CONTAINER_TOOL)" IMG="$(IMG)" PLATFORMS="$(PLATFORMS)" bash hack/build-multiarch.sh

.PHONY: build-installer
build-installer: manifests generate kustomize ## Generate a consolidated YAML with CRDs and deployment.
mkdir -p dist
Expand Down
3 changes: 1 addition & 2 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ spec:
spec:
# TODO(user): Uncomment the following code to configure the nodeAffinity expression
# according to the platforms which are supported by your solution.
# It is considered best practice to support multiple architectures. You can
# build your manager image using the makefile target docker-buildx.
# It is considered best practice to support multiple architectures. Release images are published for linux/amd64 and linux/arm64.
# affinity:
# nodeAffinity:
# requiredDuringSchedulingIgnoredDuringExecution:
Expand Down
11 changes: 7 additions & 4 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,13 @@ the same group.

## Releasing

Releases are cut from tags; the `Release` workflow builds and pushes the
multi-arch image to `ghcr.io/polarsquad/uck`, signs it keylessly, builds
`dist/install.yaml`, and publishes the GitHub release in
`polarsquad/upcloud-operator`. Only releases cut after the rename use the
Releases are cut from tags; the `Release` workflow builds each architecture
(linux/amd64, linux/arm64) on a native runner without QEMU emulation. The
per-arch tags `<tag>-linux-amd64` and `<tag>-linux-arm64` are intermediate
artifacts only; only the `<tag>` manifest index is signed and supported. The
workflow then signs the image keylessly, builds `dist/install.yaml`, and
publishes the GitHub release in `polarsquad/upcloud-operator`.
Only releases cut after the rename use the
UCK image and Kubernetes object names; existing tags are not moved or
republished. Choose a new version for `TAG` below. Before the first UCK
release, confirm GHCR package ownership, Actions write access and public
Expand Down
1 change: 0 additions & 1 deletion docs/migration-to-uck.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ are not republished under the new name.
| UpCloud ownership label | `managed-by=upcloud-operator` | `managed-by=uck` |
| UpCloud HTTP user agent | `upcloud-operator` | `uck` |
| Default smoke-test kind cluster | `upcloud-operator-test-e2e` | `uck-test-e2e` |
| Buildx builder | `upcloud-operator-builder` | `uck-builder` |

Role, ClusterRole, binding, and optional monitoring object names also use
`uck-`. Update external references to those objects, not just the
Expand Down
34 changes: 0 additions & 34 deletions hack/build-multiarch.sh

This file was deleted.

28 changes: 0 additions & 28 deletions test/release/buildx_assertions_test.go

This file was deleted.

66 changes: 0 additions & 66 deletions test/release/buildx_status_test.go

This file was deleted.

Loading
Loading