diff --git a/.github/workflows/release_cli.yaml b/.github/workflows/release_cli.yaml index c215701a..d5190a75 100644 --- a/.github/workflows/release_cli.yaml +++ b/.github/workflows/release_cli.yaml @@ -253,6 +253,115 @@ jobs: name: surfpool-${{ env.SHORT_TARGET_NAME }} path: surfpool-${{ env.SHORT_TARGET_NAME }}.tar.gz + build-image-amd64: + name: Build Docker Image (amd64) + runs-on: ubuntu-latest + needs: get_release_info + if: startsWith(github.ref, 'refs/heads/main') && needs.get_release_info.outputs.tag != '' + permissions: + contents: read + env: + REGISTRY: docker.io + IMAGE_NAME: surfpool/surfpool + outputs: + digest: ${{ steps.build.outputs.digest }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and push by digest + id: build + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64 + outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true + cache-from: type=gha,scope=buildkit-amd64 + cache-to: type=gha,scope=buildkit-amd64,mode=max + + build-image-arm64: + name: Build Docker Image (arm64) + runs-on: ubuntu-24.04-arm + needs: get_release_info + if: startsWith(github.ref, 'refs/heads/main') && needs.get_release_info.outputs.tag != '' + permissions: + contents: read + env: + REGISTRY: docker.io + IMAGE_NAME: surfpool/surfpool + outputs: + digest: ${{ steps.build.outputs.digest }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Build and push by digest + id: build + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/arm64 + outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true + cache-from: type=gha,scope=buildkit-arm64 + cache-to: type=gha,scope=buildkit-arm64,mode=max + + merge-image-manifest: + name: Merge Docker Manifest + runs-on: ubuntu-latest + needs: + - get_release_info + - build-image-amd64 + - build-image-arm64 + if: startsWith(github.ref, 'refs/heads/main') && needs.get_release_info.outputs.tag != '' + permissions: + contents: read + env: + REGISTRY: docker.io + IMAGE_NAME: surfpool/surfpool + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Generate Docker tags + id: tags + run: | + VERSION="${{ needs.get_release_info.outputs.tag }}" + VERSION="${VERSION#v}" + MAJOR="${VERSION%%.*}" + MINOR="${VERSION%.*}" + echo "tags<> $GITHUB_OUTPUT + echo "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}" >> $GITHUB_OUTPUT + echo "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${MINOR}" >> $GITHUB_OUTPUT + echo "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${MAJOR}" >> $GITHUB_OUTPUT + echo "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + - name: Create multi-arch manifest + run: | + AMD64_DIGEST="${{ needs.build-image-amd64.outputs.digest }}" + ARM64_DIGEST="${{ needs.build-image-arm64.outputs.digest }}" + while IFS= read -r TAG; do + [ -z "$TAG" ] && continue + docker buildx imagetools create --tag "$TAG" \ + "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${AMD64_DIGEST}" \ + "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${ARM64_DIGEST}" + done <<< "${{ steps.tags.outputs.tags }}" + release: name: Release runs-on: ubuntu-latest diff --git a/.github/workflows/release_image.yml b/.github/workflows/release_image.yml index 936829dc..01a8f3ad 100644 --- a/.github/workflows/release_image.yml +++ b/.github/workflows/release_image.yml @@ -1,22 +1,29 @@ name: Build and Push Docker Image on: - release: - types: [published] + workflow_dispatch: + inputs: + tag: + description: "Git tag to build (e.g., v1.2.3)" + required: true + type: string env: REGISTRY: docker.io IMAGE_NAME: surfpool/surfpool jobs: - build-and-push: + build-image-amd64: runs-on: ubuntu-latest permissions: contents: read - + outputs: + digest: ${{ steps.build.outputs.digest }} steps: - name: Checkout repository uses: actions/checkout@v4 + with: + ref: ${{ inputs.tag }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 @@ -27,24 +34,85 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - - name: Extract metadata - id: meta - uses: docker/metadata-action@v5 + - name: Build and push by digest + id: build + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64 + outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true + cache-from: type=gha,scope=buildkit-amd64 + cache-to: type=gha,scope=buildkit-amd64,mode=max + + build-image-arm64: + runs-on: ubuntu-24.04-arm + permissions: + contents: read + outputs: + digest: ${{ steps.build.outputs.digest }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - tags: | - type=semver,pattern={{version}} - type=semver,pattern={{major}}.{{minor}} - type=semver,pattern={{major}} - type=raw,value=latest - - - name: Build and push Docker image - uses: docker/build-push-action@v5 + ref: ${{ inputs.tag }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push by digest + 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: linux/arm64 + outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true + cache-from: type=gha,scope=buildkit-arm64 + cache-to: type=gha,scope=buildkit-arm64,mode=max + + merge-image-manifest: + runs-on: ubuntu-latest + needs: + - build-image-amd64 + - build-image-arm64 + permissions: + contents: read + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Generate Docker tags + id: tags + run: | + VERSION="${{ inputs.tag }}" + VERSION="${VERSION#v}" + MAJOR="${VERSION%%.*}" + MINOR="${VERSION%.*}" + echo "tags<> $GITHUB_OUTPUT + echo "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${VERSION}" >> $GITHUB_OUTPUT + echo "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${MINOR}" >> $GITHUB_OUTPUT + echo "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${MAJOR}" >> $GITHUB_OUTPUT + echo "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest" >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Create multi-arch manifest + run: | + AMD64_DIGEST="${{ needs.build-image-amd64.outputs.digest }}" + ARM64_DIGEST="${{ needs.build-image-arm64.outputs.digest }}" + while IFS= read -r TAG; do + [ -z "$TAG" ] && continue + docker buildx imagetools create --tag "$TAG" \ + "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${AMD64_DIGEST}" \ + "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${ARM64_DIGEST}" + done <<< "${{ steps.tags.outputs.tags }}"