--- # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json name: Seerr Release on: push: tags: - 'v*' permissions: contents: read concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: DOCKER_HUB: seerr/seerr jobs: changelog: name: Generate changelog runs-on: ubuntu-24.04 permissions: contents: read outputs: release_body: ${{ steps.git-cliff.outputs.content }} steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 persist-credentials: false - name: Generate changelog id: git-cliff uses: orhun/git-cliff-action@f50e11560dce63f7c33227798f90b924471a88b5 # v4.8.0 with: config: .github/cliff.toml args: -vv --current env: OUTPUT: CHANGELOG.md GITHUB_REPO: ${{ github.repository }} create-draft-release: name: Create draft release runs-on: ubuntu-24.04 permissions: contents: write needs: changelog steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Draft Release run: gh release create ${GITHUB_REF_NAME} -t "Release ${GITHUB_REF_NAME}" -n "${RELEASE_BODY}" --draft env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} RELEASE_BODY: ${{ needs.changelog.outputs.release_body }} build: name: Build (${{ matrix.arch }}) strategy: matrix: include: - runner: ubuntu-24.04 platform: linux/amd64 arch: amd64 - runner: ubuntu-24.04-arm platform: linux/arm64 arch: arm64 runs-on: ${{ matrix.runner }} env: VERSION: ${{ github.ref_name }} steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Commit timestamp id: ts run: echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> "$GITHUB_OUTPUT" - name: Set up Docker Buildx uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4 - name: Warm cache [${{ matrix.platform }}] uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 with: context: . file: ./Dockerfile platforms: ${{ matrix.platform }} push: false build-args: | COMMIT_TAG=${{ github.sha }} BUILD_VERSION=${{ env.VERSION }} SOURCE_DATE_EPOCH=${{ steps.ts.outputs.TIMESTAMP }} cache-from: type=gha,scope=${{ matrix.platform }} cache-to: type=gha,mode=max,scope=${{ matrix.platform }} provenance: false publish: name: Publish multi-arch manifests needs: build runs-on: ubuntu-24.04 permissions: contents: read packages: write outputs: image_digest: ${{ steps.digests.outputs.IMAGE_DIGEST }} env: VERSION: ${{ github.ref_name }} steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Commit timestamp id: ts run: echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> "$GITHUB_OUTPUT" - name: Set up Docker Buildx uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4 - name: Log in to Docker Hub uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_TOKEN }} - name: Log in to GitHub Container Registry uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata id: meta uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v6 with: images: | ${{ env.DOCKER_HUB }} ghcr.io/${{ github.repository }} tags: | type=semver,pattern={{raw}} type=semver,pattern=v{{major}}.{{minor}} type=semver,pattern=v{{major}} labels: | org.opencontainers.image.created=${{ steps.ts.outputs.TIMESTAMP }} - name: Build & Push (multi-arch) uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 with: context: . file: ./Dockerfile platforms: linux/amd64,linux/arm64 push: true build-args: | COMMIT_TAG=${{ github.sha }} BUILD_VERSION=${{ env.VERSION }} SOURCE_DATE_EPOCH=${{ steps.ts.outputs.TIMESTAMP }} labels: ${{ steps.meta.outputs.labels }} tags: ${{ steps.meta.outputs.tags }} cache-from: | type=gha,scope=linux/amd64 type=gha,scope=linux/arm64 cache-to: type=gha,mode=max provenance: false - name: Resolve manifest digest id: digests run: | DIGEST=$(docker buildx imagetools inspect "${{ env.DOCKER_HUB }}:${{ env.VERSION }}" --format '{{json .Manifest.Digest}}' | tr -d '"') echo "IMAGE_DIGEST=$DIGEST" >> $GITHUB_OUTPUT - name: Also tag :latest (non-pre-release only) shell: bash if: ${{ !contains(env.VERSION, '-') }} run: | docker buildx imagetools create \ -t ${{ env.DOCKER_HUB }}:latest \ ${{ env.DOCKER_HUB }}:${{ env.VERSION }} docker buildx imagetools create \ -t ghcr.io/${{ github.repository }}:latest \ ghcr.io/${{ github.repository }}:${{ env.VERSION }} sign: name: Sign images and create SBOM attestations needs: publish runs-on: ubuntu-24.04 permissions: contents: read id-token: write packages: write env: VERSION: ${{ github.ref_name }} COSIGN_YES: 'true' steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false - name: Install Cosign uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - name: Install Trivy uses: aquasecurity/setup-trivy@3fb12ec12f41e471780db15c232d5dd185dcb514 # v0.2.6 - name: Log in to Docker Hub uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_TOKEN }} - name: Log in to GitHub Container Registry uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Sign images run: | cosign sign --recursive "ghcr.io/${{ github.repository }}@${{ needs.publish.outputs.image_digest }}" cosign sign --recursive "${{ env.DOCKER_HUB }}@${{ needs.publish.outputs.image_digest }}" - name: Generate SBOMs run: | trivy image --format cyclonedx --output seerr-ghcr-image-${{ env.VERSION }}.sbom \ "ghcr.io/${{ github.repository }}@${{ needs.publish.outputs.image_digest }}" trivy image --format cyclonedx --output seerr-dockerhub-image-${{ env.VERSION }}.sbom \ "${{ env.DOCKER_HUB }}@${{ needs.publish.outputs.image_digest }}" - name: Attest SBOMs run: | cosign attest \ --type cyclonedx \ --predicate seerr-ghcr-image-${{ env.VERSION }}.sbom \ "ghcr.io/${{ github.repository }}@${{ needs.publish.outputs.image_digest }}" cosign attest \ --type cyclonedx \ --predicate seerr-dockerhub-image-${{ env.VERSION }}.sbom \ "${{ env.DOCKER_HUB }}@${{ needs.publish.outputs.image_digest }}" - name: Upload SBOMs uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: sboms-${{ env.VERSION }} path: '*.sbom' if-no-files-found: error retention-days: 1 verify: name: Verify signatures and attestations needs: [publish, sign] runs-on: ubuntu-24.04 permissions: contents: read env: VERSION: ${{ github.ref_name }} steps: - name: Install Cosign uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - name: Verify signatures run: | cosign verify "ghcr.io/${{ github.repository }}@${{ needs.publish.outputs.image_digest }}" \ --certificate-identity "https://github.com/${{ github.workflow_ref }}" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" cosign verify "${{ env.DOCKER_HUB }}@${{ needs.publish.outputs.image_digest }}" \ --certificate-identity "https://github.com/${{ github.workflow_ref }}" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" # - name: Verify attestations # run: | # cosign verify-attestation "ghcr.io/${{ github.repository }}@${{ needs.publish.outputs.image_digest }}" \ # --type cyclonedx \ # --certificate-identity "https://github.com/${{ github.workflow_ref }}" \ # --certificate-oidc-issuer "https://token.actions.githubusercontent.com" > /dev/null # cosign verify-attestation "${{ env.DOCKER_HUB }}@${{ needs.publish.outputs.image_digest }}" \ # --type cyclonedx \ # --certificate-identity "https://github.com/${{ github.workflow_ref }}" \ # --certificate-oidc-issuer "https://token.actions.githubusercontent.com" > /dev/null publish-release: name: Publish release needs: [create-draft-release, verify] runs-on: ubuntu-24.04 permissions: contents: write env: VERSION: ${{ github.ref_name }} steps: - name: Publish release run: gh release edit "${{ env.VERSION }}" --draft=false --repo "${{ github.repository }}" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}