diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 612d3a40..5562f82b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,7 +28,10 @@ jobs: # Pushes and dispatches verify everything. A pull request whose every path # is docs skips verify; unlisted paths count as code. `verify` also checks # Markdown; `markdown` covers pull requests that change Markdown, including - # the docs-only ones that skip verify. + # the docs-only ones that skip verify. This job runs on every event, so it + # also checks Markdown links and scans each pushed range. A link or scan + # failure fails this job without skipping the jobs below, which use + # `!cancelled()`. outputs: code: ${{ github.event_name != 'pull_request' || steps.filter.outputs.code == 'true' }} markdown: ${{ github.event_name == 'pull_request' && steps.filter.outputs.markdown == 'true' }} @@ -49,10 +52,22 @@ jobs: markdown: - '**/*.md' + - name: Check out repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Check Markdown links + uses: putdotio/.github/.github/actions/links@c1830f7938b7dc98f085082e988d3c46437bb15c # v1.2.0 + + - name: Scan secrets and workflows + if: ${{ !cancelled() }} + uses: putdotio/.github/.github/actions/scan@c1830f7938b7dc98f085082e988d3c46437bb15c # v1.2.0 + markdown: name: Check Markdown needs: changes - if: needs.changes.outputs.markdown == 'true' + if: ${{ !cancelled() && needs.changes.outputs.markdown == 'true' }} runs-on: ubuntu-24.04 timeout-minutes: 10 @@ -82,7 +97,7 @@ jobs: release: name: Build release needs: changes - if: needs.changes.outputs.code == 'true' + if: ${{ !cancelled() && needs.changes.outputs.code == 'true' }} runs-on: ubuntu-24.04 timeout-minutes: 40 @@ -113,7 +128,7 @@ jobs: verify: name: Verify Android app needs: changes - if: needs.changes.outputs.code == 'true' + if: ${{ !cancelled() && needs.changes.outputs.code == 'true' }} runs-on: ubuntu-24.04 timeout-minutes: 40 diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml deleted file mode 100644 index 8ce2a453..00000000 --- a/.github/workflows/links.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Links - -on: - pull_request: - push: - branches: - - main - -permissions: {} - -# Same policy as CI: a new pull-request push cancels the stale run; every main -# commit keeps its own verdict. -concurrency: - group: links-${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }} - cancel-in-progress: ${{ github.event_name == 'pull_request' }} - -jobs: - links: - permissions: - contents: read - uses: putdotio/.github/.github/workflows/frontend-links.yml@1ee0d3b473cbc6fada08831f01ff80fe653c434a # v1.1.0 diff --git a/.github/workflows/scan.yml b/.github/workflows/scan.yml deleted file mode 100644 index 486e0b22..00000000 --- a/.github/workflows/scan.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Scan - -on: - pull_request: - schedule: - - cron: "41 6 * * 1" - workflow_dispatch: - -permissions: {} - -concurrency: - group: scan-${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - scan: - permissions: - contents: read - uses: putdotio/.github/.github/workflows/frontend-scan.yml@1ee0d3b473cbc6fada08831f01ff80fe653c434a # v1.1.0 diff --git a/AGENTS.md b/AGENTS.md index 76b7b742..d3072d9f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -138,8 +138,7 @@ names the tests that pin it; a new device lane gets a section in ## Delivery and CI Open pull requests against `main`; the repository squash-merges. A push to -`main` runs [CI](.github/workflows/ci.yml) and -[Links](.github/workflows/links.yml) and nothing else: `verify` compiles +`main` runs [CI](.github/workflows/ci.yml) and nothing else: `verify` compiles the release variants unsigned, and nothing signs, publishes, or uploads to Play. CI runs `./gradlew verify` plus all four debug assembles on every `main` push and on pull requests that change more than @@ -150,8 +149,8 @@ runs `verify` with them excluded plus the debug assembles. When either command changes, compare their `--dry-run` task lists with the full command's; together they must run exactly the same tasks. A pull request that changes Markdown also runs `Check Markdown` (`./gradlew markdownCheck`), so docs-only changes still -get the formatting check. Links checks relative Markdown links and anchors on -every pull request. CI holds no secrets and keeps +get the formatting check. `Detect code changes` runs on every event and +checks relative Markdown links and anchors offline. CI holds no secrets and keeps failed unit-test XML as the `failed-unit-test-reports` artifact. A new push to a pull request cancels its running check; `main` runs never replace each other. @@ -160,9 +159,10 @@ and `StaleOAuthCallbackTest` on a Gradle Managed Device weekly and on dispatch. It is not a pull-request gate because shared-runner emulator boots are too slow and flaky; `scripts/prove.sh` stays the local proof. -[Scan](.github/workflows/scan.yml) runs the shared put.io scan weekly and on -every pull request: Gitleaks and TruffleHog look for secrets, and Actionlint -and Zizmor audit `.github/` when a pull request changes it. +`Detect code changes` also runs the shared put.io scan on each `main` push: +Actionlint and Zizmor audit `.github/` when the pushed range changes it, and a +manual dispatch of CI audits every workflow. GitHub secret scanning and push +protection catch secrets at push time. To reproduce a CI failure, check out the app SHA from the run summary in a detached worktree with `sdk.dir` set and `putioSdkKotlinPath` unset, then run