Skip to content

feat(ci): add Vale style check workflow#6816

Merged
jstirnaman merged 13 commits intomasterfrom
docs-v2-jts-vale-ci
Mar 28, 2026
Merged

feat(ci): add Vale style check workflow#6816
jstirnaman merged 13 commits intomasterfrom
docs-v2-jts-vale-ci

Conversation

@jstirnaman
Copy link
Copy Markdown
Contributor

@jstirnaman jstirnaman commented Feb 11, 2026

Summary

Adds Vale style linting to GitHub Actions that blocks PRs on errors and provides actionable feedback.

Changes:

  • .github/scripts/resolve-shared-content.sh - Resolves shared content files to their consuming product pages
  • .github/scripts/vale-check.sh - Maps files to product-specific Vale configs and runs Vale via Docker
  • .github/workflows/pr-vale-check.yml - CI workflow with annotations and PR comments

Test plan

  • Vale workflow runs on this PR
  • Test file triggers Vale errors (intentional)
  • Annotations appear on changed lines
  • PR comment is posted with results
  • Check fails due to errors (as expected)
  • Remove test file and verify check passes

Vale CI Integration Design

Overview

Add Vale style linting to GitHub Actions CI to enforce documentation quality standards on pull requests. The workflow blocks merging on style errors and provides actionable feedback through inline annotations and PR summary comments.

Goals

  1. Block merging on style errors - PRs with Vale errors cannot be merged
  2. Provide informational feedback - Warnings and suggestions shown but don't block
  3. Support humans and AI agents - Structured output that both can act on autonomously

Design Decisions

Decision Choice Rationale
Scope Content + instruction files Match local Lefthook behavior
Config handling Smart detection per file Respect product-specific branding rules
Reporting Inline annotations + PR comment Context on lines + overview for agents
Filter mode Added lines only Avoid noise from pre-existing issues
Alert level Errors block, warnings don't Match current local behavior
Vale installation Docker (jdkato/vale:latest) Always current, matches local setup

Files to Create

.github/
├── scripts/
│   ├── resolve-shared-content.sh   # Shared content resolution
│   └── vale-check.sh               # Vale runner with config mapping
└── workflows/
    └── pr-vale-check.yml           # Main workflow

Workflow Architecture

pr-vale-check.yml
├── Trigger: pull_request on markdown files
├── Steps:
│   ├── 1. Checkout repository
│   ├── 2. Detect changed files (GitHub API)
│   ├── 3. Skip if no files to check
│   ├── 4. Resolve shared content → product pages
│   ├── 5. Run Vale via Docker (grouped by config)
│   ├── 6. Process results & generate annotations
│   ├── 7. Post PR comment summary
│   ├── 8. Upload results artifact
│   └── 9. Fail if errors found

Trigger Paths

on:
  pull_request:
    paths:
      - 'content/**/*.md'
      - 'README.md'
      - 'DOCS-*.md'
      - '**/AGENTS.md'
      - '**/CLAUDE.md'
      - '.github/**/*.md'
      - '.claude/**/*.md'
    types: [opened, synchronize, reopened]

Shared Content Resolution

Files in content/shared/ are sourced by product-specific pages. When a shared file changes, Vale must lint the consuming pages (which have product-specific configs).

Script: .github/scripts/resolve-shared-content.sh

Logic:

  1. For each changed file:
    • If content/shared/*: find all pages with source: frontmatter pointing to it
    • Else: pass through unchanged
  2. Output resolved file list

Example:

Input:
  content/shared/influxdb3-cli/admin/database/create.md

Output:
  content/influxdb3/core/reference/cli/influxdb3/admin/database/create.md
  content/influxdb3/enterprise/reference/cli/influxdb3/admin/database/create.md

Reusability: This script can be used by other workflows (link-checker, tests) that also need shared content resolution.

Vale Config Mapping

Script: .github/scripts/vale-check.sh

Maps files to their Vale config based on path:

File Pattern Vale Config
content/influxdb3/cloud-dedicated/** content/influxdb3/cloud-dedicated/.vale.ini
content/influxdb3/cloud-serverless/** content/influxdb3/cloud-serverless/.vale.ini
content/influxdb/v2/** content/influxdb/v2/.vale.ini
content/**/*.md (other) .vale.ini
Non-content files .vale-instructions.ini

Files are grouped by config, then Vale runs once per group to minimize Docker invocations.

Vale Execution

Uses Docker to match local development:

docker run --rm \
  -v $(pwd):/workdir \
  -w /workdir \
  jdkato/vale:latest \
  --config=$CONFIG \
  --output=JSON \
  $FILES

Output Processing

GitHub Annotations

# Errors (visible in Files Changed, block merge)
echo "::error file=${FILE},line=${LINE},title=${CHECK}::${MESSAGE}"

# Warnings (visible, don't block)
echo "::warning file=${FILE},line=${LINE},title=${CHECK}::${MESSAGE}"

# Suggestions (visible, don't block)
echo "::notice file=${FILE},line=${LINE},title=${CHECK}::${MESSAGE}"

PR Summary Comment

Posted via github-script action:

## Vale Style Check Results

| Metric | Count |
|--------|-------|
| Files checked | 12 |
| Errors | 3 |
| Warnings | 7 |
| Suggestions | 2 |

### Errors (blocking)

| File | Line | Rule | Message |
|------|------|------|---------|
| `content/influxdb3/core/get-started.md` | 42 | InfluxDataDocs.Branding | Use 'InfluxDB' instead of 'influxdb' |

<details>
<summary>Warnings (7)</summary>

| File | Line | Rule | Message |
|------|------|------|---------|
| ... |

</details>

---**Check failed** — fix 3 error(s) before merging.

