diff --git a/.github/workflows/docker-hub-platform.yml b/.github/workflows/docker-hub-platform.yml index 32f9fe5d2..db4f323f1 100644 --- a/.github/workflows/docker-hub-platform.yml +++ b/.github/workflows/docker-hub-platform.yml @@ -14,7 +14,9 @@ concurrency: cancel-in-progress: true env: - IMAGE_NAME: index.docker.io/metacall/core + DOCKER_REGISTRY: index.docker.io + DOCKER_USERNAME: metacall + IMAGE_NAME: core BUILDKIT_VERSION: 0.13.0 jobs: @@ -26,41 +28,28 @@ jobs: matrix: platform: - linux/amd64 + - linux/386 - linux/arm64 - linux/riscv64 - linux/ppc64le - linux/s390x - - linux/386 - linux/arm/v7 - linux/arm/v6 - # - linux/mips64le - # - linux/mips64 - steps: - - name: Checkout the code + - name: Checkout Repository uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.IMAGE_NAME }} - - name: Set up QEMU uses: docker/setup-qemu-action@v3 - - name: Docker Setup BuildX + - name: Set up Docker BuildX uses: docker/setup-buildx-action@v3 with: version: v${{ env.BUILDKIT_VERSION }} - - name: Verify Docker BuildX Version - run: docker buildx version - - - name: Authenticate to Docker registry - if: github.event_name != 'pull_request' + - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} @@ -72,93 +61,101 @@ jobs: run: | ./docker-compose.sh platform - # - name: Generate images - # if: github.event_name != 'pull_request' - # run: | - # for tag in "deps" "dev" "runtime" "cli"; do - # mkdir -p "/tmp/images/${tag}" - # digest="$(docker images --no-trunc --quiet metacall/core:${tag})" - # echo "FROM metacall/core:${tag}@${digest}" &> "/tmp/images/${tag}/Dockerfile" - # done - - # - name: Build and push by digest (deps) - # id: build - # uses: docker/build-push-action@v6 - # if: github.event_name != 'pull_request' - # with: - # context: /tmp/images/deps/Dockerfile - # platforms: ${{ matrix.platform }} - # labels: ${{ steps.meta.outputs.labels }} - # outputs: type=image,name=docker.io/${{ env.IMAGE_NAME }}:deps,push-by-digest=true,name-canonical=true,push=true - - - name: Export digests - if: github.event_name != 'pull_request' + - name: Tag Platform Images run: | - PLATFORM=${{ matrix.platform }} - echo "PLATFORM=${PLATFORM//\//-}" >> $GITHUB_ENV + platform_tag=$(echo "${{ matrix.platform }}" | tr '/' '-') + echo "Platform Tag: ${platform_tag}" for tag in "deps" "dev" "runtime" "cli"; do - mkdir -p "/tmp/digests/${tag}" - digest="$(docker images --no-trunc --quiet metacall/core:${tag})" - touch "/tmp/digests/${tag}/${digest#sha256:}" + docker tag metacall/${IMAGE_NAME}:${tag} \ + ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag}-${platform_tag} done - - name: Upload digests - if: github.event_name != 'pull_request' - uses: actions/upload-artifact@v4 - with: - name: digests-${{ env.PLATFORM }} - path: /tmp/digests/* - if-no-files-found: error - retention-days: 1 + - name: Push Platform Images + run: | + platform_tag=$(echo "${{ matrix.platform }}" | tr '/' '-') + for tag in "deps" "dev" "runtime" "cli"; do + echo "Pushing image for tag: ${tag} with platform: ${platform_tag}" + docker push ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag}-${platform_tag} + done - merge: - name: Merge digests for the manifest + - name: Run Tests + run: | + set -exuo pipefail + platform_tag=$(echo "${{ matrix.platform }}" | tr '/' '-') + cat < Dockerfile.test + FROM ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:cli-${platform_tag} + RUN echo "console.log('abcde')" > script.js + RUN metacallcli script.js + EOF + + docker build --platform ${{ matrix.platform }} -f Dockerfile.test -t test-image . + docker run --rm --platform=${{ matrix.platform }} test-image + + manifest: + name: Create and Push Manifest Lists + needs: build runs-on: ubuntu-latest - if: github.event_name != 'pull_request' - needs: - - build steps: - - name: Download digests - uses: actions/download-artifact@v4 - with: - path: /tmp/digests - pattern: digests-* - merge-multiple: true - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - with: - version: v${{ env.BUILDKIT_VERSION }} - - - name: Docker meta - id: meta - uses: docker/metadata-action@v5 - with: - images: ${{ env.IMAGE_NAME }} - - - name: Authenticate to Docker registry + - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} - - name: Create manifest list and push - if: github.ref == 'refs/heads/master' || contains(github.ref, 'refs/tags/') + - name: Create and Push Manifest Lists run: | for tag in "deps" "dev" "runtime" "cli"; do - cd "/tmp/digests/${tag}" - IMAGE_HASHES=$(printf '${{ env.IMAGE_NAME }}:${tag}@sha256:%s ' *) - for image in ${IMAGE_HASHES}; do - docker image tag ${image} ${{ env.IMAGE_NAME }}:${tag} - docker push ${{ env.IMAGE_NAME }}:${tag} + echo "Creating manifest for tag: $tag" + platform_tags="" + for platform in "linux/amd64" "linux/386" "linux/arm64" "linux/riscv64" "linux/ppc64le" "linux/s390x" "linux/arm/v7" "linux/arm/v6"; do + platform_tag=$(echo "${platform}" | tr '/' '-') + platform_tags="${platform_tags} ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag}-${platform_tag}" + done + echo "Creating manifest with tags: ${platform_tags}" + docker manifest create ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag} ${platform_tags} --amend + docker manifest push ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag} + done + + - name: Create Version Specific Tags + if: startsWith(github.ref, 'refs/tags/') + run: | + VERSION=${GITHUB_REF#refs/tags/v} + tags=("deps" "dev" "runtime" "cli") + platforms=("linux/amd64" "linux/386" "linux/arm64" "linux/riscv64" "linux/ppc64le" "linux/s390x" "linux/arm/v7" "linux/arm/v6") + for tag in "${tags[@]}"; do + platform_tags="" + for platform in "${platforms[@]}"; do + platform_tags="${platform_tags} ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${tag}-${platform}" + done + docker manifest create ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${VERSION}-${tag} ${platform_tags} --amend + docker manifest push ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:${VERSION}-${tag} + done + + cli_platform_tags="" + for platform in ${{ matrix.platform }}; do + cli_platform_tags="${cli_platform_tags} ${DOCKER_USERNAME}/${IMAGE_NAME}:cli-${platform}" + done + docker manifest create ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:latest ${cli_platform_tags} --amend + docker manifest push ${DOCKER_REGISTRY}/${DOCKER_USERNAME}/${IMAGE_NAME}:latest + + cleanup: + name: Cleanup Platform Specific Tags + needs: [build, manifest] + runs-on: ubuntu-latest + if: always() + steps: + - name: Remove Platform-Specific Tags + run: | + platforms=("linux-amd64" "linux-386" "linux-arm64" "linux-riscv64" "linux-ppc64le" "linux-s390x" "linux-arm-v7" "linux-arm-v6") + tags=("deps" "dev" "runtime" "cli") + + for platform in "${platforms[@]}"; do + for tag in "${tags[@]}"; do + tag_to_delete="${tag}-${platform}" + echo "Deleting tag: ${tag_to_delete}" + + curl -X DELETE \ + -H "Authorization: Bearer ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}" \ + "https://hub.docker.com/v2/repositories/${DOCKER_USERNAME}/${IMAGE_NAME}/tags/${tag_to_delete}/" done - docker buildx imagetools create -t ${{ env.IMAGE_NAME }}:${tag} ${IMAGE_HASHES} - if [[ "${tag}" = "cli" ]]; then - docker buildx imagetools create -t ${{ env.IMAGE_NAME }}:latest ${IMAGE_HASHES} - if [[ "${{ contains(github.ref, 'refs/tags/') }}" = true ]]; then - TAG=${GITHUB_REF#refs/*/} - VERSION=${TAG#v} - docker buildx imagetools create -t ${{ env.IMAGE_NAME }}:${VERSION} ${IMAGE_HASHES} - fi - fi done