Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 0 additions & 18 deletions .github/vale-problem-matcher.json

This file was deleted.

58 changes: 42 additions & 16 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -162,15 +162,19 @@ jobs:
- name: Check docs
run: pnpm check-docs

# Vale prose linter, advisory only. Scoped to changed Markdown under
# docs/. Every Vale step is `continue-on-error` so this section can
# never block the required `lint-docs` job: a `vale sync` network
# blip or a baseline rule violation surfaces as an annotation, not a
# merge gate. Only markdownlint/table-formatter above stay blocking.
# `vale --no-exit` additionally keeps the baseline error count from
# un-overridden upstream Google rules from failing the step. Lives
# here rather than a standalone workflow so docs lint stays in the
# single required CI umbrella (see #25608). See DOCS-40.
# Vale prose linter. Scoped to changed Markdown under docs/. The
# surrounding setup steps (cache restore, sync, cache save) stay
# `continue-on-error` so cache or network flakes never block merge;
# only the prose lint step itself is allowed to fail the job.
# Severity model: error-level Vale findings exit non-zero and fail
# the step, which fails the required `lint-docs` job and blocks
# merge. Warning- and suggestion-level findings render as PR
# annotations but do not affect the exit code. This matches Vale's
# native exit semantics (only errors trigger non-zero exit) and the
# repo's style-guide doctrine that any rule we enable ships with
# zero baseline noise. Lives here rather than a standalone workflow
# so docs lint stays in the single required CI umbrella (see
# #25608). See DOCS-40, DOCS-425, DOCS-426.
- name: Detect changed Markdown
id: changed-md
continue-on-error: true
Expand Down Expand Up @@ -216,16 +220,18 @@ jobs:

