Skip to content
Merged
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
12 changes: 9 additions & 3 deletions .github/CI_CD_DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ This repository implements comprehensive quality gates to ensure code quality an
All pull requests to `main` undergo automated validation:

- **Linting** - Code style and quality checks via ESLint
- **Unit Tests** - Vitest coverage for TypeScript utilities
- **Spell Checking** - Source and generated HTML spelling checks via CSpell
- **Prose Linting** - Article terminology and style checks via Vale
- **Vale Fixture Tests** - Terminology rule fixtures that assert expected pass/fail behavior
- **Type Checking** - TypeScript validation via `astro check`
- **Build Verification** - Ensures the site builds successfully
- **Link Validation** - Checks all internal links are valid
Expand All @@ -32,7 +36,9 @@ Custom Node.js script that:
**Usage:**
```bash
npm run validate:links # Run link validation
npm run validate:all # Run all validation (lint, build, links)
npm run lint:prose # Run Vale prose linting
npm run test:vale # Run Vale terminology fixture tests
npm run validate:all # Run validation (lint, prose, Vale fixtures, build, links)
```

### 3. Deployment Workflow
Expand Down Expand Up @@ -84,7 +90,7 @@ Edit files, add content, modify styles, etc.

### 3. Test Locally
```bash
npm run validate:all # Run all checks locally
npm run test:ci # Run all CI checks locally
```

### 4. Create Pull Request
Expand Down Expand Up @@ -151,4 +157,4 @@ Changes are automatically deployed to GitHub Pages.
- [Branch Protection Setup](./BRANCH_PROTECTION.md)
- [PR Validation Workflow](./workflows/pr-validation.yml)
- [Deployment Workflow](./workflows/deploy.yml)
- [Link Validation Script](../scripts/validate-links.js)
- [Link Validation Script](../scripts/validate-links.js)
7 changes: 6 additions & 1 deletion .github/WORKFLOW_ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ This repository uses a modular GitHub Actions workflow architecture to ensure co
- Accepts optional `checkout-ref` input for specific git references
- Performs all validation steps:
- Linting (ESLint)
- Unit tests
- Spell checking (source files)
- Prose linting (Vale)
- Vale fixture tests
- TypeScript checking and Astro build
- Spell checking (generated HTML)
- Internal link validation
Expand Down Expand Up @@ -64,6 +67,8 @@ Multiple safeguards prevent accidental deployment:
PRs undergo the exact same validation as deployment, including:
- All linting and type checking
- Spell checking (both source and generated HTML)
- Prose linting
- Vale fixture tests
- Full site build
- Link validation

Expand Down Expand Up @@ -120,4 +125,4 @@ if: |
### Permission Model
- **PR Validation**: Read-only access (can't modify repository or deploy)
- **Deployment**: Write access only when pushing to main branch
- **Manual Workflow**: Deployment only allowed from main branch with explicit flag
- **Manual Workflow**: Deployment only allowed from main branch with explicit flag
6 changes: 6 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ jobs:

- name: Run Spell Check (Source)
run: npm run spellcheck

- name: Run Prose Lint (Vale)
run: npm run lint:prose

- name: Run Vale Fixture Tests
run: npm run test:vale

- name: Build Site
run: npm run build
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/pr-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ jobs:
// Build check list with actual results
const checks = [
'✓ Linting',
'✓ Unit tests',
'✓ Spell check (source)',
'✓ Prose lint (Vale)',
'✓ Vale fixture tests',
'✓ Type checking & Build',
'✓ Spell check (HTML)',
'✓ Internal link validation',
Expand All @@ -59,4 +62,4 @@ jobs:
owner: context.repo.owner,
repo: context.repo.repo,
body: `## PR Validation ${icon}\n\n${message}\n\n### Checks Performed:\n${checkList}\n\n*This is a complete dry-run of the deployment process, ensuring your changes will deploy successfully when merged.*`
});
});
12 changes: 12 additions & 0 deletions .vale.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
StylesPath = .vale/styles
MinAlertLevel = warning
IgnoredScopes = code, tt

[formats]
mdx = md

[src/content/**/*.{md,mdx}]
BasedOnStyles = Terminology

