name: PR Workflow concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.head.sha }} cancel-in-progress: true on: pull_request_target: types: - labeled - synchronize - reopened - opened branches: - 'master' jobs: test: if: contains(github.event.pull_request.labels.*.name, 'safe to test') uses: ./.github/workflows/testAndSanity.yml with: ref: ${{ github.event.pull_request.head.sha }} build-snapshot: name: Build OCI snapshot needs: test if: contains(github.event.pull_request.labels.*.name, 'safe to test') runs-on: ${{ matrix.os }} permissions: packages: write contents: read strategy: fail-fast: false matrix: include: - os: ubuntu-latest arch: amd64 platform: linux/amd64 - os: ubuntu-24.04-arm arch: arm64 platform: linux/arm64 steps: - name: Prepare run: | platform=${{ matrix.platform }} echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV # list all registries to push to and join all non-empty with comma # https://unix.stackexchange.com/a/693165/116849 # https://stackoverflow.com/a/9429887/1469797 strings=("${VARS_DOCKERHUB_SLUG}" "${VARS_GHCR_SLUG}") for i in ${!strings[@]}; do [[ -z ${strings[i]} ]] && unset strings[i]; done joined_string=$(IFS=, ; echo "${strings[*]}") echo "REGISTRIES_JOINED=$joined_string" >> $GITHUB_ENV date=$(date -u +"%Y-%m-%dT%H:%M:%SZ") echo "BUILD_DATE=$date" >> $GITHUB_ENV env: VARS_DOCKERHUB_SLUG: ${{ vars.DOCKERHUB_SLUG }} VARS_GHCR_SLUG: ${{vars.GHCR_SLUG}} # do not use here! # instead we can specify repo#sha in build-push-action so we only deal with foreign SHA for actually building image # - uses: actions/checkout@v4 # with: # ref: ${{ github.event.pull_request.head.sha }} - name: Set short git commit SHA run: | short=$(echo "${{ github.event.pull_request.head.sha }}" | head -c7) echo "COMMIT_SHORT_SHA=$short" >> $GITHUB_ENV - name: Get App Version id: appversion env: APP_VERSION: ${{ format('pr{0}-{1}', github.event.number, env.COMMIT_SHORT_SHA ) }} run: | echo appversion=$APP_VERSION >>${GITHUB_OUTPUT} - name: Login to Docker Hub if: ${{ vars.DOCKERHUB_SLUG != '' }} uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Login to GitHub Container Registry if: ${{ vars.GHCR_SLUG != '' }} uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} # metadata extract for docker labels/image names is done in merge job - name: Set up Buildx uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 #v3.11.1 # https://github.com/docker/build-push-action/issues/671#issuecomment-1619353328 # for caching - name: Build and push by digest id: build uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 #v6.18.0 with: # specify foreign repo#sha from PR that is used to build image context: ${{github.event.pull_request.head.repo.clone_url}}#${{github.event.pull_request.head.sha}} build-args: | APP_BUILD_VERSION=${{steps.appversion.outputs.appversion}} BUILD_DATE=${{ env.BUILD_DATE }} platforms: ${{ matrix.platform }} labels: ${{ steps.meta.outputs.labels }} outputs: type=image,"name=${{ env.REGISTRIES_JOINED }}",push-by-digest=true,name-canonical=true,push=true #cache-from: type=gha,scope=build-${{ env.PLATFORM_PAIR }} #cache-to: type=gha,scope=build-${{ env.PLATFORM_PAIR }} - name: Export digest run: | mkdir -p /tmp/digests digest="${{ steps.build.outputs.digest }}" touch "/tmp/digests/${digest#sha256:}" - name: Upload digest uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f #7.0.0 with: name: digests-${{ env.PLATFORM_PAIR }} path: /tmp/digests/* if-no-files-found: error retention-days: 1 release-snapshot: name: Merge OCI Images and Push if: ${{ vars.DOCKERHUB_SLUG != '' || vars.GHCR_SLUG != '' }} runs-on: ubuntu-latest permissions: packages: write contents: read needs: - build-snapshot - test steps: - name: Download digests uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c #8.0.1 with: path: /tmp/digests pattern: digests-* merge-multiple: true - name: Login to Docker Hub if: ${{ vars.DOCKERHUB_SLUG != '' }} uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Login to GitHub Container Registry if: ${{ vars.GHCR_SLUG != '' }} uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 - name: Extract metadata (tags, labels) id: meta uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf #6.0.0 with: images: | ${{ vars.DOCKERHUB_SLUG }} ${{ vars.GHCR_SLUG }} # generate Docker tags based on the following events/attributes # https://github.com/docker/metadata-action/issues/247#issuecomment-1511259674 for NOT is default branch, eventually tags: | type=ref,event=pr flavor: | latest=false labels: | org.opencontainers.image.title=Multi-Scrobbler org.opencontainers.image.description=Scrobble from many sources to many clients org.opencontainers.image.vendor=FoxxMD - name: Create manifest list and push dockerhub if: ${{ vars.DOCKERHUB_SLUG != '' }} working-directory: /tmp/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ $(printf "${VARS_DOCKERHUB_SLUG}@sha256:%s " *) env: VARS_DOCKERHUB_SLUG: ${{ vars.DOCKERHUB_SLUG }} - name: Create manifest list and push gchr if: ${{ vars.GHCR_SLUG != '' }} working-directory: /tmp/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ $(printf "${VARS_GHCR_SLUG}@sha256:%s " *) env: VARS_GHCR_SLUG: ${{ vars.GHCR_SLUG }} - name: Inspect image dockerhub if: ${{ vars.DOCKERHUB_SLUG != '' }} run: | docker buildx imagetools inspect ${VARS_DOCKERHUB_SLUG}:${STEPS_META_OUTPUTS_VERSION} env: VARS_DOCKERHUB_SLUG: ${{ vars.DOCKERHUB_SLUG }} STEPS_META_OUTPUTS_VERSION: ${{ steps.meta.outputs.version }} - name: Inspect image ghcr if: ${{ vars.GHCR_SLUG != '' }} run: | docker buildx imagetools inspect ${VARS_GHCR_SLUG}:${STEPS_META_OUTPUTS_VERSION} env: VARS_GHCR_SLUG: ${{ vars.GHCR_SLUG }} STEPS_META_OUTPUTS_VERSION: ${{ steps.meta.outputs.version }} combine-and-comment: name: Leave comment runs-on: ubuntu-latest needs: release-snapshot if: contains(github.event.pull_request.labels.*.name, 'safe to test') steps: - name: Create comment uses: marocchino/sticky-pull-request-comment@d4d6b0936434b21bc8345ad45a440c5f7d2c40ff #3.0.3 with: recreate: true header: "pr-release" message: | #### :package: A new release has been made for this pull request. To play around with this PR, pull an image: * `foxxmd/multi-scrobbler:pr-${{ github.event.number }}` Images are available for x86_64 and ARM64. > Latest commit: ${{ github.event.pull_request.head.sha }}