name: Build & Publish to Docker Hub on: workflow_call: inputs: base_version: description: 'Base version (latest or develop)' required: true type: string info_version: description: 'Informational version number (e.g. 0.3.7-alpha)' required: true type: string tag_version: description: 'Docker tag version (e.g. v0.3.7)' required: true type: string secrets: docker_hub_username: required: true docker_hub_access_token: required: true jobs: build_images: name: Build ${{ matrix.name }} image runs-on: ${{ matrix.os }} if: contains(github.event.head_commit.message, '[no build]') == false strategy: matrix: include: - name: amd64 os: ubuntu-latest path: '' suffix: '-amd64' platform: 'linux/amd64' - name: arm32v7 os: ubuntu-latest path: 'arm32v7/' suffix: '-arm' platform: 'linux/arm/v7' - name: arm64 os: ubuntu-24.04-arm path: 'arm64/' suffix: '-arm64' platform: 'linux/arm64' steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up QEMU if: ${{ matrix.name == 'arm32v7' }} uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to DockerHub uses: docker/login-action@v3 with: username: ${{ secrets.docker_hub_username }} password: ${{ secrets.docker_hub_access_token }} - name: Log in to the Container registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push by digest id: build uses: docker/build-push-action@v5 with: context: . file: ./docker/${{ matrix.path }}Dockerfile push: true provenance: false platforms: ${{ matrix.platform }} build-args: | INFO_VERSION=${{ inputs.info_version }}-docker${{ matrix.suffix }} outputs: | type=image,name=jasongdove/ersatztv,name-canonical=true,push-by-digest=true type=image,name=ghcr.io/ersatztv/ersatztv,name-canonical=true,push-by-digest=true - name: Save digest to artifact run: echo ${{ steps.build.outputs.digest }} > digest.txt - name: Upload digest artifact uses: actions/upload-artifact@v4 with: name: digest-${{ matrix.name }} path: digest.txt merge_manifests: name: Merge Manifests runs-on: ubuntu-latest needs: build_images steps: - name: Login to DockerHub uses: docker/login-action@v3 with: username: ${{ secrets.docker_hub_username }} password: ${{ secrets.docker_hub_access_token }} - name: Log in to the Container registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Download all digest artifacts uses: actions/download-artifact@v4 with: path: digests/ - name: Read digests from artifacts id: digests run: | AMD64_HASH=$(cat digests/digest-amd64/digest.txt) ARM32V7_HASH=$(cat digests/digest-arm32v7/digest.txt) ARM64_HASH=$(cat digests/digest-arm64/digest.txt) DOCKER_HUB_DIGESTS="jasongdove/ersatztv@${AMD64_HASH} jasongdove/ersatztv@${ARM64_HASH} jasongdove/ersatztv@${ARM32V7_HASH}" GHCR_DIGESTS="ghcr.io/ersatztv/ersatztv@${AMD64_HASH} ghcr.io/ersatztv/ersatztv@${ARM64_HASH} ghcr.io/ersatztv/ersatztv@${ARM32V7_HASH}" echo "docker_hub_digests=${DOCKER_HUB_DIGESTS}" >> $GITHUB_OUTPUT echo "ghcr_digests=${GHCR_DIGESTS}" >> $GITHUB_OUTPUT - name: Create and push manifests run: | docker manifest create jasongdove/ersatztv:${{ inputs.base_version }} ${{ steps.digests.outputs.docker_hub_digests }} docker manifest push jasongdove/ersatztv:${{ inputs.base_version }} docker manifest create jasongdove/ersatztv:${{ inputs.tag_version }} ${{ steps.digests.outputs.docker_hub_digests }} docker manifest push jasongdove/ersatztv:${{ inputs.tag_version }} docker manifest create ghcr.io/ersatztv/ersatztv:${{ inputs.base_version }} ${{ steps.digests.outputs.ghcr_digests }} docker manifest push ghcr.io/ersatztv/ersatztv:${{ inputs.base_version }} docker manifest create ghcr.io/ersatztv/ersatztv:${{ inputs.tag_version }} ${{ steps.digests.outputs.ghcr_digests }} docker manifest push ghcr.io/ersatztv/ersatztv:${{ inputs.tag_version }}