Skip to content

Added missing reference to NGINX Ingress Controller with both NGINX App Protect WAF and NGINX App Protect DoS image #13199

Added missing reference to NGINX Ingress Controller with both NGINX App Protect WAF and NGINX App Protect DoS image

Added missing reference to NGINX Ingress Controller with both NGINX App Protect WAF and NGINX App Protect DoS image #13199

Workflow file for this run

name: CI
on:
push:
branches:
- main
- release-*
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
pull_request:
branches:
- main
- release-*
merge_group:
schedule:
- cron: "0 4 * * *" # run every day at 04:00 UTC
workflow_dispatch:
inputs:
publish-image:
description: Publish of the generated images
type: boolean
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-22.04
outputs:
docs_only: ${{ github.event.pull_request && steps.docs.outputs.docs_only == 'true' }}
k8s_latest: ${{ steps.vars.outputs.k8s_latest }}
latest_kindest_node_versions: ${{ steps.vars.outputs.latest_kindest_node_versions }}
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 }}
publish_images: ${{ steps.vars.outputs.publish }}
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 }}
steps:
- name: Checkout Repository
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
with:
fetch-depth: 0
- name: Filter only docs changes
id: docs
run: |
files=$(git diff --name-only HEAD^ | egrep -v "^docs/" | egrep -v "^examples/" | egrep -v "^README.md")
if [ -z "$files" ]; then
echo "docs_only=true" >> $GITHUB_OUTPUT
else
echo "docs_only=false" >> $GITHUB_OUTPUT
fi
echo $files
cat $GITHUB_OUTPUT
shell: bash --noprofile --norc -o pipefail {0}
- name: Setup Golang Environment
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.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
kindest_versions=$(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 \
| awk -F. '!seen[$1"."$2]++' \
| head -n 7 \
| sort -V \
| sed 's/v//g' \
| sed 's/$//' \
| sed 's/, $//' \
| jq -R -s -c 'split("\n")[:-1]')
echo "latest_kindest_node_versions=$kindest_versions" >> $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.head.repo.full_name != github.github.event.pull_request.base.repo.full_name) || github.repository != 'nginxinc/kubernetes-ingress' }}" >> $GITHUB_OUTPUT
publish=false
if ${{ github.event_name == 'workflow_dispatch' && inputs.publish-image }}; then
publish=true
elif ${{ github.ref_type == 'tag' && startsWith(github.ref, 'refs/heads/release-') }}; then
publish=true
elif ${{ github.event_name != 'workflow_dispatch' && github.event_name != 'pull_request' && ! startsWith(github.ref, 'refs/heads/release-') }}; then
publish=true
fi
echo "publish=$publish" >> $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
cat $GITHUB_OUTPUT
- name: Fetch Cached Binary Artifacts
id: binary-cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: ${{ github.workspace }}/dist
key: nginx-ingress-${{ steps.vars.outputs.go_code_md5 }}
lookup-only: true
- 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
unit-tests:
name: Unit Tests
runs-on: ubuntu-22.04
needs: checks
steps:
- name: Checkout Repository
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
- name: Setup Golang Environment
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.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@84508663e988701840491b86de86b666e8a86bed # v4.3.0
with:
files: ./coverage.txt
token: ${{ secrets.CODECOV_TOKEN }} # required
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
release-notes:
name: Release Notes
runs-on: ubuntu-22.04
needs: [checks, unit-tests]
outputs:
release-url: ${{ steps.release-notes.outputs.release-url }}
permissions:
contents: write # for lucacome/draft-release
steps:
- name: Checkout Repository
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
with:
fetch-depth: 0
- name: Create/Update Draft
uses: lucacome/draft-release@e076259ceb036bc5f2c2a76559784c12cf8d2e74 # v1.0.4
id: release-notes
with:
minor-label: "enhancement"
major-label: "change"
publish: ${{ github.ref_type == 'tag' }}
collapse-after: 50
variables: |
helm-chart=${{ needs.checks.outputs.chart_version }}
notes-footer: |
## Upgrade
- For NGINX, use the {{version}} images from our [DockerHub](https://hub.docker.com/r/nginx/nginx-ingress/tags?page=1&ordering=last_updated&name={{version-number}}), [GitHub Container](https://github.com/nginxinc/kubernetes-ingress/pkgs/container/kubernetes-ingress), [Amazon ECR Public Gallery](https://gallery.ecr.aws/nginx/nginx-ingress) or [Quay.io](https://quay.io/repository/nginx/nginx-ingress).
- For NGINX Plus, use the {{version}} images from the F5 Container registry, the [AWS Marketplace](https://aws.amazon.com/marketplace/search/?CREATOR=741df81b-dfdc-4d36-b8da-945ea66b522c&FULFILLMENT_OPTION_TYPE=CONTAINER&filters=CREATOR%2CFULFILLMENT_OPTION_TYPE), the [GCP Marketplace](https://console.cloud.google.com/marketplace/browse?filter=partner:F5,%20Inc.&filter=solution-type:k8s&filter=category:networking) or build your own image using the {{version}} source code.
- For Helm, use version {{helm-chart}} of the chart.
## Resources
- Documentation -- https://docs.nginx.com/nginx-ingress-controller/
- Configuration examples -- https://github.com/nginxinc/kubernetes-ingress/tree/{{version}}/examples
- Helm Chart -- https://github.com/nginxinc/kubernetes-ingress/tree/{{version}}/charts/nginx-ingress
- Operator -- https://github.com/nginxinc/nginx-ingress-helm-operator
if: ${{ github.event_name == 'push' && github.ref != 'refs/heads/main' }}
binaries:
name: Build Binaries
runs-on: ubuntu-22.04
needs: [checks, unit-tests]
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@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
with:
fetch-depth: 0
- name: Setup Golang Environment
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version-file: go.mod
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
- name: Download Syft
uses: anchore/sbom-action/download-syft@ab5d7b5f48981941c4c5d6bf33aeb98fe3bae38c # v0.15.10
if: github.ref_type == 'tag'
- name: Install Cosign
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0
if: github.ref_type == 'tag'
- name: Build binaries
uses: goreleaser/goreleaser-action@7ec5c2b0c6cdda6e8bbb49444bc797dd33d74dd8 # v5.0.0
with:
version: latest
args: ${{ github.ref_type == 'tag' && 'release' || 'build --snapshot' }} ${{ github.event_name == 'pull_request' && '--single-target' || '' }} --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 }}
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_COMMUNITY }}
AZURE_STORAGE_ACCOUNT: ${{ secrets.AZURE_STORAGE_ACCOUNT }}
AZURE_STORAGE_KEY: ${{ secrets.AZURE_STORAGE_KEY }}
AZURE_BUCKET_NAME: ${{ secrets.AZURE_BUCKET_NAME }}
GORELEASER_CURRENT_TAG: ${{ needs.checks.outputs.ic_version }}
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
- name: Store Artifacts in Cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: ${{ github.workspace }}/dist
key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
if: ${{ needs.checks.outputs.binary_cache_hit != 'true' }}
helm-tests:
if: ${{ needs.checks.outputs.docs_only != 'true' }}
name: Helm Tests ${{ matrix.base-os }}
runs-on: ubuntu-22.04
needs: [checks, binaries]
strategy:
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
platforms: "linux/arm, linux/arm64, linux/amd64, linux/ppc64le, linux/s390x"
- 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
platforms: "linux/arm64, linux/amd64"
permissions:
contents: read
id-token: write
steps:
- name: Checkout Repository
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
- name: Fetch Cached Artifacts
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
with:
path: ${{ github.workspace }}/dist
key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
- name: Docker Buildx
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
- name: Setup QEMU
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
with:
platforms: ${{ matrix.platforms }}
if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
- name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@55bd3a7c6e2ae7cf1877fd1ccb9d54c0503c457c # v2.1.2
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' }}
- name: Login to GCR
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0
with:
registry: gcr.io
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
- name: Check if base images exist
id: base_exists
run: |
if docker manifest inspect gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/${{ matrix.type }}:${{ needs.checks.outputs.docker_md5 }}-${{ matrix.base-os }}; then
echo "exists=0" >> $GITHUB_OUTPUT
else
echo "exists=1" >> $GITHUB_OUTPUT
fi
if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
- name: Build Base Container
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
with:
file: build/Dockerfile
context: "."
cache-from: type=gha,scope=${{ matrix.base-os }}
cache-to: type=gha,scope=${{ matrix.base-os }},mode=max
target: common
tags: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/${{ matrix.type }}:${{ needs.checks.outputs.docker_md5 }}-${{ matrix.base-os }}
platforms: ${{ matrix.platforms }}
pull: true
push: true
build-args: |
BUILD_OS=${{ matrix.base-os }}
IC_VERSION=${{ needs.checks.outputs.ic_version }}
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 == 'false' && steps.base_exists.outputs.exists != 0 }}
- name: Build Docker Image ${{ matrix.base-os }}
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
with:
file: build/Dockerfile
context: "."
cache-from: type=gha,scope=${{ matrix.base-os }}
target: goreleaser${{ needs.checks.outputs.forked_workflow == 'false' && '-prebuilt' || '' }}
tags: "${{ matrix.image }}:${{ matrix.tag }}"
pull: true
load: true
build-args: |
BUILD_OS=${{ matrix.base-os }}
PREBUILT_BASE_IMG=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/${{ matrix.type }}:${{ needs.checks.outputs.docker_md5 }}-${{ 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) || '' }}
- 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 }}
- 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
- name: Expose Test Ingresses
run: |
kubectl port-forward service/${{ matrix.type }}-nginx-ingress-controller 8080:80 8443:443 &
- 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
- 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
setup-matrix:
if: ${{ needs.checks.outputs.docs_only != 'true' }}
name: Setup Matrix for Smoke Tests
runs-on: ubuntu-22.04
needs: [binaries, checks]
permissions:
contents: read
id-token: write
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Checkout Repository
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
- id: set-matrix
run: |
if [ "${{ github.event_name }}" == "schedule" ]; then
echo "matrix=$(cat .github/data/matrix-regression.json | jq -c --argjson latest '${{ needs.checks.outputs.latest_kindest_node_versions }}' '.k8s += $latest')" >> $GITHUB_OUTPUT
else
echo "matrix=$(cat .github/data/matrix-smoke.json | jq -c --arg latest "${{ needs.checks.outputs.k8s_latest }}" '.k8s += [$latest]')" >> $GITHUB_OUTPUT
fi
- name: Docker Buildx
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
- name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@55bd3a7c6e2ae7cf1877fd1ccb9d54c0503c457c # v2.1.2
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' }}
- name: Login to GCR
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0
with:
registry: gcr.io
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
- name: Check if test image exists
id: check-image
run: |
docker manifest inspect "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
shell: bash
continue-on-error: true
if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
- name: Build Test-Runner Container
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.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') || 'latest' }}"
pull: true
push: ${{ needs.checks.outputs.forked_workflow == 'false' }}
load: false
if: ${{ steps.check-image.outcome == 'failure' }}
smoke-tests:
if: ${{ needs.checks.outputs.docs_only != 'true' }}
name: ${{ matrix.images.label }} ${{ matrix.images.image }} ${{ matrix.k8s }} smoke tests
runs-on: ubuntu-22.04
needs: [checks, setup-matrix]
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.setup-matrix.outputs.matrix) }}
permissions:
contents: read
id-token: write
steps:
- name: Checkout Repository
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
- name: Set image variables
id: image_details
run: |
echo "name=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic${{ contains(matrix.images.nap_modules, 'dos') && '-dos' || '' }}${{ contains(matrix.images.nap_modules, 'waf') && '-nap' || '' }}/nginx${{ contains(matrix.images.image, 'plus') && '-plus' || '' }}-ingress" >> $GITHUB_OUTPUT
echo "build_tag=${{ needs.checks.outputs.build_tag }}${{ contains(matrix.images.image, 'ubi') && '-ubi' || '' }}${{ contains(matrix.images.image, 'alpine') && '-alpine' || '' }}${{ contains(matrix.images.target, 'aws') && '-mktpl' || '' }}${{ contains(matrix.images.image, 'fips') && '-fips' || ''}}" >> $GITHUB_OUTPUT
echo "stable_tag=${{ needs.checks.outputs.stable_tag }}${{ contains(matrix.images.image, 'ubi') && '-ubi' || '' }}${{ contains(matrix.images.image, 'alpine') && '-alpine' || '' }}${{ contains(matrix.images.target, 'aws') && '-mktpl' || '' }}${{ contains(matrix.images.image, 'fips') && '-fips' || ''}}" >> $GITHUB_OUTPUT
- name: NAP modules
id: nap_modules
run: |
[[ "${{ matrix.images.nap_modules }}" == "waf,dos" ]] && modules="waf-dos" || name="${{ matrix.images.nap_modules }}"
[[ "${{ matrix.images.nap_modules }}" == "waf,dos" ]] && modules="both" || modules="${{ matrix.images.nap_modules }}"
echo "modules=${modules}" >> $GITHUB_OUTPUT
echo "name=${name}" >> $GITHUB_OUTPUT
if: ${{ matrix.images.nap_modules }}
- name: Authenticate to Google Cloud
id: auth
uses: google-github-actions/auth@55bd3a7c6e2ae7cf1877fd1ccb9d54c0503c457c # v2.1.2
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' }}
- name: Login to GCR
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0
with:
registry: gcr.io
username: oauth2accesstoken
password: ${{ steps.auth.outputs.access_token }}
if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
- name: Check if base images exist
id: base_exists
run: |
if docker manifest inspect gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/${{ matrix.images.type }}:${{ needs.checks.outputs.docker_md5 }}-${{ matrix.images.image }}${{ matrix.images.nap_modules && format('-{0}', steps.nap_modules.outputs.name) || '' }}; then
echo "exists=0" >> $GITHUB_OUTPUT
else
echo "exists=1" >> $GITHUB_OUTPUT
fi
if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
- name: Docker Buildx
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0
- name: Setup QEMU
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
with:
platforms: ${{ matrix.platforms }}
- name: Build Base Container
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.0
with:
file: build/Dockerfile
context: "."
cache-from: type=gha,scope=${{ matrix.images.image }}${{ matrix.images.nap_modules && format('-{0}', steps.nap_modules.outputs.name) || '' }}
cache-to: type=gha,scope=${{ matrix.images.image }}${{ matrix.images.nap_modules && format('-{0}', steps.nap_modules.outputs.name) || '' }},mode=max
target: common
tags: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/${{ matrix.images.type }}:${{ needs.checks.outputs.docker_md5 }}-${{ matrix.images.image }}${{ matrix.images.nap_modules && format('-{0}', steps.nap_modules.outputs.name) || '' }}
platforms: ${{ matrix.images.platforms }}
pull: true
push: true
build-args: |
BUILD_OS=${{ matrix.images.image }}
IC_VERSION=${{ needs.checks.outputs.ic_version }}
${{ steps.nap_modules.outputs.modules != '' && format('NAP_MODULES={0}', steps.nap_modules.outputs.modules) || '' }}
secrets: |
${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.crt={0}"', secrets.NGINX_AP_CRT) || format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) }}
${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.key={0}"', secrets.NGINX_AP_KEY) || format('"nginx-repo.key={0}"', secrets.NGINX_KEY) }}
${{ contains(matrix.images.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
if: ${{ needs.checks.outputs.forked_workflow == 'false' && steps.base_exists.outputs.exists != 0 }}
- name: Fetch Cached Artifacts
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/dist
key: nginx-ingress-${{ needs.checks.outputs.go_code_md5 }}
- name: Check if test image exists
id: check-image
run: |
docker manifest inspect "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
shell: bash
continue-on-error: true
if: ${{ needs.checks.outputs.forked_workflow == 'false' }}
- name: Build Test-Runner Container
uses: docker/build-push-action@2cdde995de11925a030ce8070c3d77a52ffcf1c0 # v5.3.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') || 'latest' }}"
pull: true
push: ${{ needs.checks.outputs.forked_workflow == 'false' }}
load: ${{ needs.checks.outputs.forked_workflow == 'true' }}
if: ${{ needs.checks.outputs.forked_workflow == 'true' || steps.check-image.outcome == 'failure' }}
- name: Build ${{ matrix.images.image }} Container
uses: docker/build-push-action@v5
with:
file: build/Dockerfile
context: "."
cache-from: type=gha,scope=${{ matrix.images.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}
cache-to: type=gha,scope=${{ matrix.images.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }},mode=max
target: goreleaser${{ needs.checks.outputs.forked_workflow == 'false' && '-prebuilt' || '' }}
tags: "${{ steps.image_details.outputs.name }}:${{ steps.image_details.outputs.build_tag }}"
load: true
pull: true
build-args: |
BUILD_OS=${{ matrix.images.image }}
IC_VERSION=CI
PREBUILT_BASE_IMG=gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/nginx-ic-base/${{ matrix.images.type }}:${{ needs.checks.outputs.docker_md5 }}-${{ matrix.images.image }}${{ steps.nap_modules.outputs.name != '' && format('-{0}', steps.nap_modules.outputs.name) || '' }}
${{ contains(matrix.images.image, 'nap') && format('NAP_MODULES={0}', steps.nap_modules.outputs.modules) || '' }}
${{ contains(matrix.images.marker, 'appprotect') && 'DEBIAN_VERSION=buster-slim' || '' }}
secrets: |
${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.crt={0}"', secrets.NGINX_AP_CRT) || format('"nginx-repo.crt={0}"', secrets.NGINX_CRT) }}
${{ contains(matrix.images.image, 'nap') && format('"nginx-repo.key={0}"', secrets.NGINX_AP_KEY) || format('"nginx-repo.key={0}"', secrets.NGINX_KEY) }}
${{ contains(matrix.images.image, 'ubi') && format('"rhel_license={0}"', secrets.RHEL_LICENSE) || '' }}
- name: Run Smoke Tests
id: smoke-tests
uses: ./.github/actions/smoke-tests
with:
image-type: ${{ matrix.images.image }}
image-name: ${{ steps.image_details.outputs.name }}
tag: ${{ steps.image_details.outputs.build_tag }}
marker: ${{ matrix.images.marker != '' && matrix.images.marker || '' }}
k8s-version: ${{ matrix.k8s }}
azure-ad-secret: ${{ secrets.AZURE_AD_AUTOMATION }}
test-image: "gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/dev/test-runner:${{ hashFiles('./tests/requirements.txt') || 'latest' }}"
- name: Upload Test Results
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3
with:
name: ${{ steps.smoke-tests.outputs.test-results-name }}
path: ${{ github.workspace }}/tests/${{ steps.smoke-tests.outputs.test-results-name }}.html
if: always()
smoke-results:
if: ${{ always() }}
runs-on: ubuntu-22.04
name: Final Smoke Test Results
needs: [smoke-tests]
steps:
- run: |
result="${{ needs.smoke-tests.result }}"
if [[ $result == "success" || $result == "skipped" ]]; then
exit 0
else
exit 1
fi
build-docker:
if: ${{ needs.checks.outputs.docs_only != 'true' }}
name: Build Docker OSS
needs: [checks, smoke-results]
strategy:
fail-fast: false
matrix:
image: [debian, alpine]
platforms:
["linux/arm, linux/arm64, linux/amd64, linux/ppc64le, linux/s390x"]
include:
- image: ubi
platforms: "linux/arm64, linux/amd64, linux/ppc64le, linux/s390x"
uses: ./.github/workflows/build-oss.yml
with:
platforms: ${{ matrix.platforms }}
image: ${{ matrix.image }}
go-md5: ${{ needs.checks.outputs.go_code_md5 }}
publish-image: ${{ needs.checks.outputs.publish_images == 'true' }}
base-image-md5: ${{ needs.checks.outputs.docker_md5 }}
forked-workflow: ${{ needs.checks.outputs.forked_workflow == 'true' }}
permissions:
contents: read
actions: read
security-events: write
id-token: write
packages: write
secrets: inherit
build-docker-plus:
if: ${{ needs.checks.outputs.docs_only != 'true' }}
name: Build Docker Plus
needs: [checks, smoke-results, release-notes]
strategy:
fail-fast: false
matrix:
image: [debian-plus, alpine-plus, alpine-plus-fips]
platforms: ["linux/arm64, linux/amd64"]
target: [goreleaser, aws]
include:
- image: ubi-plus
platforms: "linux/arm64, linux/amd64, linux/s390x"
target: goreleaser
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 }}
release-url: ${{ needs.release-notes.outputs.release-url }}
publish-image: ${{ needs.checks.outputs.publish_images == 'true' }}
publish-aws-market-place: ${{ github.ref_type == 'tag' && startsWith(github.ref, 'refs/heads/release-') && contains(matrix.target, 'aws') }}
publish-nginx-reqistry: ${{ needs.checks.outputs.publish_images == 'true' && ! contains(matrix.target, 'aws') }}
forked-workflow: ${{ needs.checks.outputs.forked_workflow == 'true' }}
permissions:
contents: read
security-events: write
id-token: write
secrets: inherit
build-docker-nap:
if: ${{ needs.checks.outputs.docs_only != 'true' }}
name: Build Docker NAP
needs: [checks, smoke-results, release-notes]
strategy:
fail-fast: false
matrix:
image: [debian-plus-nap]
platforms: ["linux/amd64"]
target: [goreleaser, aws]
nap_modules: [dos, waf, "waf,dos"]
include:
- image: ubi-9-plus-nap
target: goreleaser
platforms: "linux/amd64"
nap_modules: waf
- image: ubi-8-plus-nap
target: goreleaser
platforms: "linux/amd64"
nap_modules: dos
- image: ubi-8-plus-nap
target: goreleaser
platforms: "linux/amd64"
nap_modules: "waf,dos"
- image: ubi-9-plus-nap
target: aws
platforms: "linux/amd64"
nap_modules: waf
- image: ubi-8-plus-nap
target: aws
platforms: "linux/amd64"
nap_modules: dos
- image: ubi-8-plus-nap
target: aws
platforms: "linux/amd64"
nap_modules: "waf,dos"
- image: alpine-plus-nap-fips
target: goreleaser
platforms: "linux/amd64"
nap_modules: waf
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 }}
nap_modules: ${{ matrix.nap_modules }}
release-url: ${{ needs.release-notes.outputs.release-url }}
publish-image: ${{ needs.checks.outputs.publish_images == 'true' }}
publish-aws-market-place: ${{ github.ref_type == 'tag' && startsWith(github.ref, 'refs/heads/release-') && contains(matrix.target, 'aws') }}
publish-nginx-reqistry: ${{ needs.checks.outputs.publish_images == 'true' && ! contains(matrix.target, 'aws') }}
forked-workflow: ${{ needs.checks.outputs.forked_workflow == 'true' }}
permissions:
contents: read
security-events: write
id-token: write
secrets: inherit
publish-helm:
name: Package and Publish Helm Chart
runs-on: ubuntu-22.04
needs: [checks, helm-tests]
if: ${{ github.event_name == 'push' && ! startsWith(github.ref, 'refs/heads/release-') }}
permissions:
contents: write # for pushing to Helm Charts repository
packages: write # for helm to push to GHCR
steps:
- name: Checkout Repository
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
with:
path: kic
- name: Login to GitHub Container Registry
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: DockerHub Login
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Package
id: package
run: |
helm_versions=""
if [ ${{ github.ref_type }} != "tag" ]; then
helm_versions="--app-version edge --version 0.0.0-edge"
else
helm_versions="--app-version ${{ steps.checks.outputs.ic_version }} --version ${{ steps.checks.outputs.chart_version }}"
fi
output=$(helm package ${helm_versions} kic/charts/nginx-ingress)
echo "path=$(basename -- $(echo $output | cut -d: -f2))" >> $GITHUB_OUTPUT
- name: Push to OCI registries
run: |
helm push ${{ steps.package.outputs.path }} oci://ghcr.io/nginxinc/charts
helm push ${{ steps.package.outputs.path }} oci://registry-1.docker.io/nginxcharts
- name: Checkout Repository
uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b # v4.1.4
with:
repository: nginxinc/helm-charts
fetch-depth: 1
token: ${{ secrets.NGINX_PAT }}
path: helm-charts
if: github.ref_type == 'tag'
- name: Push Helm Chart to Helm Charts Repository
run: |
mv ${{ steps.package.outputs.path }} ${{ github.workspace }}/helm-charts/stable/
cd ${{ github.workspace }}/helm-charts
helm repo index stable --url https://helm.nginx.com/stable
git add -A
git -c user.name='NGINX Kubernetes Team' -c user.email='kubernetes@nginx.com' \
commit -m "NGINX Ingress Controller - Release ${{ needs.checks.outputs.chart_version }}"
git push -u origin master
if: github.ref_type == 'tag'
operator:
name: Trigger PR for Operator
runs-on: ubuntu-22.04
needs: [checks, publish-helm]
steps:
- name:
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
github-token: ${{ secrets.NGINX_PAT }}
script: |
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: 'nginx-ingress-helm-operator',
workflow_id: 'sync-chart.yml',
ref: 'main',
inputs: {
chart_version: '${{ needs.checks.outputs.chart_version }}'
},
})
if: github.ref_type == 'tag'
gcp-marketplace:
name: Trigger PR for GCP Marketplace
runs-on: ubuntu-22.04
needs: [checks, build-docker-plus, build-docker-nap]
steps:
- name:
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
github-token: ${{ secrets.NGINX_PAT }}
script: |
await github.rest.actions.createWorkflowDispatch({
owner: context.repo.owner,
repo: 'kubernetes-ingress-gcp',
workflow_id: 'sync-chart.yml',
ref: 'main',
inputs: {
chart_version: '${{ needs.checks.outputs.chart_version }}'
},
})
if: github.ref_type == 'tag'