From 1f5a99efa288ff20405b1079087ef382c34983c7 Mon Sep 17 00:00:00 2001 From: Paul Abel <128620221+pdabelf5@users.noreply.github.com> Date: Mon, 29 Jul 2024 12:02:33 +0100 Subject: [PATCH 1/3] set ic-version parameter when building images (#6075) --- .github/workflows/ci.yml | 3 +++ .github/workflows/image-promotion.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 46884b641b..4bc2c4e05c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -304,6 +304,7 @@ jobs: 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 @@ -329,6 +330,7 @@ jobs: 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 @@ -353,6 +355,7 @@ jobs: 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 diff --git a/.github/workflows/image-promotion.yml b/.github/workflows/image-promotion.yml index 415fb0840f..1f451e8b11 100644 --- a/.github/workflows/image-promotion.yml +++ b/.github/workflows/image-promotion.yml @@ -170,6 +170,7 @@ jobs: authenticated: true tag: ${{ needs.checks.outputs.build_tag }} branch: ${{ github.ref }} + ic-version: ${{ needs.checks.outputs.ic_version }} permissions: contents: read actions: read @@ -196,6 +197,7 @@ jobs: authenticated: true tag: ${{ needs.checks.outputs.build_tag }} branch: ${{ github.ref }} + ic-version: ${{ needs.checks.outputs.ic_version }} permissions: contents: read actions: read @@ -223,6 +225,7 @@ jobs: authenticated: true tag: ${{ needs.checks.outputs.build_tag }} branch: ${{ github.ref }} + ic-version: ${{ needs.checks.outputs.ic_version }} permissions: contents: read actions: read From 95fd76ec83f98744e737f4edc7df4d82c5186a9f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 Jul 2024 11:15:10 +0000 Subject: [PATCH 2/3] Bump the actions group with 2 updates (#6076) Bumps the actions group with 2 updates: [github/codeql-action](https://github.com/github/codeql-action) and [ossf/scorecard-action](https://github.com/ossf/scorecard-action). Updates `github/codeql-action` from 3.25.14 to 3.25.15 - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/5cf07d8b700b67e235fbb65cbc84f69c0cf10464...afb54ba388a7dca6ecae48f608c4ff05ff4cc77a) Updates `ossf/scorecard-action` from 2.3.3 to 2.4.0 - [Release notes](https://github.com/ossf/scorecard-action/releases) - [Changelog](https://github.com/ossf/scorecard-action/blob/main/RELEASE.md) - [Commits](https://github.com/ossf/scorecard-action/compare/dc50aa9510b46c811795eb24b2f1ba02a914e534...62b2cac7ed8198b15735ed49ab1e5cf35480ba46) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch dependency-group: actions - dependency-name: ossf/scorecard-action dependency-type: direct:production update-type: version-update:semver-minor dependency-group: actions ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Paul Abel <128620221+pdabelf5@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 6 +++--- .github/workflows/image-promotion.yml | 6 +++--- .github/workflows/scorecards.yml | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 8ead427001..92e2a44e54 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -70,7 +70,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@5cf07d8b700b67e235fbb65cbc84f69c0cf10464 # v3.25.14 + uses: github/codeql-action/init@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -89,7 +89,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@5cf07d8b700b67e235fbb65cbc84f69c0cf10464 # v3.25.14 + uses: github/codeql-action/autobuild@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15 # ℹī¸ Command-line programs to run using the OS shell. # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun @@ -102,6 +102,6 @@ jobs: # ./location_of_script_within_repo/buildscript.sh - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@5cf07d8b700b67e235fbb65cbc84f69c0cf10464 # v3.25.14 + uses: github/codeql-action/analyze@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15 with: category: "/language:${{matrix.language}}" diff --git a/.github/workflows/image-promotion.yml b/.github/workflows/image-promotion.yml index 1f451e8b11..46cc42c402 100644 --- a/.github/workflows/image-promotion.yml +++ b/.github/workflows/image-promotion.yml @@ -430,7 +430,7 @@ jobs: overwrite: true - name: Upload Scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@5cf07d8b700b67e235fbb65cbc84f69c0cf10464 # v3.25.14 + uses: github/codeql-action/upload-sarif@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15 with: sarif_file: "${{ steps.directory.outputs.directory }}/" @@ -520,7 +520,7 @@ jobs: overwrite: true - name: Upload Scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@5cf07d8b700b67e235fbb65cbc84f69c0cf10464 # v3.25.14 + uses: github/codeql-action/upload-sarif@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15 with: sarif_file: "${{ steps.directory.outputs.directory }}/" @@ -617,7 +617,7 @@ jobs: overwrite: true - name: Upload Scan results to GitHub Security tab - uses: github/codeql-action/upload-sarif@5cf07d8b700b67e235fbb65cbc84f69c0cf10464 # v3.25.14 + uses: github/codeql-action/upload-sarif@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15 with: sarif_file: "${{ steps.directory.outputs.directory }}/" diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index 390b5ff47f..efb1413a3d 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -34,7 +34,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3 + uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0 with: results_file: results.sarif results_format: sarif @@ -57,6 +57,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard. - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@5cf07d8b700b67e235fbb65cbc84f69c0cf10464 # v3.25.14 + uses: github/codeql-action/upload-sarif@afb54ba388a7dca6ecae48f608c4ff05ff4cc77a # v3.25.15 with: sarif_file: results.sarif From 25bfece8187e78bc2caa9b454475c3825544ea18 Mon Sep 17 00:00:00 2001 From: Paul Abel <128620221+pdabelf5@users.noreply.github.com> Date: Mon, 29 Jul 2024 13:39:34 +0100 Subject: [PATCH 3/3] build single image (#6069) --- .github/scripts/exclude_ci_files.txt | 2 + .github/workflows/build-single-image.yml | 82 ++++++++++++++++++++++++ Makefile | 3 +- build/Dockerfile | 27 +++++--- 4 files changed, 103 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/build-single-image.yml diff --git a/.github/scripts/exclude_ci_files.txt b/.github/scripts/exclude_ci_files.txt index 457bb41969..476d958b78 100644 --- a/.github/scripts/exclude_ci_files.txt +++ b/.github/scripts/exclude_ci_files.txt @@ -15,6 +15,8 @@ .github/workflows/build-base-images.yml .github/workflows/build-ot-dependency.yml .github/workflows/build-test-image.yml +.github/workflows/build-ubi-dependency.yml +.github/workflows/build-single-image.yml .github/workflows/cache-update.yml .github/workflows/cherry-pick.yml .github/workflows/codeql-analysis.yml diff --git a/.github/workflows/build-single-image.yml b/.github/workflows/build-single-image.yml new file mode 100644 index 0000000000..d8258bc474 --- /dev/null +++ b/.github/workflows/build-single-image.yml @@ -0,0 +1,82 @@ +name: Build single image +run-name: Building gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/${{ github.actor }}-dev/${{ inputs.prefix }}:${{ inputs.tag }} by @${{ github.actor }} + +on: + workflow_dispatch: + inputs: + target: + description: 'Image build make target to call' + required: true + type: string + prefix: + description: 'Image prefix to use in GCR, e.g. nginx-ic' + required: true + type: string + tag: + description: 'Image tag to use in GCR, e.g. 3.7.0-SNAPSHOT' + required: true + type: string + branch: + description: 'Branch to checkout for build' + required: false + type: string + default: main + plus_repo: + description: 'Plus repo to install from' + required: true + default: 'pkgs.nginx.com' + type: choice + options: + - pkgs.nginx.com + - pkgs-test.nginx.com + +defaults: + run: + shell: bash + +permissions: + contents: read + +jobs: + build: + permissions: + contents: read # for docker/build-push-action to read repo content + id-token: write # for login to GCP + runs-on: ubuntu-22.04 + steps: + - name: Checkout Repository + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + ref: ${{ inputs.branch }} + fetch-depth: 0 + + - name: Authenticate to Google Cloud + id: auth + uses: google-github-actions/auth@71fee32a0bb7e97b4d33d548e7d957010649d8fa # v2.1.3 + with: + token_format: access_token + workload_identity_provider: ${{ secrets.GCR_WORKLOAD_IDENTITY }} + service_account: ${{ secrets.GCR_SERVICE_ACCOUNT }} + + - name: Login to GCR + uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 + with: + registry: gcr.io + username: oauth2accesstoken + password: ${{ steps.auth.outputs.access_token }} + + - name: Docker Buildx + uses: docker/setup-buildx-action@aa33708b10e362ff993539393ff100fa93ed6a27 # v3.5.0 + + - name: Build Image + run: | + make ${{ inputs.target }} + env: + REGISTRY: gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/${{ github.actor }}-dev + PREFIX: ${{ inputs.prefix }} + TAG: ${{ inputs.tag }} + PLUS_REPO: ${{ inputs.plus_repo }} + + - name: Push image + run: + docker push gcr.io/f5-gcs-7899-ptg-ingrss-ctlr/${{ github.actor }}-dev/${{ inputs.prefix }}:${{ inputs.tag }} diff --git a/Makefile b/Makefile index e7d789db6b..9f44a2afa3 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,8 @@ PLUS_ARGS = --secret id=nginx-repo.crt,src=nginx-repo.crt --secret id=nginx-repo PREFIX ?= nginx/nginx-ingress ## The name of the image. For example, nginx/nginx-ingress TAG ?= $(VERSION:v%=%) ## The tag of the image. For example, 2.0.0 TARGET ?= local ## The target of the build. Possible values: local, container and download -override DOCKER_BUILD_OPTIONS += --build-arg IC_VERSION=$(VERSION) ## The options for the docker build command. For example, --pull +PLUS_REPO ?= "pkgs.nginx.com" ## The package repo to install nginx-plus from +override DOCKER_BUILD_OPTIONS += --build-arg IC_VERSION=$(VERSION) --build-arg PACKAGE_REPO=$(PLUS_REPO) ## The options for the docker build command. For example, --pull ARCH ?= amd64 ## The architecture of the image or binary. For example: amd64, arm64, ppc64le, s390x. Not all architectures are supported for all targets GOOS ?= linux ## The OS of the binary. For example linux, darwin NGINX_AGENT ?= true diff --git a/build/Dockerfile b/build/Dockerfile index d918957c83..6e4a6a07f2 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -7,6 +7,7 @@ ARG PREBUILT_BASE_IMG=nginx/nginx-ingress:${DOWNLOAD_TAG} ARG NGINX_AGENT=false ARG IMAGE_NAME=nginx/nginx-ingress ARG WAF_VERSION=v4 +ARG PACKAGE_REPO=pkgs.nginx.com ############################################# Base images containing libs for Opentracing and FIPS ############################################# @@ -45,6 +46,7 @@ FROM scratch AS nginx-files ARG IC_VERSION ARG BUILD_OS ARG NGINX_PLUS_VERSION +ARG PACKAGE_REPO # the following links can be replaced with local files if needed, i.e. ADD --chown=101:0 ADD --link --chown=101:0 https://cs.nginx.com/static/files/90pkgs-nginx 90pkgs-nginx @@ -64,15 +66,17 @@ ADD --link --chown=101:0 https://raw.githubusercontent.com/nginxinc/k8s-common/m ADD --link --chown=101:0 https://raw.githubusercontent.com/nginxinc/k8s-common/main/files/nap-dos-debian-12.repo nap-dos-12.sources ADD --link --chown=101:0 https://raw.githubusercontent.com/nginxinc/k8s-common/main/files/nap-waf-v5-debian-12.repo nap-waf-v5-12.sources ADD --link --chown=101:0 https://raw.githubusercontent.com/nginxinc/k8s-common/main/files/agent-debian-12.repo debian-agent-12.sources +ADD --link --chown=101:0 https://cs.nginx.com/static/files/nginx-agent.repo nginx-agent.repo RUN --mount=from=busybox:musl,src=/bin/,dst=/bin/ printf "%s\n" "Acquire::https::pkgs.nginx.com::User-Agent k8s-ic-$IC_VERSION${BUILD_OS##debian-plus}-apt;" >> 90pkgs-nginx \ + && if ! grep -q "${PACKAGE_REPO}" 90pkgs-nginx ; then cat 90pkgs-nginx | sed -e "s/pkgs.nginx.com/${PACKAGE_REPO}/g" >> 90pkgs-nginx; fi \ && printf "%s\n" "user_agent=k8s-ic-$IC_VERSION${BUILD_OS##ubi*plus}-dnf" | tee -a nginx-plus-*.repo \ - && sed -i -e "s;%VERSION%;${NGINX_PLUS_VERSION};g" *.sources \ + && sed -i -e "s;%VERSION%;${NGINX_PLUS_VERSION};g" -e "s;pkgs.nginx.com;${PACKAGE_REPO};g" -e "s;${PACKAGE_REPO}/app-protect-security-updates;pkgs.nginx.com/app-protect-security-updates;g" *.sources \ && sed -i -e "y/0/1/" app-protect-v5-*.repo \ - && sed -i -e "y/0/1/" -e "1,8s;/centos;/${NGINX_PLUS_VERSION}/centos;" nginx-plus-*.repo app-protect-?.repo app-protect-dos-8.repo \ + && sed -i -e "y/0/1/" -e "1,8s;/centos;/${NGINX_PLUS_VERSION}/centos;" -e "s;pkgs.nginx.com;${PACKAGE_REPO};g" -e "s;${PACKAGE_REPO}/app-protect-security-updates;pkgs.nginx.com/app-protect-security-updates;g" nginx-plus-*.repo app-protect-?.repo app-protect-dos-8.repo \ + && sed -i -e "y/0/1/" -e "s;pkgs.nginx.com;${PACKAGE_REPO};g" nginx-agent.repo app-protect-v5-?.repo \ && echo HTTP_USER_AGENT="k8s-ic-$IC_VERSION${BUILD_OS##alpine-plus}-apk" > user_agent -ADD --link --chown=101:0 https://cs.nginx.com/static/files/nginx-agent.repo nginx-agent.repo ADD --link --chown=101:0 --chmod=0755 https://raw.githubusercontent.com/nginxinc/k8s-common/main/files/patch-os.sh patch-os.sh ADD --link --chown=101:0 --chmod=0755 build/scripts/common.sh common.sh ADD --link --chown=101:0 --chmod=0755 build/scripts/nap-waf.sh nap-waf.sh @@ -100,6 +104,7 @@ USER 101 ############################################# Base image for Alpine with NGINX Plus ############################################# FROM alpine:3.20@sha256:0a4eaa0eecf5f8c050e5bba433f58c052be7587ee8af3e8b3910ef9ab5fbe9f5 AS alpine-plus ARG NGINX_PLUS_VERSION +ARG PACKAGE_REPO ENV NGINX_VERSION=${NGINX_PLUS_VERSION} @@ -109,7 +114,7 @@ RUN --mount=type=secret,id=nginx-repo.crt,dst=/etc/apk/cert.pem,mode=0644 \ --mount=type=bind,from=nginx-files,src=nginx_signing.rsa.pub,target=/etc/apk/keys/nginx_signing.rsa.pub \ --mount=type=bind,from=nginx-files,src=user_agent,target=/tmp/user_agent \ export $(cat /tmp/user_agent) \ - && printf "%s\n" "https://pkgs.nginx.com/plus/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ + && printf "%s\n" "https://${PACKAGE_REPO}/plus/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && apk add --no-cache nginx-plus nginx-plus-module-njs nginx-plus-module-opentracing nginx-plus-module-fips-check libcap libcurl \ && cp -av /tmp/ot/usr/local/lib/libjaegertracing*so* /tmp/ot/usr/local/lib/libzipkin*so* /tmp/ot/usr/local/lib/libdd*so* /tmp/ot/usr/local/lib/libyaml*so* /usr/local/lib/ \ && ldconfig /usr/local/lib/ \ @@ -134,6 +139,7 @@ FROM alpine:3.17@sha256:ef813b2faa3dd1a37f9ef6ca98347b72cd0f55e4ab29fb90946f1b85 ARG NGINX_PLUS_VERSION ARG NGINX_AGENT ARG NGINX_PLUS_VERSION +ARG PACKAGE_REPO ENV NGINX_VERSION=${NGINX_PLUS_VERSION} @@ -145,10 +151,10 @@ RUN --mount=type=bind,from=alpine-fips-3.17,target=/tmp/fips/ \ --mount=type=bind,from=nginx-files,src=nginx_signing.rsa.pub,target=/etc/apk/keys/nginx_signing.rsa.pub \ --mount=type=bind,from=nginx-files,src=agent.sh,target=/usr/local/bin/agent.sh \ --mount=type=bind,from=nginx-files,src=nap-waf.sh,target=/usr/local/bin/nap-waf.sh \ - printf "%s\n" "https://pkgs.nginx.com/plus/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ - && printf "%s\n" "https://pkgs.nginx.com/app-protect/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ + printf "%s\n" "https://${PACKAGE_REPO}/plus/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ + && printf "%s\n" "https://${PACKAGE_REPO}/app-protect/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && printf "%s\n" "https://pkgs.nginx.com/app-protect-security-updates/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ - && printf "%s\n" "https://pkgs.nginx.com/nginx-agent/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ + && printf "%s\n" "https://${PACKAGE_REPO}/nginx-agent/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-opentracing nginx-plus-module-fips-check \ && if [ "${NGINX_AGENT}" = "true" ]; then apk add --no-cache nginx-agent; fi \ && mkdir -p /usr/ssl \ @@ -170,6 +176,7 @@ FROM alpine:3.17@sha256:ef813b2faa3dd1a37f9ef6ca98347b72cd0f55e4ab29fb90946f1b85 ARG NGINX_PLUS_VERSION ARG NGINX_AGENT ARG NGINX_PLUS_VERSION +ARG PACKAGE_REPO ENV NGINX_VERSION=${NGINX_PLUS_VERSION} @@ -180,9 +187,9 @@ RUN --mount=type=bind,from=alpine-fips-3.17,target=/tmp/fips/ \ --mount=type=bind,from=nginx-files,src=nginx_signing.rsa.pub,target=/etc/apk/keys/nginx_signing.rsa.pub \ --mount=type=bind,from=nginx-files,src=agent.sh,target=/usr/local/bin/agent.sh \ --mount=type=bind,from=nginx-files,src=nap-waf.sh,target=/usr/local/bin/nap-waf.sh \ - printf "%s\n" "https://pkgs.nginx.com/plus/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ - && printf "%s\n" "https://pkgs.nginx.com/app-protect-x-plus/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ - && printf "%s\n" "https://pkgs.nginx.com/nginx-agent/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ + printf "%s\n" "https://${PACKAGE_REPO}/plus/${NGINX_PLUS_VERSION}/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ + && printf "%s\n" "https://${PACKAGE_REPO}/app-protect-x-plus/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ + && printf "%s\n" "https://${PACKAGE_REPO}/nginx-agent/alpine/v$(grep -E -o '^[0-9]+\.[0-9]+' /etc/alpine-release)/main" >> /etc/apk/repositories \ && apk add --no-cache libcap-utils libcurl nginx-plus nginx-plus-module-njs nginx-plus-module-opentracing nginx-plus-module-fips-check \ && if [ "${NGINX_AGENT}" = "true" ]; then apk add --no-cache nginx-agent; fi \ && mkdir -p /usr/ssl \