Docker Build and Publish #82
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: Docker Build and Publish | |
| on: | |
| # Trigger after CI workflow completes successfully (branches and tags) | |
| workflow_run: | |
| workflows: ["CI"] | |
| types: | |
| - completed | |
| # Allow PR builds (build but don't push) | |
| pull_request: | |
| branches: | |
| - main | |
| # Emergency manual override | |
| workflow_dispatch: | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| jobs: | |
| build-and-push: | |
| runs-on: ubuntu-latest | |
| # Only run if CI succeeded (for workflow_run) or if manually triggered or PR | |
| if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name != 'workflow_run' }} | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write # For signing images with cosign | |
| attestations: write # For build provenance attestation | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| # For workflow_run, checkout the commit that triggered CI | |
| ref: ${{ github.event.workflow_run.head_sha || github.ref }} | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@v3 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Determine tags from workflow_run | |
| id: tag-check | |
| run: | | |
| if [[ "${{ github.event_name }}" == "workflow_run" ]]; then | |
| HEAD_BRANCH="${{ github.event.workflow_run.head_branch }}" | |
| echo "head_branch=$HEAD_BRANCH" >> $GITHUB_OUTPUT | |
| # Check if it's a tag (starts with v) | |
| if [[ $HEAD_BRANCH == v* ]]; then | |
| VERSION=${HEAD_BRANCH#v} | |
| MAJOR=$(echo $VERSION | cut -d. -f1) | |
| MINOR=$(echo $VERSION | cut -d. -f1-2) | |
| echo "is_tag=true" >> $GITHUB_OUTPUT | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "major=$MAJOR" >> $GITHUB_OUTPUT | |
| echo "minor=$MINOR" >> $GITHUB_OUTPUT | |
| echo "is_main=false" >> $GITHUB_OUTPUT | |
| elif [[ $HEAD_BRANCH == "main" ]]; then | |
| echo "is_tag=false" >> $GITHUB_OUTPUT | |
| echo "is_main=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "is_tag=false" >> $GITHUB_OUTPUT | |
| echo "is_main=false" >> $GITHUB_OUTPUT | |
| fi | |
| else | |
| echo "is_tag=false" >> $GITHUB_OUTPUT | |
| echo "is_main=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Log into registry ${{ env.REGISTRY }} | |
| if: github.event_name != 'pull_request' | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract Docker metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| # Version tags for workflow_run from tags | |
| type=raw,value=${{ steps.tag-check.outputs.version }},enable=${{ steps.tag-check.outputs.is_tag == 'true' }} | |
| type=raw,value=${{ steps.tag-check.outputs.minor }},enable=${{ steps.tag-check.outputs.is_tag == 'true' }} | |
| type=raw,value=${{ steps.tag-check.outputs.major }},enable=${{ steps.tag-check.outputs.is_tag == 'true' }} | |
| # Version tags for direct tag pushes (v1.2.3) | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| type=semver,pattern={{major}} | |
| # Branch tags | |
| type=ref,event=branch | |
| # PR tags | |
| type=ref,event=pr | |
| # Latest tag for main branch or version tags | |
| type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' || github.ref_type == 'tag' || (github.event_name == 'workflow_run' && (steps.tag-check.outputs.is_main == 'true' || steps.tag-check.outputs.is_tag == 'true')) }} | |
| # Edge tag for develop branch | |
| type=raw,value=edge,enable=${{ github.ref == 'refs/heads/develop' }} | |
| # Git commit SHA (short) - only for branch builds | |
| type=sha,prefix={{branch}}-,enable=${{ github.ref_type == 'branch' }} | |
| labels: | | |
| org.opencontainers.image.title=Data Archiver | |
| org.opencontainers.image.description=Archive database data to object storage. Currently supports PostgreSQL input and S3-compatible output. | |
| org.opencontainers.image.vendor=Airframes.io | |
| org.opencontainers.image.authors=Airframes.io | |
| org.opencontainers.image.documentation=https://github.com/airframesio/data-archiver | |
| org.opencontainers.image.source=https://github.com/airframesio/data-archiver | |
| - name: Extract version from tag | |
| id: version | |
| run: | | |
| # For workflow_run events, check the head_branch | |
| if [[ "${{ github.event_name }}" == "workflow_run" ]]; then | |
| HEAD_BRANCH="${{ github.event.workflow_run.head_branch }}" | |
| if [[ $HEAD_BRANCH == v* ]]; then | |
| VERSION=${HEAD_BRANCH#v} | |
| else | |
| VERSION=dev | |
| fi | |
| elif [[ $GITHUB_REF == refs/tags/v* ]]; then | |
| VERSION=${GITHUB_REF#refs/tags/v} | |
| else | |
| VERSION=dev | |
| fi | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| - name: Build and push Docker image | |
| id: build-and-push | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| platforms: linux/amd64,linux/arm64 | |
| push: ${{ github.event_name != 'pull_request' }} | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| build-args: | | |
| VERSION=${{ steps.version.outputs.version }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| provenance: true | |
| sbom: true | |
| - name: Generate artifact attestation | |
| if: github.event_name != 'pull_request' | |
| uses: actions/attest-build-provenance@v1 | |
| with: | |
| subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| subject-digest: ${{ steps.build-and-push.outputs.digest }} | |
| push-to-registry: true | |
| - name: Create summary | |
| if: github.event_name != 'pull_request' | |
| run: | | |
| echo "## Docker Image Published 🐳" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Registry:** \`${{ env.REGISTRY }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Image:** \`${{ env.IMAGE_NAME }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Digest:** \`${{ steps.build-and-push.outputs.digest }}\`" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Tags:**" >> $GITHUB_STEP_SUMMARY | |
| echo '```' >> $GITHUB_STEP_SUMMARY | |
| echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY | |
| echo '```' >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Platforms:** linux/amd64, linux/arm64" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "### Pull Command" >> $GITHUB_STEP_SUMMARY | |
| echo '```bash' >> $GITHUB_STEP_SUMMARY | |
| echo "docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" >> $GITHUB_STEP_SUMMARY | |
| echo '```' >> $GITHUB_STEP_SUMMARY | |
| test-image: | |
| runs-on: ubuntu-latest | |
| needs: build-and-push | |
| if: github.event_name != 'pull_request' | |
| steps: | |
| - name: Log into registry ${{ env.REGISTRY }} | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract tag for testing | |
| id: tag | |
| run: | | |
| # For workflow_run events, check the head_branch | |
| if [[ "${{ github.event_name }}" == "workflow_run" ]]; then | |
| HEAD_BRANCH="${{ github.event.workflow_run.head_branch }}" | |
| if [[ $HEAD_BRANCH == v* ]]; then | |
| TAG=${HEAD_BRANCH#v} | |
| elif [[ $HEAD_BRANCH == "main" ]]; then | |
| TAG=latest | |
| elif [[ $HEAD_BRANCH == "develop" ]]; then | |
| TAG=edge | |
| else | |
| TAG=$HEAD_BRANCH | |
| fi | |
| elif [[ $GITHUB_REF == refs/tags/v* ]]; then | |
| TAG=${GITHUB_REF#refs/tags/v} | |
| elif [[ $GITHUB_REF == refs/heads/main ]]; then | |
| TAG=latest | |
| elif [[ $GITHUB_REF == refs/heads/develop ]]; then | |
| TAG=edge | |
| else | |
| TAG=${GITHUB_REF#refs/heads/} | |
| fi | |
| echo "tag=$TAG" >> $GITHUB_OUTPUT | |
| - name: Pull and test image | |
| run: | | |
| echo "Testing image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }}" | |
| # Pull the image | |
| docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }} | |
| # Test basic functionality (help command) | |
| docker run --rm ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }} --help | |
| # Test version command | |
| docker run --rm ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }} --version | |
| # Inspect image | |
| docker inspect ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }} | |
| echo "✅ Image tests passed successfully!" | |
| - name: Test result summary | |
| run: | | |
| echo "## Image Testing Complete ✅" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "Successfully tested image: \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.tag.outputs.tag }}\`" >> $GITHUB_STEP_SUMMARY |