OverviewFilesCommitsIssuesDocsReleasesPeers

P2P-Hiverelay / .github / workflows / docker-publish.yml

85 lines · yaml ref:
name: Publish Docker image

# Build and push the p2p-hiverelay container image to GitHub Container Registry.
# Triggers:
#   - push to main        → publishes :latest + :main-<sha>
#   - manual workflow run → publishes selected branch snapshot tags
#
# Release tags are intentionally handled by release-surfaces.yml so the image,
# digest capture, fleet channels, Umbrel metadata, and StartOS package update
# together after the release audit gates pass.

on:
  push:
    branches: [main]
  workflow_dispatch:

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository_owner }}/p2p-hiverelay

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
      # Required for cosign keyless (OIDC) signing: the job mints a short-lived
      # OIDC token that Fulcio exchanges for an ephemeral signing certificate.
      # No long-lived signing key is stored anywhere (audit HR-DIS-001).
      id-token: write

    steps:
      - name: Checkout
        uses: actions/checkout@v7

      - name: Set up QEMU (for multi-arch)
        uses: docker/setup-qemu-action@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v4

      - name: Login to GitHub Container Registry
        uses: docker/login-action@v4
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata (tags, labels)
        id: meta
        uses: docker/metadata-action@v6
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=raw,value=latest,enable={{is_default_branch}}
            type=sha,prefix=main-,enable={{is_default_branch}}

      - name: Build and push
        id: build
        uses: docker/build-push-action@v7
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

      - name: Install cosign
        uses: sigstore/cosign-installer@v3

      # Keyless (OIDC) signature over the pushed multi-arch manifest DIGEST
      # (never a tag — tags move, digests don't). Signing by digest binds the
      # signature to the exact bytes. Consumers verify with the identity +
      # issuer below; see docs/SUPPLY-CHAIN.md (audit HR-DIS-001).
      - name: Sign image (cosign keyless)
        env:
          COSIGN_YES: "true"
          DIGEST: ${{ steps.build.outputs.digest }}
        run: |
          set -euo pipefail
          cosign sign --recursive "${REGISTRY}/${IMAGE_NAME}@${DIGEST}"