Skip to content
Open
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
67 changes: 67 additions & 0 deletions .github/workflows/vale-comment.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Vale Comments

# Posts Vale results from vale.yml as PR review comments, including for fork PRs.

on:
workflow_run:
workflows: ['Vale Linting']
types: [completed]

permissions:
actions: read
contents: read
pull-requests: write

jobs:
comment:
if: github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
steps:
# SECURITY: This workflow has write permissions, so never add a step that checks out or runs code from the PR.

- name: Download results
uses: actions/download-artifact@v8
with:
name: vale-results
path: vale-results
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ github.token }}

- name: Validate PR number
id: pr
run: |
PR_NUMBER=$(head -n 1 vale-results/pr-number)
# The artifact is untrusted: accept only a plain integer
if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
echo "Invalid PR number"
exit 1
fi
# Confirm the PR's head commit is the commit that was linted
PR_SHA=$(gh api "repos/${{ github.repository }}/pulls/$PR_NUMBER" --jq '.head.sha')
if [ "$PR_SHA" != "${{ github.event.workflow_run.head_sha }}" ]; then
echo "PR head ($PR_SHA) differs from linted commit; skipping stale results"
echo "skip=true" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "number=$PR_NUMBER" >> "$GITHUB_OUTPUT"
if [ -s vale-results/results.rdjsonl ]; then echo "has_results=true" >> "$GITHUB_OUTPUT"; fi
env:
GH_TOKEN: ${{ github.token }}

- name: Set up reviewdog
if: steps.pr.outputs.has_results == 'true'
# Pin to a commit (v1.5.0) because this job has write permissions
uses: reviewdog/action-setup@d8a7baabd7f3e8544ee4dbde3ee41d0011c3a93f

- name: Post review comments
if: steps.pr.outputs.has_results == 'true'
run: |
# reviewdog needs a git repo; filter-mode=added comments only on lines the PR changed
git init -q
env -u GITHUB_ACTIONS reviewdog -f=rdjsonl -name=vale -reporter=github-pr-review -filter-mode=added -fail-on-error=false -level=info < vale-results/results.rdjsonl
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ github.token }}
CI_PULL_REQUEST: ${{ steps.pr.outputs.number }}
CI_COMMIT: ${{ github.event.workflow_run.head_sha }}
CI_REPO_OWNER: ${{ github.repository_owner }}
CI_REPO_NAME: ${{ github.event.repository.name }}
51 changes: 35 additions & 16 deletions .github/workflows/vale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,20 @@ on:
paths:
- 'content/en/docs/**/*.md'

# Allow reading repo contents and posting PR comments
# Note: Fork PRs from org members run automatically but get read-only tokens,
# so reviewdog falls back to check annotations instead of review comments.
# External contributors require workflow approval per repo settings.
# Fork PRs don't have write permissions, so posting review comments happens in vale-comment.yml after this workflow finishes.
# This workflow only runs Vale and uploads the results as an artifact.

permissions:
contents: read
pull-requests: write
pull-requests: read

jobs:
vale:
# Only run on Mendix repo, not forks, and not on draft PRs
if: github.repository_owner == 'mendix' && github.event.pull_request.draft == false
runs-on: ubuntu-latest
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
VALE_VERSION: 3.26.0
# Cancel old runs when new commits are pushed
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
Expand All @@ -39,18 +38,38 @@ jobs:
- name: Get changed files
id: changed-files
run: |
FILES=$(gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files --paginate --jq '.[] | select(.status != "removed") | .filename' | { grep '^content/en/docs/.*\.md$' || true; } | paste -sd, -)
echo "files=$FILES" >> $GITHUB_OUTPUT
# Also writes the PR number and an empty results file for vale-comment.yml
mkdir -p vale-results
echo "${{ github.event.pull_request.number }}" > vale-results/pr-number
gh api repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files --paginate --jq '.[] | select(.status != "removed") | .filename' | { grep '^content/en/docs/.*\.md$' || true; } > changed-files.txt
: > vale-results/results.rdjsonl
if [ -s changed-files.txt ]; then echo "has_files=true" >> "$GITHUB_OUTPUT"; fi
env:
GH_TOKEN: ${{ github.token }}

