name: Build and Publish Docker Image on: push: tags: - "v*" env: REGISTRY: ghcr.io IMAGE_NAME: krau/saveany-bot concurrency: group: docker-build-${{ github.repository }} cancel-in-progress: true jobs: prepare: runs-on: ubuntu-latest permissions: contents: read outputs: version: ${{ steps.vars.outputs.version }} major_minor: ${{ steps.vars.outputs.major_minor }} short_sha: ${{ steps.vars.outputs.short_sha }} build_time: ${{ steps.vars.outputs.build_time }} steps: - name: Checkout repository uses: actions/checkout@v6 - name: Extract Version Components id: vars run: | VERSION=${GITHUB_REF#refs/tags/v} MAJOR_MINOR=$(echo "$VERSION" | cut -d. -f1,2) SHORT_SHA=$(git rev-parse --short HEAD) echo "version=$VERSION" >> "$GITHUB_OUTPUT" echo "major_minor=$MAJOR_MINOR" >> "$GITHUB_OUTPUT" echo "short_sha=$SHORT_SHA" >> "$GITHUB_OUTPUT" echo "build_time=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> "$GITHUB_OUTPUT" build: needs: prepare permissions: contents: read packages: write strategy: matrix: arch: [amd64, arm64] type: [default, micro, pico] fail-fast: false runs-on: ${{ matrix.arch == 'amd64' && 'ubuntu-latest' || 'ubuntu-24.04-arm' }} steps: - name: Checkout repository uses: actions/checkout@v6 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push by digest id: build uses: docker/build-push-action@v6 with: context: . file: ${{ matrix.type == 'default' && './Dockerfile' || format('./Dockerfile.{0}', matrix.type) }} platforms: ${{ matrix.arch == 'amd64' && 'linux/amd64' || 'linux/arm64' }} # 关键修改:不再使用 tags,而是通过 image output 按摘要推送 outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true build-args: | VERSION=${{ needs.prepare.outputs.version }} GitCommit=${{ needs.prepare.outputs.short_sha }} BuildTime=${{ needs.prepare.outputs.build_time }} cache-from: type=gha cache-to: type=gha,mode=max - name: Export digest # 将 digest 写入文件,供后续步骤读取 run: | mkdir -p /tmp/digests digest="${{ steps.build.outputs.digest }}" touch "/tmp/digests/${digest#sha256:}" echo "$digest" > /tmp/digests/digest - name: Upload digest uses: actions/upload-artifact@v6 with: name: digest-${{ matrix.type }}-${{ matrix.arch }} path: /tmp/digests/digest if-no-files-found: error retention-days: 1 create-manifest: needs: [prepare, build] runs-on: ubuntu-latest permissions: packages: write strategy: matrix: type: [default, micro, pico] steps: - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Download digests uses: actions/download-artifact@v7 with: path: /tmp/digests pattern: digest-${{ matrix.type }}-* merge-multiple: false - name: Create and push manifest lists run: | REPO="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}" VERSION="${{ needs.prepare.outputs.version }}" MAJOR_MINOR="${{ needs.prepare.outputs.major_minor }}" SHA="${{ needs.prepare.outputs.short_sha }}" TYPE="${{ matrix.type }}" DIGEST_AMD64=$(cat /tmp/digests/digest-${TYPE}-amd64/digest) DIGEST_ARM64=$(cat /tmp/digests/digest-${TYPE}-arm64/digest) echo "Found digests for $TYPE:" echo "AMD64: $DIGEST_AMD64" echo "ARM64: $DIGEST_ARM64" TAGS=() if [ "$TYPE" == "default" ]; then TAGS+=("$REPO:latest") TAGS+=("$REPO:$VERSION") TAGS+=("$REPO:$MAJOR_MINOR") TAGS+=("$REPO:sha-$SHA") else TAGS+=("$REPO:$TYPE") TAGS+=("$REPO:$TYPE-latest") TAGS+=("$REPO:$TYPE-$VERSION") fi SRC_AMD64="${REPO}@${DIGEST_AMD64}" SRC_ARM64="${REPO}@${DIGEST_ARM64}" echo "Creating manifest list with sources:" echo " $SRC_AMD64" echo " $SRC_ARM64" for TAG in "${TAGS[@]}"; do echo "Pushing tag: $TAG" docker buildx imagetools create -t "$TAG" "$SRC_AMD64" "$SRC_ARM64" done