Skip to content
Merged
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
53 changes: 43 additions & 10 deletions .github/workflows/ci-operator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ name: CI · Operator

on:
push:
branches: [main]
branches: [main, operator]
pull_request:
branches: [main]

Expand Down Expand Up @@ -44,6 +44,7 @@ jobs:
- 'charts/kates/**'
- 'charts/kafka-cluster/**'
- 'config/cluster.yaml'
- 'scripts/deploy-kafka-generic.sh'
- 'versions.env'
- '.github/workflows/ci-operator.yml'

Expand Down Expand Up @@ -84,11 +85,11 @@ jobs:

- name: Generated CRDs are fresh
run: |
cargo run --locked --bin crdgen -- --out crds
if [ -n "$(git status --porcelain crds)" ]; then
git status --porcelain crds
git diff crds
echo "::error::operator/crds is stale: run cargo run --bin crdgen -- --out crds"
cargo run --locked --bin crdgen -- --out chart/crds
if [ -n "$(git status --porcelain chart/crds)" ]; then
git status --porcelain chart/crds
git diff chart/crds
echo "::error::operator/chart/crds is stale: run cargo run --bin crdgen -- --out chart/crds"
exit 1
fi

Expand All @@ -108,7 +109,7 @@ jobs:
set -euo pipefail
schemas="${RUNNER_TEMP}/schemas"
mkdir -p "${schemas}"
yq -o=json '.spec.versions[0].schema.openAPIV3Schema' operator/crds/katestests.kates.io.yaml \
yq -o=json '.spec.versions[0].schema.openAPIV3Schema' operator/chart/crds/katestests.kates.io.yaml \
| jq '.properties.spec |= walk(if type == "object" and (.properties | type) == "object"
then . + {additionalProperties: false} else . end)' \
> "${schemas}/katestest_v1alpha1.json"
Expand All @@ -123,15 +124,29 @@ jobs:
fi

e2e:
name: CRDs on Kind
name: E2E on Kind
needs: changes
if: needs.changes.outputs.e2e == 'true'
runs-on: ubuntu-latest
timeout-minutes: 15
timeout-minutes: 45
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/load-versions

- uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1
with:
version: ${{ env.HELM_VERSION }}

# deploy-kafka-generic.sh detects the cluster with it.
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
with:
go-version-file: cli/go.mod
cache-dependency-path: cli/go.sum

- name: Build kates CLI
working-directory: cli
run: go build -o ../build/kates .

# node_image is deliberately not passed, as in integration.yml:
# config/cluster.yaml names the image.
- name: Create Kind cluster
Expand All @@ -146,7 +161,25 @@ jobs:
# The apiserver is the only CEL compiler, cost and oldSelf-correlatability
# checker there is.
- name: The apiserver accepts the CRDs
run: kubectl apply --dry-run=server -f operator/crds
run: kubectl apply --dry-run=server -f operator/chart/crds

- name: Build the operator image
run: |
docker build -f operator/Dockerfile -t kates-operator:ci .
kind load docker-image kates-operator:ci --name ci-test

- name: Deploy Kafka, Kates and the operator
run: operator/e2e-stack.sh docker.io/library/kates-operator:ci

- name: Run the e2e checks
run: operator/e2e.sh payments kafka krafter

- name: Show the stack
if: failure()
run: |
kubectl get pods -A
kubectl -n kates logs deploy/kates -c kates --tail=50 || true
kubectl -n kates-operator logs deploy/kates-operator --tail=50 || true

gate:
name: Gate · Operator
Expand Down
133 changes: 133 additions & 0 deletions .github/workflows/publish-operator.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
name: Publish · Operator

# The operator's image and chart, on an operator-v<version> tag. It lives apart
# from release.yml on purpose: the operator ships on its own versions, and a
# v* Kates release never sees it.

on:
push:
tags:
- "operator-v*"

permissions:
contents: read

concurrency:
group: publish-operator-${{ github.ref }}
cancel-in-progress: false

env:
IMAGE: ghcr.io/bmscomp/kates-operator
CHART_REGISTRY: oci://ghcr.io/bmscomp/charts
# github.ref, so a signature names this tag, as publish-charts.yml's do.
IDENTITY: https://github.com/${{ github.repository }}/.github/workflows/publish-operator.yml@${{ github.ref }}
ISSUER: https://token.actions.githubusercontent.com

jobs:
check:
name: Tag matches the chart
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- id: version
run: |
set -euo pipefail
version=${GITHUB_REF_NAME#operator-v}
chart=$(yq .version operator/chart/Chart.yaml)
app=$(yq .appVersion operator/chart/Chart.yaml)
if [ "${version}" != "${chart}" ] || [ "${version}" != "${app}" ]; then
echo "::error::tag ${version}, chart ${chart}, appVersion ${app}: all three must match"
exit 1
fi
echo "version=${version}" >> "${GITHUB_OUTPUT}"

build:
name: Build (${{ matrix.arch }})
needs: check
runs-on: ${{ matrix.runner }}
timeout-minutes: 45
permissions:
contents: read
packages: write
strategy:
matrix:
include:
- {arch: amd64, runner: ubuntu-latest}
- {arch: arm64, runner: ubuntu-24.04-arm}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
with:
context: .
file: operator/Dockerfile
platforms: linux/${{ matrix.arch }}
push: true
tags: ${{ env.IMAGE }}:sha-${{ github.sha }}-${{ matrix.arch }}
provenance: mode=max
sbom: true

publish:
name: Merge, sign, push the chart
needs: [check, build]
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
packages: write
id-token: write # cosign keyless signing
env:
VERSION: ${{ needs.check.outputs.version }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: ./.github/actions/load-versions
- uses: azure/setup-helm@9bc31f4ebc9c6b171d7bfbaa5d006ae7abdb4310 # v5.0.1
with:
version: ${{ env.HELM_VERSION }}
- uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
- uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Helm logs in
env:
TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: helm registry login ghcr.io -u "${GITHUB_ACTOR}" --password-stdin <<<"${TOKEN}"

- name: Merge and sign the image
run: |
set -euo pipefail
docker buildx imagetools create -t "${IMAGE}:${VERSION}" \
"${IMAGE}:sha-${GITHUB_SHA}-amd64" "${IMAGE}:sha-${GITHUB_SHA}-arm64"
digest=$(docker buildx imagetools inspect "${IMAGE}:${VERSION}" --format '{{json .Manifest.Digest}}' | tr -d '"')
cosign sign --yes "${IMAGE}@${digest}"
cosign verify "${IMAGE}@${digest}" --certificate-identity "${IDENTITY}" \
--certificate-oidc-issuer "${ISSUER}" > /dev/null

- name: Push and sign the chart
run: |
set -euo pipefail
# helm package is not reproducible: a re-run would replace a digest
# someone may already pin, so a published version is never pushed again.
if helm show chart "${CHART_REGISTRY}/kates-operator" --version "${VERSION}" > /dev/null 2>&1; then
echo "kates-operator ${VERSION} is already published"
exit 0
fi
helm package operator/chart --destination .build/
out=$(helm push ".build/kates-operator-${VERSION}.tgz" "${CHART_REGISTRY}" 2>&1)
echo "${out}"
digest=$(sed -n 's/^Digest: //p' <<<"${out}")
repo=ghcr.io/bmscomp/charts/kates-operator
cosign sign --yes "${repo}@${digest}"
cosign verify "${repo}@${digest}" --certificate-identity "${IDENTITY}" \
--certificate-oidc-issuer "${ISSUER}" > /dev/null
Loading
Loading