- name: Install Vale
if: steps.changed-files.outputs.has_files == 'true'
run: |
cd "$RUNNER_TEMP"
ARCHIVE="vale_${VALE_VERSION}_Linux_64-bit.tar.gz"
BASE_URL="https://github.com/vale-cli/vale/releases/download/v${VALE_VERSION}"
curl -sSfLO "$BASE_URL/$ARCHIVE"
mkdir bin && tar -xzf "$ARCHIVE" -C bin vale
echo "$PWD/bin" >> "$GITHUB_PATH"
cd "$GITHUB_WORKSPACE" && "$RUNNER_TEMP/bin/vale" sync

- name: Run Vale
if: steps.changed-files.outputs.files != ''
uses: vale-cli/vale-action@v2
run: |
if [ -s changed-files.txt ]; then
# Only flag errors, not warnings or suggestions. Vale exits non-zero on errors; that is expected.
xargs -d '\n' vale --output=JSON --minAlertLevel=error < changed-files.txt > vale.json || true
# Convert Vale JSON to reviewdog's rdjsonl format
jq -c 'to_entries[] | .key as $f | .value[] | {message: ("[" + .Check + "] " + .Message), location: {path: $f, range: {start: {line: .Line, column: .Span[0]}}}, severity: (.Severity | ascii_upcase)}' vale.json > vale-results/results.rdjsonl
fi

- name: Upload results
uses: actions/upload-artifact@v7
with:
files: ${{ steps.changed-files.outputs.files }}
separator: ','
version: 3.14.2
fail_on_error: false
reporter: github-pr-review # Uses filter_mode=added (default): only comment on modified lines
vale_flags: '--minAlertLevel=error' # Only flag errors, not warnings or suggestions
name: vale-results
path: vale-results/
retention-days: 3
10 changes: 5 additions & 5 deletions .vale.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ MinAlertLevel = suggestion

# Packages to sync from vale.sh
# Microsoft = Microsoft Writing Style Guide
Packages = Microsoft
# To update pinned version, change the version in the URL, run `vale sync`, and check the Mendix rules that extend Microsoft rules
Packages = https://github.com/errata-ai/Microsoft/releases/download/v0.15.1/Microsoft.zip

# Ignore patterns
[*.{md,mdx}]
Expand All @@ -26,8 +27,8 @@ BasedOnStyles = Microsoft, Mendix
# requirements documented in content/en/docs/community-tools/contribute-to-mendix-docs/style-guide/

# Acronyms
# Extended by Mendix.Acronyms
# Microsoft requires title case for acronym definitions; Mendix allows sentence case too
# Replacement: Mendix.Acronyms accepts sentence-case definitions
Microsoft.Acronyms = NO

# Auto
Expand All @@ -47,7 +48,7 @@ Microsoft.Contractions = NO
# Microsoft removes all spaces around em/en dashes; Mendix has context-specific rules
# Mendix style guide: Em dashes (—) have no spaces; en dashes (–) have spaces except in number ranges
# Replacement: Mendix.Dashes removes spaces around em dashes
# Mendix.ListIntroductions enforces en dashes (not em dashes or spaced hyphens) for list item introductions
# Mendix.ListIntroductions enforces en dashes (not em dashes or spaced hyphens) for list item introductions
Microsoft.Dashes = NO

# Foreign
Expand Down Expand Up @@ -103,8 +104,7 @@ Microsoft.UIVerbs = NO
Microsoft.Vocab = NO

# Wordiness
# Replaced some of the substitutions
# Replacement: Mendix.Wordiness
# Extended by Mendix.Wordiness
Microsoft.Wordiness = NO

