Skip to content

Add ProviderConfig/annotation-driven connection secret key renaming and field addition #3374

Add ProviderConfig/annotation-driven connection secret key renaming and field addition

Add ProviderConfig/annotation-driven connection secret key renaming and field addition #3374

Workflow file for this run

name: CI
on:
push:
branches:
- main
- release-*
pull_request: {}
workflow_dispatch: {}
env:
# Common versions
GO_VERSION: '1.26.6'
GOLANGCI_VERSION: 'v2.12.2'
DOCKER_BUILDX_VERSION: 'v0.22.0'
UP_VERSION: 'v0.38.4'
# Registry/Org names
CROSSPLANE_REGORG: 'ghcr.io/crossplane-contrib' # xpkg.crossplane.io/crossplane-contrib
UPBOUND_REGORG: 'xpkg.upbound.io/crossplane-contrib'
PROVIDER_REPO: provider-keycloak
# Upbound registry specific variables
UP_DOMAIN: "https://upbound.io"
# Common users. We can't run a step 'if secrets.XXX != ""' but we can run a
# step 'if env.XXX != ""', so we copy these to succinctly test whether
# credentials have been provided before trying to run steps that need them.
UPBOUND_MARKETPLACE_PUSH_ROBOT_USR: ${{ secrets.UPBOUND_MARKETPLACE_PUSH_ROBOT_USR }}
jobs:
detect-noop:
runs-on: ubuntu-24.04
outputs:
noop: ${{ steps.noop.outputs.should_skip }}
# true only when BOTH e2e suites are skipped (gates the provider build)
skip-e2e: ${{ steps.e2e-scope.outputs.skip }}
# DAG-derived e2e tier + Keycloak matrix (the demo subset itself is
# recomputed in the e2e-tests job so it is visible per run)
e2e-tier: ${{ steps.e2e-scope.outputs.tier }}
e2e-keycloak-versions: ${{ steps.e2e-scope.outputs.keycloak_versions }}
# FGAPv2 suite runs in its own cluster and is selected independently
e2e-fgapv2: ${{ steps.e2e-scope.outputs.fgapv2 }}
steps:
- name: Detect No-op Changes
id: noop
uses: fkirc/skip-duplicate-actions@b974a9395958c231af965b70070979a577efa578 # v5.3.2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
paths_ignore: '["**.md", "**.png", "**.jpg"]'
do_not_skip: '["workflow_dispatch", "schedule", "push"]'
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
- name: Compute E2E scope via DAG
id: e2e-scope
run: |
# Full Keycloak version matrix (all supported releases)
ALL_VERSIONS='["26.7.0","26.6.2","26.5.1","26.4.4","26.3.5","26.2.5","26.1.5","26.0.8"]'
LATEST_VERSION='["26.7.0"]'
COMMIT_MESSAGE=$(git log -1 --pretty=%B)
if echo "$COMMIT_MESSAGE" | grep -iq "\[skip e2e\]"; then
echo "skip=true" >> "$GITHUB_OUTPUT"
echo "tier=skip" >> "$GITHUB_OUTPUT"
echo "keycloak_versions=[]" >> "$GITHUB_OUTPUT"
echo "fgapv2=false" >> "$GITHUB_OUTPUT"
echo "[skip e2e] found in commit message — skipping all e2e tests"
exit 0
fi
# On non-PR events (push to main, workflow_dispatch) always run full
if [ "${{ github.event_name }}" != "pull_request" ]; then
echo "skip=false" >> "$GITHUB_OUTPUT"
echo "tier=full" >> "$GITHUB_OUTPUT"
echo "keycloak_versions=${ALL_VERSIONS}" >> "$GITHUB_OUTPUT"
echo "fgapv2=true" >> "$GITHUB_OUTPUT"
echo "Non-PR event — running full e2e suite against all Keycloak versions"
exit 0
fi
# Compute changed files for the PR, always relative to main
git fetch --no-tags origin main:refs/remotes/origin/main
MERGE_BASE=$(git merge-base origin/main HEAD)
echo "Comparing against main (merge base ${MERGE_BASE})"
CHANGED_FILES=$(git diff --name-only "${MERGE_BASE}" HEAD)
echo "Changed files:"
echo "$CHANGED_FILES"
# Use the DAG script to determine tier + demo subset. The proof
# (which changed file matched which rule, and why each demo was
# selected) is written to the job summary.
TIER=$(echo "$CHANGED_FILES" | \
python3 scripts/e2e_dag.py select --changed-files - \
--proof-file /tmp/e2e_proof.md 2>/tmp/e2e_dag_stderr.txt)
cat /tmp/e2e_dag_stderr.txt
cat /tmp/e2e_proof.md >> "$GITHUB_STEP_SUMMARY"
echo "DAG stdout (tier/list): $TIER"
# The FGAPv2 suite runs in its own cluster (admin-fine-grained-authz:v2
# excludes the v1 feature the regular suite needs), so it is selected
# independently of the regular suite.
FGAPV2=$(echo "$CHANGED_FILES" | \
python3 scripts/e2e_dag.py select-fgapv2 --changed-files - \
--proof-file /tmp/e2e_proof_fgapv2.md 2>/tmp/e2e_dag_fgapv2_stderr.txt)
cat /tmp/e2e_dag_fgapv2_stderr.txt
cat /tmp/e2e_proof_fgapv2.md >> "$GITHUB_STEP_SUMMARY"
echo "DAG stdout (fgapv2): $FGAPV2"
if [ "$FGAPV2" = "run" ]; then
echo "fgapv2=true" >> "$GITHUB_OUTPUT"
else
echo "fgapv2=false" >> "$GITHUB_OUTPUT"
fi
if [ "$TIER" = "skip" ]; then
# Only skip the provider build when neither suite has anything to run
if [ "$FGAPV2" = "run" ]; then
echo "skip=false" >> "$GITHUB_OUTPUT"
else
echo "skip=true" >> "$GITHUB_OUTPUT"
fi
echo "tier=skip" >> "$GITHUB_OUTPUT"
echo "keycloak_versions=[]" >> "$GITHUB_OUTPUT"
echo "No e2e-relevant changes for the regular suite — skipping it"
elif [ "$TIER" = "full" ]; then
echo "skip=false" >> "$GITHUB_OUTPUT"
echo "tier=full" >> "$GITHUB_OUTPUT"
echo "keycloak_versions=${ALL_VERSIONS}" >> "$GITHUB_OUTPUT"
echo "Full tier — running all demos against all Keycloak versions"
else
# targeted: TIER contains a comma-separated list of demo paths
echo "skip=false" >> "$GITHUB_OUTPUT"
echo "tier=targeted" >> "$GITHUB_OUTPUT"
echo "keycloak_versions=${LATEST_VERSION}" >> "$GITHUB_OUTPUT"
DEMO_COUNT=$(echo "$TIER" | tr ',' '\n' | wc -l)
echo "Targeted tier — running ${DEMO_COUNT} demos against latest Keycloak only"
fi
lint:
runs-on: ubuntu-24.04
needs: detect-noop
if: needs.detect-noop.outputs.noop != 'true'
steps:
- name: Free disk space
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1
with:
tool-cache: false
android: true
dotnet: true
haskell: true
large-packages: true
docker-images: true
swap-storage: true
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
submodules: true
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: ${{ env.GO_VERSION }}
- name: Find the Go Build Cache
id: go
run: echo "cache=$(make go.cachedir)" >> $GITHUB_OUTPUT
- name: Cache the Go Build Cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: ${{ steps.go.outputs.cache }}
key: ${{ runner.os }}-build-lint-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-build-lint-
- name: Cache Go Dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .work/pkg
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-pkg-
- name: Cache Build Tools
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .cache/tools
key: ${{ runner.os }}-${{ runner.arch }}-tools-${{ hashFiles('Makefile', 'build/makelib/**/*.mk') }}
restore-keys: ${{ runner.os }}-${{ runner.arch }}-tools-
- name: Vendor Dependencies
run: make vendor vendor.check
# We could run 'make lint' but we prefer this action because it leaves
# 'annotations' (i.e. it comments on PRs to point out linter violations).
- name: Lint
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9
with:
version: ${{ env.GOLANGCI_VERSION }}
verify: false
check-diff:
runs-on: ubuntu-24.04
needs: detect-noop
if: needs.detect-noop.outputs.noop != 'true'
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
submodules: true
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: ${{ env.GO_VERSION }}
- name: Install goimports
run: go install golang.org/x/tools/cmd/goimports@latest
- name: Find the Go Build Cache
id: go
run: echo "cache=$(make go.cachedir)" >> $GITHUB_OUTPUT
- name: Cache the Go Build Cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: ${{ steps.go.outputs.cache }}
key: ${{ runner.os }}-build-check-diff-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-build-check-diff-
- name: Cache Go Dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .work/pkg
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-pkg-
- name: Cache Build Tools
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .cache/tools
key: ${{ runner.os }}-${{ runner.arch }}-tools-${{ hashFiles('Makefile', 'build/makelib/**/*.mk') }}
restore-keys: ${{ runner.os }}-${{ runner.arch }}-tools-
- name: Vendor Dependencies
run: make vendor vendor.check
- name: Validate E2E Case Coverage
run: make e2e-cases-check
- name: Check config/generated.lst Freshness
run: make generated-lst-check
- name: Check Diff
run: make check-diff
unit-tests:
runs-on: ubuntu-24.04
needs: detect-noop
if: needs.detect-noop.outputs.noop != 'true'
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
submodules: true
- name: Fetch History
run: git fetch --prune --tags --unshallow || git fetch --prune --tags
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: ${{ env.GO_VERSION }}
- name: Find the Go Build Cache
id: go
run: echo "cache=$(make go.cachedir)" >> $GITHUB_OUTPUT
- name: Cache the Go Build Cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: ${{ steps.go.outputs.cache }}
key: ${{ runner.os }}-build-unit-tests-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-build-unit-tests-
- name: Cache Go Dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .work/pkg
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-pkg-
- name: Cache Build Tools
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .cache/tools
key: ${{ runner.os }}-${{ runner.arch }}-tools-${{ hashFiles('Makefile', 'build/makelib/**/*.mk') }}
restore-keys: ${{ runner.os }}-${{ runner.arch }}-tools-
- name: Vendor Dependencies
run: make vendor vendor.check
- name: Run Unit Tests
run: make -j2 test
- name: Publish Unit Test Coverage
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7
with:
flags: unittests
file: _output/tests/linux_amd64/coverage.txt
local-deploy:
runs-on: ubuntu-24.04
needs: detect-noop
if: needs.detect-noop.outputs.noop != 'true'
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
submodules: true
- name: Fetch History
run: git fetch --prune --tags --unshallow || git fetch --prune --tags
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: ${{ env.GO_VERSION }}
- name: Find the Go Build Cache
id: go
run: echo "cache=$(make go.cachedir)" >> $GITHUB_OUTPUT
- name: Cache the Go Build Cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: ${{ steps.go.outputs.cache }}
key: ${{ runner.os }}-build-unit-tests-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-build-unit-tests-
- name: Cache Go Dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .work/pkg
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-pkg-
- name: Cache Build Tools
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .cache/tools
key: ${{ runner.os }}-${{ runner.arch }}-tools-${{ hashFiles('Makefile', 'build/makelib/**/*.mk') }}
restore-keys: ${{ runner.os }}-${{ runner.arch }}-tools-
- name: Vendor Dependencies
run: make vendor vendor.check
- name: Deploying locally built provider package
run: make local-deploy
build-provider:
runs-on: ubuntu-24.04
needs: detect-noop
if: needs.detect-noop.outputs.noop != 'true' && needs.detect-noop.outputs.skip-e2e != 'true'
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
submodules: true
- name: Fetch History
run: git fetch --prune --unshallow
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: ${{ env.GO_VERSION }}
- name: Find the Go Build Cache
id: go
run: echo "cache=$(make go.cachedir)" >> $GITHUB_OUTPUT
- name: Cache the Go Build Cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: ${{ steps.go.outputs.cache }}
key: ${{ runner.os }}-build-e2e-provider-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-build-e2e-provider-
- name: Cache Go Dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .work/pkg
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-pkg-
- name: Cache Build Tools
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .cache/tools
key: ${{ runner.os }}-${{ runner.arch }}-tools-${{ hashFiles('Makefile', 'build/makelib/**/*.mk') }}
restore-keys: ${{ runner.os }}-${{ runner.arch }}-tools-
- name: Vendor Dependencies
run: make vendor vendor.check
- name: Build Provider
run: make build BUILD_REGISTRY=ci-build
- name: Export Provider Image
run: |
docker save ci-build/provider-keycloak-amd64 -o /tmp/provider-image.tar
- name: Upload Provider Image
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: provider-image
path: /tmp/provider-image.tar
retention-days: 7
- name: Upload Provider Package
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: provider-xpkg
path: _output/xpkg/linux_amd64/
retention-days: 7
e2e-tests:
runs-on: ubuntu-24.04
needs: [detect-noop, build-provider]
if: needs.detect-noop.outputs.noop != 'true' && needs.detect-noop.outputs.e2e-tier != 'skip'
concurrency:
group: ${{ github.head_ref || github.run_id }}-${{ matrix.keycloak-version }}
cancel-in-progress: true
strategy:
fail-fast: false
matrix:
keycloak-version: ${{ fromJSON(needs.detect-noop.outputs.e2e-keycloak-versions) }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
submodules: true
- name: Fetch History
run: git fetch --prune --unshallow
- name: Calculate E2E test selection
id: select
shell: bash
env:
E2E_TIER: ${{ needs.detect-noop.outputs.e2e-tier }}
run: |
set -o pipefail
if [ "${E2E_TIER}" != "targeted" ]; then
echo "demos=" >> "$GITHUB_OUTPUT"
echo "### E2E selection: ${E2E_TIER} — running all demos" >> "$GITHUB_STEP_SUMMARY"
exit 0
fi
# Always compare against main
git fetch --no-tags origin main:refs/remotes/origin/main
MERGE_BASE=$(git merge-base origin/main HEAD)
echo "Comparing against main (merge base ${MERGE_BASE})"
DEMOS=$(git diff --name-only "${MERGE_BASE}" HEAD | \
python3 scripts/e2e_dag.py select --changed-files - \
--proof-file /tmp/e2e_proof.md)
# Always publish the proof: which file matched which rule, and why
# each demo ended up in the selection.
cat /tmp/e2e_proof.md >> "$GITHUB_STEP_SUMMARY"
if [ "${DEMOS}" = "full" ] || [ "${DEMOS}" = "skip" ] || [ -z "${DEMOS}" ]; then
echo "demos=" >> "$GITHUB_OUTPUT"
echo "### E2E selection: fallback — running all demos" >> "$GITHUB_STEP_SUMMARY"
exit 0
fi
echo "demos=${DEMOS}" >> "$GITHUB_OUTPUT"
echo "${DEMOS}" | tr ',' '\n'
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: ${{ env.GO_VERSION }}
- name: Find the Go Build Cache
id: go
run: echo "cache=$(make go.cachedir)" >> $GITHUB_OUTPUT
- name: Cache the Go Build Cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: ${{ steps.go.outputs.cache }}
key: ${{ runner.os }}-build-unit-tests-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-build-unit-tests-
- name: Cache Go Dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .work/pkg
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-pkg-
- name: Cache Build Tools
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .cache/tools
key: ${{ runner.os }}-${{ runner.arch }}-tools-${{ hashFiles('Makefile', 'build/makelib/**/*.mk') }}
restore-keys: ${{ runner.os }}-${{ runner.arch }}-tools-
- name: Vendor Dependencies
run: make vendor vendor.check
- name: Download Provider Image
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: provider-image
path: /tmp
- name: Download Provider Package
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: provider-xpkg
path: _output/xpkg/linux_amd64/
- name: Load Provider Image
run: docker load -i /tmp/provider-image.tar
- name: Pre-pull container images
run: |
docker pull quay.io/keycloak/keycloak:${{ matrix.keycloak-version }} &
docker pull docker.io/bitnamilegacy/openldap:2.6.10 &
wait
- name: Starting testsetup for E2E Tests
id: setup
continue-on-error: true
run: |
set -o pipefail
mkdir -p logs
./dev/setup_dev_environment.sh --cluster-name fenrir-1 --deploy-local-provider --direct-helm --keycloak-version ${{ matrix.keycloak-version }} | tee logs/setup-environment.log
env:
PROVIDER_PREBUILT: "true"
- name: Collect setup logs
if: steps.setup.outcome == 'failure'
shell: bash
run: |
kind export kubeconfig --name fenrir-1 || true
./dev/collect-logs.sh || true
- name: Upload setup logs
if: steps.setup.outcome == 'failure'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: e2e-setup-logs-${{ matrix.keycloak-version }}
path: |
logs/
- name: Fail on setup error
if: steps.setup.outcome == 'failure'
run: exit 1
- name: Verify kind cluster exists
run: |
echo "Checking for kind cluster fenrir-1..."
kind get clusters
if ! kind get clusters | grep -q "fenrir-1"; then
echo "ERROR: kind cluster fenrir-1 was not created"
exit 1
fi
- name: Set kind cluster as context
run: kind export kubeconfig --name fenrir-1
- name: Running E2E Tests
id: e2eTests
continue-on-error: true
shell: bash
env:
KEYCLOAK_VERSION: ${{ matrix.keycloak-version }}
E2E_DEMO_LIST: ${{ steps.select.outputs.demos }}
E2E_TIER: ${{ needs.detect-noop.outputs.e2e-tier }}
run: |
set -o pipefail
echo "E2E tier: ${E2E_TIER}"
if [ -n "${E2E_DEMO_LIST}" ]; then
echo "Targeted mode: running $(echo "${E2E_DEMO_LIST}" | tr ',' '\n' | wc -l) demos"
make uptest KEYCLOAK_VERSION="${KEYCLOAK_VERSION}" UPTEST_EXAMPLE_LIST="${E2E_DEMO_LIST}" | tee logs/uptest.log
else
echo "Full mode: running all demos"
make uptest KEYCLOAK_VERSION="${KEYCLOAK_VERSION}" | tee logs/uptest.log
fi
- name: Collect logs
if: steps.e2eTests.outcome == 'failure'
shell: bash
run: ./dev/collect-logs.sh
- name: Upload logs
if: steps.e2eTests.outcome == 'failure'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: e2e-logs-${{ matrix.keycloak-version }}
path: |
logs/
- name: Fail on error
if: steps.e2eTests.outcome == 'failure'
run: exit 1
# Controller-focused e2e tests using Kyverno chainsaw directly.
# These exercise hand-written controllers (currently: connectionsecrettransform)
# in a real kind cluster with Keycloak and the provider running, and with
# Envoy Gateway + Traefik deployed as actual OIDC consumers that validate
# the secrets the controller produces.
#
# Runs on every PR against main when the controller code or tests change.
# Always runs on push to main.
e2e-controller-tests:
runs-on: ubuntu-24.04
needs: [detect-noop, build-provider]
if: needs.detect-noop.outputs.noop != 'true'
concurrency:
group: ${{ github.head_ref || github.run_id }}-controller-e2e
cancel-in-progress: true
permissions:
contents: read
env:
CONTROLLER_E2E_KEYCLOAK_VERSION: "26.7.0"
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
submodules: true
- name: Fetch History
run: git fetch --prune --unshallow
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: ${{ env.GO_VERSION }}
- name: Find the Go Build Cache
id: go
run: echo "cache=$(make go.cachedir)" >> $GITHUB_OUTPUT
- name: Cache the Go Build Cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: ${{ steps.go.outputs.cache }}
key: ${{ runner.os }}-build-controller-e2e-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-build-controller-e2e-
- name: Cache Go Dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .work/pkg
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-pkg-
- name: Cache Build Tools
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .cache/tools
key: ${{ runner.os }}-${{ runner.arch }}-tools-${{ hashFiles('Makefile', 'build/makelib/**/*.mk') }}
restore-keys: ${{ runner.os }}-${{ runner.arch }}-tools-
- name: Vendor Dependencies
run: make vendor vendor.check
- name: Download Provider Image
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: provider-image
path: /tmp
- name: Download Provider Package
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: provider-xpkg
path: _output/xpkg/linux_amd64/
- name: Load Provider Image
run: docker load -i /tmp/provider-image.tar
- name: Pull Keycloak Image
run: docker pull quay.io/keycloak/keycloak:${{ env.CONTROLLER_E2E_KEYCLOAK_VERSION }}
- name: Starting test environment
id: setup
continue-on-error: true
run: |
set -o pipefail
mkdir -p logs
./dev/setup_dev_environment.sh \
--cluster-name fenrir-1 \
--deploy-local-provider \
--direct-helm \
--keycloak-version ${{ env.CONTROLLER_E2E_KEYCLOAK_VERSION }} \
| tee logs/setup-environment.log
env:
PROVIDER_PREBUILT: "true"
- name: Collect setup logs on failure
if: steps.setup.outcome == 'failure'
run: |
kind export kubeconfig --name fenrir-1 || true
./dev/collect-logs.sh || true
- name: Upload setup logs
if: steps.setup.outcome == 'failure'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: controller-e2e-setup-logs
path: logs/
- name: Fail on setup error
if: steps.setup.outcome == 'failure'
run: exit 1
- name: Set kind cluster as context
run: kind export kubeconfig --name fenrir-1
- name: Running controller e2e tests
id: controllerE2e
continue-on-error: true
run: |
set -o pipefail
make controller-e2e | tee logs/controller-e2e.log
- name: Collect controller e2e logs on failure
if: steps.controllerE2e.outcome == 'failure'
run: |
kind export kubeconfig --name fenrir-1 || true
./dev/collect-logs.sh || true
- name: Upload controller e2e logs
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: controller-e2e-logs
path: logs/
- name: Fail on test error
if: steps.controllerE2e.outcome == 'failure'
run: exit 1
# Fine-grained admin permissions v2 (FGAPv2) resources need Keycloak to run
# with the admin-fine-grained-authz:v2 feature. That feature replaces the v1
# feature the regular e2e suite depends on, so these demos get their own
# cluster and only run the cases listed in cluster/test/cases-fgapv2.txt.
e2e-tests-fgapv2:
runs-on: ubuntu-24.04
needs: [detect-noop, build-provider]
if: needs.detect-noop.outputs.noop != 'true' && needs.detect-noop.outputs.e2e-fgapv2 == 'true'
concurrency:
group: ${{ github.head_ref || github.run_id }}-fgapv2
cancel-in-progress: true
permissions:
contents: read
env:
FGAP_KEYCLOAK_VERSION: "26.7.0"
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
submodules: true
- name: Fetch History
run: git fetch --prune --unshallow
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: ${{ env.GO_VERSION }}
- name: Find the Go Build Cache
id: go
run: echo "cache=$(make go.cachedir)" >> $GITHUB_OUTPUT
- name: Cache the Go Build Cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: ${{ steps.go.outputs.cache }}
key: ${{ runner.os }}-build-unit-tests-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-build-unit-tests-
- name: Cache Go Dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .work/pkg
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-pkg-
- name: Cache Build Tools
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .cache/tools
key: ${{ runner.os }}-${{ runner.arch }}-tools-${{ hashFiles('Makefile', 'build/makelib/**/*.mk') }}
restore-keys: ${{ runner.os }}-${{ runner.arch }}-tools-
- name: Vendor Dependencies
run: make vendor vendor.check
- name: Download Provider Image
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: provider-image
path: /tmp
- name: Download Provider Package
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
name: provider-xpkg
path: _output/xpkg/linux_amd64/
- name: Load Provider Image
run: docker load -i /tmp/provider-image.tar
- name: Pre-pull container images
run: docker pull quay.io/keycloak/keycloak:${{ env.FGAP_KEYCLOAK_VERSION }}
- name: Starting testsetup for E2E Tests
id: setup
continue-on-error: true
run: |
set -o pipefail
mkdir -p logs
./dev/setup_dev_environment.sh --cluster-name fenrir-1 --deploy-local-provider --direct-helm --keycloak-version ${{ env.FGAP_KEYCLOAK_VERSION }} --fgap-version v2 | tee logs/setup-environment.log
env:
PROVIDER_PREBUILT: "true"
- name: Collect setup logs
if: steps.setup.outcome == 'failure'
shell: bash
run: |
kind export kubeconfig --name fenrir-1 || true
./dev/collect-logs.sh || true
- name: Upload setup logs
if: steps.setup.outcome == 'failure'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: e2e-setup-logs-fgapv2
path: |
logs/
- name: Fail on setup error
if: steps.setup.outcome == 'failure'
run: exit 1
- name: Set kind cluster as context
run: kind export kubeconfig --name fenrir-1
- name: Running E2E Tests
id: e2eTests
continue-on-error: true
shell: bash
run: |
set -o pipefail
make uptest KEYCLOAK_VERSION="${{ env.FGAP_KEYCLOAK_VERSION }}" FGAP_VERSION=v2 | tee logs/uptest.log
- name: Collect logs
if: steps.e2eTests.outcome == 'failure'
shell: bash
run: ./dev/collect-logs.sh
- name: Upload logs
if: steps.e2eTests.outcome == 'failure'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: e2e-logs-fgapv2
path: |
logs/
- name: Fail on error
if: steps.e2eTests.outcome == 'failure'
run: exit 1
publish-artifacts:
runs-on: ubuntu-24.04
needs: [detect-noop, lint, check-diff, unit-tests, local-deploy, e2e-tests, e2e-tests-fgapv2]
if: |
needs.detect-noop.outputs.noop != 'true' && needs.lint.result == 'success' && needs.check-diff.result == 'success' && needs.unit-tests.result == 'success' && needs.local-deploy.result == 'success' &&
(always() && (needs.e2e-tests.result == 'success' || needs.e2e-tests.result == 'skipped' || needs.detect-noop.outputs.skip-e2e == 'true')) &&
(always() && (needs.e2e-tests-fgapv2.result == 'success' || needs.e2e-tests-fgapv2.result == 'skipped' || needs.detect-noop.outputs.skip-e2e == 'true'))
outputs:
version: ${{ steps.version.outputs.VERSION }}
permissions:
packages: write
contents: read
attestations: write
id-token: write
steps:
- name: Setup QEMU
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4
with:
platforms: all
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
with:
version: ${{ env.DOCKER_BUILDX_VERSION }}
install: true
- name: Login to GHCR using PAT
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
submodules: true
- name: Fetch History
run: git fetch --prune --unshallow
- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7
with:
go-version: ${{ env.GO_VERSION }}
- name: Find the Go Build Cache
id: go
run: echo "cache=$(make go.cachedir)" >> $GITHUB_OUTPUT
- name: Find the version
id: version
run: make common.buildvars >> $GITHUB_OUTPUT
- name: Cache the Go Build Cache
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: ${{ steps.go.outputs.cache }}
key: ${{ runner.os }}-build-publish-artifacts-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-build-publish-artifacts-
- name: Cache Go Dependencies
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .work/pkg
key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }}
restore-keys: ${{ runner.os }}-pkg-
- name: Cache Build Tools
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
with:
path: .cache/tools
key: ${{ runner.os }}-${{ runner.arch }}-tools-${{ hashFiles('Makefile', 'build/makelib/**/*.mk') }}
restore-keys: ${{ runner.os }}-${{ runner.arch }}-tools-
- name: Vendor Dependencies
run: make vendor vendor.check
- name: Build Artifacts
run: |-
make -j2 XPKG_REG_ORGS="${{ env.CROSSPLANE_REGORG }}" XPKG_REG_ORGS_NO_PROMOTE="${{ env.CROSSPLANE_REGORG }}" BRANCH_NAME="main" VERSION="${{ steps.version.outputs.VERSION }}" build.all
env:
# We're using docker buildx, which doesn't actually load the images it
# builds by default. Specifying --load does so.
BUILD_ARGS: "--load --cache-from type=gha --cache-to type=gha,mode=max"
- name: Upload Artifacts to GitHub
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: output
path: _output/**
- name: Publish Artifacts
run: |-
make -j2 XPKG_REG_ORGS="${{ env.CROSSPLANE_REGORG }}" XPKG_REG_ORGS_NO_PROMOTE="${{ env.CROSSPLANE_REGORG }}" BRANCH_NAME="main" VERSION="${{ steps.version.outputs.VERSION }}" publish
mirror-to-xpkg-upbound-io:
needs: publish-artifacts
runs-on: ubuntu-24.04
steps:
- name: Setup QEMU
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4
with:
platforms: all
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
with:
version: ${{ env.DOCKER_BUILDX_VERSION }}
install: true
- name: Setup crane
# crane will inherit credentials from `docker login`
uses: imjasonh/setup-crane@feee3b6bb0d4c68370f256a4502498c9227e5c6b # v0.7
- name: Validate crane installation
run: crane version
- name: Login to Upbound
uses: docker/login-action@ba754150c9dbbaa912ae0ac3cfba43f84195cef2
with:
registry: "xpkg.upbound.io"
username: ${{ secrets.UPBOUND_MARKETPLACE_PUSH_ROBOT_USR }}
password: ${{ secrets.UPBOUND_MARKETPLACE_PUSH_ROBOT_PSW }}
- name: Mirror to xpkg.upbound.io
run: |
crane copy ${{ env.CROSSPLANE_REGORG }}/${{ env.PROVIDER_REPO }}:${{ needs.publish-artifacts.outputs.version }} ${{ env.UPBOUND_REGORG }}/${{ env.PROVIDER_REPO }}:${{ needs.publish-artifacts.outputs.version }} --allow-nondistributable-artifacts