name: create-manifest description: | Create and push a multi-platform Docker manifest from individual platform digests. Handles downloading digests, creating manifest lists, and pushing to registry. inputs: digest_pattern: description: Glob pattern to match digest artifacts (e.g. "digests-linux-{amd64,arm64}") required: true tag_suffix: description: Suffix to add to all Docker tags (e.g. "-maxperf") required: false default: "" images: description: Container registry images (newline-separated) required: true registry_user: description: Registry username for authentication required: false registry_password: description: Registry password for authentication required: false outputs: version: description: The version tag created for the manifest value: ${{ steps.meta.outputs.version }} tags: description: All tags created for the manifest value: ${{ steps.meta.outputs.tags }} runs: using: composite steps: - run: mkdir -p digests shell: bash - name: Download digests if: ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' }} uses: forgejo/download-artifact@v4 with: path: digests pattern: ${{ inputs.digest_pattern }} merge-multiple: true - name: Login to builtin registry if: ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' }} uses: docker/login-action@v4 with: registry: ${{ env.BUILTIN_REGISTRY }} username: ${{ inputs.registry_user }} password: ${{ inputs.registry_password }} - name: Set up Docker Buildx if: ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' }} uses: docker/setup-buildx-action@v3 with: # Use persistent BuildKit if BUILDKIT_ENDPOINT is set (e.g. tcp://buildkit:8125) driver: ${{ env.BUILDKIT_ENDPOINT != '' && 'remote' || 'docker-container' }} endpoint: ${{ env.BUILDKIT_ENDPOINT || '' }} - name: Extract metadata (tags) for Docker if: ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' }} id: meta uses: docker/metadata-action@v6 with: flavor: | latest=auto suffix=${{ inputs.tag_suffix }},onlatest=true tags: | type=semver,pattern={{version}},prefix=v type=semver,pattern={{major}}.{{minor}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.0.') }},prefix=v type=semver,pattern={{major}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.') }},prefix=v type=ref,event=branch,prefix=${{ format('refs/heads/{0}', github.event.repository.default_branch) != github.ref && 'branch-' || '' }}, type=ref,event=pr type=sha,format=short images: ${{ inputs.images }} # default labels & annotations: https://github.com/docker/metadata-action/blob/master/src/meta.ts#L509 env: DOCKER_METADATA_ANNOTATIONS_LEVELS: index - name: Create manifest list and push if: ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' }} working-directory: digests shell: bash env: IMAGES: ${{ inputs.images }} run: | set -o xtrace IFS=$'\n' IMAGES_LIST=($IMAGES) ANNOTATIONS_LIST=($DOCKER_METADATA_OUTPUT_ANNOTATIONS) TAGS_LIST=($DOCKER_METADATA_OUTPUT_TAGS) for REPO in "${IMAGES_LIST[@]}"; do docker buildx imagetools create \ $(for tag in "${TAGS_LIST[@]}"; do echo "--tag"; echo "$tag"; done) \ $(for annotation in "${ANNOTATIONS_LIST[@]}"; do echo "--annotation"; echo "$annotation"; done) \ $(for reference in *; do printf "$REPO@sha256:%s\n" $reference; done) done - name: Inspect image if: ${{ env.BUILTIN_REGISTRY_ENABLED == 'true' }} shell: bash env: IMAGES: ${{ inputs.images }} run: | set -o xtrace IMAGES_LIST=($IMAGES) for REPO in "${IMAGES_LIST[@]}"; do docker buildx imagetools inspect $REPO:${{ steps.meta.outputs.version }} done