ci: update to release workflow (#2047)

* ci: update to release workflow

* build: re-ran lock file update with typeorm 0.3.12

* build: resync lockfile with develop

* ci: syntax fix in cliff.toml

* Update .github/workflows/release.yml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* reverting co-pilots nonsense @fallenbagel's fault

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
This commit is contained in:
Joe Harrison
2025-10-16 12:53:02 +01:00
committed by GitHub
parent de0e9b1f35
commit 8688645a32
3 changed files with 278 additions and 133 deletions

94
.github/cliff.toml vendored Normal file
View File

@@ -0,0 +1,94 @@
# git-cliff ~ configuration
# https://git-cliff.org/docs/configuration
[changelog]
header = ""
body = """
{%- macro remote_url() -%}
https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}
{%- endmacro -%}
{%- set excluded_users = ["github-actions[bot]", "dependabot[bot]", "renovate[bot]"] -%}
{% macro print_commit(commit) -%}
- {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
{% if commit.breaking %}[**breaking**] {% endif %}\
{{ commit.message | upper_first }} - \
([{{ commit.id | truncate(length=7, end="") }}]({{ self::remote_url() }}/commit/{{ commit.id }}))\
{% endmacro -%}
{% if version %}\
{% if previous.version %}\
## [{{ version | trim_start_matches(pat="v") }}]({{ self::remote_url() }}/compare/{{ previous.version }}..{{ version }}) - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% endif %}\
{% else %}\
## [unreleased]
{% endif %}\
{%- for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{%- for commit in commits | filter(attribute="scope") | sort(attribute="scope") %}
{{ self::print_commit(commit=commit) }}
{%- endfor %}
{%- for commit in commits %}
{%- if not commit.scope -%}
{{ self::print_commit(commit=commit) }}
{%- endif -%}
{%- endfor -%}
{%- endfor -%}
{%- set valid_contributors = [] -%}
{%- for c in github.contributors | filter(attribute="is_first_time", value=true) %}
{%- if c.username and c.username not in excluded_users and c.username not in valid_contributors %}
{%- set_global valid_contributors = valid_contributors | concat(with=c.username) %}
{%- endif %}
{%- endfor %}
{%- if valid_contributors | length > 0 %}
## New Contributors ❤️
{%- for username in valid_contributors %}
* @{{ username }} made their first contribution
{%- endfor %}
{%- endif %}
"""
footer = """
<!-- generated by git-cliff -->
"""
trim = true
postprocessors = []
[git]
conventional_commits = true
filter_unconventional = true
split_commits = false
filter_commits = true
commit_preprocessors = [
{ pattern = '.*\[skip ci\].*', replace = "" },
{ pattern = '.*\[ci skip\].*', replace = "" },
]
commit_parsers = [
{ message = "^feat", group = "<!-- 0 -->🚀 Features" },
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
{ message = "^doc", group = "<!-- 3 -->📖 Documentation" },
{ message = "^perf", group = "<!-- 4 -->⚡ Performance" },
{ message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
{ message = "^style", group = "<!-- 5 -->🎨 Styling" },
{ message = "^test", group = "<!-- 6 -->🧪 Testing" },
{ message = "^chore\\(release\\): prepare for", skip = true },
{ message = "^chore\\(deps.*\\)", skip = true },
{ message = "^chore\\(pr\\)", skip = true },
{ message = "^chore\\(pull\\)", skip = true },
{ message = "^chore\\(git-sync\\)", skip = true },
{ message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
{ body = ".*security", group = "<!-- 8 -->🛡️ Security" },
{ message = "^revert", group = "<!-- 9 -->◀️ Revert" },
{ message = '.*\[skip ci\].*', skip = true },
{ message = '.*\[ci skip\].*', skip = true },
]
protect_breaking_commits = false
tag_pattern = "v?[0-9]+\\.[0-9]+\\.[0-9]+.*"
skip_tags = "beta|alpha|rc"
topo_order = false
sort_commits = "newest"

View File

@@ -1,9 +1,10 @@
---
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
name: Seerr Release name: Seerr Release
on: on:
workflow_dispatch: push:
tags:
- 'v*'
permissions: permissions:
contents: read contents: read
@@ -13,14 +14,13 @@ concurrency:
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
semantic-release: changelog:
name: Tag and release latest version name: Generate changelog
runs-on: ubuntu-22.04 runs-on: ubuntu-24.04
env: permissions:
HUSKY: 0 contents: read
outputs: outputs:
new_release_published: ${{ steps.release.outputs.new_release_published }} release_body: ${{ steps.git-cliff.outputs.content }}
new_release_version: ${{ steps.release.outputs.new_release_version }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
@@ -28,46 +28,36 @@ jobs:
fetch-depth: 0 fetch-depth: 0
persist-credentials: false persist-credentials: false
- name: Set up Node.js - name: Generate changelog
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0 id: git-cliff
uses: orhun/git-cliff-action@d77b37db2e3f7398432d34b72a12aa3e2ba87e51 # v4.6.0
with: with:
node-version-file: package.json config: .github/cliff.toml
package-manager-cache: false args: -vv --current
- name: Pnpm Setup
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
- name: Get pnpm store directory
shell: sh
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
- name: Setup pnpm cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: ${{ env.STORE_PATH }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
- name: Install dependencies
run: pnpm install
- name: Release
id: release
uses: cycjimmy/semantic-release-action@9cc899c47e6841430bbaedb43de1560a568dfd16 # v5.0.0
with:
extra_plugins: |
@semantic-release/git@10
@semantic-release/changelog@6
@codedependant/semantic-release-docker@5
env: env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} 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@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
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: build:
name: Build (per-arch, native runners) name: Build (${{ matrix.arch }})
needs: semantic-release
if: needs.semantic-release.outputs.new_release_published == 'true'
strategy: strategy:
matrix: matrix:
include: include:
@@ -78,6 +68,8 @@ jobs:
platform: linux/arm64 platform: linux/arm64
arch: arm64 arch: arm64
runs-on: ${{ matrix.runner }} runs-on: ${{ matrix.runner }}
env:
VERSION: ${{ github.ref_name }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
@@ -91,7 +83,7 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
- name: Warm cache (no push) — ${{ matrix.platform }} - name: Warm cache [${{ matrix.platform }}]
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with: with:
context: . context: .
@@ -100,21 +92,23 @@ jobs:
push: false push: false
build-args: | build-args: |
COMMIT_TAG=${{ github.sha }} COMMIT_TAG=${{ github.sha }}
BUILD_VERSION=${{ needs.semantic-release.outputs.new_release_version }} BUILD_VERSION=${{ env.VERSION }}
SOURCE_DATE_EPOCH=${{ steps.ts.outputs.TIMESTAMP }} SOURCE_DATE_EPOCH=${{ steps.ts.outputs.TIMESTAMP }}
cache-from: type=gha,scope=${{ matrix.platform }} cache-from: type=gha,scope=${{ matrix.platform }}
cache-to: type=gha,mode=max,scope=${{ matrix.platform }} cache-to: type=gha,mode=max,scope=${{ matrix.platform }}
provenance: false provenance: false
publish: publish:
name: Publish multi-arch image name: Publish multi-arch manifests
needs: [semantic-release, build] needs: build
if: needs.semantic-release.outputs.new_release_published == 'true'
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
permissions: permissions:
contents: read contents: read
id-token: write
packages: write packages: write
outputs:
image_digest: ${{ steps.digests.outputs.IMAGE_DIGEST }}
env:
VERSION: ${{ github.ref_name }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
@@ -149,11 +143,11 @@ jobs:
${{ github.repository }} ${{ github.repository }}
ghcr.io/${{ github.repository }} ghcr.io/${{ github.repository }}
tags: | tags: |
type=raw,value=${{ needs.semantic-release.outputs.new_release_version }} type=raw,value=${{ env.VERSION }}
labels: | labels: |
org.opencontainers.image.created=${{ steps.ts.outputs.TIMESTAMP }} org.opencontainers.image.created=${{ steps.ts.outputs.TIMESTAMP }}
- name: Build & Push (multi-arch, single tag) - name: Build & Push (multi-arch)
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
with: with:
context: . context: .
@@ -162,7 +156,7 @@ jobs:
push: true push: true
build-args: | build-args: |
COMMIT_TAG=${{ github.sha }} COMMIT_TAG=${{ github.sha }}
BUILD_VERSION=${{ needs.semantic-release.outputs.new_release_version }} BUILD_VERSION=${{ env.VERSION }}
SOURCE_DATE_EPOCH=${{ steps.ts.outputs.TIMESTAMP }} SOURCE_DATE_EPOCH=${{ steps.ts.outputs.TIMESTAMP }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
@@ -172,37 +166,158 @@ jobs:
cache-to: type=gha,mode=max cache-to: type=gha,mode=max
provenance: false provenance: false
- name: Resolve manifest digest
id: digests
run: |
DIGEST=$(docker buildx imagetools inspect "${{ github.repository }}:${{ env.VERSION }}" --format '{{json .Manifest.Digest}}' | tr -d '"')
echo "IMAGE_DIGEST=$DIGEST" >> $GITHUB_OUTPUT
- name: Also tag :latest (non-pre-release only) - name: Also tag :latest (non-pre-release only)
shell: bash shell: bash
if: ${{ !contains(env.VERSION, '-') }}
run: | run: |
VER="${{ needs.semantic-release.outputs.new_release_version }}" docker buildx imagetools create \
if [[ "$VER" != *"-"* ]]; then -t ${{ github.repository }}:latest \
docker buildx imagetools create \ ${{ github.repository }}:${{ env.VERSION }}
-t ${{ github.repository }}:latest \
${{ github.repository }}:${VER} docker buildx imagetools create \
docker buildx imagetools create \ -t ghcr.io/${{ github.repository }}:latest \
-t ghcr.io/${{ github.repository }}:latest \ ghcr.io/${{ github.repository }}:${{ env.VERSION }}
ghcr.io/${{ github.repository }}:${VER}
fi 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@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false
- name: Install Cosign
uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
- name: Install Trivy
uses: aquasecurity/setup-trivy@e6c2c5e321ed9123bda567646e2f96565e34abe1 # v0.2.4
- name: Log in to Docker Hub
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_TOKEN }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.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 "${{ github.repository }}@${{ 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 \
"${{ github.repository }}@${{ 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 \
"${{ github.repository }}@${{ needs.publish.outputs.image_digest }}"
- name: Upload SBOMs
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
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@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
- 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 "${{ github.repository }}@${{ 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 "${{ 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
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 }}
discord: discord:
name: Send Discord Notification name: Send Discord Notification
needs: publish needs: publish-release
if: always() if: always()
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- name: Determine Workflow Status - name: Determine status
id: status id: status
run: | run: |
case "${{ needs.publish.result }}" in case "${{ needs.publish-release.result }}" in
success) echo "status=Success" >> $GITHUB_OUTPUT; echo "colour=3066993" >> $GITHUB_OUTPUT ;; success) echo "status=Success" >> $GITHUB_OUTPUT; echo "colour=3066993" >> $GITHUB_OUTPUT ;;
failure) echo "status=Failure" >> $GITHUB_OUTPUT; echo "colour=15158332" >> $GITHUB_OUTPUT ;; failure) echo "status=Failure" >> $GITHUB_OUTPUT; echo "colour=15158332" >> $GITHUB_OUTPUT ;;
cancelled) echo "status=Cancelled" >> $GITHUB_OUTPUT; echo "colour=10181046" >> $GITHUB_OUTPUT ;; cancelled) echo "status=Cancelled" >> $GITHUB_OUTPUT; echo "colour=10181046" >> $GITHUB_OUTPUT ;;
*) echo "status=Skipped" >> $GITHUB_OUTPUT; echo "colour=9807270" >> $GITHUB_OUTPUT ;; *) echo "status=Skipped" >> $GITHUB_OUTPUT; echo "colour=9807270" >> $GITHUB_OUTPUT ;;
esac esac
- name: Send Discord notification - name: Send notification
shell: bash
run: | run: |
WEBHOOK="${{ secrets.DISCORD_WEBHOOK }}" WEBHOOK="${{ secrets.DISCORD_WEBHOOK }}"
@@ -217,7 +332,7 @@ jobs:
{ "name": "Event", "value": "${{ github.event_name }}", "inline": true }, { "name": "Event", "value": "${{ github.event_name }}", "inline": true },
{ "name": "Triggered by", "value": "${{ github.actor }}", "inline": true }, { "name": "Triggered by", "value": "${{ github.actor }}", "inline": true },
{ "name": "Workflow", "value": "[${{ github.workflow }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})", "inline": true } { "name": "Workflow", "value": "[${{ github.workflow }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})", "inline": true }
], ]
}] }]
} }
EOF EOF

