rios0rios0/pipelines

Change Docker build pipelines to just add the tag on the image instead of triggering the whole building process again with a different tag

开放

#230 创建于 2025年12月19日

 (0 条评论) (1 个反应) (2 位负责人)Shell (5 个派生)github user discovery
documentationenhancementhelp wanted

仓库指标

星标
 (22 个星标)
PR 合并指标
 (平均合并 8小时 32分钟) (30 天内合并 39 个 PR)

描述

Summary

Problem: When a release tag is pushed we re-run the full Docker build pipeline that already ran on main producing :latest. This wastes CI time and resources because the image content is identical — we only need to add a release tag to the already-built image.
Goal: On tag events, fetch the :latest image produced by the main build, add the release tag, and push the new tag — do not rebuild.

Background

  • Current flow: main push → build image registry/org/image:latest → push. Tag push → pipeline triggers full rebuild and pushes registry/org/image:vX.Y.Z.
  • Desired flow: main push → build and push :latest. Tag push → pull :latest, tag it as the release tag, push the new tag.
  • Benefits: faster releases, lower CI cost, consistent image content between :latest and release tags, fewer build failures caused by rebuild nondeterminism.

Proposed Solution

  1. Add a lightweight pipeline that runs on push of tags only.
  2. That pipeline should:
    • Authenticate to the container registry.
    • Pull the :latest image for the same repository.
    • Tag the pulled image with the release tag (the git tag name).
    • Push the new tag to the registry.
  3. Keep the existing build pipeline for main unchanged (it still produces :latest).
  4. Add safeguards to ensure the :latest image exists and that the digest matches the commit referenced by the tag when possible.

Implementation Plan

Pipeline trigger

  • New workflow file or job triggered on push with tags:
on:
  push:
    tags:
      - 'v*' # or your tag pattern

Example GitHub Actions job (Docker Hub or GHCR)

jobs:
  retag:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Log in to registry
        uses: docker/login-action@v2
        with:
          registry: ghcr.io
          username: ${{ secrets.REGISTRY_USER }}
          password: ${{ secrets.REGISTRY_TOKEN }}

      - name: Pull latest image
        run: |
          IMAGE=ghcr.io/org/repo
          docker pull ${IMAGE}:latest

      - name: Tag with release
        run: |
          IMAGE=ghcr.io/org/repo
          TAG=${GITHUB_REF#refs/tags/}
          docker tag ${IMAGE}:latest ${IMAGE}:${TAG}

      - name: Push release tag
        run: |
          IMAGE=ghcr.io/org/repo
          TAG=${GITHUB_REF#refs/tags/}
          docker push ${IMAGE}:${TAG}

Registry specific notes

  • ECR: use aws ecr get-login-password and docker pull/docker tag/docker push.
  • Private registries: ensure credentials are available in secrets and the runner has network access.
  • Multi-arch images: if :latest is a manifest list, use docker manifest or skopeo to copy/retag the manifest list rather than pulling individual arch images. Example: skopeo copy docker://registry/org/repo:latest docker://registry/org/repo:${TAG}.

Acceptance Criteria

  • Tag push no longer triggers a full Docker build job for that repository; instead the retag job runs and completes in under 2 minutes (network permitting).
  • The release tag points to the exact same image digest as :latest produced by the main build.
  • Existing main build pipeline remains unchanged and continues to produce :latest.
  • Logs show docker pull, docker tag, and docker push steps; no docker build is executed during tag pipeline.
  • Tests for at least one repository in the monorepo confirm the image content is identical (digest equality).

Testing Plan

  • Dry run: create a test tag vtest-<timestamp> and verify the retag job pulls :latest and pushes vtest-....
  • Digest check: after pushing, compare docker inspect --format='{{index .RepoDigests 0}}' or skopeo inspect to ensure digests match.
  • Failure modes: simulate missing :latest and confirm pipeline fails with a clear error message and guidance to rebuild main.
  • Multi-arch: test with a multi-arch :latest image and verify manifest copy preserves all architectures.

Rollback and Risks

  • Risk: :latest may not correspond to the tag commit if main build failed or was re-run. Mitigation: add a check that :latest digest is associated with the expected commit when possible (store image digest as build artifact or in registry metadata). If mismatch, fail the retag and require a rebuild.
  • Risk: network or registry rate limits. Mitigation: add retries and backoff.
  • Rollback: revert the tag-only workflow and re-enable the previous tag-triggered build job.

Tasks and Labels

  • Tasks
    • Create retag-on-tag.yml workflow (or add job to existing workflows) — implement for GHCR and Docker Hub templates.
    • Add registry credential secrets documentation.
    • Add digest verification step (optional but recommended).
    • Add tests for single-arch and multi-arch images.
    • Update README and CI docs.
  • Suggested labels: ci, docker, performance, low-risk
  • Suggested assignees: @devops-team, @owner-of-pipelines
  • Estimate: 2–4 hours for basic implementation; 1–2 additional days to cover multi-arch and digest verification.

贡献者指南