diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 000000000..fdede6574 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,198 @@ +name: Docker Multi Platform Builds + +on: + push: + branches: + - 'main' + tags: + - 'v*.*.*' + pull_request: + branches: + - 'main' + +env: + DOCKERHUB_IMAGE: ${{ 'oceanprotocol/df-py' }} + GHCR_IMAGE: ${{ 'ghcr.io/oceanprotocol/df-py' }} + +jobs: + build: + runs-on: ubuntu-latest + 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/amd64"]') || fromJSON('["linux/amd64"]') }} + 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: | + ${{ 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 + + merge: + runs-on: ubuntu-latest + if: ${{ github.actor != 'dependabot[bot]' }} + 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 + - 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: 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: 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 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 ${{ env.GHCR_IMAGE }}:${{ steps.ocean_node_meta.outputs.version }} diff --git a/.github/workflows/ghcr_cleanup.yml b/.github/workflows/ghcr_cleanup.yml new file mode 100644 index 000000000..3a9997be9 --- /dev/null +++ b/.github/workflows/ghcr_cleanup.yml @@ -0,0 +1,32 @@ +name: GHCR cleanup + +on: + workflow_dispatch: + +env: + DOCKERHUB_IMAGE: ${{ 'oceanprotocol/ocean-node' }} + GHCR_IMAGE: ${{ 'ghcr.io/oceanprotocol/ocean-node' }} + +jobs: + ghcr_cleanup: + runs-on: ubuntu-latest + steps: + - 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: 'Clean up docker images' + if: steps.ghcr_login.outcome == 'success' + uses: dataaxiom/ghcr-cleanup-action@v1 + with: + token: ${{ secrets.GHCR_PUSH_TOKEN }} + exclude-tags: latest,main,v* + older-than: 1 month + delete-untagged: true + delete-partial-images: true