diff --git a/.github/labeler.yml b/.github/labeler.yml index 2dab41e6ee4..3180205e2f5 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,25 +1,36 @@ tests: - - '**/*.spec.js' +- changed-files: + - any-glob-to-any-file: + - '**/*.spec.*' -github_actions: - - '.github/workflows/*' +ci: +- changed-files: + - any-glob-to-any-file: + - '.github/workflows/**/**' -pinia: - - 'frontend/store/**/*.ts' +'frontend:store': +- changed-files: + - any-glob-to-any-file: + - 'frontend/store/**/*.ts' -plugins: - - 'frontend/plugins/**/*.ts' +'frontend:plugins': +- changed-files: + - any-glob-to-any-file: + - 'frontend/plugins/**/*.ts' vue: - - '**/*.vue' +- changed-files: + - any-glob-to-any-file: + - '**/*.vue' -docker: - - 'Dockerfile*' +packaging: +- changed-files: + - any-glob-to-any-file: + - 'packaging/**/**' ui: - - any: - [ - 'frontend/components/**/*.vue', - 'frontend/layouts/**/*.vue', - 'frontend/pages/**/*.vue' - ] +- changed-files: + - any-glob-to-any-file: + - 'frontend/components/**/*.vue' + - 'frontend/layouts/**/*.vue' + - 'frontend/pages/**/*.vue' diff --git a/.github/workflows/TODO b/.github/workflows/TODO new file mode 100644 index 00000000000..2cf2181658d --- /dev/null +++ b/.github/workflows/TODO @@ -0,0 +1 @@ +* Reusable workflows should be under a `reusable` folder. Track https://github.com/orgs/community/discussions/10773 diff --git a/.github/workflows/codeql.yml b/.github/workflows/__codeql.yml similarity index 64% rename from .github/workflows/codeql.yml rename to .github/workflows/__codeql.yml index e079d24c9c3..de0ea311d6d 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/__codeql.yml @@ -1,29 +1,15 @@ name: GitHub CodeQL ๐Ÿ”ฌ -concurrency: - group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.ref || github.head_ref || github.run_id }} - cancel-in-progress: true - on: - push: - branches: - - master - pull_request: - paths-ignore: - - '**/*.md' - merge_group: workflow_call: - schedule: - - cron: 0 0 * * MON,FRI - + inputs: + commit: + required: true + type: string jobs: analyze: - name: Analyze ๐Ÿ”ฌ + name: Analyze ${{ matrix.language}} ๐Ÿ”ฌ runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write strategy: fail-fast: false @@ -35,6 +21,7 @@ jobs: - name: Checkout repository โฌ‡๏ธ uses: actions/checkout@v4.1.7 with: + ref: ${{ inputs.commit }} show-progress: false - name: Initialize CodeQL ๐Ÿ› ๏ธ diff --git a/.github/workflows/__deploy.yml b/.github/workflows/__deploy.yml new file mode 100644 index 00000000000..56fbe099e7b --- /dev/null +++ b/.github/workflows/__deploy.yml @@ -0,0 +1,57 @@ +name: Deploy ๐Ÿ—๏ธ + +on: + workflow_call: + inputs: + branch: + required: true + type: string + commit: + required: false + type: string + comment: + required: false + type: boolean + artifact_name: + required: false + type: string + default: frontend + +jobs: + cf-pages: + name: CloudFlare Pages ๐Ÿ“ƒ + runs-on: ubuntu-latest + environment: ${{ inputs.branch == 'master' && 'production' || 'preview' }} + outputs: + url: ${{ steps.cf.outputs.deployment-url }} + + steps: + - name: Download workflow artifact โฌ‡๏ธ + uses: actions/download-artifact@v4.1.8 + with: + name: ${{ inputs.artifact_name }} + path: dist + + - name: Publish to Cloudflare Pages ๐Ÿ“ƒ + uses: cloudflare/wrangler-action@v3.7.0 + id: cf + with: + apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + command: pages deploy dist --project-name=jf-vue --branch=${{ inputs.branch }} + + compose-comment: + name: Compose and push comment ๐Ÿ“ + # Always run so the comment is composed for the workflow summary + if: ${{ always() }} + uses: ./.github/workflows/__job_messages.yml + secrets: inherit + needs: + - cf-pages + + with: + branch: ${{ inputs.branch }} + commit: ${{ inputs.commit }} + preview_url: ${{ needs.cf-pages.outputs.url }} + in_progress: false + comment: ${{ inputs.comment }} diff --git a/.github/workflows/job_messages.yml b/.github/workflows/__job_messages.yml similarity index 71% rename from .github/workflows/job_messages.yml rename to .github/workflows/__job_messages.yml index 209f7817a8e..5955543a443 100644 --- a/.github/workflows/job_messages.yml +++ b/.github/workflows/__job_messages.yml @@ -12,29 +12,23 @@ on: preview_url: required: false type: string - build_workflow_run_id: - required: false - type: number - commenting_workflow_run_id: - required: true - type: string in_progress: required: true type: boolean - outputs: - msg: - description: The composed message - value: ${{ jobs.msg.outputs.msg }} + comment: + required: false + type: boolean marker: description: Hidden marker to detect PR comments composed by the bot - value: "CFPages-deployment" + required: false + type: string + default: "CFPages-deployment" + jobs: - msg: - name: Deployment status + cf_pages_msg: + name: CloudFlare Pages deployment status ๐Ÿ“ƒ๐Ÿš€ runs-on: ubuntu-latest - outputs: - msg: ${{ env.msg }} steps: - name: Compose message ๐Ÿ“ƒ @@ -45,8 +39,7 @@ jobs: PREVIEW_URL: ${{ inputs.preview_url != '' && (inputs.branch != 'master' && inputs.preview_url || format('https://jf-vue.pages.dev ({0})', inputs.preview_url)) || 'Not available' }} DEPLOY_STATUS: ${{ inputs.in_progress && '๐Ÿ”„ Deploying...' || (inputs.preview_url != '' && 'โœ… Deployed!' || 'โŒ Failure. Check workflow logs for details') }} DEPLOYMENT_TYPE: ${{ inputs.branch != 'master' && '๐Ÿ”€ Preview' || 'โš™๏ธ Production' }} - BUILD_WORKFLOW_RUN: ${{ !inputs.in_progress && format('**[View build logs](https://github.com/{0}/actions/runs/{1})**', 'jellyfin/jellyfin-vue', inputs.build_workflow_run_id) || '' }} - COMMENTING_WORKFLOW_RUN: ${{ format('**[View bot logs](https://github.com/{0}/actions/runs/{1})**', 'jellyfin/jellyfin-vue', inputs.commenting_workflow_run_id) }} + WORKFLOW_RUN: ${{ !inputs.in_progress && format('**[View build logs](https://github.com/{0}/actions/runs/{1})**', github.repository, github.run_id) || '' }} # EOF is needed for multiline environment variables in a GitHub Actions context run: | echo "## Cloudflare Pages deployment" > $GITHUB_STEP_SUMMARY @@ -57,9 +50,16 @@ jobs: echo "| **Preview URL** | $PREVIEW_URL |" >> $GITHUB_STEP_SUMMARY echo "| **Type** | $DEPLOYMENT_TYPE |" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "$BUILD_WORKFLOW_RUN" >> $GITHUB_STEP_SUMMARY - echo "$COMMENTING_WORKFLOW_RUN" >> $GITHUB_STEP_SUMMARY + echo "$WORKFLOW_RUN" >> $GITHUB_STEP_SUMMARY COMPOSED_MSG=$(cat $GITHUB_STEP_SUMMARY) echo "msg<> $GITHUB_ENV echo "$COMPOSED_MSG" >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV + + - name: Comment Pull Request + uses: thollander/actions-comment-pull-request@v2.5.0 + if: ${{ inputs.comment }} + with: + GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }} + message: ${{ steps.compose.outputs.msg }} + comment_tag: ${{ inputs.marker }} diff --git a/.github/workflows/package.yml b/.github/workflows/__package.yml similarity index 98% rename from .github/workflows/package.yml rename to .github/workflows/__package.yml index 02e9ebb54eb..79463e82871 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/__package.yml @@ -4,7 +4,7 @@ on: workflow_call: inputs: commit: - required: true + required: false type: string tag_name: required: false @@ -28,10 +28,6 @@ env: COMMIT_TAG: unstable DOCKER_BUILD_RECORD_UPLOAD: false -permissions: - id-token: write - attestations: write - defaults: run: shell: bash @@ -60,6 +56,7 @@ jobs: - name: Checkout โฌ‡๏ธ uses: actions/checkout@v4.1.7 with: + ref: ${{ inputs.commit || github.sha }} show-progress: false - name: Setup node environment โš™๏ธ @@ -169,6 +166,7 @@ jobs: - name: Checkout โฌ‡๏ธ uses: actions/checkout@v4.1.7 with: + ref: ${{ inputs.commit || github.sha }} show-progress: false - name: Configure QEMU โš™๏ธ @@ -262,6 +260,7 @@ jobs: - name: Checkout โฌ‡๏ธ uses: actions/checkout@v4.1.7 with: + ref: ${{ inputs.commit || github.sha }} show-progress: false - name: Configure QEMU โš™๏ธ diff --git a/.github/workflows/quality_checks.yml b/.github/workflows/__quality_checks.yml similarity index 83% rename from .github/workflows/quality_checks.yml rename to .github/workflows/__quality_checks.yml index 24b82d047bb..c52c7d534ad 100644 --- a/.github/workflows/quality_checks.yml +++ b/.github/workflows/__quality_checks.yml @@ -1,16 +1,11 @@ name: Quality checks ๐Ÿ‘Œ๐Ÿงช -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - on: - pull_request: - paths-ignore: - - '**/*.md' - merge_group: - schedule: - - cron: 30 7 * * 6 + workflow_call: + inputs: + commit: + required: true + type: string workflow_dispatch: jobs: @@ -21,6 +16,7 @@ jobs: - name: Checkout Repository uses: actions/checkout@v4.1.7 with: + ref: ${{ inputs.commit }} show-progress: false - name: Scan @@ -42,6 +38,7 @@ jobs: - name: Checkout โฌ‡๏ธ uses: actions/checkout@v4.1.7 with: + ref: ${{ inputs.commit }} show-progress: false - name: Setup node environment โš™๏ธ @@ -67,6 +64,7 @@ jobs: - name: Checkout โฌ‡๏ธ uses: actions/checkout@v4.1.7 with: + ref: ${{ inputs.commit }} show-progress: false - name: Setup node environment โš™๏ธ @@ -81,21 +79,15 @@ jobs: - name: Run typecheck ๐Ÿ“– run: npm run typecheck - build: - name: Build ๐Ÿ—๏ธ - uses: ./.github/workflows/package.yml - with: - commit: ${{ github.sha }} - conventional_commits: name: Conventional commits check ๐Ÿ’ฌ - if: ${{ github.event_name == 'pull_request' || github.event_name == 'merge_group' }} runs-on: ubuntu-latest steps: - name: Checkout โฌ‡๏ธ uses: actions/checkout@v4.1.7 with: + ref: ${{ inputs.commit }} show-progress: false - name: Check if all commits comply with the specification diff --git a/.github/workflows/automation.yml b/.github/workflows/automation.yml deleted file mode 100644 index 9348b9bfc58..00000000000 --- a/.github/workflows/automation.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Automation ๐Ÿค– - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -on: - push: - branches: - - master - paths-ignore: - - "**/*.md" - pull_request_target: - -jobs: - compose-comment: - name: Compose PR comment - if: ${{ always() && !cancelled() && github.event_name == 'pull_request_target' }} - uses: ./.github/workflows/job_messages.yml - with: - commit: ${{ github.event.pull_request.head.sha }} - commenting_workflow_run_id: ${{ github.run_id }} - in_progress: true - - push-comment: - name: Push comment to PR ๐Ÿ–ฅ๏ธ - if: ${{ always() && !cancelled() && github.event_name == 'pull_request_target' && needs.compose-comment.result == 'success' }} - runs-on: ubuntu-latest - needs: - - compose-comment - - steps: - - name: Create comment - uses: thollander/actions-comment-pull-request@v2.5.0 - with: - GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }} - message: ${{ needs.compose-comment.outputs.msg }} - comment_tag: ${{ needs.compose-comment.outputs.marker }} - - project: - name: Project board ๐Ÿ“Š - if: ${{ github.event_name == 'pull_request_target' }} - runs-on: ubuntu-latest - - steps: - - uses: alex-page/github-project-automation-plus@v0.9.0 - with: - project: Ongoing development - column: In progress - repo-token: ${{ secrets.JF_BOT_TOKEN }} - - label: - name: Labeling ๐Ÿท๏ธ - if: ${{ always() && !cancelled() }} - runs-on: ubuntu-latest - - steps: - - name: Label PR depending on modified files - uses: actions/labeler@v5.0.0 - if: ${{ github.event_name == 'pull_request_target' }} - continue-on-error: true - with: - repo-token: "${{ secrets.JF_BOT_TOKEN }}" - - - name: Check all PRs for merge conflicts โ›” - uses: eps1lon/actions-label-merge-conflict@v3.0.2 - with: - dirtyLabel: "merge conflict" - repoToken: ${{ secrets.JF_BOT_TOKEN }} diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml deleted file mode 100644 index 206949b17c0..00000000000 --- a/.github/workflows/deploy.yml +++ /dev/null @@ -1,83 +0,0 @@ -name: Deploy ๐Ÿ—๏ธ - -on: - workflow_run: - workflows: - # Deploy on pull requests - - Quality checks ๐Ÿ‘Œ๐Ÿงช - # Deploy on all releases - - Release ๐ŸŒ - types: - - completed - -jobs: - cf-pages: - name: CloudFlare Pages ๐Ÿ“ƒ - runs-on: ubuntu-latest - permissions: - contents: read - deployments: write - # We set the environment variable here (and as an output) because, - # given no real runner is dispatched in compose-comment job (it's dispatched in the reusable workflow) in this workflow definition, - # the env. context is not valid. - env: - TARGET_BRANCH: | - ${{ - github.event.workflow_run.head_repository.full_name == github.repository - && github.event.workflow_run.head_branch - || format('{0}/{1}', github.event.workflow_run.head_repository.full_name, github.event.workflow_run.head_branch) - }} - outputs: - url: ${{ steps.cf.outputs.url }} - branch: ${{ env.TARGET_BRANCH }} - - steps: - - name: Download workflow artifact โฌ‡๏ธ - uses: actions/download-artifact@v4.1.8 - with: - run-id: ${{ github.event.workflow_run.id }} - github-token: ${{ secrets.JF_BOT_TOKEN }} - name: frontend - path: dist - - - name: Publish to Cloudflare Pages ๐Ÿ“ƒ - uses: cloudflare/pages-action@v1.5.0 - id: cf - with: - apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} - accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - projectName: jf-vue - directory: dist - branch: ${{ env.TARGET_BRANCH }} - gitHubToken: ${{ secrets.GITHUB_TOKEN }} - - compose-comment: - name: Compose comment ๐Ÿ“ - if: ${{ always() }} - uses: ./.github/workflows/job_messages.yml - needs: - - cf-pages - - with: - branch: ${{ needs.cf-pages.outputs.branch }} - commit: ${{ github.event.workflow_run.head_commit.id }} - preview_url: ${{ needs.cf-pages.outputs.url }} - build_workflow_run_id: ${{ github.event.workflow_run.id }} - commenting_workflow_run_id: ${{ github.run_id }} - in_progress: false - - comment-status: - name: Create comment status ๐Ÿ“Š - if: ${{ always() && github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.pull_requests[0].number != '' }} - runs-on: ubuntu-latest - needs: - - compose-comment - - steps: - - name: Update job summary in PR comment ๐Ÿ”ƒ - uses: thollander/actions-comment-pull-request@v2.5.0 - with: - GITHUB_TOKEN: ${{ secrets.JF_BOT_TOKEN }} - message: ${{ needs.compose-comment.outputs.msg }} - pr_number: ${{ github.event.workflow_run.pull_requests[0].number }} - comment_tag: ${{ needs.compose-comment.outputs.marker }} diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml new file mode 100644 index 00000000000..526af143adb --- /dev/null +++ b/.github/workflows/pull_request.yml @@ -0,0 +1,94 @@ +name: Pull Request ๐Ÿ“ฅ + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }} + cancel-in-progress: true + +on: + pull_request_target: + paths-ignore: + - '**/*.md' + merge_group: + +jobs: + push-comment: + name: Compose and push PR comment โœ๏ธ + if: ${{ always() && !cancelled() }} + uses: ./.github/workflows/__job_messages.yml + secrets: inherit + with: + commit: ${{ github.event.pull_request.head.sha }} + in_progress: true + comment: true + + project: + name: Add to project board ๐Ÿ“Š + if: ${{ always() }} + runs-on: ubuntu-latest + + steps: + - uses: alex-page/github-project-automation-plus@v0.9.0 + with: + project: Ongoing development + column: In progress + repo-token: ${{ secrets.JF_BOT_TOKEN }} + + label: + name: Labeling ๐Ÿท๏ธ + if: ${{ always() }} + runs-on: ubuntu-latest + + steps: + - name: Label depending on modified files + uses: actions/labeler@v5.0.0 + with: + sync-labels: true + repo-token: ${{ secrets.JF_BOT_TOKEN }} + + build: + name: Build ๐Ÿ—๏ธ + if: ${{ always() && !cancelled() }} + uses: ./.github/workflows/__package.yml + # Needed for attestation publication + permissions: + id-token: write + attestations: write + with: + commit: ${{ github.event.pull_request.head.sha }} + + quality_checks: + name: Quality checks ๐Ÿ‘Œ๐Ÿงช + if: ${{ always() && !cancelled() }} + uses: ./.github/workflows/__quality_checks.yml + permissions: {} + with: + commit: ${{ github.event.pull_request.head.sha }} + + codeql: + name: GitHub CodeQL ๐Ÿ”ฌ + if: ${{ always() && !cancelled() }} + uses: ./.github/workflows/__codeql.yml + permissions: + actions: read + contents: read + security-events: write + with: + commit: ${{ github.event.pull_request.head.sha }} + + deploy: + name: Deploy ๐Ÿš€ + uses: ./.github/workflows/__deploy.yml + if: ${{ always() && !cancelled() && needs.build.result == 'success' }} + needs: + - push-comment + - build + permissions: + contents: read + deployments: write + secrets: inherit + with: + # If the PR is from the master branch of a fork, append the fork's name to the branch name + branch: ${{ github.event.pull_request.head.repo.full_name != github.repository && github.event.pull_request.head.ref == 'master' && format('{0}/{1}', github.event.pull_request.head.repo.full_name, github.event.pull_request.head.ref) || github.event.pull_request.head.ref }} + comment: true + pr_number: ${{ github.event.pull_request.number }} + commit: ${{ github.event.pull_request.head.sha }} diff --git a/.github/workflows/push_release.yml b/.github/workflows/push_release.yml new file mode 100644 index 00000000000..664427ff5b5 --- /dev/null +++ b/.github/workflows/push_release.yml @@ -0,0 +1,66 @@ +name: Push & Release ๐ŸŒ + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.ref }} + cancel-in-progress: true + +on: + release: + types: + - released + - prereleased + push: + branches: + - master + paths-ignore: + - '**/*.md' + +jobs: + label: + name: Label conflicted PRs ๐Ÿท๏ธโ›” + if: ${{ always() && !cancelled() }} + runs-on: ubuntu-latest + + steps: + - name: Check all PRs for merge conflicts and label them โ›” + uses: eps1lon/actions-label-merge-conflict@v3.0.2 + with: + dirtyLabel: "merge conflict" + repoToken: ${{ secrets.JF_BOT_TOKEN }} + + main: + name: ${{ github.event_name == 'push' && 'Unstable ๐Ÿš€โš ๏ธ' || 'Stable ๐Ÿท๏ธโœ…' }} + uses: ./.github/workflows/__package.yml + secrets: inherit + # Needed for attestation publication + permissions: + id-token: write + attestations: write + with: + commit: ${{ github.event_name == 'push' && github.sha }} + is_prerelease: ${{ github.event_name == 'release' && github.event.action == 'prereleased' }} + tag_name: ${{ github.event_name == 'release' && github.event.release.tag_name }} + push: true + + codeql: + name: GitHub CodeQL ๐Ÿ”ฌ + uses: ./.github/workflows/__codeql.yml + permissions: + actions: read + contents: read + security-events: write + with: + commit: ${{ github.sha }} + + deploy: + name: Deploy ๐Ÿš€ + uses: ./.github/workflows/__deploy.yml + needs: + - main + permissions: + contents: read + deployments: write + secrets: inherit + with: + branch: ${{ github.ref_name }} + comment: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 3b5d37e139a..00000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: Release ๐ŸŒ - -concurrency: - group: ${{ github.workflow }}-${{ github.event_name == 'push' && github.ref }} - cancel-in-progress: true - -on: - release: - types: - - released - - prereleased - push: - branches: - - master - paths-ignore: - - '**/*.md' - -jobs: - main: - name: ${{ github.event_name == 'push' && 'Unstable ๐Ÿš€โš ๏ธ' || 'Stable ๐Ÿท๏ธโœ…' }} - uses: ./.github/workflows/package.yml - secrets: inherit - with: - commit: ${{ github.event_name == 'push' && github.sha }} - is_prerelease: ${{ github.event_name == 'release' && github.event.action == 'prereleased' }} - tag_name: ${{ github.event_name == 'release' && github.event.release.tag_name }} - push: true diff --git a/.github/workflows/schedule.yml b/.github/workflows/schedule.yml new file mode 100644 index 00000000000..d3e9059ab83 --- /dev/null +++ b/.github/workflows/schedule.yml @@ -0,0 +1,17 @@ +name: Scheduled tasks ๐Ÿ•’ + +on: + schedule: + - cron: 30 7 * * 6 + workflow_dispatch: + +jobs: + codeql: + name: GitHub CodeQL ๐Ÿ”ฌ + uses: ./.github/workflows/__codeql.yml + permissions: + actions: read + contents: read + security-events: write + with: + commit: ${{ github.sha }}