Skip to content

Commit 5980afb

Browse files
authored
Merge pull request #6 from akhundMurad/docs
docs: add changelog and expand MkDocs documentation
2 parents 5b61d35 + a93d9b0 commit 5980afb

10 files changed

Lines changed: 1216 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [Unreleased]
9+
10+
## [0.0.2] - 2025-01-20
11+
12+
### Added
13+
14+
- History tracking with content-addressed snapshot store
15+
- `pacta history show` command to view architecture timeline
16+
- `pacta history export` command for JSON export of history data
17+
- `pacta history trends` command with ASCII charts for visualizing metrics over time
18+
- Optional matplotlib support for PNG/SVG chart export (`pip install pacta[viz]`)
19+
- Human-readable violation explanations in text output
20+
- Expanded contributing guide with project structure and development workflow
21+
22+
### Changed
23+
24+
- License changed to Apache-2.0
25+
- README repositioned to focus on architecture governance
26+
27+
## [0.0.1] - 2025-01-15
28+
29+
### Added
30+
31+
- Initial release
32+
- Python AST analyzer for static code analysis
33+
- Architecture model definition via `architecture.yml`
34+
- System and container definitions
35+
- Layer definitions with glob patterns
36+
- Code mapping configuration
37+
- Rules DSL via `rules.pacta.yml`
38+
- Layer dependency constraints
39+
- Severity levels (error, warning, info)
40+
- Custom messages and suggestions
41+
- `pacta scan` command for architecture validation
42+
- Snapshot support for versioning architecture state
43+
- Baseline mode for incremental adoption (fail only on new violations)
44+
- `pacta snapshot save` and `pacta diff` commands
45+
- Text and JSON output formats
46+
- MkDocs documentation site
47+
48+
[Unreleased]: https://github.com/akhundMurad/pacta/compare/v0.0.2...HEAD
49+
[0.0.2]: https://github.com/akhundMurad/pacta/compare/v0.0.1...v0.0.2
50+
[0.0.1]: https://github.com/akhundMurad/pacta/releases/tag/v0.0.1

docs/changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--8<-- "CHANGELOG.md"