View File

@@ -201,70 +201,6 @@
"@commitlint/config-conventional" "@commitlint/config-conventional"
] ]
}, },
"release": {
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/npm",
[
"@codedependant/semantic-release-docker",
{
"dockerArgs": {
"COMMIT_TAG": "${GITHUB_SHA}"
},
"dockerLogin": false,
"dockerProject": "fallenbagel",
"dockerImage": "jellyseerr",
"dockerTags": [
"latest",
"{{major}}",
"{{major}}.{{minor}}",
"{{major}}.{{minor}}.{{patch}}"
],
"dockerPlatform": [
"linux/amd64",
"linux/arm64"
]
}
],
[
"@codedependant/semantic-release-docker",
{
"dockerArgs": {
"COMMIT_TAG": "${GITHUB_SHA}"
},
"dockerLogin": false,
"dockerRegistry": "ghcr.io",
"dockerProject": "fallenbagel",
"dockerImage": "jellyseerr",
"dockerTags": [
"latest",
"{{major}}",
"{{major}}.{{minor}}",
"{{major}}.{{minor}}.{{patch}}"
],
"dockerPlatform": [
"linux/amd64",
"linux/arm64"
]
}
],
[
"@semantic-release/github",
{
"addReleases": "bottom"
}
]
],
"branches": [
"main"
],
"npmPublish": false,
"publish": [
"@codedependant/semantic-release-docker",
"@semantic-release/github"
]
},
"pnpm": { "pnpm": {
"onlyBuiltDependencies": [ "onlyBuiltDependencies": [
"sqlite3", "sqlite3",