Build images (DockerHub, Windows) #2157
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: Build images (DockerHub, Windows) | |
| on: | |
| push: | |
| branches: | |
| - '[0-9]+.[0-9]+' | |
| - 'trunk' | |
| paths: | |
| - 'build.json' | |
| - 'Dockerfiles/*/windows/*' | |
| - 'templates/config/*_windows/**' | |
| - 'templates/entrypoints/**/*.go' | |
| - 'templates/entrypoints/go.mod' | |
| - 'templates/entrypoints/licenses/go-THIRD-PARTY-NOTICES.txt' | |
| - '!**/README.md' | |
| - '.github/workflows/images_build_windows.yml' | |
| - '.github/actions/docker-build-push-windows/*' | |
| schedule: | |
| - cron: '05 02 * * *' | |
| workflow_dispatch: | |
| concurrency: | |
| group: windows-build-${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| defaults: | |
| run: | |
| shell: pwsh | |
| permissions: | |
| contents: read | |
| env: | |
| TRUNK_ONLY_EVENT: ${{ contains(fromJSON('["schedule"]'), github.event_name) }} | |
| AUTO_PUSH_IMAGES: ${{ vars.AUTO_PUSH_IMAGES }} | |
| DOCKER_REGISTRY: ${{ vars.DOCKER_REGISTRY }} | |
| DOCKER_REPOSITORY: ${{ vars.DOCKER_REPOSITORY }} | |
| TRUNK_GIT_BRANCH: "refs/heads/trunk" | |
| IMAGES_PREFIX: "zabbix-" | |
| MSFT_BASE_BUILD_IMAGE: "mcr.microsoft.com/windows/servercore" | |
| OS_BASE_IMAGE_NAME: "mcr.microsoft.com/windows/nanoserver" | |
| ENTRYPOINT_BUILD_IMAGE_NAME: "golang:1.26.5-windowsservercore" | |
| BASE_IMAGE_NAME: "build-base" | |
| BASE_BUILD_IMAGE_NAME: "build-mysql" | |
| MATRIX_FILE: "build.json" | |
| DOCKERFILES_DIRECTORY: "Dockerfiles" | |
| OIDC_ISSUER: "https://token.actions.githubusercontent.com" | |
| IDENTITY_REGEX: "${{ github.server_url }}/${{ github.repository }}/.github/" | |
| jobs: | |
| init_build: | |
| name: Initialize build | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| defaults: | |
| run: | |
| shell: bash | |
| outputs: | |
| os: ${{ steps.os.outputs.list }} | |
| components: ${{ steps.components.outputs.list }} | |
| is_default_branch: ${{ steps.branch_info.outputs.is_default_branch }} | |
| current_branch: ${{ steps.branch_info.outputs.current_branch }} | |
| sha_short: ${{ steps.branch_info.outputs.sha_short }} | |
| release_version: ${{ steps.branch_info.outputs.release_version }} | |
| steps: | |
| - name: Block egress traffic | |
| uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 | |
| with: | |
| disable-sudo: true | |
| egress-policy: block | |
| disable-telemetry: true | |
| allowed-endpoints: > | |
| github.com:443 | |
| release-assets.githubusercontent.com:443 | |
| - name: Checkout repository | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| ref: ${{ env.TRUNK_ONLY_EVENT == 'true' && env.TRUNK_GIT_BRANCH || '' }} | |
| fetch-depth: 1 | |
| sparse-checkout: | | |
| ${{ env.MATRIX_FILE }} | |
| .github | |
| - name: Check matrix file | |
| env: | |
| MATRIX_FILE: ${{ env.MATRIX_FILE }} | |
| run: | | |
| if [[ ! -f "$MATRIX_FILE" ]]; then | |
| echo "::error::File $MATRIX_FILE is missing" | |
| exit 1 | |
| fi | |
| - name: Prepare Operating System list | |
| id: os | |
| env: | |
| MATRIX_FILE: ${{ env.MATRIX_FILE }} | |
| run: | | |
| os_list="$(jq -c '.["os-windows"] | keys' "$MATRIX_FILE")" | |
| echo "::group::Operating System List" | |
| echo "$os_list" | |
| echo "::endgroup::" | |
| echo "list=$os_list" >> "$GITHUB_OUTPUT" | |
| - name: Prepare Zabbix component list | |
| id: components | |
| shell: bash | |
| run: | | |
| component_list='["agent","agent2"]' | |
| echo "::group::Zabbix Component List" | |
| echo "$component_list" | |
| echo "::endgroup::" | |
| echo "list=$component_list" >> $GITHUB_OUTPUT | |
| - name: Get branch info | |
| id: branch_info | |
| uses: ./.github/actions/get-branch-info | |
| with: | |
| trunk_version: ${{ inputs.trunk_version }} | |
| trunk_git_branch: ${{ env.TRUNK_GIT_BRANCH }} | |
| build_base: | |
| name: Build ${{ matrix.component }} base on ${{ matrix.os }} | |
| needs: init_build | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 70 | |
| permissions: | |
| contents: read | |
| id-token: write | |
| attestations: write | |
| artifact-metadata: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: ${{ fromJson(needs.init_build.outputs.os) }} | |
| component: ${{ fromJson(needs.init_build.outputs.components) }} | |
| steps: | |
| - name: Block egress traffic | |
| uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 | |
| with: | |
| disable-sudo: true | |
| egress-policy: block | |
| disable-telemetry: true | |
| allowed-endpoints: > | |
| aka.ms:443 | |
| api.github.com:443 | |
| auth.docker.io:443 | |
| curl.se:443 | |
| dc.services.visualstudio.com:443 | |
| definitionupdates.microsoft.com:443 | |
| dl.google.com:443 | |
| download.visualstudio.microsoft.com:443 | |
| fulcio.sigstore.dev:443 | |
| github.com:443 | |
| go.dev:443 | |
| go.microsoft.com:443 | |
| index.docker.io:443 | |
| mcr.microsoft.com:443 | |
| mobile.events.data.microsoft.com:443 | |
| ocsp.digicert.com:80 | |
| ocsp.sectigo.com:80 | |
| production.cloudflare.docker.com:443 | |
| r12.c.lencr.org:80 | |
| raw.githubusercontent.com:443 | |
| registry-1.docker.io:443 | |
| rekor.sigstore.dev:443 | |
| tuf-repo-cdn.sigstore.dev:443 | |
| www.nasm.us:443 | |
| x1.c.lencr.org:80 | |
| zlib.net:443 | |
| - name: Checkout repository | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| ref: ${{ env.TRUNK_ONLY_EVENT == 'true' && env.TRUNK_GIT_BRANCH || '' }} | |
| fetch-depth: 1 | |
| - name: Install cosign | |
| if: ${{ env.AUTO_PUSH_IMAGES == 'true' }} | |
| uses: ./.github/actions/cosign-install | |
| - name: Base Windows OS tag | |
| id: base_os_tag | |
| env: | |
| MATRIX_OS: ${{ matrix.os }} | |
| MATRIX_FILE: ${{ env.MATRIX_FILE }} | |
| run: | | |
| $matrixFile = "$env:MATRIX_FILE" | |
| $matrixOs = "$env:MATRIX_OS" | |
| $osTag = (Get-Content -Path $matrixFile | ConvertFrom-Json).'os-windows'."$matrixOs" | |
| if ([string]::IsNullOrWhiteSpace($osTag)) { | |
| throw "Failed to detect Windows base OS tag for '$matrixOs'" | |
| } | |
| echo "::group::Base Microsoft Windows OS tag" | |
| echo "$osTag" | |
| echo "::endgroup::" | |
| Add-Content -Path $env:GITHUB_OUTPUT -Value "os_tag=$osTag" | |
| - name: Generate toolchain tag | |
| id: toolchain_tag | |
| env: | |
| COMPONENT: ${{ matrix.component }} | |
| OS_TAG: ${{ steps.base_os_tag.outputs.os_tag }} | |
| IMAGE: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, env.BASE_IMAGE_NAME ) }} | |
| CONTEXT: ${{ format('{0}/{1}/windows', env.DOCKERFILES_DIRECTORY, env.BASE_IMAGE_NAME) }} | |
| CURRENT_BRANCH: ${{ needs.init_build.outputs.current_branch }} | |
| OS_BASE_IMAGE: ${{ env.MSFT_BASE_BUILD_IMAGE }} | |
| run: | | |
| $component = "$env:COMPONENT" | |
| $osTag = "$env:OS_TAG" | |
| $epoch = Get-Date -Format 'yyyyMM' | |
| $context = "$env:CONTEXT" | |
| $branch = "$env:CURRENT_BRANCH" | |
| $baseImage = "$env:IMAGE" | |
| $osBaseImage = "$env:OS_BASE_IMAGE" | |
| $branch = ($branch -replace '[^A-Za-z0-9_.-]', '-').Trim('.-') | |
| if ([string]::IsNullOrWhiteSpace($branch)) { | |
| throw 'Current branch is empty after Docker tag normalization' | |
| } | |
| $files = @( | |
| "$context/Dockerfile.$component" | |
| ) | |
| if ($component -eq 'agent') { | |
| $files += "$context/CMakeLists.txt" | |
| } | |
| $inputText = @() | |
| foreach ($file in $files) { | |
| $inputText += "### $file" | |
| $inputText += Get-Content -Raw -Path $file | |
| } | |
| $inputText += "OS_BASE_IMAGE=${osBaseImage}:$osTag" | |
| $inputText += "TOOLCHAIN_EPOCH=$epoch" | |
| $bytes = [System.Text.Encoding]::UTF8.GetBytes(($inputText -join "`n")) | |
| $sha256 = [System.Security.Cryptography.SHA256]::Create() | |
| try { | |
| $hashBytes = $sha256.ComputeHash($bytes) | |
| } | |
| finally { | |
| $sha256.Dispose() | |
| } | |
| $hash = -join ($hashBytes | ForEach-Object { $_.ToString("x2") }) | |
| $shortHash = $hash.Substring(0, 12) | |
| $tag = "$component-$osTag-$branch-$epoch-$shortHash" | |
| $ref = "${baseImage}:${tag}" | |
| echo "::group::Base Microsoft Windows OS ref" | |
| echo "Ref - $ref" | |
| echo "::endgroup::" | |
| Add-Content -Path $env:GITHUB_OUTPUT -Value "tag=$tag" | |
| Add-Content -Path $env:GITHUB_OUTPUT -Value "ref=$ref" | |
| - name: Verify toolchain | |
| id: toolchain_lookup | |
| env: | |
| TOOLCHAIN_REF: ${{ steps.toolchain_tag.outputs.ref }} | |
| run: | | |
| $ErrorActionPreference = 'Continue' | |
| $PSNativeCommandUseErrorActionPreference = $false | |
| $toolchainRef = "$env:TOOLCHAIN_REF" | |
| if ([string]::IsNullOrWhiteSpace($toolchainRef)) { | |
| throw 'TOOLCHAIN_REF is empty. Check toolchain_tag step outputs.' | |
| } | |
| docker manifest inspect "$toolchainRef" *> $null | |
| if ($LASTEXITCODE -eq 0) { | |
| Add-Content -Path $env:GITHUB_OUTPUT -Value 'reuse=true' | |
| Write-Host "Toolchain '$toolchainRef' image exists, will reuse it." | |
| } | |
| else { | |
| Add-Content -Path $env:GITHUB_OUTPUT -Value 'reuse=false' | |
| Write-Host "Toolchain '$toolchainRef' image is missing, will build it." | |
| } | |
| $global:LASTEXITCODE = 0 | |
| exit 0 | |
| - name: Generate tags | |
| id: meta | |
| if: ${{ steps.toolchain_lookup.outputs.reuse != 'true' }} | |
| uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 | |
| with: | |
| images: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, env.BASE_IMAGE_NAME ) }} | |
| context: ${{ env.TRUNK_ONLY_EVENT == 'true' && 'git' || '' }} | |
| tags: | | |
| type=semver,enable=${{ needs.init_build.outputs.release_version != '' }},value=${{ needs.init_build.outputs.release_version }},pattern={{version}},prefix=${{ matrix.component }}-${{ steps.base_os_tag.outputs.os_tag }}- | |
| type=semver,enable=${{ needs.init_build.outputs.release_version != '' }},value=${{ needs.init_build.outputs.release_version }},pattern={{version}},suffix=-${{ steps.base_os_tag.outputs.os_tag }},prefix=${{ matrix.component }}- | |
| type=ref,enable=${{ needs.init_build.outputs.current_branch != 'trunk' }},event=branch,prefix=${{ matrix.component }}-${{ steps.base_os_tag.outputs.os_tag }}-,suffix=-latest | |
| type=ref,enable=${{ needs.init_build.outputs.current_branch != 'trunk' }},event=branch,suffix=-${{ steps.base_os_tag.outputs.os_tag }}-latest,prefix=${{ matrix.component }}- | |
| type=raw,enable=${{ needs.init_build.outputs.current_branch != 'trunk' && needs.init_build.outputs.is_default_branch == 'true' }},value=${{ matrix.component }}-${{ steps.base_os_tag.outputs.os_tag }}-latest | |
| type=ref,enable=${{ needs.init_build.outputs.current_branch == 'trunk' }},event=branch,prefix=${{ matrix.component }}-${{ steps.base_os_tag.outputs.os_tag }}- | |
| type=ref,enable=${{ needs.init_build.outputs.current_branch == 'trunk' }},event=branch,suffix=-${{ steps.base_os_tag.outputs.os_tag }},prefix=${{ matrix.component }}- | |
| flavor: | | |
| latest=false | |
| - name: Login to DockerHub | |
| if: ${{ steps.toolchain_lookup.outputs.reuse != 'true' }} | |
| uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 | |
| with: | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_PASSWORD }} | |
| - name: Build and push image | |
| id: docker_build | |
| if: ${{ steps.toolchain_lookup.outputs.reuse != 'true' }} | |
| uses: ./.github/actions/docker-build-push-windows | |
| with: | |
| context: ${{ format('{0}/{1}/windows', env.DOCKERFILES_DIRECTORY, env.BASE_IMAGE_NAME) }} | |
| dockerfile: ${{ format('{0}\{1}\windows\Dockerfile.{2}', env.DOCKERFILES_DIRECTORY, env.BASE_IMAGE_NAME, matrix.component ) }} | |
| tags: | | |
| ${{ steps.meta.outputs.tags }} | |
| ${{ steps.toolchain_tag.outputs.ref }} | |
| label_revision: ${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} | |
| label_created: ${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} | |
| pull_images: | | |
| ${{ env.MSFT_BASE_BUILD_IMAGE }}:${{ steps.base_os_tag.outputs.os_tag }} | |
| build_args: | | |
| OS_BASE_IMAGE=${{ env.MSFT_BASE_BUILD_IMAGE }}:${{ steps.base_os_tag.outputs.os_tag }} | |
| push: true | |
| - name: Sign the images with GitHub OIDC Token | |
| if: ${{ steps.toolchain_lookup.outputs.reuse != 'true' }} | |
| uses: ./.github/actions/cosign-sign | |
| with: | |
| digest: ${{ steps.docker_build.outputs.digest }} | |
| tags: | | |
| ${{ steps.meta.outputs.tags }} | |
| ${{ steps.toolchain_tag.outputs.ref }} | |
| - name: Attest images | |
| if: ${{ steps.toolchain_lookup.outputs.reuse != 'true' }} | |
| uses: ./.github/actions/attest-image | |
| with: | |
| subject_name: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, env.BASE_IMAGE_NAME ) }} | |
| subject_digest: ${{ steps.docker_build.outputs.digest }} | |
| - name: Image ref | |
| env: | |
| DIGEST: ${{ steps.docker_build.outputs.digest }} | |
| IMAGE: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, env.BASE_IMAGE_NAME ) }} | |
| REUSE: ${{ steps.toolchain_lookup.outputs.reuse }} | |
| REUSE_IMAGE_REF: ${{ steps.toolchain_tag.outputs.ref }} | |
| CACHE_FILE_NAME: ${{ env.BASE_IMAGE_NAME }}_${{ matrix.os }}_${{ matrix.component }} | |
| run: | | |
| $reuse = "$env:REUSE" | |
| $image = "$env:IMAGE" | |
| $digest = "$env:DIGEST" | |
| $reuseImageRef = "$env:REUSE_IMAGE_REF" | |
| $cacheFileName = "$env:CACHE_FILE_NAME" | |
| if ($reuse -eq 'true') { | |
| $imageRef = "$reuseImageRef" | |
| } | |
| else { | |
| if ([string]::IsNullOrWhiteSpace($digest)) { | |
| throw 'Built image digest is empty' | |
| } | |
| $imageRef = "${image}@${digest}" | |
| } | |
| if ([string]::IsNullOrWhiteSpace($imageRef)) { | |
| throw 'Image ref is empty' | |
| } | |
| echo "::group::Image ref" | |
| echo "$imageRef" | |
| echo "::endgroup::" | |
| echo "::group::Cache file name" | |
| echo "$cacheFileName" | |
| echo "::endgroup::" | |
| Set-Content -Path $cacheFileName -Value $imageRef -NoNewline | |
| - name: Upload artifact metadata | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| path: ${{ env.BASE_IMAGE_NAME }}_${{ matrix.os }}_${{ matrix.component }} | |
| name: ${{ env.BASE_IMAGE_NAME }}-${{ matrix.os }}-${{ matrix.component }}-${{ github.run_id }} | |
| build_components: | |
| name: Build ${{ matrix.component }} sources on ${{ matrix.os }} | |
| needs: ["build_base", "init_build"] | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 70 | |
| permissions: | |
| contents: read | |
| id-token: write | |
| attestations: write | |
| artifact-metadata: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: ${{ fromJson(needs.init_build.outputs.os) }} | |
| component: ${{ fromJson(needs.init_build.outputs.components) }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| ref: ${{ env.TRUNK_ONLY_EVENT == 'true' && env.TRUNK_GIT_BRANCH || '' }} | |
| fetch-depth: 1 | |
| - name: Install cosign | |
| uses: ./.github/actions/cosign-install | |
| - name: Login to DockerHub | |
| uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 | |
| with: | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_PASSWORD }} | |
| - name: Base OS tag | |
| id: base_os_tag | |
| env: | |
| MATRIX_OS: ${{ matrix.os }} | |
| MATRIX_FILE: ${{ env.MATRIX_FILE }} | |
| run: | | |
| $matrixFile = "$env:MATRIX_FILE" | |
| $matrixOs = "$env:MATRIX_OS" | |
| $osTag = (Get-Content -Path $matrixFile | ConvertFrom-Json).'os-windows'."$matrixOs" | |
| if ([string]::IsNullOrWhiteSpace($osTag)) { | |
| throw "Failed to detect Windows base OS tag for '$matrixOs'" | |
| } | |
| echo "::group::Base Windows OS tag" | |
| echo "$osTag" | |
| echo "::endgroup::" | |
| Add-Content -Path $env:GITHUB_OUTPUT -Value "os_tag=$osTag" | |
| - name: Generate tags | |
| id: meta | |
| uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 | |
| with: | |
| images: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, env.BASE_BUILD_IMAGE_NAME ) }} | |
| context: ${{ env.TRUNK_ONLY_EVENT == 'true' && 'git' || '' }} | |
| tags: | | |
| type=semver,enable=${{ needs.init_build.outputs.release_version != '' }},value=${{ needs.init_build.outputs.release_version }},pattern={{version}},prefix=${{ matrix.component }}-${{ steps.base_os_tag.outputs.os_tag }}- | |
| type=semver,enable=${{ needs.init_build.outputs.release_version != '' }},value=${{ needs.init_build.outputs.release_version }},pattern={{version}},suffix=-${{ steps.base_os_tag.outputs.os_tag }},prefix=${{ matrix.component }}- | |
| type=ref,enable=${{ needs.init_build.outputs.current_branch != 'trunk' }},event=branch,prefix=${{ matrix.component }}-${{ steps.base_os_tag.outputs.os_tag }}-,suffix=-latest | |
| type=ref,enable=${{ needs.init_build.outputs.current_branch != 'trunk' }},event=branch,suffix=-${{ steps.base_os_tag.outputs.os_tag }}-latest,prefix=${{ matrix.component }}- | |
| type=raw,enable=${{ (needs.init_build.outputs.current_branch != 'trunk') && (needs.init_build.outputs.is_default_branch == 'true') }},value=${{ matrix.component }}-${{ steps.base_os_tag.outputs.os_tag }}-latest | |
| type=ref,enable=${{ needs.init_build.outputs.current_branch == 'trunk' }},event=branch,prefix=${{ matrix.component }}-${{ steps.base_os_tag.outputs.os_tag }}- | |
| type=ref,enable=${{ needs.init_build.outputs.current_branch == 'trunk' }},event=branch,suffix=-${{ steps.base_os_tag.outputs.os_tag }},prefix=${{ matrix.component }}- | |
| flavor: | | |
| latest=false | |
| - name: Download image ref of ${{ env.BASE_IMAGE_NAME }}:${{ matrix.os }} | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: ${{ env.BASE_IMAGE_NAME }}-${{ matrix.os }}-${{ matrix.component }}-${{ github.run_id }} | |
| - name: Retrieve ${{ env.BASE_IMAGE_NAME }}:${{ matrix.os }} image ref | |
| id: base_build | |
| env: | |
| BASE_IMAGE_FILE: ${{ format('{0}_{1}_{2}', env.BASE_IMAGE_NAME, matrix.os, matrix.component) }} | |
| run: | | |
| $baseImageFile = "$env:BASE_IMAGE_FILE" | |
| if (-not (Test-Path $baseImageFile)) { | |
| throw "Missing cached base image ref file: $baseImageFile" | |
| } | |
| $buildBaseImage = (Get-Content $baseImageFile -Raw).Trim() | |
| if ([string]::IsNullOrWhiteSpace($buildBaseImage)) { | |
| throw "Base image ref is empty in file: $baseImageFile" | |
| } | |
| echo "::group::Base image info" | |
| echo "base_build_image=$buildBaseImage" | |
| echo "::endgroup::" | |
| Add-Content -Path $env:GITHUB_OUTPUT -Value "base_build_image=$buildBaseImage" | |
| - name: Verify ${{ env.BASE_IMAGE_NAME }}:${{ matrix.os }} cosign | |
| uses: ./.github/actions/cosign-verify | |
| with: | |
| image: ${{ steps.base_build.outputs.base_build_image }} | |
| oidc_issuer: ${{ env.OIDC_ISSUER }} | |
| identity_regexp: ${{ env.IDENTITY_REGEX }} | |
| - name: Build and push image | |
| id: docker_build | |
| uses: ./.github/actions/docker-build-push-windows | |
| with: | |
| context: ${{ env.DOCKERFILES_DIRECTORY }}\${{ env.BASE_BUILD_IMAGE_NAME }}\windows | |
| dockerfile: ${{ env.DOCKERFILES_DIRECTORY }}\${{ env.BASE_BUILD_IMAGE_NAME }}\windows\Dockerfile.${{ matrix.component }} | |
| tags: ${{ steps.meta.outputs.tags }} | |
| label_revision: ${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} | |
| label_created: ${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} | |
| pull_images: | | |
| ${{ steps.base_build.outputs.base_build_image }} | |
| build_args: | | |
| BUILD_BASE_IMAGE=${{ steps.base_build.outputs.base_build_image }} | |
| push: true | |
| - name: Attest images | |
| uses: ./.github/actions/attest-image | |
| with: | |
| subject_name: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, env.BASE_BUILD_IMAGE_NAME ) }} | |
| subject_digest: ${{ steps.docker_build.outputs.digest }} | |
| - name: Sign the images with GitHub OIDC Token | |
| uses: ./.github/actions/cosign-sign | |
| with: | |
| digest: ${{ steps.docker_build.outputs.digest }} | |
| tags: ${{ steps.meta.outputs.tags }} | |
| - name: Image ref | |
| env: | |
| DIGEST: ${{ steps.docker_build.outputs.digest }} | |
| IMAGE: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, env.BASE_BUILD_IMAGE_NAME ) }} | |
| CACHE_FILE_NAME: ${{ env.BASE_BUILD_IMAGE_NAME }}_${{ matrix.os }}_${{ matrix.component }} | |
| run: | | |
| $digest = "$env:DIGEST" | |
| $image = "$env:IMAGE" | |
| $cacheFileName = "$env:CACHE_FILE_NAME" | |
| if ([string]::IsNullOrWhiteSpace($digest)) { | |
| throw 'Built image digest is empty' | |
| } | |
| $imageRef = "${image}@${digest}" | |
| echo "::group::Image ref" | |
| echo "$imageRef" | |
| echo "::endgroup::" | |
| echo "::group::Cache file name" | |
| echo "$cacheFileName" | |
| echo "::endgroup::" | |
| Set-Content -Path $cacheFileName -Value $imageRef -NoNewline | |
| - name: Upload artifact metadata | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| path: ${{ env.BASE_BUILD_IMAGE_NAME }}_${{ matrix.os }}_${{ matrix.component }} | |
| name: ${{ env.BASE_BUILD_IMAGE_NAME }}-${{ matrix.os }}-${{ matrix.component }}-${{ github.run_id }} | |
| build_images: | |
| name: Build ${{ matrix.component }} on ${{ matrix.os }} | |
| needs: ["build_components", "init_build"] | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 70 | |
| permissions: | |
| contents: read | |
| id-token: write | |
| attestations: write | |
| artifact-metadata: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: ${{ fromJson(needs.init_build.outputs.os) }} | |
| component: ${{ fromJson(needs.init_build.outputs.components) }} | |
| steps: | |
| - name: Block egress traffic | |
| uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 | |
| with: | |
| disable-sudo: true | |
| egress-policy: block | |
| disable-telemetry: true | |
| allowed-endpoints: > | |
| api.github.com:443 | |
| auth.docker.io:443 | |
| dc.services.visualstudio.com:443 | |
| fulcio.sigstore.dev:443 | |
| github.com:443 | |
| index.docker.io:443 | |
| mcr.microsoft.com:443 | |
| mobile.events.data.microsoft.com:443 | |
| ocsp.sectigo.com:80 | |
| production.cloudflare.docker.com:443 | |
| r12.c.lencr.org:80 | |
| registry-1.docker.io:443 | |
| rekor.sigstore.dev:443 | |
| timestamp.sigstore.dev:443 | |
| tuf-repo-cdn.sigstore.dev:443 | |
| x1.c.lencr.org:80 | |
| - name: Checkout repository | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| ref: ${{ env.TRUNK_ONLY_EVENT == 'true' && env.TRUNK_GIT_BRANCH || '' }} | |
| fetch-depth: 1 | |
| - name: Install cosign | |
| if: ${{ env.AUTO_PUSH_IMAGES == 'true' }} | |
| uses: ./.github/actions/cosign-install | |
| - name: Login to DockerHub | |
| uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 | |
| with: | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_PASSWORD }} | |
| - name: Base OS tag | |
| id: base_os_tag | |
| env: | |
| MATRIX_OS: ${{ matrix.os }} | |
| MATRIX_FILE: ${{ env.MATRIX_FILE }} | |
| run: | | |
| $matrixFile = "$env:MATRIX_FILE" | |
| $matrixOs = "$env:MATRIX_OS" | |
| $osTag = (Get-Content -Path $matrixFile | ConvertFrom-Json).'os-windows'."$matrixOs" | |
| if ([string]::IsNullOrWhiteSpace($osTag)) { | |
| throw "Failed to detect Windows base OS tag for '$matrixOs'" | |
| } | |
| echo "::group::Base OS tag" | |
| echo "$osTag" | |
| echo "::endgroup::" | |
| Add-Content -Path $env:GITHUB_OUTPUT -Value "os_tag=$osTag" | |
| - name: Generate tags | |
| id: meta | |
| uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0 | |
| with: | |
| images: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, matrix.component ) }} | |
| context: ${{ env.TRUNK_ONLY_EVENT == 'true' && 'git' || '' }} | |
| tags: | | |
| type=semver,enable=${{ needs.init_build.outputs.release_version != '' }},value=${{ needs.init_build.outputs.release_version }},pattern={{version}},prefix=${{ steps.base_os_tag.outputs.os_tag }}- | |
| type=semver,enable=${{ needs.init_build.outputs.release_version != '' }},value=${{ needs.init_build.outputs.release_version }},pattern={{version}},suffix=-${{ steps.base_os_tag.outputs.os_tag }} | |
| type=ref,enable=${{ needs.init_build.outputs.current_branch != 'trunk' }},event=branch,prefix=${{ steps.base_os_tag.outputs.os_tag }}-,suffix=-latest | |
| type=ref,enable=${{ needs.init_build.outputs.current_branch != 'trunk' }},event=branch,suffix=-${{ steps.base_os_tag.outputs.os_tag }}-latest | |
| type=raw,enable=${{ (needs.init_build.outputs.current_branch != 'trunk') && (needs.init_build.outputs.is_default_branch == 'true') }},value=${{ steps.base_os_tag.outputs.os_tag }}-latest | |
| type=ref,enable=${{ needs.init_build.outputs.current_branch == 'trunk' }},event=branch,prefix=${{ steps.base_os_tag.outputs.os_tag }}- | |
| type=ref,enable=${{ needs.init_build.outputs.current_branch == 'trunk' }},event=branch,suffix=-${{ steps.base_os_tag.outputs.os_tag }} | |
| flavor: | | |
| latest=false | |
| - name: Download image ref of ${{ env.BASE_BUILD_IMAGE_NAME }}:${{ matrix.os }} | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: ${{ env.BASE_BUILD_IMAGE_NAME }}-${{ matrix.os }}-${{ matrix.component }}-${{ github.run_id }} | |
| - name: Retrieve ${{ env.BASE_BUILD_IMAGE_NAME }}:${{ matrix.os }} image ref | |
| id: base_build | |
| env: | |
| BASE_IMAGE_FILE: ${{ format('{0}_{1}_{2}', env.BASE_BUILD_IMAGE_NAME, matrix.os, matrix.component) }} | |
| run: | | |
| $baseImageFile = "$env:BASE_IMAGE_FILE" | |
| if (-not (Test-Path $baseImageFile)) { | |
| throw "Missing cached build-components image ref file: $baseImageFile" | |
| } | |
| $buildBaseImage = (Get-Content $baseImageFile -Raw).Trim() | |
| if ([string]::IsNullOrWhiteSpace($buildBaseImage)) { | |
| throw "Build-components image ref is empty in file: $baseImageFile" | |
| } | |
| echo "::group::Base image info" | |
| echo "base_build_image=$buildBaseImage" | |
| echo "::endgroup::" | |
| Add-Content -Path $env:GITHUB_OUTPUT -Value "base_build_image=$buildBaseImage" | |
| - name: Verify ${{ env.BASE_BUILD_IMAGE_NAME }}:${{ matrix.os }} cosign | |
| uses: ./.github/actions/cosign-verify | |
| with: | |
| image: ${{ steps.base_build.outputs.base_build_image }} | |
| oidc_issuer: ${{ env.OIDC_ISSUER }} | |
| identity_regexp: ${{ env.IDENTITY_REGEX }} | |
| - name: Build and push image | |
| id: docker_build | |
| uses: ./.github/actions/docker-build-push-windows | |
| with: | |
| context: . | |
| dockerfile: ${{ env.DOCKERFILES_DIRECTORY }}\${{ matrix.component }}\windows\Dockerfile | |
| tags: ${{ steps.meta.outputs.tags }} | |
| label_revision: ${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} | |
| label_created: ${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} | |
| pull_images: | | |
| ${{ steps.base_build.outputs.base_build_image }} | |
| ${{ env.OS_BASE_IMAGE_NAME }}:${{ steps.base_os_tag.outputs.os_tag }} | |
| ${{ env.ENTRYPOINT_BUILD_IMAGE_NAME }}-${{ steps.base_os_tag.outputs.os_tag }} | |
| build_args: | | |
| BUILD_BASE_IMAGE=${{ steps.base_build.outputs.base_build_image }} | |
| OS_BASE_IMAGE=${{ env.OS_BASE_IMAGE_NAME }}:${{ steps.base_os_tag.outputs.os_tag }} | |
| ENTRYPOINT_BUILD_IMAGE=${{ env.ENTRYPOINT_BUILD_IMAGE_NAME }}-${{ steps.base_os_tag.outputs.os_tag }} | |
| push: ${{ env.AUTO_PUSH_IMAGES }} | |
| remove_readme: false | |
| - name: Sign the images with GitHub OIDC Token | |
| if: ${{ env.AUTO_PUSH_IMAGES == 'true' }} | |
| uses: ./.github/actions/cosign-sign | |
| with: | |
| digest: ${{ steps.docker_build.outputs.digest }} | |
| tags: ${{ steps.meta.outputs.tags }} | |
| - name: Attest images | |
| uses: ./.github/actions/attest-image | |
| with: | |
| subject_name: ${{ format('{0}/{1}/{2}{3}', env.DOCKER_REGISTRY, env.DOCKER_REPOSITORY, env.IMAGES_PREFIX, matrix.component ) }} | |
| subject_digest: ${{ steps.docker_build.outputs.digest }} |