diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f42952e2bb..5cb0e81340 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -16,6 +16,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} +permissions: + contents: read + env: CARGO_TERM_COLOR: always # CI does clean builds, so incremental compilation tracking adds I/O overhead diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml new file mode 100644 index 0000000000..8aaddc38fb --- /dev/null +++ b/.github/workflows/codeql.yaml @@ -0,0 +1,40 @@ +name: codeql + +on: + push: + branches: [main] + pull_request: + branches: [main] + schedule: + - cron: '23 3 * * 1' + +permissions: + contents: read + +jobs: + analyze: + runs-on: ubuntu-24.04 + permissions: + actions: read + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + language: [actions, rust] + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + queries: +security-extended + + - name: Autobuild + if: matrix.language == 'rust' + uses: github/codeql-action/autobuild@v4 + + - name: Analyze + uses: github/codeql-action/analyze@v4 diff --git a/.github/workflows/nightly-benchmark.yaml b/.github/workflows/nightly-benchmark.yaml index 05e5370e4b..5994e76b3b 100644 --- a/.github/workflows/nightly-benchmark.yaml +++ b/.github/workflows/nightly-benchmark.yaml @@ -7,6 +7,9 @@ on: - cron: '17 4 * * *' workflow_dispatch: +permissions: + contents: read + env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: 0 diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index 647d0b949a..f1508d4ed5 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -16,6 +16,9 @@ on: - cron: '37 5 * * *' workflow_dispatch: +permissions: + contents: read + env: CARGO_TERM_COLOR: always CARGO_INCREMENTAL: 0 diff --git a/.github/workflows/publish-docs.yaml b/.github/workflows/publish-docs.yaml index 0b24e8b64f..0c4b13d67b 100644 --- a/.github/workflows/publish-docs.yaml +++ b/.github/workflows/publish-docs.yaml @@ -14,6 +14,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: + contents: read + jobs: build-docs: runs-on: ubuntu-24.04 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index b80085580b..73ba2a176d 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -19,8 +19,7 @@ # (via upload-artifact/download-artifact) is fine since it's scoped to the # current run. -permissions: - "contents": "write" +permissions: {} # This task will run whenever you push a git tag that looks like a version # like "1.0.0", "v0.1.0-prerelease.1", "my-app/0.1.0", "releases/v1.0.0", etc. @@ -55,6 +54,8 @@ jobs: # Run 'dist plan' (or host) to determine what tasks we need to do plan: runs-on: "ubuntu-24.04" + permissions: + contents: read outputs: val: ${{ steps.plan.outputs.manifest }} tag: ${{ !github.event.pull_request && github.ref_name || '' }} @@ -114,6 +115,8 @@ jobs: # - N "local" tasks that build each platform's binaries and platform-specific installers matrix: ${{ fromJson(needs.plan.outputs.val).ci.github.artifacts_matrix }} runs-on: ${{ matrix.runner }} + permissions: + contents: read container: ${{ matrix.container && matrix.container.image || null }} env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -177,6 +180,8 @@ jobs: - plan - build-local-artifacts runs-on: "ubuntu-24.04" + permissions: + contents: read env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} BUILD_MANIFEST_NAME: target/distrib/global-dist-manifest.json @@ -228,6 +233,8 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} runs-on: "ubuntu-24.04" + permissions: + contents: write outputs: val: ${{ steps.host.outputs.manifest }} steps: @@ -302,6 +309,8 @@ jobs: runs-on: ubuntu-24.04 environment: release if: ${{ needs.plan.outputs.publishing == 'true' }} + permissions: + contents: read steps: - uses: actions/checkout@v6 - name: Publish to crates.io @@ -317,6 +326,7 @@ jobs: if: ${{ needs.plan.outputs.publishing == 'true' }} env: GH_TOKEN: ${{ secrets.WORKTRUNK_BOT_TOKEN }} + permissions: {} steps: - name: Sync winget-pkgs fork with upstream run: | @@ -340,6 +350,7 @@ jobs: GITHUB_USER: "worktrunk-bot" GITHUB_EMAIL: "worktrunk-bot@users.noreply.github.com" if: ${{ needs.plan.outputs.publishing == 'true' && (!fromJson(needs.plan.outputs.val).announcement_is_prerelease || fromJson(needs.plan.outputs.val).publish_prereleases) }} + permissions: {} steps: - uses: actions/checkout@v6 with: @@ -368,6 +379,8 @@ jobs: runs-on: ubuntu-24.04 environment: release if: ${{ needs.plan.outputs.publishing == 'true' }} + permissions: + contents: read steps: - uses: actions/checkout@v6 - name: Update PKGBUILD version @@ -402,6 +415,8 @@ jobs: runs-on: "ubuntu-24.04" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + permissions: + contents: read steps: - uses: actions/checkout@v6 with: diff --git a/.github/workflows/tend-ci-fix.yaml b/.github/workflows/tend-ci-fix.yaml index 8276bba8b9..46161dbc7e 100644 --- a/.github/workflows/tend-ci-fix.yaml +++ b/.github/workflows/tend-ci-fix.yaml @@ -13,6 +13,8 @@ on: types: [completed] branches: ["main"] +permissions: {} + jobs: fix-ci: if: github.event.workflow_run.conclusion == 'failure' diff --git a/.github/workflows/tend-mention.yaml b/.github/workflows/tend-mention.yaml index 580631fb95..40561d925e 100644 --- a/.github/workflows/tend-mention.yaml +++ b/.github/workflows/tend-mention.yaml @@ -30,6 +30,8 @@ on: pull_request_review_comment: types: [edited] +permissions: {} + jobs: verify: # Filter out fork PRs for review events — secrets are unavailable there diff --git a/.github/workflows/tend-nightly.yaml b/.github/workflows/tend-nightly.yaml index b56d445518..6cc244e002 100644 --- a/.github/workflows/tend-nightly.yaml +++ b/.github/workflows/tend-nightly.yaml @@ -12,6 +12,8 @@ on: - cron: "17 6 * * *" workflow_dispatch: +permissions: {} + jobs: nightly: runs-on: ubuntu-24.04 diff --git a/.github/workflows/tend-notifications.yaml b/.github/workflows/tend-notifications.yaml index 044a43ca05..8bad6e4c66 100644 --- a/.github/workflows/tend-notifications.yaml +++ b/.github/workflows/tend-notifications.yaml @@ -12,6 +12,8 @@ on: - cron: "*/15 * * * *" workflow_dispatch: +permissions: {} + jobs: notifications: runs-on: ubuntu-24.04 diff --git a/.github/workflows/tend-review-runs.yaml b/.github/workflows/tend-review-runs.yaml index 5bdd0af590..edf774fb84 100644 --- a/.github/workflows/tend-review-runs.yaml +++ b/.github/workflows/tend-review-runs.yaml @@ -12,6 +12,8 @@ on: - cron: "47 7 * * *" workflow_dispatch: +permissions: {} + jobs: review-runs: runs-on: ubuntu-24.04 diff --git a/.github/workflows/tend-review.yaml b/.github/workflows/tend-review.yaml index c0a877a23d..2559f6bc18 100644 --- a/.github/workflows/tend-review.yaml +++ b/.github/workflows/tend-review.yaml @@ -11,6 +11,8 @@ on: pull_request_target: types: [opened, synchronize, ready_for_review, reopened] +permissions: {} + jobs: review: if: >- @@ -26,12 +28,19 @@ jobs: actions: read issues: write steps: + - name: Skip privileged review on fork PRs + if: github.event.pull_request.head.repo.full_name != github.repository + run: >- + echo "::notice::Skipping tend-review for fork PR #${{ github.event.pull_request.number }} from + ${{ github.event.pull_request.head.repo.full_name }}. Privileged review automation only runs for same-repo pull requests." + # GitHub only materializes refs/pull/N/merge for mergeable PRs — on # conflicting PRs it 404s and every downstream step cascades as skipped. # Probe first and fall back to /head so review always runs; on fallback # the review sees the PR branch in isolation rather than the post-merge # tree. - name: Resolve PR checkout ref + if: github.event.pull_request.head.repo.full_name == github.repository id: pr_ref env: GH_TOKEN: ${{ secrets.WORKTRUNK_BOT_TOKEN }} @@ -44,6 +53,7 @@ jobs: echo "::notice::refs/pull/$PR/merge unavailable (likely merge conflict); falling back to /head" fi - uses: actions/checkout@v6 + if: github.event.pull_request.head.repo.full_name == github.repository with: ref: ${{ steps.pr_ref.outputs.ref }} fetch-depth: 0 @@ -51,8 +61,10 @@ jobs: token: ${{ secrets.WORKTRUNK_BOT_TOKEN }} - uses: ./.github/actions/claude-setup + if: github.event.pull_request.head.repo.full_name == github.repository - uses: max-sixty/tend@v1 + if: github.event.pull_request.head.repo.full_name == github.repository with: github_token: ${{ secrets.WORKTRUNK_BOT_TOKEN }} claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} diff --git a/.github/workflows/tend-triage.yaml b/.github/workflows/tend-triage.yaml index 9215b9c487..1e6e17d14e 100644 --- a/.github/workflows/tend-triage.yaml +++ b/.github/workflows/tend-triage.yaml @@ -15,6 +15,8 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.issue.number }} cancel-in-progress: true +permissions: {} + jobs: triage: runs-on: ubuntu-24.04 diff --git a/.github/workflows/tend-weekly.yaml b/.github/workflows/tend-weekly.yaml index 74702ca1cf..0486faf9a9 100644 --- a/.github/workflows/tend-weekly.yaml +++ b/.github/workflows/tend-weekly.yaml @@ -12,6 +12,8 @@ on: - cron: "17 9 * * 0" workflow_dispatch: +permissions: {} + jobs: weekly: runs-on: ubuntu-24.04