diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 941c28408..d3a77f294 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -11,6 +11,10 @@ on: branches: - 'main' +env: + DOCKERHUB_IMAGE: ${{ 'oceanprotocol/ocean-node' }} + GHCR_IMAGE: ${{ 'ghcr.io/oceanprotocol/ocean-node' }} + jobs: build: runs-on: ubuntu-latest @@ -18,36 +22,154 @@ jobs: strategy: fail-fast: false matrix: - platform: ${{ github.event_name == 'pull_request' && fromJSON('["linux/amd64"]') || fromJSON('["linux/amd64","linux/arm64","linux/arm/v7"]') }} + # we keep this just in case we need to change + platform: ${{ github.event_name == 'pull_request' && fromJSON('["linux/amd64"]') || fromJSON('["linux/amd64"]') }} steps: - name: Prepare run: | platform=${{ matrix.platform }} echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v6 - name: Set up QEMU uses: docker/setup-qemu-action@v3 with: platforms: ${{ matrix.platform }} - image: tonistiigi/binfmt:qemu-v8.0.4 + #image: tonistiigi/binfmt:qemu-v8.0.4 - name: Set up Docker Buildx id: buildx uses: docker/setup-buildx-action@v3 with: platforms: ${{ matrix.platform }} - name: Login to Docker Hub + id: dockerhub_login + env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_PUSH_USERNAME }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKER_PUSH_TOKEN }} + if: env.DOCKERHUB_USERNAME != '' && env.DOCKERHUB_TOKEN != '' uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_PUSH_USERNAME }} password: ${{ secrets.DOCKER_PUSH_TOKEN }} + - name: Login to GitHub Container Registry + id: ghcr_login + env: + GHCR_PUSH_TOKEN: ${{ secrets.GHCR_PUSH_TOKEN }} + if: env.GHCR_PUSH_TOKEN != '' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GHCR_PUSH_TOKEN }} + - name: Set Docker metadata + id: ocean_node_meta + uses: docker/metadata-action@v5 + with: + images: | + ${{ env.DOCKERHUB_IMAGE }} + ${{ env.GHCR_IMAGE }} + # generate Docker tags based on the following events/attributes + tags: | + type=ref,event=branch + type=semver,pattern={{version}} + type=ref,event=pr + # type=semver,pattern={{major}}.{{minor}} + # type=semver,pattern={{major}} + # type=sha + - name: Build and push to Docker Hub + if: steps.dockerhub_login.outcome == 'success' + id: build_dockerhub + uses: docker/build-push-action@v5 + with: + builder: ${{ steps.buildx.outputs.name }} + context: . + platforms: ${{ matrix.platform }} + push: true + # tags: ${{ steps.ocean_node_meta.outputs.tags }} + labels: ${{ steps.ocean_node_meta.outputs.labels }} + outputs: type=image,name=${{ env.DOCKERHUB_IMAGE }},push-by-digest=true,name-canonical=true,push=true + - name: Build and push to GHCR + if: steps.ghcr_login.outcome == 'success' + id: build_ghcr + uses: docker/build-push-action@v5 + with: + builder: ${{ steps.buildx.outputs.name }} + context: . + platforms: ${{ matrix.platform }} + push: true + labels: ${{ steps.ocean_node_meta.outputs.labels }} + outputs: type=image,name=${{ env.GHCR_IMAGE }},push-by-digest=true,name-canonical=true,push=true + - name: Export digests + run: | + mkdir -p /tmp/digests + if [ -n "${{ steps.build_dockerhub.outputs.digest }}" ]; then + dockerhub_digest="${{ steps.build_dockerhub.outputs.digest }}" + touch "/tmp/digests/dockerhub-${dockerhub_digest#sha256:}" + fi + if [ -n "${{ steps.build_ghcr.outputs.digest }}" ]; then + ghcr_digest="${{ steps.build_ghcr.outputs.digest }}" + touch "/tmp/digests/ghcr-${ghcr_digest#sha256:}" + fi + - name: Upload digest + uses: actions/upload-artifact@v4 + with: + name: digests-${{ env.PLATFORM_PAIR }} + path: /tmp/digests/* + if-no-files-found: error + retention-days: 1 + build-arm: + runs-on: ubuntu-24.04-arm + if: ${{ github.actor != 'dependabot[bot]' }} + strategy: + fail-fast: false + matrix: + # we keep this just in case we need to change + platform: ${{ github.event_name == 'pull_request' && fromJSON('["linux/arm64"]') || fromJSON('["linux/arm64"]') }} + steps: + - name: Prepare + run: | + platform=${{ matrix.platform }} + echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV + - name: Checkout + uses: actions/checkout@v6 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + with: + platforms: ${{ matrix.platform }} + #image: tonistiigi/binfmt:qemu-v8.0.4 + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v3 + with: + platforms: ${{ matrix.platform }} + - name: Login to Docker Hub + id: dockerhub_login + env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_PUSH_USERNAME }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKER_PUSH_TOKEN }} + if: env.DOCKERHUB_USERNAME != '' && env.DOCKERHUB_TOKEN != '' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_PUSH_USERNAME }} + password: ${{ secrets.DOCKER_PUSH_TOKEN }} + - name: Login to GitHub Container Registry + id: ghcr_login + env: + GHCR_PUSH_TOKEN: ${{ secrets.GHCR_PUSH_TOKEN }} + if: env.GHCR_PUSH_TOKEN != '' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GHCR_PUSH_TOKEN }} - name: Set Docker metadata id: ocean_node_meta uses: docker/metadata-action@v5 with: images: | - oceanprotocol/ocean-node + ${{ env.DOCKERHUB_IMAGE }} + ${{ env.GHCR_IMAGE }} # generate Docker tags based on the following events/attributes tags: | type=ref,event=branch @@ -56,8 +178,9 @@ jobs: # type=semver,pattern={{major}}.{{minor}} # type=semver,pattern={{major}} # type=sha - - name: Build and push - id: build + - name: Build and push to Docker Hub + if: steps.dockerhub_login.outcome == 'success' + id: build_dockerhub uses: docker/build-push-action@v5 with: builder: ${{ steps.buildx.outputs.name }} @@ -66,12 +189,29 @@ jobs: push: true # tags: ${{ steps.ocean_node_meta.outputs.tags }} labels: ${{ steps.ocean_node_meta.outputs.labels }} - outputs: type=image,name=oceanprotocol/ocean-node,push-by-digest=true,name-canonical=true,push=true - - name: Export digest + outputs: type=image,name=${{ env.DOCKERHUB_IMAGE }},push-by-digest=true,name-canonical=true,push=true + - name: Build and push to GHCR + if: steps.ghcr_login.outcome == 'success' + id: build_ghcr + uses: docker/build-push-action@v5 + with: + builder: ${{ steps.buildx.outputs.name }} + context: . + platforms: ${{ matrix.platform }} + push: true + labels: ${{ steps.ocean_node_meta.outputs.labels }} + outputs: type=image,name=${{ env.GHCR_IMAGE }},push-by-digest=true,name-canonical=true,push=true + - name: Export digests run: | mkdir -p /tmp/digests - digest="${{ steps.build.outputs.digest }}" - touch "/tmp/digests/${digest#sha256:}" + if [ -n "${{ steps.build_dockerhub.outputs.digest }}" ]; then + dockerhub_digest="${{ steps.build_dockerhub.outputs.digest }}" + touch "/tmp/digests/dockerhub-arm64-${dockerhub_digest#sha256:}" + fi + if [ -n "${{ steps.build_ghcr.outputs.digest }}" ]; then + ghcr_digest="${{ steps.build_ghcr.outputs.digest }}" + touch "/tmp/digests/ghcr-arm64-${ghcr_digest#sha256:}" + fi - name: Upload digest uses: actions/upload-artifact@v4 with: @@ -85,6 +225,7 @@ jobs: if: ${{ github.actor != 'dependabot[bot]' }} needs: - build + - build-arm steps: - name: Download digests uses: actions/download-artifact@v4 @@ -99,7 +240,8 @@ jobs: uses: docker/metadata-action@v5 with: images: | - oceanprotocol/ocean-node + ${{ env.DOCKERHUB_IMAGE }} + ${{ env.GHCR_IMAGE }} # generate Docker tags based on the following events/attributes tags: | type=ref,event=branch @@ -109,15 +251,52 @@ jobs: # type=semver,pattern={{major}} # type=sha - name: Login to Docker Hub + id: dockerhub_login + env: + DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_PUSH_USERNAME }} + DOCKERHUB_TOKEN: ${{ secrets.DOCKER_PUSH_TOKEN }} + if: env.DOCKERHUB_USERNAME != '' && env.DOCKERHUB_TOKEN != '' uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_PUSH_USERNAME }} password: ${{ secrets.DOCKER_PUSH_TOKEN }} - - name: Create manifest list and push + - name: Login to GitHub Container Registry + id: ghcr_login + env: + GHCR_PUSH_TOKEN: ${{ secrets.GHCR_PUSH_TOKEN }} + if: env.GHCR_PUSH_TOKEN != '' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GHCR_PUSH_TOKEN }} + - name: Create manifest list and push to Docker Hub + if: steps.dockerhub_login.outcome == 'success' + working-directory: /tmp/digests + env: + DOCKERHUB_IMAGE: ${{ env.DOCKERHUB_IMAGE }} + run: | + if ls dockerhub-* 1> /dev/null 2>&1; then + TAGS=$(echo "${{ steps.ocean_node_meta.outputs.tags }}" | grep -E "^${DOCKERHUB_IMAGE}" | sed 's|^|-t |' | tr '\n' ' ') + # Strip dockerhub-arm64- and dockerhub- so digest is always just the sha256 hex + DIGESTS=$(ls dockerhub-* | sed -e "s|dockerhub-arm64-|${DOCKERHUB_IMAGE}@sha256:|" -e "s|dockerhub-|${DOCKERHUB_IMAGE}@sha256:|" | tr '\n' ' ') + docker buildx imagetools create $TAGS $DIGESTS + fi + - name: Create manifest list and push to GHCR + if: steps.ghcr_login.outcome == 'success' working-directory: /tmp/digests + env: + GHCR_IMAGE: ${{ env.GHCR_IMAGE }} + run: | + TAGS=$(echo "${{ steps.ocean_node_meta.outputs.tags }}" | grep -E "^${GHCR_IMAGE}" | sed 's|^|-t |' | tr '\n' ' ') + # Strip ghcr-arm64- and ghcr- so digest is always just the sha256 hex + DIGESTS=$(ls ghcr-* | sed -e "s|ghcr-arm64-|${GHCR_IMAGE}@sha256:|" -e "s|ghcr-|${GHCR_IMAGE}@sha256:|" | tr '\n' ' ') + docker buildx imagetools create $TAGS $DIGESTS + - name: Inspect Docker Hub image + if: steps.dockerhub_login.outcome == 'success' run: | - docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf 'oceanprotocol/ocean-node@sha256:%s ' *) - - name: Inspect image + docker buildx imagetools inspect ${{ env.DOCKERHUB_IMAGE }}:${{ steps.ocean_node_meta.outputs.version }} + - name: Inspect GHCR image + if: steps.ghcr_login.outcome == 'success' run: | - docker buildx imagetools inspect oceanprotocol/ocean-node:${{ steps.ocean_node_meta.outputs.version }} + docker buildx imagetools inspect ${{ env.GHCR_IMAGE }}:${{ steps.ocean_node_meta.outputs.version }}