docs/ci-integration.md

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
# CI/CD Integration
2+
3+
Pacta is designed for CI/CD pipelines. This guide shows how to integrate architecture checks into your workflow.
4+
5+
## Exit Codes
6+
7+
| Code | Meaning |
8+
|------|---------|
9+
| `0` | Success, no violations (or no *new* violations with baseline) |
10+
| `1` | Violations found |
11+
| `2` | Engine error (config issue, parse error, etc.) |
12+
13+
## GitHub Actions
14+
15+
### Basic Check
16+
17+
Run architecture validation on every pull request:
18+
19+
```yaml
20+
name: Architecture Check
21+
22+
on:
23+
pull_request:
24+
branches: [main]
25+
26+
jobs:
27+
architecture:
28+
runs-on: ubuntu-latest
29+
steps:
30+
- uses: actions/checkout@v4
31+
32+
- uses: actions/setup-python@v5
33+
with:
34+
python-version: '3.11'
35+
36+
- name: Install Pacta
37+
run: pip install pacta
38+
39+
- name: Check Architecture
40+
run: pacta scan . --model architecture.yml --rules rules.pacta.yml
41+
```
42+
43+
### With Baseline (Recommended)
44+
45+
For existing projects with legacy violations, use baselines to only fail on *new* violations:
46+
47+
```yaml
48+
name: Architecture Check
49+
50+
on:
51+
push:
52+
branches: [main]
53+
pull_request:
54+
branches: [main]
55+
56+
jobs:
57+
architecture:
58+
runs-on: ubuntu-latest
59+
steps:
60+
- uses: actions/checkout@v4
61+
62+
- uses: actions/setup-python@v5
63+
with:
64+
python-version: '3.11'
65+
66+
- name: Install Pacta
67+
run: pip install pacta
68+
69+
# On main branch: update baseline
70+
- name: Update Baseline
71+
if: github.ref == 'refs/heads/main'
72+
run: |
73+
pacta scan . \
74+
--model architecture.yml \
75+
--rules rules.pacta.yml \
76+
--save-ref baseline
77+
78+
# On PR: check against baseline
79+
- name: Check Against Baseline
80+
if: github.event_name == 'pull_request'
81+
run: |
82+
pacta scan . \
83+
--model architecture.yml \
84+
--rules rules.pacta.yml \
85+
--baseline baseline
86+
```
87+
88+
!!! note "Persisting baselines"
89+
The baseline is stored in `.pacta/snapshots/`. Commit this directory to your repository, or use GitHub Actions cache/artifacts to persist it between runs.
90+
91+
### JSON Output for PR Comments
92+
93+
Generate JSON output and post results as a PR comment:
94+
95+
```yaml
96+
name: Architecture Check
97+
98+
on:
99+
pull_request:
100+
branches: [main]
101+
102+
jobs:
103+
architecture:
104+
runs-on: ubuntu-latest
105+
steps:
106+
- uses: actions/checkout@v4
107+
108+
- uses: actions/setup-python@v5
109+
with:
110+
python-version: '3.11'
111+
112+
- name: Install Pacta
113+
run: pip install pacta
114+
115+
- name: Run Architecture Check
116+
id: pacta
117+
continue-on-error: true
118+
run: |
119+
pacta scan . \
120+
--model architecture.yml \
121+
--rules rules.pacta.yml \
122+
--baseline baseline \
123+
--format json > results.json
124+
125+
# Extract summary for PR comment
126+
VIOLATIONS=$(jq '.summary.total_violations' results.json)
127+
NEW=$(jq '.summary.new_violations // 0' results.json)
128+
echo "violations=$VIOLATIONS" >> $GITHUB_OUTPUT
129+
echo "new=$NEW" >> $GITHUB_OUTPUT
130+
131+
- name: Comment on PR
132+
uses: actions/github-script@v7
133+
with:
134+
script: |
135+
const violations = ${{ steps.pacta.outputs.violations }};
136+
const newViolations = ${{ steps.pacta.outputs.new }};
137+
138+
let body;
139+
if (violations === 0) {
140+
body = '### Architecture Check Passed\n\nNo architectural violations found.';
141+
} else if (newViolations === 0) {
142+
body = `### Architecture Check Passed\n\n${violations} existing violation(s), 0 new.`;
143+
} else {
144+
body = `### Architecture Check Failed\n\n**${newViolations} new violation(s)** introduced.\n\nRun \`pacta scan\` locally to see details.`;
145+
}
146+
147+
github.rest.issues.createComment({
148+
issue_number: context.issue.number,
149+
owner: context.repo.owner,
150+
repo: context.repo.repo,
151+
body: body
152+
});
153+
154+
- name: Fail on New Violations
155+
if: steps.pacta.outputs.new > 0
156+
run: exit 1
157+
```
158+
159+
## GitLab CI
160+
161+
### Basic Check
162+
163+
```yaml
164+
architecture:
165+
stage: test
166+
image: python:3.11
167+
script:
168+
- pip install pacta
169+
- pacta scan . --model architecture.yml --rules rules.pacta.yml
170+
```
171+
172+
### With Baseline
173+
174+
```yaml
175+
stages:
176+
- test
177+
178+
variables:
179+
PACTA_BASELINE: baseline
180+
181+
architecture:
182+
stage: test
183+
image: python:3.11
184+
script:
185+
- pip install pacta
186+
- |
187+
if [ "$CI_COMMIT_BRANCH" = "main" ]; then
188+
# Update baseline on main
189+
pacta scan . --model architecture.yml --rules rules.pacta.yml --save-ref $PACTA_BASELINE
190+
else
191+
# Check against baseline on feature branches
192+
pacta scan . --model architecture.yml --rules rules.pacta.yml --baseline $PACTA_BASELINE
193+
fi
194+
cache:
195+
paths:
196+
- .pacta/
197+
```
198+
199+
## Pre-commit Hook
200+
201+
Run Pacta as a pre-commit hook to catch violations before they're committed:
202+
203+
```yaml
204+
# .pre-commit-config.yaml
205+
repos:
206+
- repo: local
207+
hooks:
208+
- id: pacta
209+
name: Architecture Check
210+
entry: pacta scan . --model architecture.yml --rules rules.pacta.yml -q
211+
language: system
212+
pass_filenames: false
213+
types: [python]
214+
```
215+
216+
!!! tip "Performance"
217+
Use `-q` (quiet mode) for faster output in hooks. Consider running against baseline for large codebases with legacy violations.
218+
219+
## Makefile Integration
220+
221+
Add Pacta to your Makefile for easy local runs:
222+
223+
```makefile
224+
.PHONY: arch arch-baseline
225+
226+
# Run architecture check
227+
arch:
228+
pacta scan . --model architecture.yml --rules rules.pacta.yml
229+
230+
# Update baseline
231+
arch-baseline:
232+
pacta scan . --model architecture.yml --rules rules.pacta.yml --save-ref baseline
233+
234+
# Check against baseline (CI mode)
235+
arch-ci:
236+
pacta scan . --model architecture.yml --rules rules.pacta.yml --baseline baseline
237+
```
238+
239+
## JSON Schema
240+
241+
The `--format json` output follows this structure:
242+
243+
```json
244+
{
245+
"run_info": {
246+
"tool_version": "0.0.2",
247+
"timestamp": "2025-01-22T12:00:00+00:00",
248+
"commit": "abc1234",
249+
"branch": "main"
250+
},
251+
"summary": {
252+
"total_violations": 5,
253+
"by_severity": {
254+
"error": 3,
255+
"warning": 2
256+
},
257+
"new_violations": 1,
258+
"existing_violations": 4,
259+
"fixed_violations": 0
260+
},
261+
"violations": [
262+
{
263+
"rule_id": "no_domain_to_infra",
264+
"rule_name": "Domain cannot depend on Infrastructure",
265+
"severity": "error",
266+
"status": "new",
267+
"location": {
268+
"file": "src/domain/user.py",
269+
"line": 3,
270+
"column": 1
271+
},
272+
"message": "Domain layer must not import from Infrastructure",
273+
"suggestion": "Use dependency injection...",
274+
"explanation": "\"myapp.domain.UserService\" in domain layer imports \"myapp.infra.Database\" in infra layer"
275+
}
276+
]
277+
}
278+
```
279+
280+
Use `jq` to extract specific fields:
281+
282+
```bash
283+
# Get new violation count
284+
pacta scan . --format json | jq '.summary.new_violations'
285+
286+
# List files with violations
287+
pacta scan . --format json | jq -r '.violations[].location.file' | sort -u
288+
289+
# Filter only errors
290+
pacta scan . --format json | jq '.violations | map(select(.severity == "error"))'
291+
```

0 commit comments

Comments
 (0)