ci: add scheduled audit-docs-paths workflow (#27245)

## What

Adds `.github/workflows/audit-docs-paths.yaml`, a scheduled workflow
that runs the docs-URL drift audit (`site/scripts/audit-docs-paths.mjs`,
added in #25740) on a weekly cron and on demand, so drift is caught
automatically instead of only when someone runs the script by hand.
Scheduling was suggested by @bpmct on #25740.

## How it works

- **Triggers:** `schedule` (weekly, Monday 09:00 UTC — same cadence as
`weekly-docs`) and `workflow_dispatch`.
- **Checks out both repos:** `coder/coder` (root) and `coder/coder.com`
(into `coder.com/`, read with the `cdrci` CI-bot token). The audit
covers references in both repos.
- **Runs the audit** with absolute `--roots` (required, otherwise the
report can't classify findings by repo).
- **Always** uploads the dated report as the `audit-docs-paths-report`
artifact and writes it to the run summary.
- **On findings:** opens or updates a single deduplicated tracked issue
with the report, and fails the run (red check). **On a clean run:**
closes that issue.

## Enabling (dormant until then)

The audit reads **coder/coder.com, a private repo**, which the default
`GITHUB_TOKEN` can't read, so the coder.com checkout uses the existing
**`cdrci`** CI-bot token (`secrets.CDRCI_GITHUB_TOKEN`) — already used
for cross-repo checkouts in `release.yaml`/`tag-and-release.yaml`, and
`cdrci` is a coder.com collaborator (verified). No new App to stand up.
The job is gated behind `vars.AUDIT_DOCS_PATHS_ENABLED` so it merges
dormant and can be validated before going live.

To turn it on:
1. Set `vars.AUDIT_DOCS_PATHS_ENABLED = 'true'`.
2. Run once via `workflow_dispatch` to confirm the end-to-end run.

## Also in this PR

Removes the dormant `audit-docs-paths` job embedded in
`weekly-docs.yaml` (added in #25740, gated off pending the same
credential). The new dedicated workflow supersedes it; the
`weekly-docs.yaml` diff is exactly that job removal.

## Validation

- `actionlint -shellcheck= -ignore set-output` passes locally; PR
`title`, `lint-actions`, and `lint-docs` are green.
- **Credential check:** `cdrci` is a collaborator on coder/coder.com
(read access confirmed); `secrets.CDRCI_GITHUB_TOKEN` already exists in
this repo. (Note: `cdrci2` is *not* a coder.com collaborator, so an
earlier `CDRCI2_` attempt was corrected to `CDRCI_`.)
- **Pre-flight audit against current `main` (both repos): 0 findings** —
148 `/docs/*` redirect rules indexed; 1846 coder/coder + 432 coder.com
TS/TSX files scanned. So a `workflow_dispatch` on `main` today passes
green with no issue filed (the "empty audit succeeds" criterion). The
failure path can be checked by injecting a stale path on a throwaway
branch.

## Decisions for review

- **Mechanism** = tracked issue + failed check + artifact ("both" from
the issue). Easy to narrow to issue-only or fail-only.
- Reused `AUDIT_DOCS_PATHS_ENABLED` and removed the embedded job rather
than adding a second gate.
- Named the file `.yaml` to match the repo's other docs workflows (the
issue text said `.yml`).

Linear: https://linear.app/codercom/issue/DOCS-366
This commit is contained in:
Nick Vigilante
2026-08-10 13:40:44 -04:00
committed by GitHub
parent ad100452d4
commit 2f34e1abd0
2 changed files with 194 additions and 69 deletions
-69
View File
@@ -135,72 +135,3 @@ jobs:
echo "Sent Slack notification"
env:
LOGS_URL: https://github.com/coder/coder/actions/runs/${{ github.run_id }}
audit-docs-paths:
# Disabled by default: this audit fetches a config file from a private
# upstream source and the workflow currently lacks the credentials to
# read it. Pending provisioning of a dedicated GitHub App with the
# required cross-repo Contents: Read. To re-enable once the App
# credentials are in place, set the repository variable
# AUDIT_DOCS_PATHS_ENABLED to 'true'.
if: vars.AUDIT_DOCS_PATHS_ENABLED == 'true'
runs-on: ubuntu-22.04
permissions:
contents: read
steps:
- name: Harden Runner
uses: step-security/harden-runner@bf7454d06d71f1098171f2acdf0cd4708d7b5920 # v2.20.0
with:
egress-policy: audit
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Check for audit script
id: check-script
run: |
if [ ! -f site/scripts/audit-docs-paths.mjs ]; then
echo "::notice::Audit script not yet available (pending PR #25740). Skipping."
echo "skip=true" >> "$GITHUB_OUTPUT"
fi
- name: Set up mise tools
if: steps.check-script.outputs.skip != 'true'
uses: ./.github/actions/setup-mise
with:
install-args: "node"
- name: Fetch redirects.json
if: steps.check-script.outputs.skip != 'true'
run: |
curl -sfL \
https://raw.githubusercontent.com/coder/coder.com/refs/heads/main/redirects.json \
-o /tmp/redirects.json
- name: Audit TS/TSX docs paths against redirects
if: steps.check-script.outputs.skip != 'true'
run: |
node site/scripts/audit-docs-paths.mjs \
--redirects=/tmp/redirects.json \
--roots=site/src \
--out=/tmp/audit-report.md 2>&1 | tee /tmp/audit-output.txt
count=$(grep -oP 'Total findings: \K\d+' /tmp/audit-output.txt || echo "0")
if [ "$count" -gt 0 ]; then
echo "::error::Found $count stale docs path(s) pointing at redirect sources"
cat /tmp/audit-report.md >> "$GITHUB_STEP_SUMMARY"
exit 1
fi
- name: Send Slack notification
if: failure() && github.event_name != 'pull_request'
run: |
curl \
-X POST \
-H 'Content-type: application/json' \
-d '{"text":":warning: *Stale docs paths found in site/src/.*\nTS/TSX files reference docs URLs that now redirect. Please check the logs: '"${LOGS_URL}"'"}' "${{ secrets.DOCS_LINK_SLACK_WEBHOOK }}"
echo "Sent Slack notification"
env:
LOGS_URL: https://github.com/coder/coder/actions/runs/${{ github.run_id }}