ci: Run workflows on GitHub-hosted ubuntu-26.04 runners (backport #72… #391
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release Please | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| finalize_tag: | |
| description: Existing release tag to sign and update, for example v2.15.1 | |
| required: false | |
| push: | |
| branches: | |
| - main | |
| - "release-[0-9]*.[0-9]*" | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| env: | |
| # arduino/setup-task and actions4gh/setup-gh (both latest) still | |
| # declare node20; opt in to the 2026-06-16 node24 default early. | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" | |
| jobs: | |
| validate-release-ref: | |
| name: Validate Release Ref | |
| runs-on: ubuntu-26.04 | |
| steps: | |
| - name: Allow only release refs | |
| run: | | |
| if [[ "${GITHUB_REF_NAME}" == "main" || "${GITHUB_REF_NAME}" =~ ^release-[0-9]+\.[0-9]+$ ]]; then | |
| exit 0 | |
| fi | |
| echo "::error::Release Please can only run on main or release-X.Y branches. Current ref: ${GITHUB_REF_NAME}" | |
| exit 1 | |
| release-please: | |
| needs: [validate-release-ref] | |
| if: ${{ github.event_name != 'workflow_dispatch' || inputs.finalize_tag == '' }} | |
| runs-on: ubuntu-26.04 | |
| outputs: | |
| release_created: ${{ steps.release.outputs.release_created }} | |
| tag_name: ${{ steps.release.outputs.tag_name }} | |
| version: ${{ steps.release.outputs.version }} | |
| major: ${{ steps.release.outputs.major }} | |
| minor: ${{ steps.release.outputs.minor }} | |
| patch: ${{ steps.release.outputs.patch }} | |
| prs_created: ${{ steps.release.outputs.prs_created }} | |
| prs: ${{ steps.release.outputs.prs }} | |
| steps: | |
| - uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0 | |
| id: release | |
| with: | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| target-branch: ${{ github.ref_name }} | |
| config-file: ${{ github.ref_name == 'main' && 'release-please-config.json' || 'release-please-config-maintenance.json' }} | |
| manifest-file: .release-please-manifest.json | |
| preview-release-notes: | |
| name: Preview Release Notes | |
| needs: [release-please] | |
| if: ${{ needs.release-please.outputs.prs_created == 'true' && needs.release-please.outputs.release_created != 'true' }} | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| uses: ./.github/workflows/release-notes-engine.yml | |
| with: | |
| checkout_ref: ${{ fromJSON(needs.release-please.outputs.prs)[0].headBranchName }} | |
| preview_pr_number: ${{ fromJSON(needs.release-please.outputs.prs)[0].number }} | |
| secrets: | |
| SYNC_APP_PRIVATE_KEY: ${{ secrets.SYNC_APP_PRIVATE_KEY }} | |
| create-maintenance-branch: | |
| name: Create Maintenance Branch | |
| needs: [release-please] | |
| if: >- | |
| ${{ | |
| github.ref_name == 'main' && | |
| needs.release-please.outputs.release_created == 'true' && | |
| needs.release-please.outputs.patch == '0' | |
| }} | |
| runs-on: ubuntu-26.04 | |
| permissions: | |
| contents: write | |
| env: | |
| TAG_NAME: ${{ needs.release-please.outputs.tag_name }} | |
| MAJOR: ${{ needs.release-please.outputs.major }} | |
| MINOR: ${{ needs.release-please.outputs.minor }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 0 | |
| - name: Create branch for patch releases | |
| run: | | |
| branch="release-${MAJOR}.${MINOR}" | |
| if git ls-remote --exit-code --heads origin "${branch}" >/dev/null 2>&1; then | |
| echo "${branch} already exists" | |
| exit 0 | |
| fi | |
| git fetch --depth=1 origin "refs/tags/${TAG_NAME}:refs/tags/${TAG_NAME}" | |
| sha=$(git rev-list -n 1 "${TAG_NAME}") | |
| git push origin "${sha}:refs/heads/${branch}" | |
| build: | |
| name: "${{ matrix.component }} (${{ matrix.platform }})" | |
| needs: [release-please] | |
| if: ${{ always() && (needs.release-please.outputs.release_created == 'true' || inputs.finalize_tag != '') }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| component: [core, jobservice, registryctl, exporter, portal, registry, trivy-adapter] | |
| platform: | |
| - linux/amd64 | |
| - linux/arm64 | |
| runs-on: ubuntu-26.04 | |
| permissions: | |
| contents: read | |
| env: | |
| REGISTRY_ADDRESS: ${{ vars.REGISTRY_ADDRESS || '8gears.container-registry.com' }} | |
| REGISTRY_PROJECT: ${{ vars.REGISTRY_PROJECT || '8gcr' }} | |
| RELEASE_VERSION: ${{ needs.release-please.outputs.version }} | |
| TAG_NAME: ${{ needs.release-please.outputs.tag_name || inputs.finalize_tag }} | |
| steps: | |
| - name: Prepare | |
| id: prepare | |
| run: | | |
| platform=${{ matrix.platform }} | |
| echo "PLATFORM_PAIR=${platform//\//-}" >> "$GITHUB_ENV" | |
| if [ "${{ matrix.component }}" = "trivy-adapter" ]; then | |
| echo "image_name=trivy-adapter" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "image_name=harbor-${{ matrix.component }}" >> "$GITHUB_OUTPUT" | |
| fi | |
| if [ -n "$BUILDX_HOST" ]; then | |
| echo "BUILDX_HOST=$BUILDX_HOST" >> "$GITHUB_ENV" | |
| fi | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| ref: ${{ needs.release-please.outputs.tag_name || inputs.finalize_tag }} | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Install Task | |
| uses: arduino/setup-task@b91d5d2c96a56797b48ac1e0e89220bf64044611 # v2.0.0 | |
| with: | |
| version: 3.x | |
| repo-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Install jj | |
| env: | |
| JJ_VERSION: "0.44.0" | |
| run: | | |
| if command -v jj >/dev/null 2>&1; then | |
| jj --version | |
| exit 0 | |
| fi | |
| case "$(uname -m)" in | |
| x86_64|amd64) arch="x86_64" ;; | |
| aarch64|arm64) arch="aarch64" ;; | |
| *) | |
| echo "::error::Unsupported architecture: $(uname -m)" | |
| exit 1 | |
| ;; | |
| esac | |
| curl -fsSL "https://github.com/jj-vcs/jj/releases/download/v${JJ_VERSION}/jj-v${JJ_VERSION}-${arch}-unknown-linux-musl.tar.gz" -o /tmp/jj.tar.gz | |
| mkdir -p /tmp/jj-extract | |
| tar -xzf /tmp/jj.tar.gz -C /tmp/jj-extract | |
| sudo install -m 755 /tmp/jj-extract/jj /usr/local/bin/jj | |
| rm -rf /tmp/jj.tar.gz /tmp/jj-extract | |
| jj --version | |
| # Root Taskfile evaluation reads Go cache paths, even for apply-patches. | |
| - name: Setup Go | |
| uses: ./.github/actions/setup-go-cached | |
| with: | |
| go-version-file: src/go.mod | |
| go-sum-path: src/go.sum | |
| - name: Generate GitHub App token | |
| id: app-token | |
| uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | |
| with: | |
| app-id: ${{ vars.SYNC_APP_ID }} | |
| private-key: ${{ secrets.SYNC_APP_PRIVATE_KEY }} | |
| owner: container-registry | |
| repositories: 8gcr | |
| permission-contents: read | |
| - name: Apply commercial patches | |
| env: | |
| PATCHES_TOKEN: ${{ steps.app-token.outputs.token }} | |
| run: task apply-patches | |
| - name: Load versions | |
| run: | | |
| grep -E '^[A-Z_]+=' versions.env >> "$GITHUB_ENV" | |
| echo "RELEASE_VERSION=${RELEASE_VERSION:-${TAG_NAME#v}}" >> "$GITHUB_ENV" | |
| - name: Generate API code | |
| if: ${{ contains(fromJSON('["core","jobservice","registryctl","exporter","registry","trivy-adapter"]'), matrix.component) }} | |
| run: task build:gen-apis | |
| - name: Compile Go binary | |
| if: ${{ contains(fromJSON('["core","jobservice","registryctl","exporter","registry","trivy-adapter"]'), matrix.component) }} | |
| run: task build:binary:${{ matrix.component }}:${{ env.PLATFORM_PAIR }} GIT_COMMIT="${GITHUB_SHA:0:8}" | |
| - name: Compile image helper binaries | |
| env: | |
| COMPONENT: ${{ matrix.component }} | |
| PLATFORM_PAIR: ${{ env.PLATFORM_PAIR }} | |
| run: | | |
| task build:binary:lprobe:${PLATFORM_PAIR} | |
| if [ "${COMPONENT}" = "trivy-adapter" ]; then | |
| task build:binary:trivy:${PLATFORM_PAIR} | |
| fi | |
| - uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 | |
| if: env.BUILDX_HOST == '' | |
| - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 | |
| with: | |
| driver: ${{ env.BUILDX_HOST && 'remote' || '' }} | |
| endpoint: ${{ env.BUILDX_HOST }} | |
| - name: Log in to registry | |
| uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 | |
| with: | |
| registry: ${{ env.REGISTRY_ADDRESS }} | |
| username: ${{ vars.REGISTRY_USERNAME }} | |
| password: ${{ secrets.REGISTRY_PASSWORD }} | |
| - name: Build and push by digest | |
| id: build | |
| uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 | |
| with: | |
| context: . | |
| file: dockerfile/${{ matrix.component }}.dockerfile | |
| platforms: ${{ matrix.platform }} | |
| build-args: | | |
| ALPINE_VERSION=${{ env.ALPINE_VERSION }} | |
| LPROBE_VERSION=${{ env.LPROBE_VERSION }} | |
| NGINX_VERSION=${{ env.NGINX_VERSION }} | |
| BUN_VERSION=${{ env.BUN_VERSION }} | |
| GO_VERSION=${{ env.GO_VERSION }} | |
| DISTRIBUTION_VERSION=${{ env.DISTRIBUTION_VERSION }} | |
| TRIVY_VERSION=${{ env.TRIVY_VERSION }} | |
| TRIVY_BASE_IMAGE_VERSION=${{ env.TRIVY_BASE_IMAGE_VERSION }} | |
| HARBOR_SCANNER_TRIVY_VERSION=${{ env.HARBOR_SCANNER_TRIVY_VERSION }} | |
| tags: ${{ env.REGISTRY_ADDRESS }}/${{ env.REGISTRY_PROJECT }}/${{ steps.prepare.outputs.image_name }} | |
| outputs: type=image,push-by-digest=true,name-canonical=true,push=true | |
| - name: Export digest | |
| run: | | |
| mkdir -p "${{ runner.temp }}/digests" | |
| digest="${{ steps.build.outputs.digest }}" | |
| touch "${{ runner.temp }}/digests/${digest#sha256:}" | |
| - name: Upload digest | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: digest-${{ matrix.component }}-${{ env.PLATFORM_PAIR }} | |
| path: ${{ runner.temp }}/digests/* | |
| if-no-files-found: error | |
| retention-days: 1 | |
| merge: | |
| name: "Merge ${{ matrix.component }}" | |
| needs: [release-please, build] | |
| if: ${{ always() && needs.build.result == 'success' && (needs.release-please.outputs.release_created == 'true' || inputs.finalize_tag != '') }} | |
| strategy: | |
| matrix: | |
| component: [core, jobservice, registryctl, exporter, portal, registry, trivy-adapter] | |
| runs-on: ubuntu-26.04 | |
| permissions: | |
| contents: read | |
| env: | |
| REGISTRY_ADDRESS: ${{ vars.REGISTRY_ADDRESS || '8gears.container-registry.com' }} | |
| REGISTRY_PROJECT: ${{ vars.REGISTRY_PROJECT || '8gcr' }} | |
| VERSION: ${{ needs.release-please.outputs.version }} | |
| TAG_NAME: ${{ needs.release-please.outputs.tag_name || inputs.finalize_tag }} | |
| RELEASE_BRANCH: ${{ github.ref_name }} | |
| steps: | |
| - name: Prepare BuildKit | |
| id: prepare | |
| run: | | |
| if [ "${{ matrix.component }}" = "trivy-adapter" ]; then | |
| echo "image_name=trivy-adapter" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "image_name=harbor-${{ matrix.component }}" >> "$GITHUB_OUTPUT" | |
| fi | |
| if [ -n "$BUILDX_HOST" ]; then | |
| echo "BUILDX_HOST=$BUILDX_HOST" >> "$GITHUB_ENV" | |
| fi | |
| - name: Download digests | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| path: ${{ runner.temp }}/digests | |
| pattern: digest-${{ matrix.component }}-* | |
| merge-multiple: true | |
| - name: Log in to registry | |
| uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 | |
| with: | |
| registry: ${{ env.REGISTRY_ADDRESS }} | |
| username: ${{ vars.REGISTRY_USERNAME }} | |
| password: ${{ secrets.REGISTRY_PASSWORD }} | |
| - uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0 | |
| with: | |
| driver: ${{ env.BUILDX_HOST && 'remote' || '' }} | |
| endpoint: ${{ env.BUILDX_HOST }} | |
| - name: Create manifest list and push | |
| working-directory: ${{ runner.temp }}/digests | |
| env: | |
| IMAGE: ${{ env.REGISTRY_ADDRESS }}/${{ env.REGISTRY_PROJECT }}/${{ steps.prepare.outputs.image_name }} | |
| run: | | |
| # shellcheck disable=SC2046 | |
| docker buildx imagetools create \ | |
| -t "${IMAGE}:${TAG_NAME}" \ | |
| $(printf "${IMAGE}@sha256:%s " *) | |
| sign: | |
| name: Sign and Release | |
| needs: [validate-release-ref, release-please, merge] | |
| if: >- | |
| ${{ | |
| always() && | |
| needs.validate-release-ref.result == 'success' && | |
| ( | |
| needs.release-please.outputs.release_created == 'true' || | |
| inputs.finalize_tag != '' | |
| ) | |
| }} | |
| runs-on: ubuntu-26.04 | |
| permissions: | |
| contents: write | |
| id-token: write | |
| env: | |
| REGISTRY_ADDRESS: ${{ vars.REGISTRY_ADDRESS || '8gears.container-registry.com' }} | |
| REGISTRY_PROJECT: ${{ vars.REGISTRY_PROJECT || '8gcr' }} | |
| TAG_NAME: ${{ needs.release-please.outputs.tag_name || inputs.finalize_tag }} | |
| RELEASE_BRANCH: ${{ github.ref_name }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install envsubst | |
| run: command -v envsubst || (sudo apt-get update && sudo apt-get install -y gettext-base) | |
| - name: Install cosign | |
| uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 | |
| - name: Log in to registry | |
| uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 | |
| with: | |
| registry: ${{ env.REGISTRY_ADDRESS }} | |
| username: ${{ vars.REGISTRY_USERNAME }} | |
| password: ${{ secrets.REGISTRY_PASSWORD }} | |
| - name: Sign images | |
| run: | | |
| for image in core jobservice registryctl exporter portal registry trivy-adapter; do | |
| image_name="harbor-${image}" | |
| if [ "${image}" = "trivy-adapter" ]; then | |
| image_name="trivy-adapter" | |
| fi | |
| cosign sign --yes \ | |
| "${REGISTRY_ADDRESS}/${REGISTRY_PROJECT}/${image_name}:${TAG_NAME}" | |
| done | |
| update-release-notes: | |
| name: Update Release Notes | |
| needs: [release-please, sign] | |
| if: ${{ always() && needs.sign.result == 'success' }} | |
| permissions: | |
| contents: write | |
| uses: ./.github/workflows/release-notes-engine.yml | |
| with: | |
| tag_name: ${{ needs.release-please.outputs.tag_name || inputs.finalize_tag }} | |
| secrets: | |
| SYNC_APP_PRIVATE_KEY: ${{ secrets.SYNC_APP_PRIVATE_KEY }} |