Files
2025-11-29 18:16:51 +08:00

273 lines
6.1 KiB
Markdown

# CI/CD Integration Examples
Ready-to-use configurations for automated CLAUDE.md validation.
## Pre-Commit Hook
### Basic Validation
```bash
#!/bin/bash
# .git/hooks/pre-commit
if git diff --cached --name-only | grep -q "CLAUDE.md"; then
echo "Validating CLAUDE.md..."
FILE=$(git diff --cached --name-only | grep "CLAUDE.md" | head -1)
# Check file length
LINES=$(wc -l < "$FILE")
if [ "$LINES" -gt 500 ]; then
echo "ERROR: CLAUDE.md is $LINES lines (max 500)"
exit 1
fi
# Check for secrets
if grep -qE "password|secret|token|api_key|-----BEGIN" "$FILE"; then
echo "ERROR: Potential secrets detected in CLAUDE.md"
echo "Run: grep -nE 'password|secret|token|api_key' $FILE"
exit 1
fi
# Check for broken imports
grep "^@" "$FILE" | while read -r import; do
path="${import#@}"
if [ ! -f "$path" ]; then
echo "ERROR: Broken import: $import"
exit 1
fi
done
echo "CLAUDE.md validation passed"
fi
```
### Installation
```bash
chmod +x .git/hooks/pre-commit
```
## GitHub Actions
### Basic Workflow
```yaml
# .github/workflows/claude-md-audit.yml
name: CLAUDE.md Audit
on:
pull_request:
paths:
- '**/CLAUDE.md'
- '**/.claude/CLAUDE.md'
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Find CLAUDE.md files
id: find
run: |
files=$(find . -name "CLAUDE.md" -type f)
echo "files=$files" >> $GITHUB_OUTPUT
- name: Check file lengths
run: |
for file in ${{ steps.find.outputs.files }}; do
lines=$(wc -l < "$file")
if [ "$lines" -gt 500 ]; then
echo "::error file=$file::File is $lines lines (max 500)"
exit 1
fi
echo "OK: $file ($lines lines)"
done
- name: Check for secrets
run: |
for file in ${{ steps.find.outputs.files }}; do
if grep -qE "password|secret|token|api_key|-----BEGIN" "$file"; then
echo "::error file=$file::Potential secrets detected"
grep -nE "password|secret|token|api_key" "$file" || true
exit 1
fi
done
echo "No secrets detected"
- name: Check imports
run: |
for file in ${{ steps.find.outputs.files }}; do
dir=$(dirname "$file")
grep "^@" "$file" | while read -r import; do
path="${import#@}"
if [ ! -f "$dir/$path" ]; then
echo "::error file=$file::Broken import: $import"
exit 1
fi
done
done
echo "All imports valid"
```
### With PR Comment
```yaml
- name: Post audit summary
if: always()
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
// Collect results
const results = {
files: 0,
passed: 0,
failed: 0,
warnings: []
};
// Post comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: `## CLAUDE.md Audit Results
- Files checked: ${results.files}
- Passed: ${results.passed}
- Failed: ${results.failed}
${results.warnings.length > 0 ? '### Warnings\n' + results.warnings.join('\n') : ''}
`
});
```
## VS Code Task
### tasks.json
```json
{
"version": "2.0.0",
"tasks": [
{
"label": "Audit CLAUDE.md",
"type": "shell",
"command": "bash",
"args": [
"-c",
"echo 'Auditing CLAUDE.md...' && wc -l CLAUDE.md && grep -c '^##' CLAUDE.md && echo 'Done'"
],
"group": "test",
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},
{
"label": "Check CLAUDE.md secrets",
"type": "shell",
"command": "bash",
"args": [
"-c",
"if grep -qE 'password|secret|token|api_key' CLAUDE.md; then echo 'WARNING: Potential secrets found:' && grep -nE 'password|secret|token|api_key' CLAUDE.md; else echo 'No secrets detected'; fi"
],
"group": "test",
"problemMatcher": []
}
]
}
```
### Keyboard Shortcut
```json
// keybindings.json
{
"key": "ctrl+shift+a",
"command": "workbench.action.tasks.runTask",
"args": "Audit CLAUDE.md"
}
```
## Husky + lint-staged
### Installation
```bash
npm install -D husky lint-staged
npx husky init
```
### package.json
```json
{
"lint-staged": {
"**/CLAUDE.md": [
"bash -c 'wc -l \"$0\" | awk \"{if (\\$1 > 500) {print \\\"ERROR: \\\" \\$1 \\\" lines\\\"; exit 1}}\"'",
"bash -c 'grep -qE \"password|secret|token\" \"$0\" && exit 1 || true'"
]
}
}
```
### .husky/pre-commit
```bash
npx lint-staged
```
## GitLab CI
```yaml
# .gitlab-ci.yml
claude-md-audit:
stage: test
rules:
- changes:
- "**/CLAUDE.md"
script:
- |
for file in $(find . -name "CLAUDE.md"); do
echo "Checking $file"
lines=$(wc -l < "$file")
if [ "$lines" -gt 500 ]; then
echo "ERROR: $file is $lines lines"
exit 1
fi
done
- echo "CLAUDE.md audit passed"
```
## Makefile Target
```makefile
.PHONY: audit-claude-md
audit-claude-md:
@echo "Auditing CLAUDE.md files..."
@find . -name "CLAUDE.md" -exec sh -c '\
lines=$$(wc -l < "{}"); \
if [ "$$lines" -gt 500 ]; then \
echo "ERROR: {} is $$lines lines"; \
exit 1; \
fi; \
echo "OK: {} ($$lines lines)"' \;
@echo "Checking for secrets..."
@! grep -rE "password|secret|token|api_key" --include="CLAUDE.md" . || \
(echo "ERROR: Secrets detected" && exit 1)
@echo "Audit complete"
```
## Best Practices
1. **Fail fast**: Check secrets before anything else
2. **Clear errors**: Include file path and line numbers
3. **PR feedback**: Post results as comments
4. **Gradual adoption**: Start with warnings, then enforce
5. **Skip when needed**: Allow `[skip audit]` in commit message