diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2c7644e4..c7d27ca9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -4,8 +4,6 @@ on: push: branches: - main - tags: - - "v[0-9]+.[0-9]+.[0-9]+" pull_request: branches: - main @@ -21,13 +19,38 @@ permissions: contents: read jobs: + variables: + name: Set Variables + runs-on: ubuntu-24.04 + outputs: + runner: ${{ steps.vars.outputs.runner }} + version: ${{ steps.vars.outputs.version }} + chart_version: ${{ steps.vars.outputs.chart_version }} + openshift_version: ${{ steps.vars.outputs.openshift_version }} + steps: + - name: Checkout Repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Output Variables + id: vars + run: | + runner=ubuntu-24.04 + if [ "${{ github.event_name }}" == "push" ]; then + runner=ubuntu-24.04-amd64 + fi + echo "runner=$runner" >> $GITHUB_OUTPUT + echo "version=$(git describe --tags)" >> $GITHUB_OUTPUT + echo "chart_version=$(yq '.appVersion' > $GITHUB_OUTPUT + echo "openshift_version=$(yq '.annotations["com.redhat.openshift.versions"]' > $GITHUB_OUTPUT + build: name: Build Image - runs-on: ubuntu-24.04 + runs-on: ${{ needs.variables.outputs.runner }} + needs: [variables] outputs: version: ${{ steps.meta.outputs.version }} permissions: - contents: write # for lucacome/draft-release to create a draft release + contents: read security-events: write # for github/codeql-action/upload-sarif to upload SARIF results packages: write # for docker/build-push-action to push to GHCR steps: @@ -66,13 +89,6 @@ jobs: - name: Docker Buildx uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - - name: Output Variables - id: vars - run: | - echo "version=$(git describe --tags)" >> $GITHUB_OUTPUT - echo "chart_version=$(yq '.appVersion' > $GITHUB_OUTPUT - echo "openshift_version=$(yq '.annotations["com.redhat.openshift.versions"]' > $GITHUB_OUTPUT - - name: Docker meta id: meta uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0 @@ -84,14 +100,13 @@ jobs: tags: | type=edge type=ref,event=pr - type=semver,pattern={{version}} labels: | org.opencontainers.image.documentation=https://docs.nginx.com/nginx-ingress-controller org.opencontainers.image.vendor=NGINX Inc name="NGINX Ingress Operator" maintainer="kubernetes@nginx.com" vendor="NGINX Inc" - version=${{ steps.vars.outputs.version }} + version=${{ needs.variables.outputs.version }} release=1 summary="The NGINX Ingress Operator is a Kubernetes/OpenShift component which deploys and manages one or more NGINX/NGINX Plus Ingress Controllers" description="The NGINX Ingress Operator is a Kubernetes/OpenShift component which deploys and manages one or more NGINX/NGINX Plus Ingress Controllers" @@ -120,12 +135,14 @@ jobs: format: "sarif" output: "trivy-results.sarif" ignore-unfixed: "true" + if: github.event_name != 'pull_request' - name: Upload Trivy scan results to GitHub Security tab uses: github/codeql-action/upload-sarif@64d10c13136e1c5bce3e5fbde8d4906eeaafc885 # v3.30.6 continue-on-error: true with: sarif_file: "trivy-results.sarif" + if: github.event_name != 'pull_request' - name: Upload Scan Results uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 @@ -133,17 +150,17 @@ jobs: with: name: "trivy-results.sarif" path: "trivy-results.sarif" - if: always() + if: github.event_name != 'pull_request' - name: Create/Update Draft uses: lucacome/draft-release@fd099feb33710d1fa27b915a08a7acd6a1fb7fd2 # v2.0.0 with: minor-label: "enhancement" major-label: "change" - publish: ${{ github.ref_type == 'tag' }} + publish: false variables: | - nic_version=${{ steps.vars.outputs.chart_version }} - openshift_version=${{ steps.vars.outputs.openshift_version }} + nic_version=${{ needs.variables.outputs.chart_version }} + openshift_version=${{ needs.variables.outputs.openshift_version }} notes-footer: | ## Compatibility @@ -156,65 +173,4 @@ jobs: uses: ./.github/workflows/e2e-test.yml needs: build with: - operator_version: ${{ github.ref_type == 'tag' && needs.build.outputs.version || 'edge' }} - - certify: - name: Certify for Red Hat OpenShift - runs-on: ubuntu-24.04 - needs: [build, e2e-test] - if: ${{ github.ref_type == 'tag' }} - env: - preflight_version: 1.14.1 # renovate: datasource=github-releases depName=preflight packageName=redhat-openshift-ecosystem/openshift-preflight - steps: - - name: Checkout Repository - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - - - name: Certify Images - continue-on-error: false - run: | - curl -fsSL https://github.com/redhat-openshift-ecosystem/openshift-preflight/releases/download/${{ env.preflight_version }}/preflight-linux-amd64 --output preflight - chmod +x preflight - - IFS=',' read -ra arch_list <<< "${{ env.platforms }}" - - for arch in "${arch_list[@]}"; do - architecture=("${arch#*/}") - ./preflight check container quay.io/nginx/nginx-ingress-operator:${{ needs.build.outputs.version }} --pyxis-api-token ${{ secrets.PYXIS_API_TOKEN }} --certification-project-id ${{ secrets.CERTIFICATION_PROJECT_ID }} --platform $architecture --submit - done - - ## Disable PR creation until issues with NGINX_PAT are resolved - # - name: Make - # run: | - # make bundle USE_IMAGE_DIGESTS=true - - # - name: Checkout certified-operators repo - # uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - # with: - # token: ${{ secrets.NGINX_PAT }} - # repository: nginx-bot/certified-operators - # path: certified-operators - - # - name: Update certified-operators repo - # working-directory: certified-operators/operators/nginx-ingress-operator - # run: | - # mkdir v${{ needs.build.outputs.version }} - # cp -R ../../../bundle/manifests v${{ needs.build.outputs.version }}/ - # cp -R ../../../bundle/metadata v${{ needs.build.outputs.version }}/ - - # - name: Commit changes - # uses: stefanzweifel/git-auto-commit-action@b863ae1933cb653a53c021fe36dbb774e1fb9403 # v5.2.0 - # with: - # commit_message: operator nginx-ingress-operator (v${{ needs.build.outputs.version }}) - # commit_author: nginx-bot - # commit_user_name: nginx-bot - # commit_user_email: integrations@nginx.com - # create_branch: true - # branch: update-nginx-ingress-operator-to-v${{ needs.build.outputs.version }} - # repository: certified-operators - - # - name: Create PR - # working-directory: certified-operators - # run: | - # gh pr create --title "operator nginx-ingress-operator (v${{ needs.build.outputs.version }})" --body "Update nginx-ingress-operator to v${{ needs.build.outputs.version }}" --head nginx-bot:update-nginx-ingress-operator-to-v${{ needs.build.outputs.version }} --base main --repo redhat-openshift-ecosystem/certified-operators - # env: - # GITHUB_TOKEN: ${{ secrets.NGINX_PAT }} + operator_version: ${{ needs.build.outputs.version }} diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 2b77ab53..1ac8eeb9 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -36,6 +36,35 @@ jobs: - name: Checkout Repository uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + - name: Check if image exists + id: image_exists + run: | + exists=false + if docker pull nginx/nginx-ingress-operator:${{ env.OPERATOR_VERSION }}; then + exists=true + fi + echo "exists=${exists}" >> $GITHUB_OUTPUT + + - name: Docker Buildx + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 + if: steps.image_exists.outputs.exists == 'false' + + - name: Build Image + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + context: "." + cache-from: type=gha + cache-to: type=gha,mode=max + tags: nginx/nginx-ingress-operator:${{ env.OPERATOR_VERSION }} + platforms: ${{ github.event_name != 'pull_request' && env.platforms || '' }} + load: true + push: false + no-cache: ${{ github.event_name != 'pull_request' }} + pull: true + sbom: false + provenance: false + if: steps.image_exists.outputs.exists == 'false' + - name: Get Latest Versions run: | # Get latest supported Kubernetes version from Minikube @@ -68,6 +97,7 @@ jobs: - name: Start Minikube run: | minikube start --kubernetes-version=${{ env.KUBERNETES_VERSION }} --driver=docker --memory=4g --cpus=2 + minikube image load nginx/nginx-ingress-operator:${{ env.OPERATOR_VERSION }} - name: Verify Kubernetes cluster run: | diff --git a/.github/workflows/release-operator.yml b/.github/workflows/release-operator.yml new file mode 100644 index 00000000..289026aa --- /dev/null +++ b/.github/workflows/release-operator.yml @@ -0,0 +1,236 @@ +name: Release Operator + +run-name: ${{ inputs.dry_run && '[DRY RUN] ' || '' }}Release Operator ${{ inputs.operator_version }} by @${{ github.actor }} + +on: + workflow_dispatch: + inputs: + operator_version: + description: "Operator version to release" + required: true + type: string + dry_run: + description: "Dry Run?" + type: boolean + default: false + +defaults: + run: + shell: bash + +permissions: + contents: read + +jobs: + variables: + name: Set Variables + runs-on: ubuntu-24.04 + permissions: + contents: read + outputs: + chart_version: ${{ steps.vars.outputs.chart_version }} + openshift_version: ${{ steps.vars.outputs.openshift_version }} + steps: + - name: Checkout Repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Output Variables + id: vars + run: | + echo "chart_version=$(yq '.appVersion' > $GITHUB_OUTPUT + echo "openshift_version=$(yq '.annotations["com.redhat.openshift.versions"]' > $GITHUB_OUTPUT + cat $GITHUB_OUTPUT + + tag: + name: Create Tag on release branch + runs-on: ubuntu-24.04 + needs: [variables] + permissions: + contents: write + steps: + - name: Checkout Repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + fetch-depth: 0 + + - name: Create new release Tag + run: | + git config --global user.email "kubernetes@nginx.com" + git config --global user.name "NGINX Kubernetes Team" + tag="v${{ inputs.operator_version }}" + if ! git rev-parse --verify refs/tags/${tag}; then + echo "Adding tag ${tag}." + git tag -a ${tag} -m "Version ${tag#v*}" + echo "Pushing tag ${tag} to main branch" + if ! ${{ inputs.dry_run }}; then + git push origin "${tag}" + else + echo "DRY RUN not making any changes" + git push --dry-run origin "${tag}" + fi + else + echo "Warning: Tag ${tag} already exists. Not making any changes" + fi + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + build: + name: Build Operator Image + runs-on: ubuntu-24.04-amd64 + needs: [variables] + outputs: + version: ${{ steps.meta.outputs.version }} + permissions: + contents: read + packages: write + security-events: write + steps: + - name: Checkout Repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: DockerHub Login + uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + if: ${{ ! inputs.dry_run }} + + - name: Login to GitHub Container Registry + uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to Quay.io + uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0 + with: + registry: quay.io + username: ${{ secrets.QUAY_USERNAME }} + password: ${{ secrets.QUAY_ROBOT_TOKEN }} + if: ${{ ! inputs.dry_run }} + + - name: Setup QEMU + uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0 + with: + platforms: arm64 + + - name: Docker Buildx + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 + + - name: Output Variables + id: vars + run: | + echo "version=v${{ inputs.operator_version }}" >> $GITHUB_OUTPUT + + - name: Docker meta + id: meta + uses: docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0 + with: + images: | + nginx/nginx-ingress-operator + ghcr.io/nginx/nginx-ingress-operator + quay.io/nginx/nginx-ingress-operator + tags: | + type=semver,pattern={{version}},value=v${{ inputs.operator_version }} + type=semver,pattern={{major}}.{{minor}},value=v${{ inputs.operator_version }} + type=raw,value=latest + labels: | + org.opencontainers.image.documentation=https://docs.nginx.com/nginx-ingress-controller + org.opencontainers.image.vendor=NGINX Inc + name="NGINX Ingress Operator" + maintainer="kubernetes@nginx.com" + vendor="NGINX Inc" + version=${{ steps.vars.outputs.version }} + release=1 + summary="The NGINX Ingress Operator is a Kubernetes/OpenShift component which deploys and manages one or more NGINX/NGINX Plus Ingress Controllers" + description="The NGINX Ingress Operator is a Kubernetes/OpenShift component which deploys and manages one or more NGINX/NGINX Plus Ingress Controllers" + + - name: Build and Push Operator Image + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 + with: + context: "." + cache-from: type=gha + cache-to: type=gha,mode=max + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + platforms: linux/amd64,linux/arm64 + push: ${{ ! inputs.dry_run }} + no-cache: false + pull: true + sbom: true + provenance: false + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@b6643a29fecd7f34b3597bc6acb0a98b03d33ff8 # 0.33.1 + continue-on-error: true + with: + image-ref: nginx/nginx-ingress-operator:v${{ inputs.operator_version }} + format: "sarif" + output: "trivy-results.sarif" + ignore-unfixed: "true" + + - name: Upload Trivy scan results to GitHub Security tab + uses: github/codeql-action/upload-sarif@192325c86100d080feab897ff886c34abd4c83a3 # v3.30.3 + continue-on-error: true + with: + sarif_file: "trivy-results.sarif" + + - name: Upload Scan Results + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + continue-on-error: true + with: + name: "trivy-results.sarif" + path: "trivy-results.sarif" + if: always() + + certify-openshift-images: + if: ${{ ! cancelled() && ! failure() && ! inputs.dry_run }} + name: Certify for Red Hat OpenShift + runs-on: ubuntu-24.04-amd64 + needs: [variables, build] + env: + preflight_version: 1.14.1 # renovate: datasource=github-releases depName=preflight packageName=redhat-openshift-ecosystem/openshift-preflight + steps: + - name: Checkout Repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Certify Images + continue-on-error: false + run: | + curl -fsSL https://github.com/redhat-openshift-ecosystem/openshift-preflight/releases/download/${{ env.preflight_version }}/preflight-linux-amd64 --output preflight + chmod +x preflight + + IFS=',' read -ra arch_list <<< "linux/amd64,linux/arm64" + + for arch in "${arch_list[@]}"; do + architecture=("${arch#*/}") + ./preflight check container quay.io/nginx/nginx-ingress-operator:v${{ inputs.operator_version }} --pyxis-api-token ${{ secrets.PYXIS_API_TOKEN }} --certification-project-id ${{ secrets.CERTIFICATION_PROJECT_ID }} --platform $architecture --submit + done + + github-release: + if: ${{ ! cancelled() && ! failure() }} + name: Publish release to GitHub + runs-on: ubuntu-24.04 + needs: [variables, build, tag, certify-openshift-images] + permissions: + contents: write + issues: write + steps: + - name: Checkout Repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Create/Publish Release + uses: lucacome/draft-release@00f74370c044c322da6cb52acc707d62c7762c71 # v1.2.4 + with: + minor-label: "enhancement" + major-label: "change" + publish: ${{ ! inputs.dry_run }} + variables: | + nic_version=${{ needs.variables.outputs.chart_version }} + openshift_version=${{ needs.variables.outputs.openshift_version }} + notes-footer: | + ## Compatibility + + - NGINX Ingress Controller {{nic_version}} + - OpenShift {{openshift_version}} or newer.