Exit Behavior

  • Exit 0: No errors (warnings/suggestions allowed)
  • Exit 1: One or more errors (blocks merge)
  • Summary comment posted in both cases

Implementation Tasks

  1. Create .github/scripts/resolve-shared-content.sh
  2. Create .github/scripts/vale-check.sh
  3. Create .github/workflows/pr-vale-check.yml
  4. Test on a PR with intentional Vale errors
  5. Update pr-link-check.yml to use shared resolution script
  6. Document in DOCS-TESTING.md

Future Considerations

  • Caching: Cache Docker image pull across runs
  • Parallel execution: Run Vale config groups in parallel if performance becomes an issue
  • Shared workflow: Consider workflow_call if other repos need the same check
  • Remove npm Vale: Once CI uses Docker, @vvago/vale can be removed from devDependencies

Vale CI Implementation Plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: Add Vale style linting to GitHub Actions that blocks PRs on errors and provides actionable feedback.

Architecture: Single workflow with two supporting scripts. The shared content resolution script expands content/shared/ files to their consuming product pages. The vale-check script maps files to product-specific Vale configs and runs Vale via Docker.

Tech Stack: Bash scripts, GitHub Actions YAML, Docker (jdkato/vale), jq for JSON processing

Implementation

Summary

After completing all tasks, you will have:

  1. .github/scripts/resolve-shared-content.sh - Reusable script for expanding shared content
  2. .github/scripts/vale-check.sh - Vale runner with config mapping
  3. .github/workflows/pr-vale-check.yml - CI workflow with annotations and PR comments
  4. Updated DOCS-TESTING.md with CI documentation

The workflow mirrors local Lefthook behavior, using Docker-based Vale and product-specific configs.

@jstirnaman jstirnaman requested a review from a team as a code owner February 11, 2026 23:16
@jstirnaman jstirnaman requested review from sanderson and removed request for a team February 11, 2026 23:16
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 11, 2026

Vale Style Check Results

Metric Count
Errors 0
Warnings 16
Suggestions 17
Warnings (16)
File Line Rule Message
DOCS-TESTING.md 16 write-good.TooWordy 'Validate' is too wordy.
DOCS-TESTING.md 76 write-good.Passive 'be deleted' may be passive voice. Use active voice if you can.
DOCS-TESTING.md 77 write-good.Passive 'is configured' may be passive voice. Use active voice if you can.
DOCS-TESTING.md 193 write-good.TooWordy 'additional' is too wordy.
DOCS-TESTING.md 239 write-good.TooWordy 'validate' is too wordy.
DOCS-TESTING.md 338 write-good.TooWordy 'validate' is too wordy.
DOCS-TESTING.md 361 write-good.Passive 'is distributed' may be passive voice. Use active voice if you can.
DOCS-TESTING.md 425 write-good.Passive 'is required' may be passive voice. Use active voice if you can.
DOCS-TESTING.md 464 write-good.Passive 'be found' may be passive voice. Use active voice if you can.
DOCS-TESTING.md 465 write-good.TooWordy 'validate' is too wordy.
DOCS-TESTING.md 532 write-good.TooWordy 'modify' is too wordy.
DOCS-TESTING.md 627 write-good.TooWordy 'modify' is too wordy.
DOCS-TESTING.md 749 write-good.Passive 'are evaluated' may be passive voice. Use active voice if you can.
DOCS-TESTING.md 750 write-good.Passive 'are removed' may be passive voice. Use active voice if you can.
DOCS-TESTING.md 757 write-good.TooWordy 'Monitor' is too wordy.
DOCS-TESTING.md 784 write-good.TooWordy 'substantial' is too wordy.

Check passed

@github-actions
Copy link
Copy Markdown
Contributor

PR Preview Action v1.4.8
🚀 Deployed preview to https://influxdata.github.io/docs-v2/pr-preview/pr-6816/
on branch gh-pages at 2026-02-11 23:19 UTC

@github-actions
Copy link
Copy Markdown
Contributor

PR Preview

Status Details
Preview View preview
Pages 1 page(s) deployed
Build time 66s
Last updated 2026-02-11 23:19:11 UTC
Pages included in this preview
  • /influxdb3/core/test-vale-errors/

Preview auto-deploys on push. Will be cleaned up when PR closes.

Design for adding Vale style linting to GitHub Actions PR checks:
- Block merging on style errors
- Inline annotations + PR summary comments
- Smart config detection per product area
- Shared content resolution script (reusable by other workflows)
- Docker-based Vale execution (matches local setup)
Detailed step-by-step plan for implementing Vale CI:
- Task 1: Shared content resolution script
- Task 2: Vale check script with config mapping
- Task 3: GitHub Actions workflow
- Task 4: Testing procedure
- Task 5: Documentation updates
- Task 6: Final verification
Resolves content/shared/* files to their consuming product pages
by searching for matching source: frontmatter. Reusable by Vale,
link-checker, and other workflows that need shared content expansion.
Maps files to product-specific Vale configs matching lefthook.yml:
- cloud-dedicated, cloud-serverless, v2 use product configs
- Other content uses root .vale.ini
- Non-content uses .vale-instructions.ini

Runs Vale via Docker for version consistency with local dev.
Runs Vale on PR changes with product-specific configs:
- Blocks merging on errors
- Shows warnings/suggestions as annotations
- Posts summary comment for humans and AI agents
- Uses Docker for Vale version consistency
Add `|| [[ -n "$f" ]]` to while read loops to catch the last line
even when input doesn't end with a newline. This is a common bash
pitfall where `while read` skips the final line without a terminator.
@jstirnaman jstirnaman merged commit 1cea1dd into master Mar 28, 2026
3 checks passed
@jstirnaman jstirnaman deleted the docs-v2-jts-vale-ci branch March 28, 2026 02:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants