Skip to Content
GuidesCI/CD integration

CI/CD integration

Validate rules, detect drift, and enforce team standards in your CI pipeline.

Tip: Locally you can run aligntrue check without flags for an interactive spinner. The workflows below keep --ci so output stays deterministic inside CI, hooks, or other scripts.

Quick setup

# .github/workflows/aligntrue.yml name: AlignTrue on: [push, pull_request] jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "20" - name: Install AlignTrue run: npm install -g @aligntrue/cli - name: Validate rules run: aligntrue check --ci - name: Check drift (team mode) run: aligntrue drift --gates if: hashFiles('.aligntrue/lock.json') != ''

Validation checks

Schema validation

Validate that rules conform to AlignTrue schema:

# Local aligntrue check # CI or scripts aligntrue check --ci

Checks:

  • YAML/JSON syntax
  • Required fields present
  • Valid rule IDs
  • Correct data types
  • No duplicate rules

Exit codes:

  • 0 - All checks passed
  • 1 - Validation errors found

Example output:

✓ Schema validation passed ✓ 15 rules validated ✓ No duplicates found

Lockfile validation (team mode)

Validate lockfile matches current rules:

# Local aligntrue check # CI or scripts aligntrue check --ci

With team mode enabled, this also checks:

  • Lockfile exists
  • Lockfile is up to date
  • Hashes match current rules
  • Lockfile v2 contains only version and bundle_hash (team rules + team config)

Lockfile modes:

# .aligntrue/config.team.yaml (team) or .aligntrue/config.yaml (solo) lockfile: mode: strict # Fail CI if lockfile out of sync # or: soft # Warn but don't fail # or: off # No lockfile validation

Drift detection

Basic drift check

Detect when the current bundle hash (team rules + team config) differs from the lockfile:

aligntrue drift

Exit codes:

  • 0 - Completed (drift reported but does not fail)
  • 1 - Team mode required but not enabled

Fail CI on drift

aligntrue drift --gates

Exit codes:

  • 0 - No drift detected
  • 2 - Drift detected (fails CI)

Use cases:

  • Enforce approved rule versions
  • Prevent accidental updates
  • Require explicit update PRs

Drift categories

lockfile (only) — bundle hash in .aligntrue/lock.json differs from current rules + team config.

aligntrue drift --json

Output example:

{ "mode": "team", "has_drift": true, "lockfile_path": ".aligntrue/lock.json", "findings": [ { "category": "lockfile", "ruleId": "_bundle", "description": "Rules or team config have changed since last lockfile generation", "lockfile_hash": "sha256:abc123...", "expected_hash": "sha256:def456..." } ], "summary": { "total": 1, "by_category": { "lockfile": 1 } } }

CI workflows

Solo developer workflow

Goal: Validate rules on every commit

# .github/workflows/aligntrue.yml name: Validate Rules on: [push, pull_request] jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "20" - run: npm install -g @aligntrue/cli - run: aligntrue check --ci

Team workflow with lockfile

Goal: Enforce lockfile, fail on drift

# .github/workflows/aligntrue.yml name: AlignTrue Team Checks on: pull_request: branches: [main] push: branches: [main] jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "20" - name: Install AlignTrue run: npm install -g @aligntrue/cli - name: Validate schema run: aligntrue check --ci - name: Validate lockfile run: | if [ ! -f .aligntrue/lock.json ]; then echo "Error: Lockfile missing" exit 1 fi - name: Check drift run: aligntrue drift --gates - name: Verify sync run: aligntrue sync --dry-run

Monorepo with scopes

Goal: Validate each scope’s configuration

Each scope in a monorepo has its own .aligntrue/config.yaml and rules. Validate from each scope directory:

# .github/workflows/aligntrue.yml name: Validate Scopes on: [push, pull_request] jobs: validate: runs-on: ubuntu-latest strategy: matrix: scope: - root - packages/api - packages/web steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "20" - run: npm install -g @aligntrue/cli - working-directory: ${{ matrix.scope }} run: aligntrue check --ci

Advanced CI patterns

Auto-update PRs

Create PRs when drift is detected:

# .github/workflows/aligntrue-auto-update.yml name: Auto-update Rules on: schedule: - cron: "0 0 * * 1" # Weekly on Monday workflow_dispatch: jobs: update: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "20" - name: Install AlignTrue run: npm install -g @aligntrue/cli - name: Check for updates id: drift run: | aligntrue drift --json > drift.json if [ $(jq -r '.has_drift' drift.json) == "true" ]; then echo "drift=true" >> $GITHUB_OUTPUT fi - name: Create PR for Review if: steps.drift.outputs.drift == 'true' uses: peter-evans/create-pull-request@v5 with: title: "chore: Review AlignTrue drift" body: | Drift detected in rules. Detected drift in: $(jq -r '.summary.by_category | to_entries[] | select(.value>0) | "\(.key): \(.value)"' drift.json) Approve this PR to accept the drift or make corrections. branch: aligntrue-drift-review commit-message: "chore: Review AlignTrue drift"

Lockfile regeneration

Regenerate lockfile on rule changes:

# .github/workflows/aligntrue-lock.yml name: Update Lockfile on: pull_request: paths: - ".aligntrue/**" jobs: update-lock: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: ref: ${{ github.head_ref }} - uses: actions/setup-node@v4 with: node-version: "20" - name: Install AlignTrue run: npm install -g @aligntrue/cli - name: Regenerate lockfile run: aligntrue sync - name: Commit if changed run: | if [ -n "$(git status --porcelain .aligntrue/lock.json)" ]; then git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" git add .aligntrue/lock.json git commit -m "chore: Regenerate lockfile" git push fi

SARIF output for GitHub

Generate SARIF for GitHub Code Scanning using drift detection (reports compliance issues):

# .github/workflows/aligntrue-sarif.yml name: AlignTrue SARIF on: [push, pull_request] jobs: scan: runs-on: ubuntu-latest permissions: security-events: write steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: "20" - name: Install AlignTrue run: npm install -g @aligntrue/cli - name: Detect drift (SARIF) run: aligntrue drift --sarif > aligntrue.sarif continue-on-error: true - name: Upload SARIF uses: github/codeql-action/upload-sarif@v2 with: sarif_file: aligntrue.sarif

Caching

Cache AlignTrue installation

- name: Cache AlignTrue uses: actions/cache@v3 with: path: ~/.npm key: ${{ runner.os }}-aligntrue-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.os }}-aligntrue-

Cache git sources

- name: Cache git sources uses: actions/cache@v3 with: path: .aligntrue/.cache key: ${{ runner.os }}-aligntrue-cache-${{ hashFiles('.aligntrue/lock.json') }} restore-keys: | ${{ runner.os }}-aligntrue-cache-

Exit codes

AlignTrue uses standard exit codes:

  • 0 - Success (includes drift checks without --gates)
  • 1 - Validation error (schema/lockfile) or drift run outside team mode
  • 2 - System error for aligntrue check; drift detected when using --gates

CI configuration:

- name: Validate rules run: aligntrue check --ci # Fails on exit code 1 or higher - name: Check drift (informational) run: aligntrue drift || true # Never fails CI - name: Check drift (strict) run: aligntrue drift --gates # Fails on exit code 2

Automating sync

AlignTrue can be automated to sync rules whenever they change. Since rules change infrequently (unlike source code), a few approaches work well:

Pre-commit hook

Automatically run aligntrue sync before commits to ensure exports are always up-to-date:

#!/bin/bash # .git/hooks/pre-commit aligntrue sync || exit 1 git add .cursor/rules/ AGENTS.md

Enable with:

chmod +x .git/hooks/pre-commit

Manual sync

For most workflows, simply running aligntrue sync manually is sufficient:

# Edit rules nano .aligntrue/rules/typescript.md # Export changes aligntrue sync # Review and commit git add .aligntrue/rules/ .cursor/rules/ AGENTS.md git commit -m "Update TypeScript rules"

CI validation

Use CI/CD as the enforcement point. Rules are validated on every PR:

- name: Validate rules run: aligntrue check --ci - name: Verify exports up-to-date run: git diff --exit-code .cursor/rules/ AGENTS.md

This catches cases where someone forgot to sync before committing.

Editor integration

For continuous development workflows, configure your editor to run sync on save. Example for VS Code:

{ "emeraldwalk.runonsave": { "commands": [ { "match": "\\.aligntrue/rules/.*\\.md$", "cmd": "aligntrue sync" } ] } }

Troubleshooting CI

”Command not found: aligntrue”

Cause: AlignTrue not installed or not in PATH

Fix:

- name: Install AlignTrue run: npm install -g @aligntrue/cli - name: Verify installation run: aligntrue --version

“Config file not found”

Cause: .aligntrue/ directory not committed to git

Fix:

# Ensure .aligntrue/ is tracked git add .aligntrue/ git commit -m "Add AlignTrue config"

Lockfile validation fails

Cause: Lockfile out of sync with rules

Fix:

# Regenerate locally aligntrue sync # Commit updated lockfile git add .aligntrue/lock.json git commit -m "Update lockfile"

Git sources fail in CI

Cause: Network access or authentication

Fix:

# Cache git sources during sync to avoid network calls in check - name: Cache git sources uses: actions/cache@v3 with: path: .aligntrue/.cache key: aligntrue-cache-${{ hashFiles('.aligntrue/lock.json') }} restore-keys: | aligntrue-cache- - name: Validate (uses cached sources) run: aligntrue check --ci

Drift always detected

Cause: Volatile fields included in hash

Fix:

# .aligntrue/config.yaml vendor: _meta: volatile: ["cursor.timestamp"]

Best practices

1. Validate on every PR

on: pull_request: branches: [main]

2. Use lockfile in team mode

- name: Validate lockfile exists run: test -f .aligntrue/lock.json

3. Cache dependencies

- uses: actions/cache@v3 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}

4. Fail fast

- name: Validate schema run: aligntrue check --ci # Fails immediately if schema invalid - name: Check drift run: aligntrue drift --gates # Only runs if schema valid

5. Use matrix for monorepos

strategy: matrix: scope: [root, packages/api, packages/web]

See also

Last updated on