From a06b11980e71d7fc08b2346a491382b9d65407e6 Mon Sep 17 00:00:00 2001 From: Ben Vincent Date: Tue, 11 Aug 2026 07:23:43 +1000 Subject: [PATCH] ci: add Woodpecker build+test pipeline, drop GitHub Actions Why: - The fork inherited GitHub Actions workflows that target the upstream's self-hosted GitHub runners and do not run on this Gitea/Woodpecker infrastructure, so source changes (such as the scan-leader lease work) currently land without any CI validation. How: - Add .woodpecker/ci.yaml running restore, build and test of Jellyfin.sln on pull_request and push, using the .NET 9 SDK that global.json pins. - Filter out RequiresDocker and Integration tests, mirroring the upstream test selection so the suite runs without extra services. - Set memory-heavy resource requests/limits and a dedicated serviceAccountName for the build+test step. - Remove the inherited .github/workflows/ pipelines that only run on the upstream's GitHub Actions runners. --- .github/workflows/ci-codeql-analysis.yml | 39 --- .github/workflows/ci-compat.yml | 159 ------------ .github/workflows/ci-openapi.yml | 271 -------------------- .github/workflows/ci-tests.yml | 102 -------- .github/workflows/commands.yml | 60 ----- .github/workflows/ha-build.yml | 93 ------- .github/workflows/issue-stale.yml | 35 --- .github/workflows/issue-template-check.yml | 29 --- .github/workflows/project-automation.yml | 65 ----- .github/workflows/pull-request-conflict.yml | 23 -- .github/workflows/pull-request-stale.yaml | 30 --- .github/workflows/release-bump-version.yaml | 82 ------ .woodpecker/ci.yaml | 24 ++ 13 files changed, 24 insertions(+), 988 deletions(-) delete mode 100644 .github/workflows/ci-codeql-analysis.yml delete mode 100644 .github/workflows/ci-compat.yml delete mode 100644 .github/workflows/ci-openapi.yml delete mode 100644 .github/workflows/ci-tests.yml delete mode 100644 .github/workflows/commands.yml delete mode 100644 .github/workflows/ha-build.yml delete mode 100644 .github/workflows/issue-stale.yml delete mode 100644 .github/workflows/issue-template-check.yml delete mode 100644 .github/workflows/project-automation.yml delete mode 100644 .github/workflows/pull-request-conflict.yml delete mode 100644 .github/workflows/pull-request-stale.yaml delete mode 100644 .github/workflows/release-bump-version.yaml create mode 100644 .woodpecker/ci.yaml diff --git a/.github/workflows/ci-codeql-analysis.yml b/.github/workflows/ci-codeql-analysis.yml deleted file mode 100644 index 152fa0af2..000000000 --- a/.github/workflows/ci-codeql-analysis.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: "CodeQL" - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - schedule: - - cron: '24 2 * * 4' - -jobs: - analyze: - name: Analyze - # Disabled in fork — upstream CodeQL requires specific GitHub org permissions and .NET 10 support - if: false - runs-on: [self-hosted, k3s, linux, amd64] - - strategy: - fail-fast: false - matrix: - language: [ 'csharp' ] - - steps: - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - name: Setup .NET - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 - with: - dotnet-version: '9.0.x' - - - name: Initialize CodeQL - uses: github/codeql-action/init@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 - with: - languages: ${{ matrix.language }} - queries: +security-extended - - name: Autobuild - uses: github/codeql-action/autobuild@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fe4161a26a8629af62121b670040955b330f9af2 # v4.31.6 diff --git a/.github/workflows/ci-compat.yml b/.github/workflows/ci-compat.yml deleted file mode 100644 index 0041d53da..000000000 --- a/.github/workflows/ci-compat.yml +++ /dev/null @@ -1,159 +0,0 @@ -name: ABI Compatibility -on: - pull_request: - -permissions: {} - -jobs: - abi-head: - name: ABI - HEAD - runs-on: ubuntu-latest - permissions: read-all - steps: - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - ref: ${{ github.event.pull_request.head.sha }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - - name: Setup .NET - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 - with: - dotnet-version: '9.0.x' - - - name: Build - run: | - dotnet build Jellyfin.Server -o ./out - - - name: Upload Head - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 - with: - name: abi-head - retention-days: 14 - if-no-files-found: error - path: out/ - - abi-base: - name: ABI - BASE - if: ${{ github.base_ref != '' }} - runs-on: ubuntu-latest - permissions: read-all - steps: - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - ref: ${{ github.event.pull_request.head.sha }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - fetch-depth: 0 - - - name: Setup .NET - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 - with: - dotnet-version: '9.0.x' - - - name: Checkout common ancestor - env: - HEAD_REF: ${{ github.head_ref }} - run: | - git remote add upstream https://github.com/${{ github.event.pull_request.base.repo.full_name }} - git -c protocol.version=2 fetch --prune --progress --no-recurse-submodules upstream +refs/heads/*:refs/remotes/upstream/* +refs/tags/*:refs/tags/* - ANCESTOR_REF=$(git merge-base upstream/${{ github.base_ref }} origin/$HEAD_REF) - git checkout --progress --force $ANCESTOR_REF - - - name: Build - run: | - dotnet build Jellyfin.Server -o ./out - - - name: Upload Head - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 - with: - name: abi-base - retention-days: 14 - if-no-files-found: error - path: out/ - - abi-diff: - permissions: - pull-requests: write # to create or update comment (peter-evans/create-or-update-comment) - - name: ABI - Difference - if: ${{ github.event_name == 'pull_request' }} - runs-on: ubuntu-latest - needs: - - abi-head - - abi-base - - steps: - - name: Download abi-head - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - with: - name: abi-head - path: abi-head - - - name: Download abi-base - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - with: - name: abi-base - path: abi-base - - - name: Setup ApiCompat - run: | - dotnet tool install --global Microsoft.DotNet.ApiCompat.Tool - - - name: Run ApiCompat - id: diff - run: | - { - echo 'body<> $GITHUB_OUTPUT - - - name: Find difference comment - uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad # v4.0.0 - id: find-comment - with: - issue-number: ${{ github.event.pull_request.number }} - direction: last - body-includes: abi-diff-workflow-comment - - - name: Reply or edit difference comment (changed) - uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0 - if: ${{ steps.diff.outputs.body != '' }} - with: - issue-number: ${{ github.event.pull_request.number }} - comment-id: ${{ steps.find-comment.outputs.comment-id }} - edit-mode: replace - token: ${{ secrets.JF_BOT_TOKEN }} - body: | - -
- ABI Difference - - ``` - ${{ steps.diff.outputs.body }} - ``` - -
- - - name: Reply or edit difference comment (unchanged) - uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0 - if: ${{ steps.diff.outputs.body == '' && steps.find-comment.outputs.comment-id != '' }} - with: - issue-number: ${{ github.event.pull_request.number }} - comment-id: ${{ steps.find-comment.outputs.comment-id }} - edit-mode: replace - token: ${{ secrets.JF_BOT_TOKEN }} - body: | - -
- ABI Difference - - No changes to the ABI found. See history of this comment for previous changes. - -
diff --git a/.github/workflows/ci-openapi.yml b/.github/workflows/ci-openapi.yml deleted file mode 100644 index 968cd07be..000000000 --- a/.github/workflows/ci-openapi.yml +++ /dev/null @@ -1,271 +0,0 @@ -name: OpenAPI -on: - push: - branches: - - master - tags: - - 'v*' - pull_request: - -permissions: {} - -jobs: - openapi-head: - name: OpenAPI - HEAD - runs-on: ubuntu-latest - permissions: read-all - steps: - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - ref: ${{ github.event.pull_request.head.sha }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - - name: Setup .NET - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 - with: - dotnet-version: '9.0.x' - - name: Generate openapi.json - run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests" - - name: Upload openapi.json - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 - with: - name: openapi-head - retention-days: 14 - if-no-files-found: error - path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net9.0/openapi.json - - openapi-base: - name: OpenAPI - BASE - if: ${{ github.base_ref != '' }} - runs-on: ubuntu-latest - permissions: read-all - steps: - - name: Checkout repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - ref: ${{ github.event.pull_request.head.sha }} - repository: ${{ github.event.pull_request.head.repo.full_name }} - fetch-depth: 0 - - name: Checkout common ancestor - env: - HEAD_REF: ${{ github.head_ref }} - run: | - git remote add upstream https://github.com/${{ github.event.pull_request.base.repo.full_name }} - git -c protocol.version=2 fetch --prune --progress --no-recurse-submodules upstream +refs/heads/*:refs/remotes/upstream/* +refs/tags/*:refs/tags/* - ANCESTOR_REF=$(git merge-base upstream/${{ github.base_ref }} origin/$HEAD_REF) - git checkout --progress --force $ANCESTOR_REF - - name: Setup .NET - uses: actions/setup-dotnet@2016bd2012dba4e32de620c46fe006a3ac9f0602 # v5.0.1 - with: - dotnet-version: '9.0.x' - - name: Generate openapi.json - run: dotnet test tests/Jellyfin.Server.Integration.Tests/Jellyfin.Server.Integration.Tests.csproj -c Release --filter "Jellyfin.Server.Integration.Tests.OpenApiSpecTests" - - name: Upload openapi.json - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 - with: - name: openapi-base - retention-days: 14 - if-no-files-found: error - path: tests/Jellyfin.Server.Integration.Tests/bin/Release/net9.0/openapi.json - - openapi-diff: - permissions: - pull-requests: write # to create or update comment (peter-evans/create-or-update-comment) - - name: OpenAPI - Difference - if: ${{ github.event_name == 'pull_request' }} - runs-on: ubuntu-latest - needs: - - openapi-head - - openapi-base - steps: - - name: Download openapi-head - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - with: - name: openapi-head - path: openapi-head - - name: Download openapi-base - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - with: - name: openapi-base - path: openapi-base - - name: Workaround openapi-diff issue - run: | - sed -i 's/"allOf"/"oneOf"/g' openapi-head/openapi.json - sed -i 's/"allOf"/"oneOf"/g' openapi-base/openapi.json - - name: Calculate OpenAPI difference - uses: docker://openapitools/openapi-diff - continue-on-error: true - with: - args: --fail-on-changed --markdown openapi-changes.md openapi-base/openapi.json openapi-head/openapi.json - - id: read-diff - name: Read openapi-diff output - run: | - # Read and fix markdown - body=$(cat openapi-changes.md) - # Write to workflow summary - echo "$body" >> $GITHUB_STEP_SUMMARY - # Set ApiChanged var - if [ "$body" != '' ]; then - echo "ApiChanged=1" >> "$GITHUB_OUTPUT" - else - echo "ApiChanged=0" >> "$GITHUB_OUTPUT" - fi - # Add header/footer for diff comment - echo '' > openapi-changes-reply.md - echo "
" >> openapi-changes-reply.md - echo "Changes in OpenAPI specification found. Expand to see details." >> openapi-changes-reply.md - echo "" >> openapi-changes-reply.md - echo "$body" >> openapi-changes-reply.md - echo "" >> openapi-changes-reply.md - echo "
" >> openapi-changes-reply.md - - name: Find difference comment - uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad # v4.0.0 - id: find-comment - with: - issue-number: ${{ github.event.pull_request.number }} - direction: last - body-includes: openapi-diff-workflow-comment - - name: Reply or edit difference comment (changed) - uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0 - if: ${{ steps.read-diff.outputs.ApiChanged == '1' }} - with: - issue-number: ${{ github.event.pull_request.number }} - comment-id: ${{ steps.find-comment.outputs.comment-id }} - edit-mode: replace - body-path: openapi-changes-reply.md - - name: Edit difference comment (unchanged) - uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0 - if: ${{ steps.read-diff.outputs.ApiChanged == '0' && steps.find-comment.outputs.comment-id != '' }} - with: - issue-number: ${{ github.event.pull_request.number }} - comment-id: ${{ steps.find-comment.outputs.comment-id }} - edit-mode: replace - body: | - - - No changes to OpenAPI specification found. See history of this comment for previous changes. - - publish-unstable: - name: OpenAPI - Publish Unstable Spec - if: ${{ github.event_name != 'pull_request' && !startsWith(github.ref, 'refs/tags/v') && contains(github.repository_owner, 'jellyfin') }} - runs-on: ubuntu-latest - needs: - - openapi-head - steps: - - name: Set unstable dated version - id: version - run: |- - echo "JELLYFIN_VERSION=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV - - name: Download openapi-head - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - with: - name: openapi-head - path: openapi-head - - name: Upload openapi.json (unstable) to repository server - uses: appleboy/scp-action@ff85246acaad7bdce478db94a363cd2bf7c90345 # v1.0.0 - with: - host: "${{ secrets.REPO_HOST }}" - username: "${{ secrets.REPO_USER }}" - key: "${{ secrets.REPO_KEY }}" - source: openapi-head/openapi.json - strip_components: 1 - target: "/srv/incoming/openapi/unstable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}" - - name: Move openapi.json (unstable) into place - uses: appleboy/ssh-action@823bd89e131d8d508129f9443cad5855e9ba96f0 # v1.2.4 - with: - host: "${{ secrets.REPO_HOST }}" - username: "${{ secrets.REPO_USER }}" - key: "${{ secrets.REPO_KEY }}" - debug: false - script_stop: false - script: | - if ! test -d /run/workflows; then - sudo mkdir -p /run/workflows - sudo chown ${{ secrets.REPO_USER }} /run/workflows - fi - ( - flock -x -w 300 200 || exit 1 - TGT_DIR="/srv/repository/main/openapi" - LAST_SPEC="$( ls -lt ${TGT_DIR}/unstable/ | grep 'jellyfin-openapi' | head -1 | awk '{ print $NF }' )" - # If new and previous spec don't differ (diff retcode 0), remove incoming and finish - if diff /srv/incoming/openapi/unstable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}/openapi.json ${TGT_DIR}/unstable/${LAST_SPEC} &>/dev/null; then - rm -r /srv/incoming/openapi/unstable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }} - exit 0 - fi - # Move new spec into place - sudo mv /srv/incoming/openapi/unstable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}/openapi.json ${TGT_DIR}/unstable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}.json - # Delete previous jellyfin-openapi-unstable_previous.json - sudo rm ${TGT_DIR}/jellyfin-openapi-unstable_previous.json - # Move current jellyfin-openapi-unstable.json symlink to jellyfin-openapi-unstable_previous.json - sudo mv ${TGT_DIR}/jellyfin-openapi-unstable.json ${TGT_DIR}/jellyfin-openapi-unstable_previous.json - # Create new jellyfin-openapi-unstable.json symlink - sudo ln -s unstable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}.json ${TGT_DIR}/jellyfin-openapi-unstable.json - # Check that the previous openapi unstable spec link is correct - if [[ "$( readlink ${TGT_DIR}/jellyfin-openapi-unstable_previous.json )" != "unstable/${LAST_SPEC}" ]]; then - sudo rm ${TGT_DIR}/jellyfin-openapi-unstable_previous.json - sudo ln -s unstable/${LAST_SPEC} ${TGT_DIR}/jellyfin-openapi-unstable_previous.json - fi - ) 200>/run/workflows/openapi-unstable.lock - - publish-stable: - name: OpenAPI - Publish Stable Spec - if: ${{ startsWith(github.ref, 'refs/tags/v') && contains(github.repository_owner, 'jellyfin') }} - runs-on: ubuntu-latest - needs: - - openapi-head - steps: - - name: Set version number - id: version - run: |- - echo "JELLYFIN_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV - - name: Download openapi-head - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 - with: - name: openapi-head - path: openapi-head - - name: Upload openapi.json (stable) to repository server - uses: appleboy/scp-action@ff85246acaad7bdce478db94a363cd2bf7c90345 # v1.0.0 - with: - host: "${{ secrets.REPO_HOST }}" - username: "${{ secrets.REPO_USER }}" - key: "${{ secrets.REPO_KEY }}" - source: openapi-head/openapi.json - strip_components: 1 - target: "/srv/incoming/openapi/stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}" - - name: Move openapi.json (stable) into place - uses: appleboy/ssh-action@823bd89e131d8d508129f9443cad5855e9ba96f0 # v1.2.4 - with: - host: "${{ secrets.REPO_HOST }}" - username: "${{ secrets.REPO_USER }}" - key: "${{ secrets.REPO_KEY }}" - debug: false - script_stop: false - script: | - if ! test -d /run/workflows; then - sudo mkdir -p /run/workflows - sudo chown ${{ secrets.REPO_USER }} /run/workflows - fi - ( - flock -x -w 300 200 || exit 1 - TGT_DIR="/srv/repository/main/openapi" - LAST_SPEC="$( ls -lt ${TGT_DIR}/stable/ | grep 'jellyfin-openapi' | head -1 | awk '{ print $NF }' )" - # If new and previous spec don't differ (diff retcode 0), remove incoming and finish - if diff /srv/incoming/openapi/stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}/openapi.json ${TGT_DIR}/stable/${LAST_SPEC} &>/dev/null; then - rm -r /srv/incoming/openapi/stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }} - exit 0 - fi - # Move new spec into place - sudo mv /srv/incoming/openapi/stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}/openapi.json ${TGT_DIR}/stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}.json - # Delete previous jellyfin-openapi-stable_previous.json - sudo rm ${TGT_DIR}/jellyfin-openapi-stable_previous.json - # Move current jellyfin-openapi-stable.json symlink to jellyfin-openapi-stable_previous.json - sudo mv ${TGT_DIR}/jellyfin-openapi-stable.json ${TGT_DIR}/jellyfin-openapi-stable_previous.json - # Create new jellyfin-openapi-stable.json symlink - sudo ln -s stable/jellyfin-openapi-${{ env.JELLYFIN_VERSION }}.json ${TGT_DIR}/jellyfin-openapi-stable.json - # Check that the previous openapi stable spec link is correct - if [[ "$( readlink ${TGT_DIR}/jellyfin-openapi-stable_previous.json )" != "stable/${LAST_SPEC}" ]]; then - sudo rm ${TGT_DIR}/jellyfin-openapi-stable_previous.json - sudo ln -s stable/${LAST_SPEC} ${TGT_DIR}/jellyfin-openapi-stable_previous.json - fi - ) 200>/run/workflows/openapi-stable.lock diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml deleted file mode 100644 index d204c95d6..000000000 --- a/.github/workflows/ci-tests.yml +++ /dev/null @@ -1,102 +0,0 @@ -name: Tests -on: - push: - branches: - - master - # Run tests against the forked branch, but - # do not allow access to secrets - # https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories - pull_request: - -env: - SDK_VERSION: "9.0.x" - -jobs: - run-tests: - runs-on: [self-hosted, k3s, linux, amd64] - steps: - - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - - # Install .NET — use GITHUB_ENV (not GITHUB_PATH) to set PATH because - # ARC self-hosted runner pods don't pick up GITHUB_PATH between steps. - - name: Install .NET SDK - run: | - DOTNET_INSTALL_DIR="$HOME/.dotnet" - mkdir -p "$DOTNET_INSTALL_DIR" - curl -fsSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel 10.0 --install-dir "$DOTNET_INSTALL_DIR" - echo "DOTNET_ROOT=$DOTNET_INSTALL_DIR" >> "$GITHUB_ENV" - echo "PATH=$DOTNET_INSTALL_DIR:$PATH" >> "$GITHUB_ENV" - - - name: Run DotNet CLI Tests - run: | - export PATH="$HOME/.dotnet:$PATH" - dotnet test Jellyfin.sln \ - --configuration Release \ - --collect:"XPlat Code Coverage" \ - --settings tests/coverletArgs.runsettings \ - --verbosity minimal \ - --filter "Category!=RequiresDocker&FullyQualifiedName!~Integration" - - - name: Merge code coverage results - uses: danielpalme/ReportGenerator-GitHub-Action@ee0ae774f6d3afedcbd1683c1ab21b83670bdf8e # v5.5.1 - with: - reports: "**/coverage.cobertura.xml" - targetdir: "merged/" - reporttypes: "Cobertura" - - # TODO - which action / tool to use to publish code coverage results? - # - name: Publish code coverage results - - # Phase 5 transcode coverage gate — runs in parallel with run-tests. - # Explicitly targets the three test assemblies most affected by Phase 5 HLS - # session-sharing and PostgreSQL media-encoding changes so failures surface - # with a dedicated check status independent of the full test matrix. - run-phase5-tests: - runs-on: [self-hosted, k3s, linux, amd64] - steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Install .NET SDK - run: | - DOTNET_INSTALL_DIR="$HOME/.dotnet" - mkdir -p "$DOTNET_INSTALL_DIR" - curl -fsSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel 10.0 --install-dir "$DOTNET_INSTALL_DIR" - echo "DOTNET_ROOT=$DOTNET_INSTALL_DIR" >> "$GITHUB_ENV" - echo "PATH=$DOTNET_INSTALL_DIR:$PATH" >> "$GITHUB_ENV" - - - name: Run Phase 5 Transcode Tests (API) - run: | - export PATH="$HOME/.dotnet:$PATH" - dotnet test tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj \ - --configuration Release \ - --collect:"XPlat Code Coverage" \ - --settings tests/coverletArgs.runsettings \ - --verbosity minimal \ - --filter "Category!=RequiresDocker" - - - name: Run Phase 5 Transcode Tests (HLS) - run: | - export PATH="$HOME/.dotnet:$PATH" - dotnet test tests/Jellyfin.MediaEncoding.Hls.Tests/Jellyfin.MediaEncoding.Hls.Tests.csproj \ - --configuration Release \ - --collect:"XPlat Code Coverage" \ - --settings tests/coverletArgs.runsettings \ - --verbosity minimal \ - --filter "Category!=RequiresDocker" - - - name: Run Phase 5 Transcode Tests (Server.Implementations) - run: | - export PATH="$HOME/.dotnet:$PATH" - dotnet test tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj \ - --configuration Release \ - --collect:"XPlat Code Coverage" \ - --settings tests/coverletArgs.runsettings \ - --verbosity minimal \ - --filter "Category!=RequiresDocker" - - - name: Merge Phase 5 code coverage results - uses: danielpalme/ReportGenerator-GitHub-Action@2a7030e9775aab6c78e80cb66843051acdacee3e # v5.5.2 - with: - reports: "**/coverage.cobertura.xml" - targetdir: "merged-phase5/" - reporttypes: "Cobertura" diff --git a/.github/workflows/commands.yml b/.github/workflows/commands.yml deleted file mode 100644 index 0775051f9..000000000 --- a/.github/workflows/commands.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: Commands -on: - issue_comment: - types: - - created - - edited - pull_request: - types: - - labeled - - synchronize - -permissions: {} -jobs: - rebase: - name: Rebase - if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '@jellyfin-bot rebase') && github.event.comment.author_association == 'MEMBER' - runs-on: ubuntu-latest - steps: - - name: Notify as seen - uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0 - with: - token: ${{ secrets.JF_BOT_TOKEN }} - comment-id: ${{ github.event.comment.id }} - reactions: '+1' - - - name: Checkout the latest code - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - token: ${{ secrets.JF_BOT_TOKEN }} - fetch-depth: 0 - - - name: Automatic Rebase - uses: cirrus-actions/rebase@b87d48154a87a85666003575337e27b8cd65f691 # 1.8 - env: - GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }} - - rename: - name: Rename - if: contains(github.event.comment.body, '@jellyfin-bot rename') && github.event.comment.author_association == 'MEMBER' - runs-on: ubuntu-latest - steps: - - name: pull in script - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - repository: jellyfin/jellyfin-triage-script - - name: install python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 - with: - python-version: '3.14' - cache: 'pip' - - name: install python packages - run: pip install -r rename/requirements.txt - - name: run rename script - run: python3 rename.py - working-directory: ./rename - env: - GH_TOKEN: ${{ secrets.JF_BOT_TOKEN }} - GH_REPO: ${{ github.repository }} - ISSUE: ${{ github.event.issue.number }} - COMMENT_ID: ${{ github.event.comment.id }} diff --git a/.github/workflows/ha-build.yml b/.github/workflows/ha-build.yml deleted file mode 100644 index d56c0e61b..000000000 --- a/.github/workflows/ha-build.yml +++ /dev/null @@ -1,93 +0,0 @@ -name: HA Build & Push to ECR - -on: - push: - branches: - - master - - main - - "feat/ha-*" - - "feat/phase*" - - "copilot/*" - # pull_request intentionally removed: this workflow runs on self-hosted k3s - # runners. Allowing pull_request events from a public repo would let any - # internet user execute arbitrary code inside the cluster network. - # CI build feedback on PRs is provided by ci-tests.yml (GitHub-hosted runners). - -# Cancel in-progress runs when a new push arrives on the same branch. -concurrency: - group: ha-build-${{ github.ref }} - cancel-in-progress: true - -jobs: - build-and-push: - runs-on: [self-hosted, k3s, linux, amd64] - - permissions: - contents: read - - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@e3dd6a429d7300a6a4c196c26e071d42e0343502 # v4.0.2 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ secrets.AWS_REGION }} - - - name: Login to Amazon ECR - id: ecr-login - uses: aws-actions/amazon-ecr-login@062b18b96a7aff071d4dc91bc00c4c1a7945b076 # v2.0.1 - - - name: Set image metadata - id: meta - run: | - REPO="${{ steps.ecr-login.outputs.registry }}/${{ secrets.ECR_REPOSITORY }}" - SHORT_SHA="${GITHUB_SHA::7}" - echo "image_repo=${REPO}" >> "$GITHUB_OUTPUT" - echo "short_sha=${SHORT_SHA}" >> "$GITHUB_OUTPUT" - - - name: Install .NET SDK - # Build on the runner host filesystem (native I/O) to avoid DinD - # overlay-on-overlay throttling which makes dotnet publish ~20x slower. - run: | - DOTNET_INSTALL_DIR="$HOME/.dotnet" - mkdir -p "$DOTNET_INSTALL_DIR" - if ! "$DOTNET_INSTALL_DIR/dotnet" --version 2>/dev/null | grep -q "^10\\."; then - curl -fsSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel 10.0 --install-dir "$DOTNET_INSTALL_DIR" - fi - echo "DOTNET_ROOT=$DOTNET_INSTALL_DIR" >> "$GITHUB_ENV" - echo "PATH=$DOTNET_INSTALL_DIR:$PATH" >> "$GITHUB_ENV" - - - name: Restore NuGet packages - run: | - export PATH="$HOME/.dotnet:$PATH" - dotnet restore Jellyfin.Server/Jellyfin.Server.csproj --runtime linux-x64 - - - name: Publish Jellyfin server - run: | - export PATH="$HOME/.dotnet:$PATH" - dotnet publish Jellyfin.Server/Jellyfin.Server.csproj \ - --configuration Release \ - --runtime linux-x64 \ - --self-contained false \ - --no-restore \ - -p:TreatWarningsAsErrors=false \ - --output ./publish-output - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Build and push image - uses: docker/build-push-action@v6 - with: - context: . - file: Dockerfile.runtime - platforms: linux/amd64 - # Only push the image on direct branch pushes, not on pull_request events. - push: ${{ github.event_name == 'push' }} - provenance: false - tags: | - ${{ steps.meta.outputs.image_repo }}:${{ steps.meta.outputs.short_sha }} - ${{ steps.meta.outputs.image_repo }}:latest diff --git a/.github/workflows/issue-stale.yml b/.github/workflows/issue-stale.yml deleted file mode 100644 index cb535297e..000000000 --- a/.github/workflows/issue-stale.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: Stale Issue Labeler - -on: - schedule: - - cron: '30 1 * * *' - workflow_dispatch: - -permissions: - issues: write - pull-requests: write - actions: write - -jobs: - issues: - name: Check for stale issues - runs-on: ubuntu-latest - if: ${{ contains(github.repository, 'jellyfin/') }} - steps: - - uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1 - with: - repo-token: ${{ secrets.JF_BOT_TOKEN }} - ascending: true - days-before-stale: 120 - days-before-pr-stale: -1 - days-before-close: 21 - days-before-pr-close: -1 - operations-per-run: 500 - exempt-issue-labels: regression,security,roadmap,future,feature,enhancement,confirmed - stale-issue-label: stale - stale-issue-message: |- - This issue has gone 120 days without an update and will be closed within 21 days if there is no new activity. To prevent this issue from being closed, please confirm the issue has not already been fixed by providing updated examples or logs. - - If you have any questions you can use one of several ways to [contact us](https://jellyfin.org/contact). - close-issue-message: |- - This issue was closed due to inactivity. diff --git a/.github/workflows/issue-template-check.yml b/.github/workflows/issue-template-check.yml deleted file mode 100644 index 8be48b5c3..000000000 --- a/.github/workflows/issue-template-check.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Check Issue Template -on: - issues: - types: - - opened -jobs: - check_issue: - runs-on: ubuntu-latest - permissions: - issues: write - steps: - - name: pull in script - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - repository: jellyfin/jellyfin-triage-script - - name: install python - uses: actions/setup-python@83679a892e2d95755f2dac6acb0bfd1e9ac5d548 # v6.1.0 - with: - python-version: '3.14' - cache: 'pip' - - name: install python packages - run: pip install -r main-repo-triage/requirements.txt - - name: check and comment issue - working-directory: ./main-repo-triage - run: python3 single_issue_gha.py - env: - GH_TOKEN: ${{ secrets.JF_BOT_TOKEN }} - GH_REPO: ${{ github.repository }} - ISSUE: ${{ github.event.issue.number }} diff --git a/.github/workflows/project-automation.yml b/.github/workflows/project-automation.yml deleted file mode 100644 index b50947877..000000000 --- a/.github/workflows/project-automation.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: Project Automation - -on: - push: - branches: - - master - pull_request: - issue_comment: - -permissions: {} -jobs: - project: - name: Project board - runs-on: ubuntu-latest - if: ${{ github.repository == 'jellyfin/jellyfin' }} - steps: - - name: Remove from 'Current Release' project - uses: alex-page/github-project-automation-plus@303f24a24c67ce7adf565a07e96720faf126fe36 # v0.9.0 - if: (github.event.pull_request || github.event.issue.pull_request) && !contains(github.event.*.labels.*.name, 'stable backport') - continue-on-error: true - with: - project: Current Release - action: delete - repo-token: ${{ secrets.JF_BOT_TOKEN }} - - - name: Add to 'Release Next' project - uses: alex-page/github-project-automation-plus@303f24a24c67ce7adf565a07e96720faf126fe36 # v0.9.0 - if: (github.event.pull_request || github.event.issue.pull_request) && github.event.action == 'opened' - continue-on-error: true - with: - project: Release Next - column: In progress - repo-token: ${{ secrets.JF_BOT_TOKEN }} - - - name: Add to 'Current Release' project - uses: alex-page/github-project-automation-plus@303f24a24c67ce7adf565a07e96720faf126fe36 # v0.9.0 - if: (github.event.pull_request || github.event.issue.pull_request) && !contains(github.event.*.labels.*.name, 'stable backport') - continue-on-error: true - with: - project: Current Release - column: In progress - repo-token: ${{ secrets.JF_BOT_TOKEN }} - - - name: Check number of comments from the team member - if: github.event.issue.pull_request == '' && github.event.comment.author_association == 'MEMBER' - id: member_comments - run: echo "::set-output name=number::$(curl -s ${{ github.event.issue.comments_url }} | jq '.[] | select(.author_association == "MEMBER") | .author_association' | wc -l)" - - - name: Move issue to needs triage - uses: alex-page/github-project-automation-plus@303f24a24c67ce7adf565a07e96720faf126fe36 # v0.9.0 - if: github.event.issue.pull_request == '' && github.event.comment.author_association == 'MEMBER' && steps.member_comments.outputs.number <= 1 - continue-on-error: true - with: - project: Issue Triage for Main Repo - column: Needs triage - repo-token: ${{ secrets.JF_BOT_TOKEN }} - - - name: Add issue to triage project - uses: alex-page/github-project-automation-plus@303f24a24c67ce7adf565a07e96720faf126fe36 # v0.9.0 - if: github.event.issue.pull_request == '' && github.event.action == 'opened' - continue-on-error: true - with: - project: Issue Triage for Main Repo - column: Pending response - repo-token: ${{ secrets.JF_BOT_TOKEN }} diff --git a/.github/workflows/pull-request-conflict.yml b/.github/workflows/pull-request-conflict.yml deleted file mode 100644 index b003636a6..000000000 --- a/.github/workflows/pull-request-conflict.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Merge Conflict Labeler - -on: - push: - branches: - - master - pull_request: - issue_comment: - -permissions: {} -jobs: - label: - name: Labeling - runs-on: ubuntu-latest - if: ${{ github.repository == 'jellyfin/jellyfin' && github.event.issue.pull_request }} - steps: - - name: Apply label - uses: eps1lon/actions-label-merge-conflict@1df065ebe6e3310545d4f4c4e862e43bdca146f0 # v3.0.3 - if: ${{ github.event_name == 'push' || github.event_name == 'pull_request'}} - with: - dirtyLabel: 'merge conflict' - commentOnDirty: 'This pull request has merge conflicts. Please resolve the conflicts so the PR can be successfully reviewed and merged.' - repoToken: ${{ secrets.JF_BOT_TOKEN }} diff --git a/.github/workflows/pull-request-stale.yaml b/.github/workflows/pull-request-stale.yaml deleted file mode 100644 index 0d74e643e..000000000 --- a/.github/workflows/pull-request-stale.yaml +++ /dev/null @@ -1,30 +0,0 @@ -name: Stale PR Check - -on: - schedule: - - cron: '30 */12 * * *' - workflow_dispatch: - -permissions: - pull-requests: write - actions: write - -jobs: - prs-stale-conflicts: - name: Check PRs with merge conflicts - runs-on: ubuntu-latest - if: ${{ contains(github.repository, 'jellyfin/') }} - steps: - - uses: actions/stale@997185467fa4f803885201cee163a9f38240193d # v10.1.1 - with: - repo-token: ${{ secrets.JF_BOT_TOKEN }} - ascending: true - operations-per-run: 150 - # The merge conflict action will remove the label when updated - remove-stale-when-updated: false - days-before-stale: -1 - days-before-close: 90 - days-before-issue-close: -1 - stale-pr-label: merge conflict - close-pr-message: |- - This PR has been closed due to having unresolved merge conflicts. diff --git a/.github/workflows/release-bump-version.yaml b/.github/workflows/release-bump-version.yaml deleted file mode 100644 index d39d2cb9c..000000000 --- a/.github/workflows/release-bump-version.yaml +++ /dev/null @@ -1,82 +0,0 @@ -name: '🆙 Auto bump_version' - -on: - release: - types: - - published - workflow_dispatch: - inputs: - TAG_BRANCH: - required: true - description: release-x.y.z - NEXT_VERSION: - required: true - description: x.y.z - -jobs: - auto_bump_version: - runs-on: ubuntu-latest - if: ${{ github.event_name == 'release' && !contains(github.event.release.tag_name, 'rc') }} - env: - TAG_BRANCH: ${{ github.event.release.target_commitish }} - steps: - - name: Wait for deploy checks to finish - uses: jitterbit/await-check-suites@292a541bb7618078395b2ce711a0d89cfb8a568a # v1 - with: - ref: ${{ env.TAG_BRANCH }} - intervalSeconds: 60 - timeoutSeconds: 3600 - - - name: Setup YQ - uses: chrisdickinson/setup-yq@latest - with: - yq-version: v4.9.8 - - - name: Checkout Repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - ref: ${{ env.TAG_BRANCH }} - - - name: Setup EnvVars - run: |- - CURRENT_VERSION=$(yq e '.version' build.yaml) - CURRENT_MAJOR_MINOR=${CURRENT_VERSION%.*} - CURRENT_PATCH=${CURRENT_VERSION##*.} - echo "CURRENT_VERSION=${CURRENT_VERSION}" >> $GITHUB_ENV - echo "CURRENT_MAJOR_MINOR=${CURRENT_MAJOR_MINOR}" >> $GITHUB_ENV - echo "CURRENT_PATCH=${CURRENT_PATCH}" >> $GITHUB_ENV - echo "NEXT_VERSION=${CURRENT_MAJOR_MINOR}.$(($CURRENT_PATCH + 1))" >> $GITHUB_ENV - - - name: Run bump_version - run: ./bump_version ${{ env.NEXT_VERSION }} - - - name: Commit Changes - run: |- - git config user.name "jellyfin-bot" - git config user.email "team@jellyfin.org" - git checkout ${{ env.TAG_BRANCH }} - git commit -am "Bump version to ${{ env.NEXT_VERSION }}" - git push origin ${{ env.TAG_BRANCH }} - - manual_bump_version: - runs-on: ubuntu-latest - if: ${{ github.event_name == 'workflow_dispatch' }} - env: - TAG_BRANCH: ${{ github.event.inputs.TAG_BRANCH }} - NEXT_VERSION: ${{ github.event.inputs.NEXT_VERSION }} - steps: - - name: Checkout Repository - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1 - with: - ref: ${{ env.TAG_BRANCH }} - - - name: Run bump_version - run: ./bump_version ${{ env.NEXT_VERSION }} - - - name: Commit Changes - run: |- - git config user.name "jellyfin-bot" - git config user.email "team@jellyfin.org" - git checkout ${{ env.TAG_BRANCH }} - git commit -am "Bump version to ${{ env.NEXT_VERSION }}" - git push origin ${{ env.TAG_BRANCH }} diff --git a/.woodpecker/ci.yaml b/.woodpecker/ci.yaml new file mode 100644 index 000000000..5c31e73a8 --- /dev/null +++ b/.woodpecker/ci.yaml @@ -0,0 +1,24 @@ +when: + - event: pull_request + - event: push + +steps: + # Restore, build and test the full solution. global.json pins the .NET 9 + # SDK (9.0.0, rollForward latestMinor), so build on the 9.0 SDK image. + - name: build-test + image: mcr.microsoft.com/dotnet/sdk:9.0 + commands: + - dotnet --info + - dotnet restore Jellyfin.sln + - dotnet build Jellyfin.sln -c Release --no-restore + - dotnet test Jellyfin.sln -c Release --no-build --verbosity minimal --filter "Category!=RequiresDocker&FullyQualifiedName!~Integration" + backend_options: + kubernetes: + serviceAccountName: jellyfin-ha-src + resources: + requests: + memory: 2Gi + cpu: 2 + limits: + memory: 6Gi + cpu: 4