feat: add optional registry CA certificate installation step #1
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
| # Reusable Docker Build Workflow | ||
|
Check failure on line 1 in .github/workflows/docker-build.yml
|
||
| # Equivalent to docker-build-pipe for Bitbucket | ||
| # | ||
| # Builds images using docker buildx bake, pushes to Artifactory, | ||
| # and uploads build metadata JSON for downstream deploy workflows. | ||
| name: Docker Build | ||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| bake_file: | ||
| description: 'Path to docker-bake.hcl file' | ||
| type: string | ||
| default: docker-bake.hcl | ||
| bake_target: | ||
| description: 'Bake target(s) to build' | ||
| type: string | ||
| default: default | ||
| platforms: | ||
| description: 'Target platforms (comma-separated)' | ||
| type: string | ||
| default: linux/amd64 | ||
| image_namespace: | ||
| description: 'Image namespace in registry' | ||
| type: string | ||
| default: mwlr-private | ||
| push: | ||
| description: 'Push images to registry' | ||
| type: boolean | ||
| default: true | ||
| registry_host: | ||
| description: 'Artifactory hostname' | ||
| type: string | ||
| required: true | ||
| registry_username: | ||
| description: 'Artifactory username' | ||
| type: string | ||
| required: true | ||
| secrets: | ||
| ARTIFACTORY_TOKEN: | ||
| required: true | ||
| description: 'Artifactory identity token' | ||
| BAKE_SECRETS: | ||
| required: false | ||
| description: 'Build secrets in docker secret format' | ||
| REGISTRY_CA_CERT: | ||
| required: false | ||
| description: 'CA certificate for registry TLS verification (PEM format)' | ||
| outputs: | ||
| build_id: | ||
| description: 'Build identifier (run_number-sha)' | ||
| value: ${{ jobs.build.outputs.build_id }} | ||
| image_tag: | ||
| description: 'Image tag' | ||
| value: ${{ jobs.build.outputs.image_tag }} | ||
| registry_prefix: | ||
| description: 'Registry prefix for images' | ||
| value: ${{ jobs.build.outputs.registry_prefix }} | ||
| metadata_url: | ||
| description: 'URL to build index JSON' | ||
| value: ${{ jobs.build.outputs.metadata_url }} | ||
| jobs: | ||
| build: | ||
| runs-on: ubuntu-latest | ||
| outputs: | ||
| build_id: ${{ steps.vars.outputs.build_id }} | ||
| image_tag: ${{ steps.vars.outputs.image_tag }} | ||
| registry_prefix: ${{ steps.vars.outputs.registry_prefix }} | ||
| metadata_url: ${{ steps.metadata.outputs.metadata_url }} | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
| - name: Set build variables | ||
| id: vars | ||
| run: | | ||
| # Build ID matches Bitbucket convention: build_number-commit_sha | ||
| BUILD_ID="${{ github.run_number }}-${GITHUB_SHA}" | ||
| REPO_NAME="${{ github.event.repository.name }}" | ||
| REGISTRY_PREFIX="${{ inputs.registry_host }}/docker/${{ inputs.image_namespace }}/${REPO_NAME}" | ||
| echo "build_id=${BUILD_ID}" >> $GITHUB_OUTPUT | ||
| echo "image_tag=${BUILD_ID}" >> $GITHUB_OUTPUT | ||
| echo "registry_prefix=${REGISTRY_PREFIX}" >> $GITHUB_OUTPUT | ||
| echo "repo_name=${REPO_NAME}" >> $GITHUB_OUTPUT | ||
| # For bake file interpolation | ||
| echo "REGISTRY_PREFIX=${REGISTRY_PREFIX}" >> $GITHUB_ENV | ||
| echo "IMAGE_TAG=${BUILD_ID}" >> $GITHUB_ENV | ||
| echo "GIT_ORIGIN=${{ github.server_url }}/${{ github.repository }}" >> $GITHUB_ENV | ||
| echo "GIT_REVISION=${GITHUB_SHA}" >> $GITHUB_ENV | ||
| - name: Install registry CA certificate | ||
| if: ${{ secrets.REGISTRY_CA_CERT != '' }} | ||
| run: | | ||
| # Add CA to system trust store | ||
| echo "${{ secrets.REGISTRY_CA_CERT }}" | sudo tee /usr/local/share/ca-certificates/registry-ca.crt | ||
| sudo update-ca-certificates | ||
| # Add CA to Docker daemon for registry access | ||
| sudo mkdir -p /etc/docker/certs.d/${{ inputs.registry_host }} | ||
| echo "${{ secrets.REGISTRY_CA_CERT }}" | sudo tee /etc/docker/certs.d/${{ inputs.registry_host }}/ca.crt | ||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@v3 | ||
| - name: Login to Artifactory | ||
| uses: docker/login-action@v3 | ||
| with: | ||
| registry: ${{ inputs.registry_host }} | ||
| username: ${{ inputs.registry_username }} | ||
| password: ${{ secrets.ARTIFACTORY_TOKEN }} | ||
| - name: Build and push | ||
| id: bake | ||
| uses: docker/bake-action@v5 | ||
| with: | ||
| files: ${{ inputs.bake_file }} | ||
| targets: ${{ inputs.bake_target }} | ||
| push: ${{ inputs.push }} | ||
| provenance: true | ||
| sbom: true | ||
| set: | | ||
| *.platform=${{ inputs.platforms }} | ||
| *.cache-from=type=registry,ref=${{ steps.vars.outputs.registry_prefix }}:cache | ||
| env: | ||
| REGISTRY_PREFIX: ${{ steps.vars.outputs.registry_prefix }} | ||
| IMAGE_TAG: ${{ steps.vars.outputs.image_tag }} | ||
| - name: Parse bake metadata | ||
| id: parse | ||
| run: | | ||
| # Extract metadata from bake output | ||
| BAKE_METADATA='${{ steps.bake.outputs.metadata }}' | ||
| # Create index.json matching docker-build-pipe format | ||
| echo "$BAKE_METADATA" | jq '{ | ||
| build_id: "${{ steps.vars.outputs.build_id }}", | ||
| git_origin: "${{ github.server_url }}/${{ github.repository }}", | ||
| git_revision: "${{ github.sha }}", | ||
| git_ref: "${{ github.ref }}", | ||
| timestamp: (now | strftime("%Y-%m-%dT%H:%M:%SZ")), | ||
| outputs: [ | ||
| to_entries[] | { | ||
| target: .key, | ||
| digest: .value."containerimage.digest", | ||
| image: (.value."image.name" // "" | split(",") | .[0]) | ||
| } | ||
| ] | ||
| }' > build-index.json | ||
| echo "Build index:" | ||
| cat build-index.json | ||
| - name: Upload build metadata to Artifactory | ||
| id: metadata | ||
| if: inputs.push | ||
| run: | | ||
| REPO_NAME="${{ steps.vars.outputs.repo_name }}" | ||
| BUILD_ID="${{ steps.vars.outputs.build_id }}" | ||
| METADATA_PATH="docker-build-metadata/${REPO_NAME}/builds/${BUILD_ID}" | ||
| METADATA_URL="https://${{ inputs.registry_host }}/artifactory/${METADATA_PATH}/index.json" | ||
| echo "Uploading build metadata to: ${METADATA_URL}" | ||
| curl -fsSL \ | ||
| -H "Authorization: Bearer ${{ secrets.ARTIFACTORY_TOKEN }}" \ | ||
| -H "Content-Type: application/json" \ | ||
| -T build-index.json \ | ||
| "${METADATA_URL}" | ||
| echo "metadata_url=${METADATA_URL}" >> $GITHUB_OUTPUT | ||
| echo "✓ Metadata uploaded successfully" | ||
| - name: Upload build-index as artifact | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: build-index | ||
| path: build-index.json | ||
| retention-days: 90 | ||
| - name: Summary | ||
| run: | | ||
| echo "## Build Summary" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Property | Value |" >> $GITHUB_STEP_SUMMARY | ||
| echo "|----------|-------|" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Build ID | \`${{ steps.vars.outputs.build_id }}\` |" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Registry | \`${{ steps.vars.outputs.registry_prefix }}\` |" >> $GITHUB_STEP_SUMMARY | ||
| echo "| Metadata | [${{ steps.metadata.outputs.metadata_url }}](${{ steps.metadata.outputs.metadata_url }}) |" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| echo "### Built Images" >> $GITHUB_STEP_SUMMARY | ||
| echo "" >> $GITHUB_STEP_SUMMARY | ||
| jq -r '.outputs[] | "- **\(.target)**: `\(.digest)`"' build-index.json >> $GITHUB_STEP_SUMMARY | ||