build-images #3352
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| --- | |
| # desc: build container images, perform static tests then publish | |
| name: build-images | |
| on: | |
| push: | |
| branches: | |
| - '**' | |
| tags: | |
| - keycloak-[0-9]+-[0-9]+-[0-9]+-[0-9]+-[0-9]+ # `keycloak-23-yyyy-mm-dd-xxx`: only keycloak 23 | |
| - '[0-9]+-[0-9]+-[0-9]+-[0-9]+' # `yyyy-mm-dd-xxx`: all keycloak versions | |
| schedule: | |
| - cron: 0 3 * * * | |
| workflow_dispatch: | |
| inputs: | |
| notify_back_error_message: | |
| description: \ Error message if retry was not successful. This parameter is used for internal call back actions. | |
| required: false | |
| default: '' | |
| env: | |
| # Public registry available on docker hub | |
| CONTAINER_REGISTRY_HUB: docker.io | |
| CONTAINER_IMAGE_NAME_HUB: camunda/keycloak | |
| # Enterprise registry available for customers | |
| CONTAINER_REGISTRY_CAMUNDA: registry.camunda.cloud | |
| CONTAINER_IMAGE_NAME_CAMUNDA: keycloak-ee/keycloak | |
| # Internal registry only used for ci tests | |
| CONTAINER_REGISTRY_CI: registry.camunda.cloud | |
| CONTAINER_IMAGE_NAME_CI: team-infrastructure-experience/keycloak | |
| jobs: | |
| triage: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Display notify_back_error_message if present | |
| if: ${{ inputs.notify_back_error_message != '' }} | |
| run: | | |
| echo "A previous workflow failed but has attempted to retry: ${{ inputs.notify_back_error_message }}" | |
| exit 1 | |
| list-keycloak-versions: | |
| runs-on: ubuntu-24.04 | |
| needs: | |
| - triage | |
| outputs: | |
| matrix_keycloak_versions: ${{ steps.set-matrix.outputs.matrix_keycloak_versions }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: List Keycloak Versions from repository's folders | |
| id: set-matrix | |
| run: | | |
| set -euo pipefail | |
| : # if we release a specified version of keycloak, the matrix should only contain it | |
| if [[ $GITHUB_REF =~ ^refs/tags/keycloak-([0-9]+)- ]]; then | |
| keycloak_version=${BASH_REMATCH[1]} | |
| matrix_json=$(jq -n --arg v "$keycloak_version" '["\($v)-prem", "\($v)-hub", "\($v)-quay", "\($v)-quay-optimized"]') | |
| else | |
| : # List folders matching the pattern keycloak-* | |
| : # Export the list as an output in JSON format | |
| versions=$(printf "%s\n" keycloak-*/ | sed 's/\/$//' | sed 's/keycloak-//') | |
| matrix_json=$(echo "$versions" | jq -R -s -c 'split("\n")[:-1] | map("\(.)-prem", "\(.)-hub", "\(.)-quay", "\(.)-quay-optimized") | flatten') | |
| fi | |
| echo "matrix_keycloak_versions=${matrix_json}" | tee -a "$GITHUB_OUTPUT" | |
| build-image: | |
| runs-on: ubuntu-24.04 | |
| outputs: | |
| full_image_name: ${{ steps.compute-image-name-step.outputs.full_image_name }} | |
| needs: | |
| - list-keycloak-versions | |
| strategy: | |
| fail-fast: false # don't propagate failing jobs | |
| matrix: | |
| keycloak_version: ${{ fromJson(needs.list-keycloak-versions.outputs.matrix_keycloak_versions) }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: Install asdf tools with cache | |
| uses: camunda/infraex-common-config/./.github/actions/asdf-install-tooling@18718a9ca7599dc71ef3624230ad624720e85ee9 # 1.6.0 | |
| - name: Import secrets | |
| uses: hashicorp/vault-action@4c06c5ccf5c0761b6029f56cfb1dcf5565918a3b # v3.4.0 | |
| id: secrets | |
| with: | |
| url: ${{ secrets.VAULT_ADDR }} | |
| method: approle | |
| roleId: ${{ secrets.VAULT_ROLE_ID }} | |
| secretId: ${{ secrets.VAULT_SECRET_ID }} | |
| exportEnv: false | |
| secrets: | | |
| secret/data/products/infrastructure-experience/ci/common MACHINE_PWD; | |
| secret/data/products/infrastructure-experience/ci/common MACHINE_USR; | |
| secret/data/products/infrastructure-experience/ci/common DOCKERHUB_USER; | |
| secret/data/products/infrastructure-experience/ci/common DOCKERHUB_PASSWORD; | |
| - name: Login to the dockerhub registry # prevents pull limit rate | |
| uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4 | |
| with: | |
| registry: ${{ env.CONTAINER_REGISTRY_HUB }} | |
| username: ${{ steps.secrets.outputs.DOCKERHUB_USER }} | |
| password: ${{ steps.secrets.outputs.DOCKERHUB_PASSWORD }} | |
| - name: Extract version variables | |
| id: version-vars | |
| uses: ./.github/actions/extract-version-vars | |
| with: | |
| keycloak_version: ${{ matrix.keycloak_version }} | |
| - name: Compute build image variables | |
| id: compute-build-image-name-step | |
| run: | | |
| set -euo pipefail | |
| base_path="keycloak-${{ steps.version-vars.outputs.base_version }}" # e.g. "keycloak-24" | |
| base_image_name=$(yq e ".sources.${{ steps.version-vars.outputs.base_type }}.image.repository" "${base_path}/bases.yml") | |
| base_image_tag=$(yq e ".sources.${{ steps.version-vars.outputs.base_type }}.image.tag" "${base_path}/bases.yml" | cut -d@ -f1) | |
| base_image_digest=$(yq e ".sources.${{ steps.version-vars.outputs.base_type }}.image.tag" "${base_path}/bases.yml" | cut -d@ -f2) | |
| # Set the Dockerfile path based on base type | |
| if [[ "${{ steps.version-vars.outputs.base_type }}" == "quay" ]]; then | |
| dockerfile_path="Dockerfile.quay" | |
| else | |
| dockerfile_path="Dockerfile" | |
| fi | |
| echo "base_version=${{ steps.version-vars.outputs.base_version }}" | tee -a "$GITHUB_OUTPUT" | |
| echo "base_type=${{ steps.version-vars.outputs.base_type }}" | tee -a "$GITHUB_OUTPUT" | |
| echo "base_image_name=$base_image_name" | tee -a "$GITHUB_OUTPUT" | |
| echo "base_image_tag=$base_image_tag" | tee -a "$GITHUB_OUTPUT" | |
| echo "base_image_digest=$base_image_digest" | tee -a "$GITHUB_OUTPUT" | |
| echo "dockerfile_path=$dockerfile_path" | tee -a "$GITHUB_OUTPUT" | |
| - name: Build image using Camunda docker build | |
| id: build-image-step | |
| uses: camunda/infra-global-github-actions/build-docker-image@8e32450404891a0eea66404c8cf3cbfe8e602d38 # main | |
| with: | |
| registry_host: ${{ env.CONTAINER_REGISTRY_CI }} | |
| registry_username: ${{ steps.secrets.outputs.MACHINE_USR }} | |
| registry_password: ${{ steps.secrets.outputs.MACHINE_PWD }} | |
| force_push: true | |
| image_name: ${{ env.CONTAINER_IMAGE_NAME_CI }} | |
| build_context: ./keycloak-${{ steps.compute-build-image-name-step.outputs.base_version }}/ | |
| build_docker_file: | | |
| ./keycloak-${{ steps.compute-build-image-name-step.outputs.base_version }}/${{ steps.compute-build-image-name-step.outputs.dockerfile_path }} | |
| build_platforms: linux/amd64,linux/arm64 | |
| build_args: | | |
| BASE_IMAGE_NAME=${{ steps.compute-build-image-name-step.outputs.base_image_name }} | |
| BASE_IMAGE_TAG=${{ steps.compute-build-image-name-step.outputs.base_image_tag }} | |
| BASE_IMAGE_DIGEST=${{ steps.compute-build-image-name-step.outputs.base_image_digest }} | |
| BUILD_OPTIMIZED=${{ steps.version-vars.outputs.is_optimized }} | |
| extra_tags: | | |
| type=sha,enable=true,priority=1000,prefix=ci-${{ matrix.keycloak_version }}-sha-,suffix=,format=short | |
| - name: Compute target built image fully qualified name from metadata | |
| id: compute-image-name-step | |
| env: | |
| IMAGE_METADATA: ${{ steps.build-image-step.outputs.image_metadata }} | |
| run: | | |
| set -euo pipefail | |
| image_name=$(echo "${IMAGE_METADATA}" | tr -d '\n' | jq -r '."image.name"' | tr ',' '\n' | head -n 1 | tr -d ' ') | |
| digest=$(echo "${IMAGE_METADATA}" | tr -d '\n' | jq -r '."containerimage.digest"') | |
| full_image_name="${image_name}@${digest}" | |
| echo "full_image_name=${full_image_name}" | tee -a "$GITHUB_OUTPUT" | |
| ## Write for matrix outputs workaround | |
| - uses: cloudposse/github-action-matrix-outputs-write@ed06cf3a6bf23b8dce36d1cf0d63123885bb8375 # v1 | |
| id: out | |
| with: | |
| matrix-step-name: ${{ github.job }} | |
| matrix-key: ${{ matrix.keycloak_version }} | |
| outputs: |- | |
| full_image_name: ${{ steps.compute-image-name-step.outputs.full_image_name }} | |
| ## Read matrix outputs | |
| read-build-image-output: | |
| runs-on: ubuntu-24.04 | |
| needs: [build-image] | |
| steps: | |
| - uses: cloudposse/github-action-matrix-outputs-read@33cac12fa9282a7230a418d859b93fdbc4f27b5a # v1 | |
| id: read | |
| with: | |
| matrix-step-name: build-image | |
| outputs: | |
| result: ${{ steps.read.outputs.result }} | |
| test-base-image: | |
| runs-on: ubuntu-24.04 | |
| needs: | |
| - list-keycloak-versions | |
| - build-image | |
| - read-build-image-output | |
| strategy: | |
| fail-fast: false # don't propagate failing jobs | |
| matrix: | |
| keycloak_version: ${{ fromJson(needs.list-keycloak-versions.outputs.matrix_keycloak_versions) }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: Install asdf tools with cache | |
| uses: camunda/infraex-common-config/./.github/actions/asdf-install-tooling@18718a9ca7599dc71ef3624230ad624720e85ee9 # 1.6.0 | |
| - name: Set Keycloak Image Name | |
| id: set-keycloak-image-name | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| keycloak_image_name="${{ fromJson(needs.read-build-image-output.outputs.result).full_image_name[matrix.keycloak_version] }}" | |
| echo "keycloak_image_name=${keycloak_image_name}" | tee -a "$GITHUB_ENV" | |
| - name: Import secrets | |
| uses: hashicorp/vault-action@4c06c5ccf5c0761b6029f56cfb1dcf5565918a3b # v3.4.0 | |
| id: secrets | |
| with: | |
| url: ${{ secrets.VAULT_ADDR }} | |
| method: approle | |
| roleId: ${{ secrets.VAULT_ROLE_ID }} | |
| secretId: ${{ secrets.VAULT_SECRET_ID }} | |
| exportEnv: false | |
| secrets: | | |
| secret/data/products/infrastructure-experience/ci/common MACHINE_PWD; | |
| secret/data/products/infrastructure-experience/ci/common MACHINE_USR; | |
| - name: Login to the registry | |
| uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4 | |
| with: | |
| registry: ${{ env.CONTAINER_REGISTRY_CI }} | |
| username: ${{ steps.secrets.outputs.MACHINE_USR }} | |
| password: ${{ steps.secrets.outputs.MACHINE_PWD }} | |
| - name: Extract version variables | |
| id: version-vars | |
| uses: ./.github/actions/extract-version-vars | |
| with: | |
| keycloak_version: ${{ matrix.keycloak_version }} | |
| include_optimized: 'false' | |
| include_image_type: 'true' | |
| - name: Check Keycloak Providers/Config | |
| run: | | |
| set -euo pipefail | |
| python3 ./.github/scripts/build-check/check_providers.py "${{ env.keycloak_image_name }}" "${{ steps.version-vars.outputs.image_type }}" | |
| test-postgres-integ: | |
| strategy: | |
| fail-fast: false # don't propagate failing jobs | |
| matrix: | |
| runner_desc: | |
| - runner: ubuntu-24.04 | |
| postgres_replicas: 1 | |
| keycloak_jdbc_driver: postgresql | |
| keycloak_db_driver: org.postgresql.Driver | |
| keycloak_db_host_template: postgres | |
| keycloak_db_jdbc_query: '' | |
| keycloak_db_port: '5432' | |
| - runner: aws-core-2-default | |
| postgres_replicas: 0 | |
| keycloak_jdbc_driver: aws-wrapper:postgresql | |
| keycloak_db_driver: software.amazon.jdbc.Driver | |
| keycloak_db_host_template: camunda-ci-eks-aurora-postgresql-{{ postgres_version }}.cluster-clnwzia8ptad.eu-central-1.rds.amazonaws.com | |
| keycloak_db_jdbc_query: wrapperPlugins=iam&ssl=true&sslmode=require | |
| keycloak_db_port: '5432' | |
| - runner: aws-arm-core-2-default | |
| postgres_replicas: 0 | |
| keycloak_jdbc_driver: aws-wrapper:postgresql | |
| keycloak_db_driver: software.amazon.jdbc.Driver | |
| keycloak_db_host_template: camunda-ci-eks-aurora-postgresql-{{ postgres_version }}.cluster-clnwzia8ptad.eu-central-1.rds.amazonaws.com | |
| keycloak_db_jdbc_query: wrapperPlugins=iam&ssl=true&sslmode=require | |
| keycloak_db_port: '5432' | |
| # Add the gcp runner when GCloud SQL is available | |
| # GCloud SQL is not tested yet as we don't have a dedicated db | |
| keycloak_version: ${{ fromJson(needs.list-keycloak-versions.outputs.matrix_keycloak_versions) }} | |
| runs-on: ${{ matrix.runner_desc.runner }} | |
| needs: | |
| - list-keycloak-versions | |
| - build-image | |
| - read-build-image-output | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: Install build-essentials for asdf | |
| run: | | |
| set -euo pipefail | |
| sudo apt-get update | |
| sudo apt-get install -y build-essential git libexpat1-dev libssl-dev zlib1g-dev \ | |
| libncurses5-dev libbz2-dev liblzma-dev \ | |
| libsqlite3-dev libffi-dev tcl-dev linux-headers-generic libgdbm-dev \ | |
| libreadline-dev tk tk-dev | |
| - name: Install asdf tools with cache | |
| uses: camunda/infraex-common-config/./.github/actions/asdf-install-tooling@18718a9ca7599dc71ef3624230ad624720e85ee9 # 1.6.0 | |
| - name: Set Keycloak Image Name | |
| id: set-keycloak-image-name | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| keycloak_image_name="${{ fromJson(needs.read-build-image-output.outputs.result).full_image_name[matrix.keycloak_version] }}" | |
| echo "keycloak_image_name=${keycloak_image_name}" | tee -a "$GITHUB_ENV" | |
| - name: Import secrets | |
| uses: hashicorp/vault-action@4c06c5ccf5c0761b6029f56cfb1dcf5565918a3b # v3.4.0 | |
| id: secrets | |
| with: | |
| url: ${{ secrets.VAULT_ADDR }} | |
| method: approle | |
| roleId: ${{ secrets.VAULT_ROLE_ID }} | |
| secretId: ${{ secrets.VAULT_SECRET_ID }} | |
| exportEnv: true | |
| secrets: | | |
| secret/data/products/infrastructure-experience/ci/common MACHINE_PWD; | |
| secret/data/products/infrastructure-experience/ci/common MACHINE_USR; | |
| secret/data/products/infrastructure-experience/aurorapg AURORA_POSTGRESQL_PASSWORD | postgres_superuser_password; | |
| secret/data/products/infrastructure-experience/aurorapg AURORA_POSTGRESQL_USERNAME | postgres_superuser; | |
| secret/data/products/infrastructure-experience/ci/common DOCKERHUB_USER; | |
| secret/data/products/infrastructure-experience/ci/common DOCKERHUB_PASSWORD; | |
| - name: Login to the dockerhub registry # prevents pull limit rate | |
| uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4 | |
| with: | |
| registry: ${{ env.CONTAINER_REGISTRY_HUB }} | |
| username: ${{ steps.secrets.outputs.DOCKERHUB_USER }} | |
| password: ${{ steps.secrets.outputs.DOCKERHUB_PASSWORD }} | |
| - name: Login to the registry | |
| uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4 | |
| with: | |
| registry: ${{ env.CONTAINER_REGISTRY_CI }} | |
| username: ${{ steps.secrets.outputs.MACHINE_USR }} | |
| password: ${{ steps.secrets.outputs.MACHINE_PWD }} | |
| - name: Extract version variables | |
| id: version-vars | |
| uses: ./.github/actions/extract-version-vars | |
| with: | |
| keycloak_version: ${{ matrix.keycloak_version }} | |
| include_optimized: 'false' | |
| - name: Compute AWS variables | |
| if: startsWith(matrix.runner_desc.runner, 'aws') | |
| run: | | |
| set -euo pipefail | |
| : # aws aurora superuser is only used for bootstrapping a standard user that will auth using irsa | |
| echo "postgres_user=keycloak-irsa" | tee -a "$GITHUB_ENV" | |
| echo "postgres_password=" | tee -a "$GITHUB_ENV" | |
| echo "compose_keycloak_volume_1=$AWS_WEB_IDENTITY_TOKEN_FILE:$AWS_WEB_IDENTITY_TOKEN_FILE" >> "$GITHUB_ENV" | |
| : # export AWS variables | |
| echo "AWS_STS_REGIONAL_ENDPOINTS=$AWS_STS_REGIONAL_ENDPOINTS" | tee -a "$GITHUB_ENV" | |
| echo "AWS_DEFAULT_REGION=$AWS_DEFAULT_REGION" | tee -a "$GITHUB_ENV" | |
| echo "AWS_REGION=$AWS_REGION" | tee -a "$GITHUB_ENV" | |
| echo "AWS_ROLE_ARN=$AWS_ROLE_ARN" | tee -a "$GITHUB_ENV" | |
| echo "AWS_WEB_IDENTITY_TOKEN_FILE=$AWS_WEB_IDENTITY_TOKEN_FILE" | tee -a "$GITHUB_ENV" | |
| - name: Compute Ubuntu variables | |
| if: startsWith(matrix.runner_desc.runner, 'ubuntu') | |
| run: | | |
| set -euo pipefail | |
| : # we use plain values that will be used by the postgres container | |
| echo "postgres_user=keycloak" | tee -a "$GITHUB_ENV" | |
| echo "postgres_password=password" | tee -a "$GITHUB_ENV" | |
| - name: Declare test recipe variables | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| if (( "${{ matrix.runner_desc.postgres_replicas }}" < 1 )); then | |
| echo "compose_keycloak_depends_on=" | tee -a "$GITHUB_ENV" | |
| else | |
| echo "compose_keycloak_depends_on=postgres" | tee -a "$GITHUB_ENV" | |
| fi | |
| : # ensure uniqueness of the db name | |
| uuid="$(cat /proc/sys/kernel/random/uuid)" | |
| postgres_database="infex-keycloak-db-${uuid}-${{ github.sha }}" | |
| echo "postgres_database=${postgres_database}" | tee -a "$GITHUB_ENV" | |
| : # get the postgres version to test | |
| keycloak_version_git="$(echo '${{ matrix.keycloak_version }}' | sed -E 's/^([0-9]+)\.?(.*)$/\1.0/g')" # make sure to have a major.0 format | |
| postgres_version=$( | |
| curl -s "https://raw.githubusercontent.com/keycloak/keycloak/release/${keycloak_version_git}/pom.xml" \ | |
| | awk -F'[><]' '/<postgresql.version>/{print $3}' | |
| ) | |
| echo "postgres_version=${postgres_version}" | tee -a "$GITHUB_ENV" | |
| : # apply template on the address | |
| postgres_host=$(echo "${{ matrix.runner_desc.keycloak_db_host_template }}" | sed "s/{{ postgres_version }}/${postgres_version}/g") | |
| echo "postgres_host=${postgres_host}" | tee -a "$GITHUB_ENV" | |
| # The self-hosted runner doesn't provide a postgres client and the prerequisites for make, | |
| # so we need to install them manually | |
| - name: Install required packages | |
| run: sudo apt-get update && sudo apt-get install -y build-essential postgresql-client | |
| - name: Tear up Aurora PG (aws only) | |
| if: startsWith(matrix.runner_desc.runner, 'aws') | |
| run: ./.helpers/actions/create_aurora_pg_db.sh | |
| env: | |
| PGDATABASE: ${{ env.postgres_database }} | |
| PGHOST: ${{ env.postgres_host }} | |
| PGPORT: ${{ matrix.runner_desc.keycloak_db_port }} | |
| PGPASSWORD: ${{ env.postgres_superuser_password }} | |
| PGUSER: ${{ env.postgres_superuser }} | |
| PGUSER_IRSA: ${{ env.postgres_user }} | |
| - name: Generate a db auth token using aws for simple psql db connection test (aws only) | |
| if: startsWith(matrix.runner_desc.runner, 'aws') | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| : # We generate a db auth token using the aws cli because IRSA access in Keycloak might not be easy to debug. | |
| : # This token will be used in the "Test psql db connection" step, and then it will be reset for the Keycloak integration test. | |
| : # The aws command uses the environment variables provided by the runner | |
| AWS_PG_PASSWORD="$(aws rds generate-db-auth-token --hostname ${{ env.postgres_host }} \ | |
| --port ${{ matrix.runner_desc.keycloak_db_port }} --region ${{ env.AWS_REGION }} --username ${{ env.postgres_user }})" | |
| echo "postgres_password=${AWS_PG_PASSWORD}" >> "$GITHUB_ENV" | |
| - name: Test psql db connection (for external db only) | |
| if: ${{ matrix.runner_desc.postgres_replicas == 0 }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| : # Perform a simple psql connection test to ensure the database can be reached. | |
| : # The psql command provides clear and simple error messages compared to jdbc, | |
| : # which is why we perform this step. | |
| PGPASSWORD="${{ env.postgres_password }}" | |
| export PGPASSWORD | |
| psql -h "${{ env.postgres_host }}" -p "${{ matrix.runner_desc.keycloak_db_port }}" \ | |
| "dbname=${{ env.postgres_database }} user=${{ env.postgres_user }}" -c 'SELECT version();' | |
| - name: Reset postgres_password for IRSA connection (aws only) | |
| if: startsWith(matrix.runner_desc.runner, 'aws') | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| : # For AWS IRSA connection, we don't use password-based authentication. | |
| : # Since a password was generated in the previous steps, we need to ensure it is empty. | |
| echo "postgres_password=" >> "$GITHUB_ENV" | |
| - name: Set compose file based on image type | |
| id: set-compose-file | |
| run: | | |
| set -euo pipefail | |
| if [[ "${{ steps.version-vars.outputs.base_type }}" == "quay" ]]; then | |
| echo "compose_file=docker-compose.quay.yml" | tee -a "$GITHUB_OUTPUT" | |
| else | |
| echo "compose_file=docker-compose.yml" | tee -a "$GITHUB_OUTPUT" | |
| fi | |
| - name: Start Test Environment | |
| uses: ./.github/actions/compose | |
| with: | |
| project_name: keycloak | |
| compose_file: ${{ steps.set-compose-file.outputs.compose_file }} | |
| env: | |
| POSTGRES_DB: ${{ env.postgres_database }} | |
| POSTGRES_USER: ${{ env.postgres_user }} | |
| POSTGRES_PASSWORD: ${{ env.postgres_password }} | |
| KEYCLOAK_DATABASE_USER: ${{ env.postgres_user }} | |
| KEYCLOAK_DATABASE_PASSWORD: ${{ env.postgres_password }} | |
| KEYCLOAK_DATABASE_NAME: ${{ env.postgres_database }} | |
| KEYCLOAK_DATABASE_HOST: ${{ env.postgres_host }} | |
| KEYCLOAK_DATABASE_PORT: ${{ matrix.runner_desc.keycloak_db_port }} | |
| KEYCLOAK_JDBC_DRIVER: ${{ matrix.runner_desc.keycloak_jdbc_driver }} | |
| KEYCLOAK_JDBC_PARAMS: ${{ matrix.runner_desc.keycloak_db_jdbc_query }} | |
| KC_DB: postgres | |
| KC_DB_DRIVER: ${{ matrix.runner_desc.keycloak_db_driver }} | |
| KC_TRANSACTION_XA_ENABLED: false | |
| KC_HEALTH_ENABLED: true | |
| KC_METRICS_ENABLED: true | |
| # Disable HTTPS for tests - force HTTP mode | |
| KC_HTTP_ENABLED: true | |
| KC_HOSTNAME_STRICT_HTTPS: false | |
| KC_HOSTNAME_STRICT: false | |
| # Bootstrap admin user for Quay images | |
| KC_BOOTSTRAP_ADMIN_USERNAME: admin | |
| KC_BOOTSTRAP_ADMIN_PASSWORD: admin | |
| # Alternative admin user variables (for compatibility, KC_BOOTSTRAP is not sufficient) | |
| KEYCLOAK_ADMIN: admin | |
| KEYCLOAK_ADMIN_PASSWORD: admin | |
| KEYCLOAK_LOG_LEVEL: INFO,software.amazon.jdbc:INFO | |
| COMPOSE_POSTGRES_IMAGE: docker.io/postgres:${{ env.postgres_version }} | |
| COMPOSE_POSTGRES_DEPLOY_REPLICAS: ${{ matrix.runner_desc.postgres_replicas }} | |
| COMPOSE_KEYCLOAK_DEPENDS_ON: ${{ env.compose_keycloak_depends_on }} | |
| COMPOSE_KEYCLOAK_VOLUME_1: ${{ env.compose_keycloak_volume_1 || '/dev/null:/dummynull1' }} | |
| COMPOSE_KEYCLOAK_IMAGE: ${{ env.keycloak_image_name }} | |
| # AWS specific variables to forward, | |
| # see https://confluence.camunda.com/pages/viewpage.action?pageId=178590693#IAMRolesforServiceAccountsTesting(IRSA)-EnvironmentVariables | |
| AWS_STS_REGIONAL_ENDPOINTS: ${{ env.AWS_STS_REGIONAL_ENDPOINTS }} | |
| AWS_DEFAULT_REGION: ${{ env.AWS_DEFAULT_REGION }} | |
| AWS_REGION: ${{ env.AWS_REGION }} | |
| AWS_ROLE_ARN: ${{ env.AWS_ROLE_ARN }} | |
| AWS_WEB_IDENTITY_TOKEN_FILE: ${{ env.AWS_WEB_IDENTITY_TOKEN_FILE }} | |
| - name: Install dependencies | |
| run: | | |
| set -euo pipefail | |
| python -m pip install --upgrade pip | |
| pip install -r ./.github/scripts/integration/requirements.txt | |
| - name: Test Environment | |
| run: python3 ./.github/scripts/integration/main.py | |
| - name: Tear down Aurora PG (aws only) | |
| if: startsWith(matrix.runner_desc.runner, 'aws') && always() | |
| run: ./.helpers/actions/delete_aurora_pg_db.sh | |
| env: | |
| PGDATABASE: ${{ env.postgres_database }} | |
| PGHOST: ${{ env.postgres_host }} | |
| PGPORT: ${{ matrix.runner_desc.keycloak_db_port }} | |
| PGPASSWORD: ${{ env.postgres_superuser_password }} | |
| PGUSER: ${{ env.postgres_superuser }} | |
| publish-image: | |
| runs-on: ubuntu-24.04 | |
| # to release all versions of keycloak, tag it using the date (e.g.: `2024-03-10-001`) | |
| # to release only one version keycloak, tag it using the date prefixed by the version of keycloak (e.g.: `keycloak-23-2024-03-10-001`) | |
| if: startsWith(github.ref, 'refs/tags') | |
| strategy: | |
| fail-fast: false # don't propagate failing jobs | |
| matrix: | |
| keycloak_version: ${{ fromJson(needs.list-keycloak-versions.outputs.matrix_keycloak_versions) }} | |
| needs: | |
| - read-build-image-output | |
| - list-keycloak-versions | |
| - test-postgres-integ | |
| - test-base-image | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 | |
| - name: Install if required common software tooling | |
| uses: camunda/infra-global-github-actions/common-tooling@8e32450404891a0eea66404c8cf3cbfe8e602d38 # main | |
| with: | |
| node-enabled: false | |
| java-enabled: false | |
| yarn-enabled: false | |
| python-enabled: false | |
| buildx-install: true | |
| - name: Install asdf tools with cache | |
| uses: camunda/infraex-common-config/./.github/actions/asdf-install-tooling@18718a9ca7599dc71ef3624230ad624720e85ee9 # 1.6.0 | |
| - name: Import secrets | |
| uses: hashicorp/vault-action@4c06c5ccf5c0761b6029f56cfb1dcf5565918a3b # v3.4.0 | |
| id: secrets | |
| with: | |
| url: ${{ secrets.VAULT_ADDR }} | |
| method: approle | |
| roleId: ${{ secrets.VAULT_ROLE_ID }} | |
| secretId: ${{ secrets.VAULT_SECRET_ID }} | |
| exportEnv: false | |
| secrets: | | |
| secret/data/products/infrastructure-experience/ci/common MACHINE_PWD; | |
| secret/data/products/infrastructure-experience/ci/common MACHINE_USR; | |
| secret/data/products/infrastructure-experience/ci/common DOCKERHUB_USER; | |
| secret/data/products/infrastructure-experience/ci/common DOCKERHUB_PASSWORD; | |
| - name: Login to the registry | |
| uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4 | |
| with: | |
| registry: ${{ env.CONTAINER_REGISTRY_CI }} | |
| username: ${{ steps.secrets.outputs.MACHINE_USR }} | |
| password: ${{ steps.secrets.outputs.MACHINE_PWD }} | |
| - name: Extract version variables | |
| id: version-vars | |
| uses: ./.github/actions/extract-version-vars | |
| with: | |
| keycloak_version: ${{ matrix.keycloak_version }} | |
| - name: Set registry credentials based on keycloak_version | |
| id: publishing-registry | |
| run: | | |
| version="${{ matrix.keycloak_version }}" | |
| if [[ "${{ steps.version-vars.outputs.base_type }}" == "hub" ]]; then | |
| echo "publishing_registry=${{ env.CONTAINER_REGISTRY_HUB }}" | tee -a "$GITHUB_OUTPUT" | |
| echo "publishing_registry_username=${{ steps.secrets.outputs.DOCKERHUB_USER }}" | tee -a "$GITHUB_OUTPUT" | |
| echo "publishing_registry_password=${{ steps.secrets.outputs.DOCKERHUB_PASSWORD }}" | tee -a "$GITHUB_OUTPUT" | |
| # Image target for Hub | |
| echo "publishing_image_name=${{ env.CONTAINER_IMAGE_NAME_HUB }}" | tee -a "$GITHUB_OUTPUT" | |
| elif [[ "${{ steps.version-vars.outputs.base_type }}" == "prem" ]]; then | |
| echo "publishing_registry=${{ env.CONTAINER_REGISTRY_CAMUNDA }}" | tee -a "$GITHUB_OUTPUT" | |
| echo "publishing_registry_username=${{ steps.secrets.outputs.MACHINE_USR }}" | tee -a "$GITHUB_OUTPUT" | |
| echo "publishing_registry_password=${{ steps.secrets.outputs.MACHINE_PWD }}" | tee -a "$GITHUB_OUTPUT" | |
| # Image target for Camunda | |
| echo "publishing_image_name=${{ env.CONTAINER_IMAGE_NAME_CAMUNDA }}" | tee -a "$GITHUB_OUTPUT" | |
| elif [[ "${{ steps.version-vars.outputs.base_type }}" == "quay" ]]; then | |
| echo "publishing_registry=${{ env.CONTAINER_REGISTRY_HUB }}" | tee -a "$GITHUB_OUTPUT" | |
| echo "publishing_registry_username=${{ steps.secrets.outputs.DOCKERHUB_USER }}" | tee -a "$GITHUB_OUTPUT" | |
| echo "publishing_registry_password=${{ steps.secrets.outputs.DOCKERHUB_PASSWORD }}" | tee -a "$GITHUB_OUTPUT" | |
| # Image target for Hub with quay- prefix in tags | |
| echo "publishing_image_name=${{ env.CONTAINER_IMAGE_NAME_HUB }}" | tee -a "$GITHUB_OUTPUT" | |
| else | |
| echo "❌ Error: Unsupported version suffix in '$version'. Expected '-hub', '-prem', or '-quay'." | |
| exit 1 | |
| fi | |
| - name: Login to the publishing registry | |
| uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4 | |
| with: | |
| registry: ${{ steps.publishing-registry.outputs.publishing_registry }} | |
| username: ${{ steps.publishing-registry.outputs.publishing_registry_username }} | |
| password: ${{ steps.publishing-registry.outputs.publishing_registry_password }} | |
| - name: Set Keycloak Version | |
| id: set-keycloak-version | |
| run: | | |
| set -euo pipefail | |
| keycloak_image_name="${{ fromJson(needs.read-build-image-output.outputs.result).full_image_name[matrix.keycloak_version] }}" | |
| echo "keycloak_image_name=${keycloak_image_name}" | tee -a "$GITHUB_OUTPUT" | |
| publishing_image_target_name="${{ steps.publishing-registry.outputs.publishing_registry }}/${{ steps.publishing-registry.outputs.publishing_image_name }}" | |
| echo "publishing_image_target_name=${publishing_image_target_name}" | tee -a "$GITHUB_OUTPUT" | |
| - name: Pull built image | |
| run: | | |
| set -euo pipefail | |
| docker pull "${{ steps.set-keycloak-version.outputs.keycloak_image_name }}" | |
| - name: Retag and push the image | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| base_path="keycloak-${{ steps.version-vars.outputs.base_version }}" # e.g. "keycloak-24" | |
| # e.g. base_image_tag=23.0.7-debian-12-r5 or 23.0.7 for quay | |
| base_image_tag=$(yq e ".sources.${{ steps.version-vars.outputs.base_type }}.image.tag" "${base_path}/bases.yml" | cut -d@ -f1) | |
| echo "base_image_tag=${base_image_tag}" | |
| : # version of keycloak (e.g.: 23.0.1) | |
| # For quay images, the tag is just the semver, for bitnami it includes extra suffix | |
| if [[ "${{ steps.version-vars.outputs.base_type }}" == "quay" ]]; then | |
| semver_tag=$(echo "${base_image_tag}" | awk -F'-' '{print $1}') | |
| if [[ "${{ steps.version-vars.outputs.is_optimized }}" == "true" ]]; then | |
| tag_prefix="quay-optimized-" | |
| else | |
| tag_prefix="quay-" | |
| fi | |
| elif [[ "${{ steps.version-vars.outputs.base_type }}" == "hub" ]]; then | |
| semver_tag=$(echo "${base_image_tag}" | awk -F'-' '{print $1}') | |
| tag_prefix="bitnami-" | |
| elif [[ "${{ steps.version-vars.outputs.base_type }}" == "prem" ]]; then | |
| semver_tag=$(echo "${base_image_tag}" | awk -F'-' '{print $1}') | |
| tag_prefix="bitnami-ee-" | |
| else | |
| echo "❌ Error: Unsupported base_type '${{ steps.version-vars.outputs.base_type }}'. Expected 'hub', 'prem', or 'quay'." | |
| exit 1 | |
| fi | |
| : # remove keycloak- prefix | |
| suffix_version=$(echo '${{ github.ref_name }}' | sed 's/keycloak-[0-9]*-//') | |
| # Create tags with appropriate prefix | |
| docker buildx imagetools create \ | |
| -t "${{ steps.set-keycloak-version.outputs.publishing_image_target_name }}:${tag_prefix}${{ steps.version-vars.outputs.base_version }}" \ | |
| "${{ steps.set-keycloak-version.outputs.keycloak_image_name }}" | |
| docker buildx imagetools create \ | |
| -t "${{ steps.set-keycloak-version.outputs.publishing_image_target_name }}:${tag_prefix}${base_image_tag}" \ | |
| "${{ steps.set-keycloak-version.outputs.keycloak_image_name }}" | |
| docker buildx imagetools create \ | |
| -t "${{ steps.set-keycloak-version.outputs.publishing_image_target_name }}:${tag_prefix}${base_image_tag}-${suffix_version}" \ | |
| "${{ steps.set-keycloak-version.outputs.keycloak_image_name }}" | |
| docker buildx imagetools create -t "${{ steps.set-keycloak-version.outputs.publishing_image_target_name }}:${tag_prefix}${semver_tag}" \ | |
| "${{ steps.set-keycloak-version.outputs.keycloak_image_name }}" | |
| # For backward compatibility, also publish bitnami images without prefix | |
| base_type="${{ steps.version-vars.outputs.base_type }}" | |
| if [[ "$base_type" == "hub" || "$base_type" == "prem" ]]; then | |
| docker buildx imagetools create \ | |
| -t "${{ steps.set-keycloak-version.outputs.publishing_image_target_name }}:${{ steps.version-vars.outputs.base_version }}" \ | |
| "${{ steps.set-keycloak-version.outputs.keycloak_image_name }}" | |
| docker buildx imagetools create -t "${{ steps.set-keycloak-version.outputs.publishing_image_target_name }}:${base_image_tag}" \ | |
| "${{ steps.set-keycloak-version.outputs.keycloak_image_name }}" | |
| docker buildx imagetools create -t "${{ steps.set-keycloak-version.outputs.publishing_image_target_name }}:${base_image_tag}-${suffix_version}" \ | |
| "${{ steps.set-keycloak-version.outputs.keycloak_image_name }}" | |
| docker buildx imagetools create -t "${{ steps.set-keycloak-version.outputs.publishing_image_target_name }}:${semver_tag}" \ | |
| "${{ steps.set-keycloak-version.outputs.keycloak_image_name }}" | |
| fi | |
| # Make Quay standard (non-optimized) the default latest | |
| if [ "$(./.github/scripts/utils/find_latest_keycloak.sh)" = "${{ steps.version-vars.outputs.base_version }}" ]; then | |
| if [[ "${{ steps.version-vars.outputs.base_type }}" == "quay" && "${{ steps.version-vars.outputs.is_optimized }}" == "false" ]]; then | |
| # Quay standard becomes the main latest | |
| docker buildx imagetools create -t "${{ steps.set-keycloak-version.outputs.publishing_image_target_name }}:latest" \ | |
| "${{ steps.set-keycloak-version.outputs.keycloak_image_name }}" | |
| fi | |
| # Create prefixed latest tags for all types | |
| docker buildx imagetools create -t "${{ steps.set-keycloak-version.outputs.publishing_image_target_name }}:${tag_prefix}latest" \ | |
| "${{ steps.set-keycloak-version.outputs.keycloak_image_name }}" | |
| # For backward compatibility, also create non-prefixed latest for bitnami hub images | |
| # (prem images are in a different registry so no conflict with quay) | |
| if [[ "${{ steps.version-vars.outputs.base_type }}" == "hub" ]]; then | |
| docker buildx imagetools create -t "${{ steps.set-keycloak-version.outputs.publishing_image_target_name }}:latest-bitnami" \ | |
| "${{ steps.set-keycloak-version.outputs.keycloak_image_name }}" | |
| elif [[ "${{ steps.version-vars.outputs.base_type }}" == "prem" ]]; then | |
| # Prem images are in separate registry, so they can have their own latest | |
| docker buildx imagetools create -t "${{ steps.set-keycloak-version.outputs.publishing_image_target_name }}:latest" \ | |
| "${{ steps.set-keycloak-version.outputs.keycloak_image_name }}" | |
| fi | |
| fi | |
| # Rerun failed jobs running on self-hosted runners in case of network issues or node preemption | |
| rerun-failed-jobs: | |
| needs: | |
| - test-postgres-integ | |
| if: failure() && fromJSON(github.run_attempt) < 3 && inputs.notify_back_error_message == '' | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Retrigger job | |
| uses: camunda/infra-global-github-actions/rerun-failed-run@8e32450404891a0eea66404c8cf3cbfe8e602d38 # main | |
| with: | |
| error-messages: | | |
| lost communication with the server | |
| The runner has received a shutdown signal | |
| run-id: ${{ github.run_id }} | |
| repository: ${{ github.repository }} | |
| vault-addr: ${{ secrets.VAULT_ADDR }} | |
| vault-role-id: ${{ secrets.VAULT_ROLE_ID }} | |
| vault-secret-id: ${{ secrets.VAULT_SECRET_ID }} | |
| notify-back-on-error: 'true' | |
| notify-on-failure: | |
| runs-on: ubuntu-latest | |
| if: failure() && (fromJSON(github.run_attempt) >= 3 || inputs.notify_back_error_message != '') && github.event_name == 'schedule' | |
| needs: | |
| - publish-image | |
| - read-build-image-output | |
| - list-keycloak-versions | |
| - test-postgres-integ | |
| - test-base-image | |
| - rerun-failed-jobs | |
| steps: | |
| - name: Notify in Slack in case of failure | |
| id: slack-notification | |
| uses: camunda/infraex-common-config/.github/actions/report-failure-on-slack@18718a9ca7599dc71ef3624230ad624720e85ee9 # 1.6.0 | |
| with: | |
| vault_addr: ${{ secrets.VAULT_ADDR }} | |
| vault_role_id: ${{ secrets.VAULT_ROLE_ID }} | |
| vault_secret_id: ${{ secrets.VAULT_SECRET_ID }} |