# ============================================================================
Expand Down
4 changes: 4 additions & 0 deletions .vale/SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ After installing Vale:
vale --version
```

Vale 3.20 or later is required. If you have an older version, update it:
* On macOS, run `brew upgrade vale`
* On Windows, download the latest version from [the releases page](https://github.com/vale-cli/vale/releases) and replace `vale.exe`

2. **Sync the Microsoft Style Guide rules:**

Navigate to the root of your docs repository (for example, `cd ~/docs`), then run:
Expand Down
70 changes: 5 additions & 65 deletions .vale/styles/Mendix/Acronyms.yml
Original file line number Diff line number Diff line change
@@ -1,87 +1,27 @@
extends: conditional
# Extends Microsoft.Acronyms (requires Vale 3.20 or later).
# Ensures that the existence of 'first' implies the existence of 'second'.
extends: Microsoft.Acronyms
message: "Define '%s' on first use."
link: https://docs.mendix.com/community-tools/contribute-to-mendix-docs/style-guide/grammar-formatting/#acronyms-and-initialisms
level: suggestion
ignorecase: false
scope:
- paragraph
- heading
- list
- table
- blockquote
# Ensures that the existence of 'first' implies the existence of 'second'.
# Known issue: Doesn't recognize hyperlinks for acronym definitions
# Known issue: Doesn't recognize CLOB (Character Large Object) always expects definition first—"Character Large Object (CLOB)" even if acronym is more common than definition
# Modified from Microsoft.Acronyms to accept sentence-case definitions (e.g., "personal access token (PAT)" not just "Personal Access Token (PAT)")
first: '\b([A-Z]{3,5})\b'
second: '(?:\b[A-Za-z][a-z]+ )+\(([A-Z]{3,5})\)'
# ... with the exception of these:
exceptions:
- API
- ASP
# ... with the exception of these (and the Microsoft.Acronyms exceptions):
exceptions+:
- BTP
- CLI
- CPU
- CSS
- CSV
- DEBUG
- DOM
- DPI
- FAQ
- GCC
- GDB
- GET
- GIF
- GPU
- GTK
- GUI
- HANA
- HTML
- HTTP
- HTTPS
- IDE
- JAR
- JDBC
- JPEG
- JPG
- JSON
- JSX
- LESS
- LLDB
- LTS
- MCP
- MDA
- MPR
- MTS
- NET
- NOTE
- NVDA
- OSS
- PATH
- PDF
- PHP
- PNG
- POST
- RAM
- REPL
- REST
- RSA
- SAP
- SCM
- SCSS
- SDK
- SQL
- SSH
- SSL
- SVG
- TBD
- TCP
- TODO
- URI
- URL
- USB
- UTF
- XML
- XSS
- YAML
- ZIP
1 change: 0 additions & 1 deletion .vale/styles/Mendix/Dashes.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Reference: content/en/docs/community-tools/contribute-to-mendix-docs/style-guide/grammar-formatting.md (Dashes)
# Known issue: False positive around links, code snippets. Also check Bold and Italics to see if they are also problematic.
extends: substitution
message: "Remove spaces around the em dash (—). Or, to set off a list item intro or number range, use an en dash (–) instead."
link: https://docs.mendix.com/community-tools/contribute-to-mendix-docs/style-guide/grammar-formatting/#em-dash
Expand Down
2 changes: 1 addition & 1 deletion .vale/styles/Mendix/IconShortcodes.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Mendix custom rule: Use icon shortcodes with tooltips when describing clickable icons
# Reference: content/en/docs/community-tools/contribute-to-mendix-docs/icon-demo.md
# Known issue: Only matches plaintext
# Known issue: Doesn't match code font icon descriptions.
extends: substitution
message: "Use the icon shortcode and tooltip: '%s' instead of '%s'"
link: https://docs.mendix.com/icons/
Expand Down
2 changes: 1 addition & 1 deletion .vale/styles/Mendix/ListIntroductions.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Reference: content/en/docs/community-tools/contribute-to-mendix-docs/style-guide/grammar-formatting.md (Lists)
# Known issue: Only matches plaintext list intros
# Known issue: Doesn't match code font list intros
extends: substitution
message: "Set off list item introductions with an en dash (–), not an em dash (—)."
link: https://docs.mendix.com/community-tools/contribute-to-mendix-docs/style-guide/grammar-formatting/#en-dash
Expand Down
Loading