From 86d11496c5ddac3bf3c990f258287c054581fd4f Mon Sep 17 00:00:00 2001 From: Ludovic Ortega Date: Sat, 4 Jul 2026 23:02:30 +0200 Subject: [PATCH 1/3] ci: parallelize the action steps when possible Signed-off-by: Ludovic Ortega --- .github/workflows/ci.yml | 94 +++-- .github/workflows/codeql.yml | 19 +- .github/workflows/create-tag.yml | 46 ++- .github/workflows/cypress.yml | 16 +- .github/workflows/detect-duplicate.yml | 13 +- .github/workflows/docs-deploy.yml | 16 +- .github/workflows/helm.yml | 135 +++--- .github/workflows/lint-helm-charts.yml | 48 +-- .github/workflows/pr-validation.yml | 387 +++++++++--------- .github/workflows/preview.yml | 112 ++--- .github/workflows/rebuild-issue-index.yml | 15 +- .github/workflows/release.yml | 193 ++++----- .../workflows/renovate-helm-custom-hooks.yml | 29 +- .github/workflows/seerr-labeller.yml | 114 +++--- .github/workflows/test-docs.yml | 17 +- 15 files changed, 641 insertions(+), 613 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0938d3f5b8..1d3a6dbed9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,13 +39,14 @@ jobs: with: persist-credentials: false - - name: Pnpm Setup - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + - parallel: + - name: Pnpm Setup + uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - - name: Set up Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version-file: 'package.json' + - name: Set up Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version-file: 'package.json' - name: Get pnpm store directory shell: bash @@ -118,14 +119,15 @@ jobs: CI: true run: pnpm install - - name: Lint - run: pnpm lint + - parallel: + - name: Lint + run: pnpm lint - - name: Formatting - run: pnpm format:check + - name: Formatting + run: pnpm format:check - - name: Build - run: pnpm build + - name: Build + run: pnpm build unit-test: name: Unit Tests @@ -186,17 +188,18 @@ jobs: arch: arm64 runs-on: ${{ matrix.runner }} steps: - - name: Checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - persist-credentials: false + - parallel: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false - - name: Commit timestamp - id: ts - run: echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> "$GITHUB_OUTPUT" + - 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 - name: Warm cache (no push) — ${{ matrix.platform }} uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 @@ -222,30 +225,31 @@ jobs: packages: write id-token: write steps: - - name: Checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 - - - name: Log in to Docker Hub - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_TOKEN }} - - - name: Log in to GitHub Container Registry - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} + - parallel: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 + + - name: Log in to Docker Hub + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Log in to GitHub Container Registry + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata id: meta diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 6187f0588a..99ccaf45db 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -36,16 +36,17 @@ jobs: matrix: language: [actions, javascript] steps: - - name: Checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - persist-credentials: false + - parallel: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false - - name: Initialize CodeQL - uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4.36.1 - with: - languages: ${{ matrix.language }} - queries: +security-and-quality + - name: Initialize CodeQL + uses: github/codeql-action/init@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4.36.1 + with: + languages: ${{ matrix.language }} + queries: +security-and-quality - name: Autobuild uses: github/codeql-action/autobuild@87557b9c84dde89fdd9b10e88954ac2f4248e463 # v4.36.1 diff --git a/.github/workflows/create-tag.yml b/.github/workflows/create-tag.yml index 35c7787fda..19e13ff9df 100644 --- a/.github/workflows/create-tag.yml +++ b/.github/workflows/create-tag.yml @@ -22,16 +22,17 @@ jobs: outputs: tag_version: ${{ steps.git-cliff.outputs.tag_version }} steps: - - name: Checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - fetch-depth: 0 - persist-credentials: false + - parallel: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + fetch-depth: 0 + persist-credentials: false - - name: Install git-cliff - uses: taiki-e/install-action@25435dc8dd3baed7417e0c96d3fe89013a5b2e09 # v2.81.3 - with: - tool: git-cliff + - name: Install git-cliff + uses: taiki-e/install-action@25435dc8dd3baed7417e0c96d3fe89013a5b2e09 # v2.81.3 + with: + tool: git-cliff - name: Get tag version id: git-cliff @@ -59,21 +60,22 @@ jobs: with: ssh-key: '${{ secrets.COMMIT_KEY }}' - - name: Pnpm Setup - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + - parallel: + - name: Pnpm Setup + uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - - name: Set up Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version-file: 'package.json' - # For workflows with elevated privileges we recommend disabling automatic caching. - # https://github.com/actions/setup-node - package-manager-cache: false + - name: Set up Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version-file: 'package.json' + # For workflows with elevated privileges we recommend disabling automatic caching. + # https://github.com/actions/setup-node + package-manager-cache: false - - name: Configure git - run: | - git config --global user.name "${{ github.actor }}" - git config --global user.email "${{ github.actor }}@users.noreply.github.com" + - name: Configure git + run: | + git config --global user.name "${{ github.actor }}" + git config --global user.email "${{ github.actor }}@users.noreply.github.com" - name: Bump package.json run: npm version ${TAG_VERSION} --no-commit-hooks --no-git-tag-version diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml index 5bd7a12acf..50ff3d63c0 100644 --- a/.github/workflows/cypress.yml +++ b/.github/workflows/cypress.yml @@ -40,15 +40,15 @@ jobs: uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 with: persist-credentials: false + - parallel: + - name: Set up Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version-file: package.json + package-manager-cache: false - - name: Set up Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version-file: package.json - package-manager-cache: false - - - name: Pnpm Setup - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + - name: Pnpm Setup + uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - name: Install dependencies run: pnpm install --frozen-lockfile diff --git a/.github/workflows/detect-duplicate.yml b/.github/workflows/detect-duplicate.yml index 35b0f98a63..502c5531df 100644 --- a/.github/workflows/detect-duplicate.yml +++ b/.github/workflows/detect-duplicate.yml @@ -25,13 +25,14 @@ jobs: - name: Checkout repository uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - - name: Pnpm Setup - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + - parallel: + - name: Pnpm Setup + uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - - name: Set up Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version-file: 'package.json' + - name: Set up Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version-file: 'package.json' - name: Get pnpm store directory shell: bash diff --git a/.github/workflows/docs-deploy.yml b/.github/workflows/docs-deploy.yml index a308422d04..565ebf8392 100644 --- a/.github/workflows/docs-deploy.yml +++ b/.github/workflows/docs-deploy.yml @@ -28,15 +28,15 @@ jobs: with: fetch-depth: 0 persist-credentials: false + - parallel: + - name: Set up Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version-file: package.json + package-manager-cache: false - - name: Set up Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version-file: package.json - package-manager-cache: false - - - name: Pnpm Setup - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + - name: Pnpm Setup + uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - name: Get pnpm store directory shell: sh diff --git a/.github/workflows/helm.yml b/.github/workflows/helm.yml index 7cc3550bd5..78ab02045c 100644 --- a/.github/workflows/helm.yml +++ b/.github/workflows/helm.yml @@ -27,24 +27,25 @@ jobs: outputs: has_artifacts: ${{ steps.check-artifacts.outputs.has_artifacts }} steps: - - name: Checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - fetch-depth: 0 - persist-credentials: false - - - name: Install helm - uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5 - - - name: Install Oras - uses: oras-project/setup-oras@38de303aac69abb66f3e6255b7198bff35f323e3 # v2 - - - name: Login to GitHub Container Registry - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + - parallel: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Install helm + uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5 + + - name: Install Oras + uses: oras-project/setup-oras@38de303aac69abb66f3e6255b7198bff35f323e3 # v2 + + - name: Login to GitHub Container Registry + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Package helm charts run: | @@ -92,33 +93,34 @@ jobs: needs: [package-helm-chart] if: needs.package-helm-chart.outputs.has_artifacts == 'true' steps: - - name: Checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - fetch-depth: 0 - persist-credentials: false - - - name: Install helm - uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5 - - - name: Install Oras - uses: oras-project/setup-oras@38de303aac69abb66f3e6255b7198bff35f323e3 # v2 - - - name: Install Cosign - uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - - - name: Downloads artifacts - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: artifacts - path: .cr-release-packages/ - - - name: Login to GitHub Container Registry - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + - parallel: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Install helm + uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5 + + - name: Install Oras + uses: oras-project/setup-oras@38de303aac69abb66f3e6255b7198bff35f323e3 # v2 + + - name: Install Cosign + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 + + - name: Downloads artifacts + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: artifacts + path: .cr-release-packages/ + + - name: Login to GitHub Container Registry + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Push charts to GHCR env: @@ -150,27 +152,28 @@ jobs: permissions: contents: read steps: - - name: Checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - fetch-depth: 0 - persist-credentials: false - - - name: Install Cosign - uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - - - name: Downloads artifacts - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 - with: - name: artifacts - path: .cr-release-packages/ - - - name: Login to GitHub Container Registry - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + - parallel: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Install Cosign + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 + + - name: Downloads artifacts + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: artifacts + path: .cr-release-packages/ + + - name: Login to GitHub Container Registry + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Verify signatures for each chart tag run: | diff --git a/.github/workflows/lint-helm-charts.yml b/.github/workflows/lint-helm-charts.yml index 5f4e6c113a..9e1853e5dd 100644 --- a/.github/workflows/lint-helm-charts.yml +++ b/.github/workflows/lint-helm-charts.yml @@ -27,29 +27,31 @@ jobs: permissions: contents: read steps: - - name: Checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - fetch-depth: 0 - persist-credentials: false - - - name: Set up Helm - uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5 - - - name: Set up chart-testing - uses: helm/chart-testing-action@6ec842c01de15ebb84c8627d2744a0c2f2755c9f # v2.8.0 - - - name: Ensure documentation is updated - uses: docker://jnorwood/helm-docs:v1.14.2@sha256:7e562b49ab6b1dbc50c3da8f2dd6ffa8a5c6bba327b1c6335cc15ce29267979c - - - name: Run chart-testing (list-changed) - id: list-changed - run: | - changed=$(ct list-changed --target-branch ${{ github.event.repository.default_branch }}) - if [[ -n "$changed" ]]; then - echo "changed=true" >> "$GITHUB_OUTPUT" - echo "$changed" - fi + - parallel: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + fetch-depth: 0 + persist-credentials: false + + - name: Set up Helm + uses: azure/setup-helm@dda3372f752e03dde6b3237bc9431cdc2f7a02a2 # v5 + + - name: Set up chart-testing + uses: helm/chart-testing-action@6ec842c01de15ebb84c8627d2744a0c2f2755c9f # v2.8.0 + + - parallel: + - name: Ensure documentation is updated + uses: docker://jnorwood/helm-docs:v1.14.2@sha256:7e562b49ab6b1dbc50c3da8f2dd6ffa8a5c6bba327b1c6335cc15ce29267979c + + - name: Run chart-testing (list-changed) + id: list-changed + run: | + changed=$(ct list-changed --target-branch ${{ github.event.repository.default_branch }}) + if [[ -n "$changed" ]]; then + echo "changed=true" >> "$GITHUB_OUTPUT" + echo "$changed" + fi - name: Run chart-testing if: steps.list-changed.outputs.changed == 'true' diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 8b76f9db68..e87e89c5c4 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -31,82 +31,83 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 - if: always() && steps.lint_pr_title.outputs.error_message != null - env: - ERROR_MESSAGE: ${{ steps.lint_pr_title.outputs.error_message }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const message = process.env.ERROR_MESSAGE; - const prNumber = context.payload.pull_request.number; + - parallel: + - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + if: always() && steps.lint_pr_title.outputs.error_message != null + env: + ERROR_MESSAGE: ${{ steps.lint_pr_title.outputs.error_message }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const message = process.env.ERROR_MESSAGE; + const prNumber = context.payload.pull_request.number; - const body = [ - `### PR Title Validation Failed\n`, - message, - `\n---\n`, - `PR titles must follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).`, - `*This check will re-run when you update your PR title.*`, - ].join('\n'); + const body = [ + `### PR Title Validation Failed\n`, + message, + `\n---\n`, + `PR titles must follow [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).`, + `*This check will re-run when you update your PR title.*`, + ].join('\n'); - const allComments = await github.paginate( - github.rest.issues.listComments, - { - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - per_page: 100, - } - ); + const allComments = await github.paginate( + github.rest.issues.listComments, + { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + per_page: 100, + } + ); - const botComment = allComments.find( - c => c.user.type === 'Bot' && c.body && c.body.includes('### PR Title Validation Failed') - ); + const botComment = allComments.find( + c => c.user.type === 'Bot' && c.body && c.body.includes('### PR Title Validation Failed') + ); - if (botComment) { - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: botComment.id, - body, - }); - } else { - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - body, - }); - } + if (botComment) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + body, + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body, + }); + } - - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 - if: always() && steps.lint_pr_title.outputs.error_message == null - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const prNumber = context.payload.pull_request.number; + - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + if: always() && steps.lint_pr_title.outputs.error_message == null + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const prNumber = context.payload.pull_request.number; - const allComments = await github.paginate( - github.rest.issues.listComments, - { - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - per_page: 100, - } - ); + const allComments = await github.paginate( + github.rest.issues.listComments, + { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + per_page: 100, + } + ); - const botComment = allComments.find( - c => c.user.type === 'Bot' && c.body && c.body.includes('### PR Title Validation Failed') - ); + const botComment = allComments.find( + c => c.user.type === 'Bot' && c.body && c.body.includes('### PR Title Validation Failed') + ); - if (botComment) { - await github.rest.issues.deleteComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: botComment.id, - }); - } + if (botComment) { + await github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + }); + } template-check: name: Validate PR Template @@ -117,10 +118,16 @@ jobs: issues: write pull-requests: write steps: - - name: Checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - persist-credentials: false + - parallel: + - name: Skip bot PRs + id: bot-check + if: github.event.pull_request.user.type == 'Bot' + run: echo "skip=true" >> "$GITHUB_OUTPUT" + + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false - name: Set up Node.js uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 @@ -128,11 +135,6 @@ jobs: node-version-file: 'package.json' package-manager-cache: false - - name: Skip bot PRs - id: bot-check - if: github.event.pull_request.user.type == 'Bot' - run: echo "skip=true" >> "$GITHUB_OUTPUT" - - name: Write PR body to file if: steps.bot-check.outputs.skip != 'true' env: @@ -156,130 +158,131 @@ jobs: } >> "$GITHUB_OUTPUT" exit 0 - - name: Label and comment on failure - if: steps.bot-check.outputs.skip != 'true' && steps.check.outputs.exit_code != '0' - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 - env: - ISSUES_JSON: ${{ steps.check.outputs.issues }} - PR_AUTHOR: ${{ github.event.pull_request.user.login }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const issues = JSON.parse(process.env.ISSUES_JSON); - const author = process.env.PR_AUTHOR; - const prNumber = context.payload.pull_request.number; - const LABEL = 'blocked:template'; + - parallel: + - name: Label and comment on failure + if: steps.bot-check.outputs.skip != 'true' && steps.check.outputs.exit_code != '0' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + env: + ISSUES_JSON: ${{ steps.check.outputs.issues }} + PR_AUTHOR: ${{ github.event.pull_request.user.login }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const issues = JSON.parse(process.env.ISSUES_JSON); + const author = process.env.PR_AUTHOR; + const prNumber = context.payload.pull_request.number; + const LABEL = 'blocked:template'; - const issueList = issues.map(i => `- ${i}`).join('\n'); + const issueList = issues.map(i => `- ${i}`).join('\n'); - const commentBody = [ - `Hey @${author}, thanks for submitting this PR! However, it looks like the PR template hasn't been fully filled out.\n`, - `### Issues found:\n`, - issueList, - `\n---\n`, - `**Please update your PR description to follow the [PR template](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/develop/.github/PULL_REQUEST_TEMPLATE.md).**`, - `Incomplete or missing PR descriptions may indicate insufficient review of the changes, and PRs that do not follow the template **may be closed without review**.`, - `See our [Contributing Guide](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/develop/CONTRIBUTING.md) for more details.\n`, - `*This check will automatically re-run when you edit your PR description.*`, - ].join('\n'); + const commentBody = [ + `Hey @${author}, thanks for submitting this PR! However, it looks like the PR template hasn't been fully filled out.\n`, + `### Issues found:\n`, + issueList, + `\n---\n`, + `**Please update your PR description to follow the [PR template](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/develop/.github/PULL_REQUEST_TEMPLATE.md).**`, + `Incomplete or missing PR descriptions may indicate insufficient review of the changes, and PRs that do not follow the template **may be closed without review**.`, + `See our [Contributing Guide](https://github.com/${context.repo.owner}/${context.repo.repo}/blob/develop/CONTRIBUTING.md) for more details.\n`, + `*This check will automatically re-run when you edit your PR description.*`, + ].join('\n'); - const allComments = await github.paginate( - github.rest.issues.listComments, - { - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - per_page: 100, - } - ); + const allComments = await github.paginate( + github.rest.issues.listComments, + { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + per_page: 100, + } + ); - const botComment = allComments.find( - c => c.user.type === 'Bot' && c.body && c.body.includes('### Issues found:') - ); + const botComment = allComments.find( + c => c.user.type === 'Bot' && c.body && c.body.includes('### Issues found:') + ); - if (botComment) { - await github.rest.issues.updateComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: botComment.id, - body: commentBody, - }); - } else { - await github.rest.issues.createComment({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - body: commentBody, - }); - } + if (botComment) { + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + body: commentBody, + }); + } else { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + body: commentBody, + }); + } - try { - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - labels: [LABEL], - }); - } catch (e) { - try { - await github.rest.issues.createLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - name: LABEL, - color: 'B60205', - description: 'PR template not properly filled out', - }); - await github.rest.issues.addLabels({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - labels: [LABEL], - }); - } catch (e2) { - console.log('Could not create/add label:', e2.message); - } - } + try { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + labels: [LABEL], + }); + } catch (e) { + try { + await github.rest.issues.createLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + name: LABEL, + color: 'B60205', + description: 'PR template not properly filled out', + }); + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + labels: [LABEL], + }); + } catch (e2) { + console.log('Could not create/add label:', e2.message); + } + } - core.setFailed('PR template is not properly filled out.'); + core.setFailed('PR template is not properly filled out.'); - - name: Remove label on success - if: steps.bot-check.outputs.skip != 'true' && steps.check.outputs.exit_code == '0' - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const prNumber = context.payload.pull_request.number; - const LABEL = 'blocked:template'; + - name: Remove label on success + if: steps.bot-check.outputs.skip != 'true' && steps.check.outputs.exit_code == '0' + uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const prNumber = context.payload.pull_request.number; + const LABEL = 'blocked:template'; - try { - await github.rest.issues.removeLabel({ - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - name: LABEL, - }); - } catch (e) { - console.log('Could not remove label', e.message); - } + try { + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + name: LABEL, + }); + } catch (e) { + console.log('Could not remove label', e.message); + } - const allComments = await github.paginate( - github.rest.issues.listComments, - { - owner: context.repo.owner, - repo: context.repo.repo, - issue_number: prNumber, - per_page: 100, - } - ); + const allComments = await github.paginate( + github.rest.issues.listComments, + { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: prNumber, + per_page: 100, + } + ); - const botComment = allComments.find( - c => c.user.type === 'Bot' && c.body && c.body.includes('### Issues found:') - ); + const botComment = allComments.find( + c => c.user.type === 'Bot' && c.body && c.body.includes('### Issues found:') + ); - if (botComment) { - await github.rest.issues.deleteComment({ - owner: context.repo.owner, - repo: context.repo.repo, - comment_id: botComment.id, - }); - } + if (botComment) { + await github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: botComment.id, + }); + } diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index fb52c968d2..5c94623c79 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -32,27 +32,28 @@ jobs: arch: arm64 runs-on: ${{ matrix.runner }} steps: - - name: Checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 - - - name: Derive preview version from tag - id: ver - shell: bash - run: | - TAG="${GITHUB_REF_NAME}" - VER="${TAG#preview-}" - VER="${VER#v}" - echo "version=${VER}" >> "$GITHUB_OUTPUT" - echo "Building preview version: ${VER}" + - parallel: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 + + - name: Derive preview version from tag + id: ver + shell: bash + run: | + TAG="${GITHUB_REF_NAME}" + VER="${TAG#preview-}" + VER="${VER#v}" + echo "version=${VER}" >> "$GITHUB_OUTPUT" + echo "Building preview version: ${VER}" - name: Warm cache (no push) — ${{ matrix.platform }} uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 @@ -78,40 +79,41 @@ jobs: packages: write id-token: write steps: - - name: Checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 - - - name: Log in to Docker Hub - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_TOKEN }} - - - name: Log in to GitHub Container Registry - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Derive preview version from tag - id: ver - shell: bash - run: | - TAG="${GITHUB_REF_NAME}" - VER="${TAG#preview-}" - VER="${VER#v}" - echo "version=${VER}" >> "$GITHUB_OUTPUT" - echo "Publishing preview version: ${VER}" + - parallel: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 + + - name: Log in to Docker Hub + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Log in to GitHub Container Registry + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Derive preview version from tag + id: ver + shell: bash + run: | + TAG="${GITHUB_REF_NAME}" + VER="${TAG#preview-}" + VER="${VER#v}" + echo "version=${VER}" >> "$GITHUB_OUTPUT" + echo "Publishing preview version: ${VER}" - name: Extract metadata id: meta diff --git a/.github/workflows/rebuild-issue-index.yml b/.github/workflows/rebuild-issue-index.yml index 764b8dd222..92fceb1aa5 100644 --- a/.github/workflows/rebuild-issue-index.yml +++ b/.github/workflows/rebuild-issue-index.yml @@ -3,7 +3,7 @@ name: Rebuild Issue Index on: schedule: - - cron: "0 3 * * *" + - cron: '0 3 * * *' workflow_dispatch: permissions: {} @@ -23,13 +23,14 @@ jobs: - name: Checkout repository uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - - name: Pnpm Setup - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + - parallel: + - name: Pnpm Setup + uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - - name: Set up Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version-file: 'package.json' + - name: Set up Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version-file: 'package.json' - name: Get pnpm store directory shell: bash diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 38b6cecffa..847b99dfde 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -75,17 +75,18 @@ jobs: env: VERSION: ${{ github.ref_name }} steps: - - name: Checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - persist-credentials: false + - parallel: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false - - name: Commit timestamp - id: ts - run: echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> "$GITHUB_OUTPUT" + - 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 - name: Warm cache [${{ matrix.platform }}] uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 @@ -114,30 +115,31 @@ jobs: env: VERSION: ${{ github.ref_name }} steps: - - name: Checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 - - - name: Log in to Docker Hub - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_TOKEN }} - - - name: Log in to GitHub Container Registry - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} + - parallel: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 + + - name: Log in to Docker Hub + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Log in to GitHub Container Registry + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata id: meta @@ -172,23 +174,24 @@ jobs: 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 }} + - parallel: + - 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 @@ -202,29 +205,30 @@ jobs: VERSION: ${{ github.ref_name }} COSIGN_YES: 'true' steps: - - name: Checkout - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - persist-credentials: false - - - name: Install Cosign - uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - - - name: Install Trivy - uses: aquasecurity/setup-trivy@81e514348e19b6112ce2a7e3ecbafe19c1e1f567 # v0.3.1 - - - name: Log in to Docker Hub - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_TOKEN }} - - - name: Log in to GitHub Container Registry - uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} + - parallel: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Install Cosign + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 + + - name: Install Trivy + uses: aquasecurity/setup-trivy@81e514348e19b6112ce2a7e3ecbafe19c1e1f567 # v0.3.1 + + - name: Log in to Docker Hub + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_TOKEN }} + + - name: Log in to GitHub Container Registry + uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - name: Sign images run: | @@ -271,27 +275,28 @@ jobs: - 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 + - parallel: + - 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" + + 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" publish-release: name: Publish release diff --git a/.github/workflows/renovate-helm-custom-hooks.yml b/.github/workflows/renovate-helm-custom-hooks.yml index 0ecfbb760a..bd31c297b9 100644 --- a/.github/workflows/renovate-helm-custom-hooks.yml +++ b/.github/workflows/renovate-helm-custom-hooks.yml @@ -24,20 +24,21 @@ jobs: pull-requests: write if: github.actor == 'renovate[bot]' steps: - - name: Checkout code - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - with: - fetch-depth: 0 - persist-credentials: false - - - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 - id: app-token - with: - app-id: 2138788 - private-key: ${{ secrets.APP_SEERR_HELM_PRIVATE_KEY }} - - - name: Set up chart-testing - uses: helm/chart-testing-action@6ec842c01de15ebb84c8627d2744a0c2f2755c9f # v2.8.0 + - parallel: + - name: Checkout code + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + fetch-depth: 0 + persist-credentials: false + + - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + id: app-token + with: + client-id: 2138788 + private-key: ${{ secrets.APP_SEERR_HELM_PRIVATE_KEY }} + + - name: Set up chart-testing + uses: helm/chart-testing-action@6ec842c01de15ebb84c8627d2744a0c2f2755c9f # v2.8.0 - name: Run chart-testing (list-changed) id: list-changed diff --git a/.github/workflows/seerr-labeller.yml b/.github/workflows/seerr-labeller.yml index 7a8330555a..823bb8bd6a 100644 --- a/.github/workflows/seerr-labeller.yml +++ b/.github/workflows/seerr-labeller.yml @@ -27,39 +27,40 @@ jobs: NUMBER: ${{ github.event.pull_request.number }} PR_AUTHOR: ${{ github.event.pull_request.user.login }} steps: - - name: Label added, comment and close pull request - if: github.event.action == 'labeled' && github.event.label.name == 'ai-generated' - shell: bash - env: - BODY: > - :wave: @${{ env.PR_AUTHOR }}, thank you for your contribution! + - parallel: + - name: Label added, comment and close pull request + if: github.event.action == 'labeled' && github.event.label.name == 'ai-generated' + shell: bash + env: + BODY: > + :wave: @${{ env.PR_AUTHOR }}, thank you for your contribution! - However, this pull request has been closed because it appears to contain a significant amount of AI-generated code without sufficient human review or supervision. + However, this pull request has been closed because it appears to contain a significant amount of AI-generated code without sufficient human review or supervision. - AI-generated code can often introduce subtle bugs, poor design patterns, or inconsistent styles that make long-term maintenance difficult and reduce overall code quality. For the sake of the project's future stability and readability, we require that all contributions meet our established coding standards and demonstrate clear developer oversight. + AI-generated code can often introduce subtle bugs, poor design patterns, or inconsistent styles that make long-term maintenance difficult and reduce overall code quality. For the sake of the project's future stability and readability, we require that all contributions meet our established coding standards and demonstrate clear developer oversight. - This pull request is also too large for effective human review. Please discuss with us on how to break down these changes into smaller, more focused PRs to ensure a thorough and efficient review process. - If you'd like to revise and resubmit your changes with careful review and cleanup, we'd be happy to take another look. - run: | - retry() { n=0; until "$@"; do n=$((n+1)); [ $n -ge 3 ] && break; echo "retry $n: $*" >&2; sleep 2; done; } - retry gh pr comment "$NUMBER" -R "$GH_REPO" -b "$BODY" || true - retry gh pr close "$NUMBER" -R "$GH_REPO" || true - gh pr lock "$NUMBER" -R "$GH_REPO" -r "spam" || true + This pull request is also too large for effective human review. Please discuss with us on how to break down these changes into smaller, more focused PRs to ensure a thorough and efficient review process. + If you'd like to revise and resubmit your changes with careful review and cleanup, we'd be happy to take another look. + run: | + retry() { n=0; until "$@"; do n=$((n+1)); [ $n -ge 3 ] && break; echo "retry $n: $*" >&2; sleep 2; done; } + retry gh pr comment "$NUMBER" -R "$GH_REPO" -b "$BODY" || true + retry gh pr close "$NUMBER" -R "$GH_REPO" || true + gh pr lock "$NUMBER" -R "$GH_REPO" -r "spam" || true - - name: Label removed, reopen and unlock pull request - if: github.event.action == 'unlabeled' && github.event.label.name == 'ai-generated' - shell: bash - run: | - retry() { n=0; until "$@"; do n=$((n+1)); [ $n -ge 3 ] && break; echo "retry $n: $*" >&2; sleep 2; done; } - retry gh pr reopen "$NUMBER" -R "$GH_REPO" || true - gh pr unlock "$NUMBER" -R "$GH_REPO" || true + - name: Label removed, reopen and unlock pull request + if: github.event.action == 'unlabeled' && github.event.label.name == 'ai-generated' + shell: bash + run: | + retry() { n=0; until "$@"; do n=$((n+1)); [ $n -ge 3 ] && break; echo "retry $n: $*" >&2; sleep 2; done; } + retry gh pr reopen "$NUMBER" -R "$GH_REPO" || true + gh pr unlock "$NUMBER" -R "$GH_REPO" || true - - name: Remove AI-generated label on manual reopen - if: github.event.action == 'reopened' - shell: bash - run: | - gh pr edit "$NUMBER" -R "$GH_REPO" --remove-label "ai-generated" || true - gh pr unlock "$NUMBER" -R "$GH_REPO" || true + - name: Remove AI-generated label on manual reopen + if: github.event.action == 'reopened' + shell: bash + run: | + gh pr edit "$NUMBER" -R "$GH_REPO" --remove-label "ai-generated" || true + gh pr unlock "$NUMBER" -R "$GH_REPO" || true support: if: > @@ -78,34 +79,35 @@ jobs: NUMBER: ${{ github.event.issue.number }} ISSUE_AUTHOR: ${{ github.event.issue.user.login }} steps: - - name: Label added, comment and close issue - if: github.event.action == 'labeled' && github.event.label.name == 'support' - shell: bash - env: - BODY: > - :wave: @${{ env.ISSUE_AUTHOR }}, we use the issue tracker exclusively - for bug reports and feature requests. However, this issue appears - to be a support request. Please use our support channels - to get help with Seerr. + - parallel: + - name: Label added, comment and close issue + if: github.event.action == 'labeled' && github.event.label.name == 'support' + shell: bash + env: + BODY: > + :wave: @${{ env.ISSUE_AUTHOR }}, we use the issue tracker exclusively + for bug reports and feature requests. However, this issue appears + to be a support request. Please use our support channels + to get help with Seerr. - - [Discord](https://discord.gg/seerr) - run: | - retry() { n=0; until "$@"; do n=$((n+1)); [ $n -ge 3 ] && break; echo "retry $n: $*" >&2; sleep 2; done; } - retry gh issue comment "$NUMBER" -R "$GH_REPO" -b "$BODY" || true - retry gh issue close "$NUMBER" -R "$GH_REPO" || true - gh issue lock "$NUMBER" -R "$GH_REPO" -r "off_topic" || true + - [Discord](https://discord.gg/seerr) + run: | + retry() { n=0; until "$@"; do n=$((n+1)); [ $n -ge 3 ] && break; echo "retry $n: $*" >&2; sleep 2; done; } + retry gh issue comment "$NUMBER" -R "$GH_REPO" -b "$BODY" || true + retry gh issue close "$NUMBER" -R "$GH_REPO" || true + gh issue lock "$NUMBER" -R "$GH_REPO" -r "off_topic" || true - - name: Label removed, reopen and unlock issue - if: github.event.action == 'unlabeled' && github.event.label.name == 'support' - shell: bash - run: | - retry() { n=0; until "$@"; do n=$((n+1)); [ $n -ge 3 ] && break; echo "retry $n: $*" >&2; sleep 2; done; } - retry gh issue reopen "$NUMBER" -R "$GH_REPO" || true - gh issue unlock "$NUMBER" -R "$GH_REPO" || true + - name: Label removed, reopen and unlock issue + if: github.event.action == 'unlabeled' && github.event.label.name == 'support' + shell: bash + run: | + retry() { n=0; until "$@"; do n=$((n+1)); [ $n -ge 3 ] && break; echo "retry $n: $*" >&2; sleep 2; done; } + retry gh issue reopen "$NUMBER" -R "$GH_REPO" || true + gh issue unlock "$NUMBER" -R "$GH_REPO" || true - - name: Remove support label on manual reopen - if: github.event.action == 'reopened' - shell: bash - run: | - gh issue edit "$NUMBER" -R "$GH_REPO" --remove-label "support" || true - gh issue unlock "$NUMBER" -R "$GH_REPO" || true + - name: Remove support label on manual reopen + if: github.event.action == 'reopened' + shell: bash + run: | + gh issue edit "$NUMBER" -R "$GH_REPO" --remove-label "support" || true + gh issue unlock "$NUMBER" -R "$GH_REPO" || true diff --git a/.github/workflows/test-docs.yml b/.github/workflows/test-docs.yml index d4e01ee044..bc70576c53 100644 --- a/.github/workflows/test-docs.yml +++ b/.github/workflows/test-docs.yml @@ -29,14 +29,15 @@ jobs: fetch-depth: 0 persist-credentials: false - - name: Set up Node.js - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 - with: - node-version-file: package.json - package-manager-cache: false - - - name: Pnpm Setup - uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 + - parallel: + - name: Set up Node.js + uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 + with: + node-version-file: package.json + package-manager-cache: false + + - name: Pnpm Setup + uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8 - name: Get pnpm store directory shell: sh From c26891aefb3650c1839274fc0ea40d743d53ded9 Mon Sep 17 00:00:00 2001 From: Ludovic Ortega Date: Sat, 4 Jul 2026 23:19:19 +0200 Subject: [PATCH 2/3] fix: move out Commit timestamp Signed-off-by: Ludovic Ortega --- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/preview.yml | 16 ++++++++-------- .github/workflows/release.yml | 16 ++++++++-------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d3a6dbed9..20abb7d290 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -194,13 +194,13 @@ jobs: 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 + - name: Commit timestamp + id: ts + run: echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> "$GITHUB_OUTPUT" + - name: Warm cache (no push) — ${{ matrix.platform }} uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 with: @@ -231,10 +231,6 @@ jobs: 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 @@ -251,6 +247,10 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Commit timestamp + id: ts + run: echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> "$GITHUB_OUTPUT" + - name: Extract metadata id: meta uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6 diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 5c94623c79..59ad99b4aa 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -38,10 +38,6 @@ jobs: 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 @@ -55,6 +51,10 @@ jobs: echo "version=${VER}" >> "$GITHUB_OUTPUT" echo "Building preview version: ${VER}" + - name: Commit timestamp + id: ts + run: echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> "$GITHUB_OUTPUT" + - name: Warm cache (no push) — ${{ matrix.platform }} uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 with: @@ -85,10 +85,6 @@ jobs: 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 @@ -115,6 +111,10 @@ jobs: echo "version=${VER}" >> "$GITHUB_OUTPUT" echo "Publishing preview version: ${VER}" + - name: Commit timestamp + id: ts + run: echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> "$GITHUB_OUTPUT" + - name: Extract metadata id: meta uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 847b99dfde..6afb7491ff 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -81,13 +81,13 @@ jobs: 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 + - name: Commit timestamp + id: ts + run: echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> "$GITHUB_OUTPUT" + - name: Warm cache [${{ matrix.platform }}] uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 with: @@ -121,10 +121,6 @@ jobs: 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@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 @@ -141,6 +137,10 @@ jobs: username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} + - name: Commit timestamp + id: ts + run: echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> "$GITHUB_OUTPUT" + - name: Extract metadata id: meta uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6 From 11ace53fed6adcdf14921fb64126ed465f4e909c Mon Sep 17 00:00:00 2001 From: Ludovic Ortega Date: Sat, 4 Jul 2026 23:25:42 +0200 Subject: [PATCH 3/3] ci: fix helm app client-id Signed-off-by: Ludovic Ortega --- .github/workflows/renovate-helm-custom-hooks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/renovate-helm-custom-hooks.yml b/.github/workflows/renovate-helm-custom-hooks.yml index bd31c297b9..7c91fe5219 100644 --- a/.github/workflows/renovate-helm-custom-hooks.yml +++ b/.github/workflows/renovate-helm-custom-hooks.yml @@ -34,7 +34,7 @@ jobs: - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 id: app-token with: - client-id: 2138788 + client-id: ${{ secrets.APP_SEERR_HELM_CLIENT_ID }} private-key: ${{ secrets.APP_SEERR_HELM_PRIVATE_KEY }} - name: Set up chart-testing