ci: require docs lint when docs change (#25608)

Move docs linting into the required CI umbrella and reuse the existing
`changes` job so docs lint runs when docs or CI files change, plus on
`main` as a backstop.

This is motivated by the docs lint failures on #25601. That PR touched
`.claude/docs/TESTING.md`; the standalone `Docs CI` workflow picked it
up because `docs-ci.yaml` used broad `**.md` matching, but local `pnpm
lint-docs` and `make lint` did not catch the same file because they only
scanned `docs/**` plus root `*.md`. The first failed Docs CI run
reported markdownlint errors in `.claude/docs/TESTING.md` (`MD040` and
`MD031`), and the next run reported a markdown table formatter failure
in the same file.

That mismatch is why this PR exists: prevent unrelated PRs from being
surprised by stale `.claude/docs/**` lint drift only after they happen
to touch one of those files. The local docs scripts now include
`.claude/docs/**`, and the old standalone `Docs CI` workflow is removed
so we do not maintain separate path-filter logic outside the required CI
workflow.

> Generated by mux, but reviewed by a human
This commit is contained in:
Ethan
2026-05-27 12:30:05 +10:00
committed by GitHub
parent 20b50dd4b8
commit e99f7171e4
6 changed files with 115 additions and 160 deletions
+2 -2
View File
@@ -9,7 +9,7 @@ not add new readiness or debug endpoints for these workflows.
`scripts/develop/main.go` defines these base defaults:
| Resource | Base default | Override |
|----------|--------------|----------|
|--------------------------|--------------|--------------------------------------------------|
| API server | `3000` | `--port`, `CODER_DEV_PORT` |
| Frontend dev server | `8080` | `--web-port`, `CODER_DEV_WEB_PORT` |
| Workspace proxy | `3010` | `--proxy-port`, `CODER_DEV_PROXY_PORT` |
@@ -38,7 +38,7 @@ The develop script also supports these existing flags and environment
variables:
| Purpose | Flag | Environment variable |
|---------|------|----------------------|
|-----------------------------------|----------------------|------------------------------|
| Per-worktree port offset | `--port-offset` | `CODER_DEV_PORT_OFFSET` |
| Access URL | `--access-url` | `CODER_DEV_ACCESS_URL` |
| Admin password | `--password` | `CODER_DEV_ADMIN_PASSWORD` |
+2 -2
View File
@@ -93,7 +93,7 @@ right column instead. The "Since" column tells you the minimum `go`
directive version required in `go.mod`.
| Old pattern | Modern replacement | Since |
|---|---|---|
|---------------------------------------------------------------------|-------------------------------------------------------------------------|-----------|
| `interface{}` | `any` | 1.18 |
| `v := v` inside loops | remove it | 1.22 |
| `for i := 0; i < n; i++` | `for i := range n` | 1.22 |
@@ -139,7 +139,7 @@ These enable things that weren't practical before. Reach for them in the
described situations.
| What | Since | When to use it |
|---|---|---|
|--------------------------------------------------|-------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `cmp.Or(a, b, c)` | 1.22 | Defaults/fallback chains: returns first non-zero value. Replaces verbose `if a != "" { return a }` cascades. |
| `context.WithoutCancel(ctx)` | 1.21 | Background work that must outlive the request (e.g. async cleanup after HTTP response). Derived context keeps parent's values but ignores cancellation. |
| `context.AfterFunc(ctx, fn)` | 1.21 | Register cleanup that fires on context cancellation without spawning a goroutine that blocks on `<-ctx.Done()`. |
+12 -12
View File
@@ -23,48 +23,48 @@
### Testing Issues
3. **"package should be X_test"**
1. **"package should be X_test"**
- **Solution**: Use `package_test` naming for test files
- Example: `identityprovider_test` for black-box testing
4. **Race conditions in tests**
2. **Race conditions in tests**
- **Solution**: Use unique identifiers instead of hardcoded names
- Example: `fmt.Sprintf("test-client-%s-%d", t.Name(), time.Now().UnixNano())`
- Never use hardcoded names in concurrent tests
5. **Missing newlines**
3. **Missing newlines**
- **Solution**: Ensure files end with newline character
- Most editors can be configured to add this automatically
### OAuth2 Issues
6. **OAuth2 endpoints returning wrong error format**
1. **OAuth2 endpoints returning wrong error format**
- **Solution**: Ensure OAuth2 endpoints return RFC 6749 compliant errors
- Use standard error codes: `invalid_client`, `invalid_grant`, `invalid_request`
- Format: `{"error": "code", "error_description": "details"}`
7. **Resource indicator validation failing**
2. **Resource indicator validation failing**
- **Solution**: Ensure database stores and retrieves resource parameters correctly
- Check both authorization code storage and token exchange handling
8. **PKCE tests failing**
3. **PKCE tests failing**
- **Solution**: Verify both authorization code storage and token exchange handle PKCE fields
- Check `CodeChallenge` and `CodeChallengeMethod` field handling
### RFC Compliance Issues
9. **RFC compliance failures**
1. **RFC compliance failures**
- **Solution**: Verify against actual RFC specifications, not assumptions
- Use WebFetch tool to get current RFC content for compliance verification
- Read the actual RFC specifications before implementation
10. **Default value mismatches**
2. **Default value mismatches**
- **Solution**: Ensure database migrations match application code defaults
- Example: RFC 7591 specifies `client_secret_basic` as default, not `client_secret_post`
### Authorization Issues
11. **Authorization context errors in public endpoints**
1. **Authorization context errors in public endpoints**
- **Solution**: Use `dbauthz.AsSystemRestricted(ctx)` pattern
- Example:
@@ -75,17 +75,17 @@
### Authentication Issues
12. **Bearer token authentication issues**
1. **Bearer token authentication issues**
- **Solution**: Check token extraction precedence and format validation
- Ensure proper RFC 6750 Bearer Token Support implementation
13. **URI validation failures**
2. **URI validation failures**
- **Solution**: Support both standard schemes and custom schemes per protocol requirements
- Native OAuth2 apps may use custom schemes
### General Development Issues
14. **Log message formatting errors**
1. **Log message formatting errors**
- **Solution**: Use lowercase, descriptive messages without special characters
- Follow Go logging conventions
+26 -1
View File
@@ -53,7 +53,8 @@ jobs:
- "**"
docs:
- "docs/**"
- "README.md"
- ".claude/docs/**"
- "*.md"
- "examples/web-server/**"
- "examples/monitoring/**"
- "examples/lima/**"
@@ -120,6 +121,28 @@ jobs:
env:
FILTER_JSON: ${{ toJSON(steps.filter.outputs) }}
lint-docs:
needs: changes
if: needs.changes.outputs.docs == 'true' || needs.changes.outputs.ci == 'true' || github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- name: Harden Runner
uses: step-security/harden-runner@f808768d1510423e83855289c910610ca9b43176 # v2.17.0
with:
egress-policy: audit
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 1
persist-credentials: false
- name: Setup Node
uses: ./.github/actions/setup-node
- name: Check docs
run: pnpm check-docs
# Disabled due to instability. See: https://github.com/coder/coder/issues/14553
# Re-enable once the flake hash calculation is stable.
# update-flake:
@@ -1132,6 +1155,7 @@ jobs:
- changes
- fmt
- lint
- lint-docs
- lint-actions
- gen
- test-go-pg
@@ -1157,6 +1181,7 @@ jobs:
echo "- changes: ${{ needs.changes.result }}"
echo "- fmt: ${{ needs.fmt.result }}"
echo "- lint: ${{ needs.lint.result }}"
echo "- lint-docs: ${{ needs.lint-docs.result }}"
echo "- lint-actions: ${{ needs.lint-actions.result }}"
echo "- gen: ${{ needs.gen.result }}"
echo "- test-go-pg: ${{ needs.test-go-pg.result }}"
-71
View File
@@ -1,71 +0,0 @@
name: Docs CI
on:
push:
branches:
- main
# Self-reference removed from both push and pull_request: the `lint`
# and `fmt` steps gate on `tj-actions/changed-files` matching
# `docs/**` or `**.md`, so a workflow-only edit produced an empty
# run. `actionlint` and `make lint/actions` catch YAML problems
# before merge regardless. See DOCS-129.
paths:
- "docs/**"
- "**.md"
pull_request:
# Self-reference removed; see comment under `push:` above.
paths:
- "docs/**"
- "**.md"
permissions:
contents: read
jobs:
docs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- name: Setup Node
uses: ./.github/actions/setup-node
# Per-tool changed-files filters. Each tool gets its own `changed-*`
# step scoped to the files it processes, keeping workflow-level `paths:`
# broad. Adding a tool (e.g. image linter) only needs a new step pair.
- uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # v45.0.7
id: changed-md
with:
files: |
**.md
separator: ","
# Both downstream tools take file paths as argv. `tj-actions/changed-files`
# joins paths with `separator: ","`, which the shell does not split on, so
# run the output through `tr ',' '\n' | xargs -d '\n'` to hand each path to
# the tool as a distinct argument. This tolerates filenames containing
# spaces and prevents silent fallbacks: `markdownlint-cli2` would treat a
# comma-joined string as a single non-matching glob, and
# `markdown-table-formatter` would fall back to scanning every `.md` in
# the working tree when invoked with no positional args.
#
# `printf '%s\n'` is used instead of `echo` so a hypothetical leading
# `-e` or `-n` in a path is treated as data, not a bash builtin flag.
- name: lint
if: steps.changed-md.outputs.any_changed == 'true'
run: |
printf '%s\n' "$ALL_CHANGED_FILES" | tr ',' '\n' | xargs -d '\n' pnpm exec markdownlint-cli2
env:
ALL_CHANGED_FILES: ${{ steps.changed-md.outputs.all_changed_files }}
- name: fmt
if: steps.changed-md.outputs.any_changed == 'true'
run: |
printf '%s\n' "$ALL_CHANGED_FILES" | tr ',' '\n' | xargs -d '\n' pnpm exec markdown-table-formatter --check
env:
ALL_CHANGED_FILES: ${{ steps.changed-md.outputs.all_changed_files }}
+3 -2
View File
@@ -4,8 +4,9 @@
"version": "0.0.0",
"packageManager": "pnpm@10.33.2+sha512.a90faf6feeab71ad6c6e57f94e0fe1a12f5dcc22cd754db40ae9593eb6a3e0b6b12e3540218bb37ae083404b1f2ce6db2a4121e979829b4aff94b99f49da1cf8",
"scripts": {
"format-docs": "markdown-table-formatter $(find docs -name '*.md') *.md",
"lint-docs": "markdownlint-cli2 --fix $(find docs -name '*.md') *.md",
"format-docs": "markdown-table-formatter $(find docs .claude/docs examples/web-server examples/monitoring examples/lima -name '*.md' 2>/dev/null) *.md",
"lint-docs": "markdownlint-cli2 --fix $(find docs .claude/docs examples/web-server examples/monitoring examples/lima -name '*.md' 2>/dev/null) *.md",
"check-docs": "markdownlint-cli2 $(find docs .claude/docs examples/web-server examples/monitoring examples/lima -name '*.md' 2>/dev/null) *.md && markdown-table-formatter --check $(find docs .claude/docs examples/web-server examples/monitoring examples/lima -name '*.md' 2>/dev/null) *.md",
"storybook": "pnpm run -C site/ storybook"
},
"devDependencies": {