- name: Vale prose lint
if: steps.changed-md.outputs.any_changed == 'true'
continue-on-error: true
env:
ALL_CHANGED_FILES: ${{ steps.changed-md.outputs.all_changed_files }}
# Non-interactive: let mise auto-install the pinned Vale on first use.
MISE_YES: "1"
run: |
# pipefail propagates Vale's exit code through the jq pipe so
# an error-level finding fails the step. Without it, jq's
# success would mask Vale's non-zero exit.
set -o pipefail
# all_changed_files is ACMRD and so lists paths this PR deleted.
# Vale errors on a missing file (--no-exit only suppresses alert
# exits, not runtime errors), so keep only docs/ paths still on
# disk. See DOCS-40.
# Vale errors on a missing file, so keep only docs/ paths still
# on disk. See DOCS-40.
files=$(printf '%s\n' "$ALL_CHANGED_FILES" \
| tr ',' '\n' \
| grep -E '^docs/' \
Expand All @@ -234,9 +240,29 @@ jobs:
echo "No changed Markdown files under docs/ on disk; skipping Vale."
exit 0
fi
echo "::add-matcher::.github/vale-problem-matcher.json"
printf '%s\n' "$files" | xargs -d '\n' mise exec "aqua:errata-ai/vale" -- vale --no-exit --output=line
echo "::remove-matcher owner=vale::"
# Vale's --output=line strips per-finding severity, so the
# previous problem-matcher approach collapsed every finding to
# a single hard-coded severity. Use --output=JSON instead and
# emit GitHub workflow commands directly so error/warning/
# suggestion render with their actual Vale severities. URL-
# encode message bodies for `%`, `\r`, and `\n` per the
# GitHub Actions workflow command spec. See DOCS-426.
# Vale exits non-zero only on error-level alerts (warnings and
# suggestions never trigger non-zero exit), so dropping
# --no-exit lets error-level findings fail the step while
# leaving lower-severity findings advisory. See DOCS-425.
printf '%s\n' "$files" \
| xargs -d '\n' mise exec "aqua:errata-ai/vale" -- vale --output=JSON \
| jq -r '
to_entries[]
| .key as $file
| .value[]
| (if .Severity == "suggestion" then "notice"
elif .Severity == "warning" then "warning"
else "error" end) as $level
| (.Message | gsub("%"; "%25") | gsub("\r"; "%0D") | gsub("\n"; "%0A")) as $msg
| "::\($level) file=\($file),line=\(.Line),col=\(.Span[0]),title=\(.Check)::\($msg)"
'

- name: Save Vale styles
# Only the default branch is trusted to write the cache, so PR
Expand Down
25 changes: 25 additions & 0 deletions docs/.style/_vale-annotation-demo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Vale annotation rendering demo

> [!NOTE]
> This page exists only to verify how GitHub renders Vale annotations
> at each severity level.
> The three `Coder.Demo*` rules under
> [`docs/.style/styles/Coder/`](styles/Coder/) fire on the marker
> strings below.
> This page and its rules disappear in a follow-up commit on the same
> PR once the rendering check completes; see DOCS-426.

## Markers

Each marker fires exactly one Vale annotation when this page lints:

- Suggestion (rendered as GitHub `notice`):
vale-demo-suggestion-marker.

Check notice on line 17 in docs/.style/_vale-annotation-demo.md

View workflow job for this annotation

GitHub Actions / lint-docs

Coder.DemoSuggestion

[Demo] Suggestion-level Vale annotation.
- Warning (rendered as GitHub `warning`):
vale-demo-warning-marker.

Check warning on line 19 in docs/.style/_vale-annotation-demo.md

View workflow job for this annotation

GitHub Actions / lint-docs

Coder.DemoWarning

[Demo] Warning-level Vale annotation.
- Error (rendered as GitHub `error`):
vale-demo-error-marker.

Check failure on line 21 in docs/.style/_vale-annotation-demo.md

View workflow job for this annotation

GitHub Actions / lint-docs

Coder.DemoError

[Demo] Error-level Vale annotation.

The rules use Vale's `existence` extension type and target a single
literal token each, so each marker produces a single annotation at its
exact location.
11 changes: 11 additions & 0 deletions docs/.style/styles/Coder/DemoError.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# DemoError - canary rule used to verify how GitHub renders error-level
# Vale annotations in PR diffs. Fires on the literal phrase
# `vale-demo-error-marker`, which appears only in
# docs/.style/_vale-annotation-demo.md. Demo rules drop in a follow-up
# commit before the parent PR merges; see DOCS-426.
extends: existence
message: "[Demo] Error-level Vale annotation."
link: https://github.com/coder/coder/blob/main/docs/.style/_vale-annotation-demo.md
level: error
tokens:
- vale-demo-error-marker
11 changes: 11 additions & 0 deletions docs/.style/styles/Coder/DemoSuggestion.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# DemoSuggestion - canary rule used to verify how GitHub renders
# suggestion-level Vale annotations in PR diffs. Fires on the literal
# phrase `vale-demo-suggestion-marker`, which appears only in
# docs/.style/_vale-annotation-demo.md. Demo rules drop in a follow-up
# commit before the parent PR merges; see DOCS-426.
extends: existence
message: "[Demo] Suggestion-level Vale annotation."
link: https://github.com/coder/coder/blob/main/docs/.style/_vale-annotation-demo.md
level: suggestion
tokens:
- vale-demo-suggestion-marker
11 changes: 11 additions & 0 deletions docs/.style/styles/Coder/DemoWarning.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# DemoWarning - canary rule used to verify how GitHub renders
# warning-level Vale annotations in PR diffs. Fires on the literal phrase
# `vale-demo-warning-marker`, which appears only in
# docs/.style/_vale-annotation-demo.md. Demo rules drop in a follow-up
# commit before the parent PR merges; see DOCS-426.
extends: existence
message: "[Demo] Warning-level Vale annotation."
link: https://github.com/coder/coder/blob/main/docs/.style/_vale-annotation-demo.md
level: warning
tokens:
- vale-demo-warning-marker
Loading