diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 19fd787..138ece0 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -9,9 +9,37 @@ permissions: contents: read packages: write +env: + IMAGE_NAME: ghcr.io/yusazh/infinite-canvas + jobs: - build: + meta: runs-on: ubuntu-latest + outputs: + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + steps: + - id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.IMAGE_NAME }} + tags: | + type=ref,event=tag + type=sha,prefix= + + build: + needs: meta + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - platform: linux/amd64 + arch: amd64 + runner: ubuntu-latest + - platform: linux/arm64 + arch: arm64 + runner: ubuntu-24.04-arm steps: - uses: actions/checkout@v4 @@ -23,20 +51,65 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - id: meta - uses: docker/metadata-action@v5 - with: - images: ghcr.io/${{ github.repository }} - tags: | - type=ref,event=tag - type=sha,prefix= - - - uses: docker/build-push-action@v6 + - id: build + uses: docker/build-push-action@v6 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 + platforms: ${{ matrix.platform }} + labels: ${{ needs.meta.outputs.labels }} + outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true + cache-from: type=gha,scope=app-${{ matrix.arch }} + cache-to: type=gha,mode=max,scope=app-${{ matrix.arch }} + + - name: Export digest + shell: bash + run: | + mkdir -p "$RUNNER_TEMP/digests" + digest="${{ steps.build.outputs.digest }}" + touch "$RUNNER_TEMP/digests/${digest#sha256:}" + + - uses: actions/upload-artifact@v4 + with: + name: digests-${{ matrix.arch }} + path: ${{ runner.temp }}/digests/* + if-no-files-found: error + retention-days: 1 + + merge: + needs: + - meta + - build + runs-on: ubuntu-latest + steps: + - uses: docker/setup-buildx-action@v3 + + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - uses: actions/download-artifact@v4 + with: + path: ${{ runner.temp }}/digests + pattern: digests-* + merge-multiple: true + + - name: Create multi-arch manifest + shell: bash + env: + TAGS: ${{ needs.meta.outputs.tags }} + run: | + tag_args=() + while IFS= read -r tag; do + if [ -n "$tag" ]; then + tag_args+=("-t" "$tag") + fi + done <<< "$TAGS" + + digest_args=() + while IFS= read -r digest_file; do + digest_args+=("${IMAGE_NAME}@sha256:${digest_file}") + done < <(find "$RUNNER_TEMP/digests" -type f -printf '%f\n' | sort) + + docker buildx imagetools create "${tag_args[@]}" "${digest_args[@]}" diff --git a/.github/workflows/docs-docker-image.yml b/.github/workflows/docs-docker-image.yml index 373526f..72ec2cc 100644 --- a/.github/workflows/docs-docker-image.yml +++ b/.github/workflows/docs-docker-image.yml @@ -9,9 +9,38 @@ permissions: contents: read packages: write +env: + IMAGE_NAME: ghcr.io/yusazh/infinite-canvas-docs + jobs: - build: + meta: runs-on: ubuntu-latest + outputs: + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + steps: + - id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.IMAGE_NAME }} + tags: | + type=raw,value=latest + type=ref,event=tag + type=sha,prefix= + + build: + needs: meta + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - platform: linux/amd64 + arch: amd64 + runner: ubuntu-latest + - platform: linux/arm64 + arch: arm64 + runner: ubuntu-24.04-arm steps: - uses: actions/checkout@v4 @@ -23,22 +52,66 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - id: meta - uses: docker/metadata-action@v5 - with: - images: ghcr.io/${{ github.repository }}-docs - tags: | - type=raw,value=latest - type=ref,event=tag - type=sha,prefix= - - - uses: docker/build-push-action@v6 + - id: build + uses: docker/build-push-action@v6 with: context: . file: ./docs/Dockerfile - platforms: linux/amd64,linux/arm64 - push: true - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha,scope=docs - cache-to: type=gha,mode=max,scope=docs + platforms: ${{ matrix.platform }} + labels: ${{ needs.meta.outputs.labels }} + outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true + cache-from: type=gha,scope=docs-${{ matrix.arch }} + cache-to: type=gha,mode=max,scope=docs-${{ matrix.arch }} + + - name: Export digest + shell: bash + run: | + mkdir -p "$RUNNER_TEMP/digests" + digest="${{ steps.build.outputs.digest }}" + touch "$RUNNER_TEMP/digests/${digest#sha256:}" + + - uses: actions/upload-artifact@v4 + with: + name: docs-digests-${{ matrix.arch }} + path: ${{ runner.temp }}/digests/* + if-no-files-found: error + retention-days: 1 + + merge: + needs: + - meta + - build + runs-on: ubuntu-latest + steps: + - uses: docker/setup-buildx-action@v3 + + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - uses: actions/download-artifact@v4 + with: + path: ${{ runner.temp }}/digests + pattern: docs-digests-* + merge-multiple: true + + - name: Create multi-arch manifest + shell: bash + env: + TAGS: ${{ needs.meta.outputs.tags }} + run: | + tag_args=() + while IFS= read -r tag; do + if [ -n "$tag" ]; then + tag_args+=("-t" "$tag") + fi + done <<< "$TAGS" + + digest_args=() + while IFS= read -r digest_file; do + digest_args+=("${IMAGE_NAME}@sha256:${digest_file}") + done < <(find "$RUNNER_TEMP/digests" -type f -printf '%f\n' | sort) + + docker buildx imagetools create "${tag_args[@]}" "${digest_args[@]}"