Skip to content

CI on "cherry-pick-release-3.7-4ce49f70d89c6aa33126fee37fc5c48b3fca05fa" by @pdabelf5 #16858

CI on "cherry-pick-release-3.7-4ce49f70d89c6aa33126fee37fc5c48b3fca05fa" by @pdabelf5

CI on "cherry-pick-release-3.7-4ce49f70d89c6aa33126fee37fc5c48b3fca05fa" by @pdabelf5 #16858

Workflow file for this run

name: CI
run-name: CI on "${{ github.head_ref && github.head_ref || github.ref }}" by @${{ github.actor }}
on:
pull_request:
branches:
- main
- release-*
merge_group:
workflow_dispatch:
inputs:
force:
type: boolean
description: "Force rebuild"
required: false
default: false
defaults:
run:
shell: bash
concurrency:
group: ${{ github.ref_name }}-ci
cancel-in-progress: true
permissions:
contents: read
jobs:
checks:
name: Checks and variables
runs-on: ubuntu-24.04
permissions:
contents: read
id-token: write
outputs:
docs_only: ${{ github.event.pull_request && steps.docs.outputs.docs_only == 'true' }}
some_docs: ${{ github.event.pull_request && steps.docs.outputs.some_docs == 'true' }}
k8s_latest: ${{ steps.vars.outputs.k8s_latest }}
go_path: ${{ steps.vars.outputs.go_path }}
go_code_md5: ${{ steps.vars.outputs.go_code_md5 }}
binary_cache_hit: ${{ steps.binary-cache.outputs.cache-hit }}
chart_version: ${{ steps.vars.outputs.chart_version }}
ic_version: ${{ steps.vars.outputs.ic_version }}
docker_md5: ${{ steps.vars.outputs.docker_md5 }}
build_tag: ${{ steps.vars.outputs.build_tag }}
stable_tag: ${{ steps.vars.outputs.stable_tag }}
forked_workflow: ${{ steps.vars.outputs.forked_workflow }}
stable_image_exists: ${{ steps.stable_exists.outputs.exists }}
additional_tag: ${{ steps.vars.outputs.additional_tag }}
image_matrix_oss: ${{ steps.vars.outputs.image_matrix_oss }}
image_matrix_plus: ${{ steps.vars.outputs.image_matrix_plus }}
image_matrix_nap: ${{ steps.vars.outputs.image_matrix_nap }}
steps:
- name: Checkout Repository
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
with:
fetch-depth: 0
- name: Filter only docs changes
id: docs
run: |
files=$(git diff --name-only HEAD^ | egrep -v "^site/" | egrep -v "^examples/" | egrep -v "^README.md")
docs_files=$(git diff --name-only HEAD^ | grep "^site/")
if [ -z "$files" ]; then
echo "docs_only=true" >> $GITHUB_OUTPUT
else
echo "docs_only=false" >> $GITHUB_OUTPUT
fi
if [ -n "$docs_files" ]; then
echo "some_docs=true" >> $GITHUB_OUTPUT
else
echo "some_docs=false" >> $GITHUB_OUTPUT
fi
echo $files
echo $docs_files
cat $GITHUB_OUTPUT
shell: bash --noprofile --norc -o pipefail {0}
- name: Setup Golang Environment
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
with:
go-version-file: go.mod
- name: Output Variables
id: vars
run: |
kindest_latest=$(curl -s "https://hub.docker.com/v2/repositories/kindest/node/tags" \
| grep -o '"name": *"[^"]*' \
| grep -o '[^"]*$' \
| grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \
| sort -rV \
| head -n 1 \
| sed 's/^.\{1\}//' \
| tr -d '\n')
echo "k8s_latest=$kindest_latest" >> $GITHUB_OUTPUT
echo "go_path=$(go env GOPATH)" >> $GITHUB_OUTPUT
source .github/data/version.txt
echo "ic_version=${IC_VERSION}" >> $GITHUB_OUTPUT
echo "chart_version=${HELM_CHART_VERSION}" >> $GITHUB_OUTPUT
echo "forked_workflow=${{ (github.event.pull_request && github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name) || github.repository != 'nginxinc/kubernetes-ingress' }}" >> $GITHUB_OUTPUT
./.github/scripts/variables.sh go_code_md5 >> $GITHUB_OUTPUT
./.github/scripts/variables.sh docker_md5 >> $GITHUB_OUTPUT
./.github/scripts/variables.sh build_tag >> $GITHUB_OUTPUT
./.github/scripts/variables.sh stable_tag >> $GITHUB_OUTPUT
ref=${{ github.ref_name }}
if [[ $ref =~ merge ]]; then
additional_tag="pr-${ref%*/merge}"
else
additional_tag="${ref//\//-}"
fi
echo "additional_tag=${additional_tag}" >> $GITHUB_OUTPUT
echo "image_matrix_oss=$(cat .github/data/matrix-images-oss.json | jq -c)" >> $GITHUB_OUTPUT
echo "image_matrix_plus=$(cat .github/data/matrix-images-plus.json | jq -c)" >> $GITHUB_OUTPUT
echo "image_matrix_nap=$(cat .github/data/matrix-images-nap.json | jq -c)" >> $GITHUB_OUTPUT
cat $GITHUB_OUTPUT
- name: Fetch Cached Binary Artifacts
id: binary-cache
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
with:
path: ${{ github.workspace }}/dist
key: nginx-ingress-${{ steps.vars.outputs.go_code_md5 }}
lookup-only: true
- name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@8254fb75a33b976a221574d287e93919e6a36f70 # v2.1.6
with:
token_format: access_token
workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
if: ${{ steps.vars.outputs.forked_workflow == 'false' }}
- name: Login to GCR
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
with:
registry: gcr.io
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
if: ${{ steps.vars.outputs.forked_workflow == 'false' }}
- name: Check if stable image exists
id: stable_exists
run: |
if docker pull gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-ingress:${{ steps.vars.outputs.stable_tag }}; then
echo "exists=true" >> $GITHUB_OUTPUT
fi
if: ${{ steps.vars.outputs.forked_workflow == 'false' }}
- name: Output variables
run: |
echo docs_only: ${{ github.event.pull_request && steps.docs.outputs.docs_only == 'true' }}
echo k8s_latest: ${{ steps.vars.outputs.k8s_latest }}
echo go_path: ${{ steps.vars.outputs.go_path }}
echo go_code_md5: ${{ steps.vars.outputs.go_code_md5 }}
echo binary_cache_hit: ${{ steps.binary-cache.outputs.cache-hit }}
echo chart_version: ${{ steps.vars.outputs.chart_version }}
echo ic_version: ${{ steps.vars.outputs.ic_version }}
echo docker_md5: ${{ steps.vars.outputs.docker_md5 }}
echo build_tag: ${{ steps.vars.outputs.build_tag }}
echo stable_tag: ${{ steps.vars.outputs.stable_tag }}
echo forked_workflow: ${{ steps.vars.outputs.forked_workflow }}
echo stable_image_exists: ${{ steps.stable_exists.outputs.exists }}
echo additional_tag: ${{ steps.vars.outputs.additional_tag }}
echo 'image_matrix_oss: ${{ steps.vars.outputs.image_matrix_oss }}'
echo 'image_matrix_plus: ${{ steps.vars.outputs.image_matrix_plus }}'
echo 'image_matrix_nap: ${{ steps.vars.outputs.image_matrix_nap }}'
verify-codegen:
name: Verify generated code
runs-on: ubuntu-24.04
permissions:
contents: read
needs: checks
steps:
- name: Checkout Repository
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- name: Setup Golang Environment
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
with:
go-version-file: go.mod
- name: Check if go.mod and go.sum are up to date
run: go mod tidy && git diff --exit-code -- go.mod go.sum
- name: Check if CRDs changed
run: make update-crds && git diff --name-only --exit-code config/crd/bases
- name: Check if Codegen changed
run: |
cd ../.. && mkdir -p github.com/nginxinc && mv kubernetes-ingress/kubernetes-ingress github.com/nginxinc/ && cd github.com/nginxinc/kubernetes-ingress
make update-codegen && git diff --name-only --exit-code pkg/**
cd ../../.. && mv github.com/nginxinc/kubernetes-ingress kubernetes-ingress/kubernetes-ingress
- name: Install gofumpt
run: go install mvdan.cc/gofumpt@latest
- name: Check if telemetry schema changed
run: |
export PATH=$PATH:$(go env GOPATH)/bin
make telemetry-schema && git diff --name-only --exit-code internal/telemetry
- name: Check if make docs builds
if: ${{ needs.checks.outputs.some_docs == 'true' }}
run: cd site && make docs-ci
unit-tests:
name: Unit Tests
runs-on: ubuntu-24.04
needs: checks
steps:
- name: Checkout Repository
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- name: Setup Golang Environment
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
with:
go-version-file: go.mod
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
- name: Run Tests
run: make cover
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
- name: Upload coverage to Codecov
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4.6.0
with:
files: ./coverage.txt
token: ${{ secrets.CODECOV_TOKEN }} # required
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
binaries:
name: Build Binaries
runs-on: ubuntu-24.04
needs: [checks, unit-tests, verify-codegen]
permissions:
contents: write # for goreleaser/goreleaser-action to manage releases
id-token: write # for goreleaser/goreleaser-action to sign artifacts
issues: write # for goreleaser/goreleaser-action to close milestone
steps:
- name: Checkout Repository
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
with:
fetch-depth: 0
- name: Setup Golang Environment
uses: actions/setup-go@41dfa10bad2bb2ae585af6ee5bb4d7d973ad74ed # v5.1.0
with:
go-version-file: go.mod
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
- name: Build binaries
uses: goreleaser/goreleaser-action@286f3b13b1b49da4ac219696163fb8c1c93e1200 # v6.0.0
with:
version: latest
args: build --snapshot --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GOPATH: ${{ needs.checks.outputs.go_path }}
AWS_PRODUCT_CODE: ${{ secrets.AWS_PRODUCT_CODE }}
AWS_PUB_KEY: ${{ secrets.AWS_PUB_KEY }}
AWS_NAP_DOS_PRODUCT_CODE: ${{ secrets.AWS_NAP_DOS_PRODUCT_CODE }}
AWS_NAP_DOS_PUB_KEY: ${{ secrets.AWS_NAP_DOS_PUB_KEY }}
AWS_NAP_WAF_PRODUCT_CODE: ${{ secrets.AWS_NAP_WAF_PRODUCT_CODE }}
AWS_NAP_WAF_PUB_KEY: ${{ secrets.AWS_NAP_WAF_PUB_KEY }}
AWS_NAP_WAF_DOS_PRODUCT_CODE: ${{ secrets.AWS_NAP_WAF_DOS_PRODUCT_CODE }}
AWS_NAP_WAF_DOS_PUB_KEY: ${{ secrets.AWS_NAP_WAF_DOS_PUB_KEY }}
GORELEASER_CURRENT_TAG: "v${{ needs.checks.outputs.ic_version }}"
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
- name: Store Artifacts in Cache
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
with:
path: ${{ github.workspace }}/dist
key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
build-docker:
name: Build Docker OSS
needs: [binaries, checks]
strategy:
fail-fast: false
matrix: ${{ fromJSON( needs.checks.outputs.image_matrix_oss ) }}
uses: ./.github/workflows/build-oss.yml
with:
platforms: ${{ matrix.platforms }}
image: ${{ matrix.image }}
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
full-build: ${{ inputs.force && inputs.force || false }}
tag: ${{ needs.checks.outputs.build_tag }}
branch: ${{ (github.head_ref && needs.checks.outputs.forked_workflow != 'true') && github.head_ref || github.ref }}
ic-version: ${{ needs.checks.outputs.ic_version }}
permissions:
contents: read
actions: read
id-token: write
packages: write
pull-requests: write # for scout report
secrets: inherit
if: ${{ inputs.force || (needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false') || (needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.stable_image_exists != 'true' && needs.checks.outputs.docs_only == 'false') }}
build-docker-plus:
name: Build Docker Plus
needs: [binaries, checks]
strategy:
fail-fast: false
matrix: ${{ fromJSON( needs.checks.outputs.image_matrix_plus ) }}
uses: ./.github/workflows/build-plus.yml
with:
platforms: ${{ matrix.platforms }}
image: ${{ matrix.image }}
target: ${{ matrix.target }}
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
branch: ${{ (github.head_ref && needs.checks.outputs.forked_workflow != 'true') && github.head_ref || github.ref }}
tag: ${{ needs.checks.outputs.build_tag }}
authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
full-build: ${{ inputs.force && inputs.force || false }}
ic-version: ${{ needs.checks.outputs.ic_version }}
permissions:
contents: read
id-token: write
pull-requests: write # for scout report
secrets: inherit
if: ${{ inputs.force || (needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false') || (needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.stable_image_exists != 'true' && needs.checks.outputs.docs_only == 'false') }}
build-docker-nap:
name: Build Docker NAP
needs: [binaries, checks]
strategy:
fail-fast: false
matrix: ${{ fromJSON( needs.checks.outputs.image_matrix_nap ) }}
uses: ./.github/workflows/build-plus.yml
with:
platforms: ${{ matrix.platforms }}
image: ${{ matrix.image }}
target: ${{ matrix.target }}
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
branch: ${{ (github.head_ref && needs.checks.outputs.forked_workflow != 'true') && github.head_ref || github.ref }}
tag: ${{ needs.checks.outputs.build_tag }}
nap-modules: ${{ matrix.nap_modules }}
authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
full-build: ${{ inputs.force && inputs.force || false }}
ic-version: ${{ needs.checks.outputs.ic_version }}
permissions:
contents: read
id-token: write # gcr login
pull-requests: write # for scout report
secrets: inherit
if: ${{ inputs.force || (needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false') || (needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.stable_image_exists != 'true' && needs.checks.outputs.docs_only == 'false') }}
tag-target:
name: Tag untested image with PR number
needs: [checks, build-docker, build-docker-plus, build-docker-nap]
permissions:
contents: read # To checkout repository
id-token: write # To sign into Google Container Registry
uses: ./.github/workflows/retag-images.yml
with:
source_tag: ${{ needs.checks.outputs.build_tag }}
target_tag: ${{ needs.checks.outputs.additional_tag }}
dry_run: false
secrets: inherit
if: ${{ inputs.force || (needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false') || (needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.stable_image_exists != 'true' && needs.checks.outputs.docs_only == 'false') }}
helm-tests:
if: ${{ needs.checks.outputs.docs_only != 'true' }}
name: Helm Tests ${{ matrix.base-os }}
runs-on: ubuntu-24.04
needs: [checks, binaries, build-docker, build-docker-plus]
strategy:
fail-fast: false
matrix:
include:
- base-os: debian
image: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-ingress
tag: ${{ needs.checks.outputs.build_tag }}
type: oss
- base-os: debian-plus
image: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic/nginx-plus-ingress
tag: ${{ needs.checks.outputs.build_tag }}
type: plus
permissions:
contents: read
id-token: write
steps:
- name: Checkout Repository
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@8254fb75a33b976a221574d287e93919e6a36f70 # v2.1.6
with:
token_format: access_token
workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
- name: Login to GCR
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
with:
registry: gcr.io
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
- name: Check if stable image exists
id: stable_exists
run: |
if docker pull ${{ matrix.image }}:${{ needs.checks.outputs.stable_tag }}; then
echo "exists=true" >> $GITHUB_OUTPUT
fi
if: ${{ needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' }}
- name: Pull build image
run: |
docker pull ${{ matrix.image }}:${{ needs.checks.outputs.build_tag }}
if: ${{ ( needs.checks.outputs.forked_workflow == 'false' || needs.checks.outputs.docs_only == 'false' ) && steps.stable_exists.outputs.exists != 'true' }}
- name: Fetch Cached Artifacts
uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
with:
path: ${{ github.workspace }}/dist
key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Docker Buildx
uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1
if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Build Docker Image ${{ matrix.base-os }}
uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0
with:
file: build/Dockerfile
context: "."
cache-from: type=gha,scope=${{ matrix.base-os }}
target: goreleaser
tags: "${{ matrix.image }}:${{ matrix.tag }}"
pull: true
load: true
build-args: |
BUILD_OS=${{ matrix.base-os }}
IC_VERSION=CI
secrets: |
${{ matrix.type == 'plus' && format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) || '' }}
${{ matrix.type == 'plus' && format('"nginx-repo.key={0}"', secrets.NGINX_KEY) || '' }}
if: ${{ needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Deploy Kubernetes
id: k8s
run: |
kind create cluster --name ${{ github.run_id }} --image=kindest/node:v${{ needs.checks.outputs.k8s_latest }} --wait 75s
kind load docker-image "${{ matrix.image }}:${{ matrix.tag }}" --name ${{ github.run_id }}
if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Install Chart
run: >
helm install
${{ matrix.type }}
.
--set controller.image.repository=${{ matrix.image }}
--set controller.image.tag=${{ matrix.tag }}
--set controller.service.type=NodePort
--set controller.nginxplus=${{ contains(matrix.type, 'plus') && 'true' || 'false' }}
--set controller.telemetryReporting.enable=false
--wait
working-directory: ${{ github.workspace }}/charts/nginx-ingress
if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Expose Test Ingresses
run: |
kubectl port-forward service/${{ matrix.type }}-nginx-ingress-controller 8080:80 8443:443 &
if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Test HTTP
run: |
counter=0
max_attempts=5
until [ $(curl --write-out %{http_code} -s --output /dev/null http://localhost:8080) -eq 404 ]; do
if [ ${counter} -eq ${max_attempts} ]; then
exit 1
fi
printf '.'; counter=$(($counter+1)); sleep 5;
done
if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
- name: Test HTTPS
run: |
counter=0
max_attempts=5
until [ $(curl --write-out %{http_code} -ks --output /dev/null https://localhost:8443) -eq 000 ]; do
if [ ${counter} -eq ${max_attempts} ]; then
exit 1
fi
printf '.'; counter=$(($counter+1)); sleep 5;
done
if: ${{ steps.stable_exists.outputs.exists != 'true' && needs.checks.outputs.docs_only == 'false' }}
setup-matrix:
if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
name: Setup Matrix for Smoke Tests
runs-on: ubuntu-24.04
needs: [binaries, checks]
permissions:
contents: read
id-token: write
outputs:
matrix_oss: ${{ steps.set-matrix.outputs.matrix_oss }}
matrix_plus: ${{ steps.set-matrix.outputs.matrix_plus }}
matrix_nap: ${{ steps.set-matrix.outputs.matrix_nap }}
steps:
- name: Checkout Repository
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
- id: set-matrix
run: |
echo "matrix_oss=$(cat .github/data/matrix-smoke-oss.json | jq -c --arg latest "${{ needs.checks.outputs.k8s_latest }}" '.k8s += [$latest]')" >> $GITHUB_OUTPUT
echo "matrix_plus=$(cat .github/data/matrix-smoke-plus.json | jq -c --arg latest "${{ needs.checks.outputs.k8s_latest }}" '.k8s += [$latest]')" >> $GITHUB_OUTPUT
echo "matrix_nap=$(cat .github/data/matrix-smoke-nap.json | jq -c --arg latest "${{ needs.checks.outputs.k8s_latest }}" '.k8s += [$latest]')" >> $GITHUB_OUTPUT
- name: Docker Buildx
uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1
- name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@8254fb75a33b976a221574d287e93919e6a36f70 # v2.1.6
with:
token_format: access_token
workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }}
service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }}
if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
- name: Login to GCR
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
with:
registry: gcr.io
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
- name: Check if test image exists
id: check-image
run: |
docker pull gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt', './tests/Dockerfile') || 'latest' }}
shell: bash
continue-on-error: true
if: ${{ needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.docs_only == 'false' }}
- name: Build Test-Runner Container
uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0
with:
file: tests/Dockerfile
context: "."
cache-from: type=gha,scope=test-runner
tags: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt', './tests/Dockerfile') || 'latest' }}"
pull: true
push: ${{ needs.checks.outputs.forked_workflow == 'false' }}
load: false
if: ${{ steps.check-image.outcome == 'failure' && needs.checks.outputs.docs_only == 'false' }}
smoke-tests-oss:
if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
name: ${{ matrix.images.label }} ${{ matrix.images.image }} ${{ matrix.k8s }} smoke tests
needs:
- checks
- setup-matrix
- build-docker
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.setup-matrix.outputs.matrix_oss) }}
permissions:
contents: read
id-token: write
uses: ./.github/workflows/setup-smoke.yml
secrets: inherit
with:
image: ${{ matrix.images.image }}
target: ${{ matrix.images.target }}
nap-modules: ${{ matrix.images.nap_modules }}
marker: ${{ matrix.images.marker }}
label: ${{ matrix.images.label }}
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
build-tag: ${{ needs.checks.outputs.build_tag }}
stable-tag: ${{ needs.checks.outputs.stable_tag }}
authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
k8s-version: ${{ matrix.k8s }}
smoke-tests-plus:
if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
name: ${{ matrix.images.label }} ${{ matrix.images.image }} ${{ matrix.k8s }} smoke tests
needs:
- checks
- setup-matrix
- build-docker-plus
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.setup-matrix.outputs.matrix_plus) }}
permissions:
contents: read
id-token: write
uses: ./.github/workflows/setup-smoke.yml
secrets: inherit
with:
image: ${{ matrix.images.image }}
target: ${{ matrix.images.target }}
nap-modules: ${{ matrix.images.nap_modules }}
marker: ${{ matrix.images.marker }}
label: ${{ matrix.images.label }}
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
build-tag: ${{ needs.checks.outputs.build_tag }}
stable-tag: ${{ needs.checks.outputs.stable_tag }}
authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
k8s-version: ${{ matrix.k8s }}
smoke-tests-nap:
if: ${{ inputs.force || needs.checks.outputs.docs_only != 'true' }}
name: ${{ matrix.images.label }} ${{ matrix.images.image }} ${{ matrix.k8s }} smoke tests
needs:
- checks
- setup-matrix
- build-docker-nap
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.setup-matrix.outputs.matrix_nap) }}
permissions:
contents: read
id-token: write
uses: ./.github/workflows/setup-smoke.yml
secrets: inherit
with:
image: ${{ matrix.images.image }}
target: ${{ matrix.images.target }}
nap-modules: ${{ matrix.images.nap_modules }}
marker: ${{ matrix.images.marker }}
label: ${{ matrix.images.label }}
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
build-tag: ${{ needs.checks.outputs.build_tag }}
stable-tag: ${{ needs.checks.outputs.stable_tag }}
authenticated: ${{ needs.checks.outputs.forked_workflow != 'true' }}
k8s-version: ${{ matrix.k8s }}
tag-stable:
name: Tag tested image as stable
needs: [checks, build-docker, build-docker-plus, build-docker-nap, smoke-tests-oss, smoke-tests-plus, smoke-tests-nap]
permissions:
contents: read # To checkout repository
id-token: write # To sign into Google Container Registry
uses: ./.github/workflows/retag-images.yml
with:
source_tag: ${{ needs.checks.outputs.build_tag }}
target_tag: ${{ needs.checks.outputs.stable_tag }}
dry_run: false
secrets: inherit
if: ${{ inputs.force || (needs.checks.outputs.forked_workflow == 'true' && needs.checks.outputs.docs_only == 'false') || (needs.checks.outputs.forked_workflow == 'false' && needs.checks.outputs.stable_image_exists != 'true' && needs.checks.outputs.docs_only == 'false') }}
final-results:
if: ${{ !cancelled() }}
runs-on: ubuntu-24.04
name: Final CI Results
needs: [tag-stable, build-docker, build-docker-plus, build-docker-nap, smoke-tests-oss, smoke-tests-plus, smoke-tests-nap]
steps:
- run: |
tagResult="${{ needs.tag-stable.result }}"
smokeOSSResult="${{ needs.smoke-tests-oss.result }}"
smokePlusResult="${{ needs.smoke-tests-plus.result }}"
smokeNAPResult="${{ needs.smoke-tests-nap.result }}"
if [[ $tagResult != "success" && $tagResult != "skipped" ]]; then
exit 1
fi
if [[ $smokeOSSResult != "success" && $smokeOSSResult != "skipped" ]]; then
exit 1
fi
if [[ $smokePlusResult != "success" && $smokePlusResult != "skipped" ]]; then
exit 1
fi
if [[ $smokeNAPResult != "success" && $smokeNAPResult != "skipped" ]]; then
exit 1
fi
trigger-image-promotion:
name: Promote images on Force Run
needs:
- build-docker
- build-docker-plus
- build-docker-nap
- final-results
permissions:
contents: write # for pushing to Helm Charts repository
id-token: write # To sign into Google Container Registry
actions: read
packages: write # for helm to push to GHCR
security-events: write
pull-requests: write # for scout report
uses: ./.github/workflows/image-promotion.yml
secrets: inherit
if: ${{ inputs.force && inputs.force || false }}