[.vale/fixtures/*.md]
BasedOnStyles = Terminology
38 changes: 38 additions & 0 deletions .vale/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Vale Prose Linting

Vale checks article prose in `src/content`.

## Structure

- `.vale.ini`: selects the content paths and enabled style namespaces.
- `.vale/styles/Terminology/`: consistency checks for product, platform, API, and brand terms.

Add new rule files under the most specific style namespace that fits the rule. If a new family of checks does not fit `Terminology`, add another directory under `.vale/styles` and include it in `.vale.ini` with `BasedOnStyles`.

## Rule Notes

Apple terminology substitutions are case-sensitive and list the incorrect forms they should catch. That keeps correctly cased terms from depending on case-insensitive substitution behavior.

The substitution list is a regression-tested guardrail for common incorrect forms, not an exhaustive casing detector. Add explicit variants when a new mistake shows up in content or review.

Historical Apple platform names such as `classic Mac OS` and `Mac OS X` are valid when discussing older systems. If a passage intentionally uses a form that a rule flags, keep the exception local:

```markdown
<!-- vale Terminology.Apple = NO -->
classic mac os spelling retained for quoted or historical context
<!-- vale Terminology.Apple = YES -->
```

MDX files are treated as Markdown. JSX component attribute values can be linted as prose, so use local Vale disable comments around intentional non-prose values when needed.

Image alt text is linted with the rest of article prose because it ships to readers and assistive technology.

The local `@vvago/vale` package downloads the Vale binary during npm install. The lint command itself uses the checked-in rules and does not run `vale sync`.

## Usage

```bash
npm run lint:prose
npm run test:vale
just lint-prose
```
7 changes: 7 additions & 0 deletions .vale/fixtures/apple-terminology-invalid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Invalid Apple Terminology

An ios app built in xcode can mention Swift UI, Objective C, Test Flight, MacOS, and Apple Silicon.

An ipad tablet can pair with an iphone, while ipad os, ipad-Os, IPad os, IPAD OS, IPAD-OS, watch os, tv os, and vision os keep platform names consistent.

Publish through the app store.
9 changes: 9 additions & 0 deletions .vale/fixtures/apple-terminology-valid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Valid Apple Terminology

An iOS app built in Xcode can mention SwiftUI, Objective-C, TestFlight, macOS, and Apple silicon.

An iPad tablet can pair with an iPhone, while iPadOS, watchOS, tvOS, and visionOS keep platform names consistent.

Publish through the App Store.

Historical names such as classic Mac OS and Mac OS X can be correct in older platform context.
19 changes: 19 additions & 0 deletions .vale/styles/Terminology/Apple.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
extends: substitution
message: "Use '%s' instead of '%s'."
level: error
ignorecase: false
swap:
'\b(ios|IOS|Ios)\b': iOS
'\b(?:ipad|IPad|Ipad|IPAD)(?![ -]?[oO][sS]\b)\b': iPad
'\b((?:ipad|IPad|Ipad|IPAD)[ -]?[oO][sS]|iPad(?:[ -][oO][sS]|os|Os|oS))\b': iPadOS
'\b(iphone|IPhone|Iphone|IPHONE)\b': iPhone
'\b(mac[ -]?os|MacOS|Mac-OS|MAC[ -]?OS)\b': macOS
'\b(watch[ -]?os|watch[ -]OS|Watch[ -]?OS|Watch[ -]?os|WATCH[ -]?OS)\b': watchOS
'\b(tv[ -]?os|tv[ -]OS|TV[ -]?OS|Tv[ -]?OS)\b': tvOS
'\b(vision[ -]?os|vision[ -]OS|Vision[ -]?OS|Vision[ -]?os|VISION[ -]?OS)\b': visionOS
'\b(xcode|XCode|XCODE)\b': Xcode
'\b(swift[ -]?ui|swift[ -]?UI|Swift[ -]UI|Swift[ -]?Ui|SWIFT[ -]?UI)\b': SwiftUI
'\b(objective[ -]?c|Objective C|Objective-c|ObjectiveC|OBJECTIVE[ -]?C)\b': Objective-C
'\b(app\s+store|App\s+store|app\s+Store|APP\s+STORE)\b': App Store
'\b(test\s*flight|Test\s+Flight|Testflight|TEST\s*FLIGHT)\b': TestFlight
'\b(apple\s+silicon|Apple\s+Silicon|APPLE\s+SILICON)\b': Apple silicon
4 changes: 3 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ Some key commands are:
- just spellcheck-html: checks spelling in built HTML output
- just lint: runs ESLint on all files
- just lint-fix: auto-fixes ESLint issues where possible
- just lint-prose: runs Vale on article content
- just test-vale: verifies Vale terminology fixture behavior
- just validate-feed: builds the site then validates the RSS feed XML (well-formedness + namespaces, via xmllint)
- just validate: runs all validation checks (lint + spellcheck + build + links + feed)
- just validate: runs all validation checks (lint + spellcheck + prose + Vale fixtures + build + links + feed)

## Key Technical Decisions

Expand Down
6 changes: 3 additions & 3 deletions SPELLCHECK.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Spell Checking Setup

This project uses CSpell for spell checking both source files and generated HTML output.
This project uses CSpell for spell checking both source files and generated HTML output. Vale is used separately for prose style and terminology consistency.

## Features

Expand Down Expand Up @@ -68,11 +68,11 @@ We evaluated several spell-checking solutions:
- **Hunspell/Aspell**: Traditional spell checkers, but poor at handling technical terms and camelCase
- **LanguageTool**: Excellent for grammar but overkill for basic spell checking
- **textlint**: Good but requires more configuration for technical content
- **Vale**: Great for style guides but complex setup for simple spell checking
- **Vale**: Strong for style guides; used here for prose style and terminology consistency, not spelling

CSpell was chosen because it:
- Has built-in understanding of code conventions
- Includes extensive technical dictionaries
- Integrates easily with npm scripts and CI/CD
- Provides fast performance
- Offers smart suggestions for technical terms
- Offers smart suggestions for technical terms
38 changes: 28 additions & 10 deletions VALIDATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,34 +45,50 @@ npm run spellcheck:html
npm run spellcheck:all
```

### 3. Build
### 3. Prose Linting
Checks article content for Vale style and terminology rules:
```bash
npm run lint:prose
```

### 4. Vale Fixture Tests
Checks that Vale terminology fixtures fail and pass as expected:
```bash
npm run test:vale
```

### 5. Build
Generates the static site:
```bash
npm run build
```

### 4. Link Validation
### 6. Link Validation
Checks for broken internal links (requires build first):
```bash
npm run validate:links
```

### 5. All Validations
### 7. All Validations
Runs everything in sequence:
```bash
npm run validate:all
# OR equivalently:

# Full CI parity, including unit tests:
npm run test:ci
```

## CI/CD Workflow

The GitHub Actions workflow runs these exact same checks:
1. Linting (`npm run lint`)
2. Source spell check (`npm run spellcheck`)
3. Build (`npm run build`)
4. HTML spell check (`npm run spellcheck:html`)
5. Link validation (`npm run validate:links`)
2. Unit tests (`npm run test:unit`)
3. Source spell check (`npm run spellcheck`)
4. Prose lint (`npm run lint:prose`)
5. Vale fixture tests (`npm run test:vale`)
6. Build (`npm run build`)
7. HTML spell check (`npm run spellcheck:html`)
8. Link validation (`npm run validate:links`)

## Troubleshooting

Expand Down Expand Up @@ -122,14 +138,16 @@ Before pushing changes:
1. ✅ Run `npm run test:ci` locally
2. ✅ Fix any issues that arise
3. ✅ If adding new terms, update `cspell.json`
4. ✅ Commit all changes including config updates
4. ✅ If adding new terminology rules, update `.vale/styles/`
5. ✅ Commit all changes including config updates

## Common Gotchas

1. **Spell check ignores entire directories**: Check `ignorePaths` in `cspell.json`
2. **HTML spell check requires build**: Always run `npm run build` first
3. **CI uses exact npm scripts**: Don't rely on different local commands
4. **Case sensitivity**: File paths are case-sensitive in CI (Linux) but may not be locally (macOS/Windows)
5. **Vale fixture failures**: Update `.vale/fixtures/` and `scripts/check-vale-fixtures.js` when changing expected terminology rule behavior

## Maintaining CI/CD Parity

Expand All @@ -141,4 +159,4 @@ To ensure local development matches CI:
4. If CI fails but local passes, check for:
- Missing files in git
- Different Node.js versions
- Platform-specific issues (Linux CI vs local macOS/Windows)
- Platform-specific issues (Linux CI vs local macOS/Windows)
10 changes: 9 additions & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,15 @@ lint-fix:
lint-markdown:
npm run lint:markdown

# Validate: runs all validation checks (lint + unit tests + spellcheck + build + links + feed)
# Lint-prose: runs Vale on article content
lint-prose:
npm run lint:prose

# Test-vale: verifies Vale terminology fixture behavior
test-vale:
npm run test:vale

# Validate: runs all validation checks (lint + unit tests + spellcheck + prose + Vale fixtures + build + links + feed)
validate:
npm run validate:all

Expand Down
Loading
Loading