Skip to content

Commit f6eac32

Browse files
committed
feat(action): add composite GitHub Action for Pacta architecture review
1 parent 37eb368 commit f6eac32

1 file changed

Lines changed: 103 additions & 0 deletions

File tree

action.yml

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
name: 'Pacta Architecture Review'
2+
description: 'Run architecture checks and post a rich PR comment describing architectural changes'
3+
branding:
4+
icon: 'layers'
5+
color: 'blue'
6+
7+
inputs:
8+
model:
9+
description: 'Path to architecture.yml'
10+
required: false
11+
default: 'architecture.yml'
12+
rules:
13+
description: 'Path to rules.pacta.yml'
14+
required: false
15+
default: 'rules.pacta.yml'
16+
baseline:
17+
description: 'Baseline ref name (omit to skip baseline comparison)'
18+
required: false
19+
default: ''
20+
python-version:
21+
description: 'Python version to use'
22+
required: false
23+
default: '3.11'
24+
fail-on-violations:
25+
description: 'Fail the check if new violations are found'
26+
required: false
27+
default: 'true'
28+
pacta-version:
29+
description: 'Pacta version to install (default: latest)'
30+
required: false
31+
default: 'pacta'
32+
33+
runs:
34+
using: 'composite'
35+
steps:
36+
- uses: actions/setup-python@v5
37+
with:
38+
python-version: ${{ inputs.python-version }}
39+
40+
- name: Install Pacta
41+
shell: bash
42+
run: pip install ${{ inputs.pacta-version }}
43+
44+
- name: Run Architecture Check
45+
id: pacta
46+
shell: bash
47+
run: |
48+
ARGS="--model ${{ inputs.model }} --rules ${{ inputs.rules }}"
49+
if [ -n "${{ inputs.baseline }}" ]; then
50+
ARGS="$ARGS --baseline ${{ inputs.baseline }}"
51+
fi
52+
53+
# Generate GitHub Markdown comment
54+
pacta scan . $ARGS --format github > "$RUNNER_TEMP/pacta-comment.md" || true
55+
56+
# Generate JSON for machine-readable results
57+
pacta scan . $ARGS --format json > "$RUNNER_TEMP/pacta-results.json" || true
58+
59+
# Extract new violation count
60+
NEW=$(jq '.summary.by_status.new // 0' "$RUNNER_TEMP/pacta-results.json" 2>/dev/null || echo 0)
61+
echo "new_violations=$NEW" >> "$GITHUB_OUTPUT"
62+
63+
- name: Post or Update PR Comment
64+
if: github.event_name == 'pull_request'
65+
uses: actions/github-script@v7
66+
with:
67+
script: |
68+
const fs = require('fs');
69+
const commentPath = '${{ runner.temp }}/pacta-comment.md';
70+
const body = fs.readFileSync(commentPath, 'utf8');
71+
const marker = '<!-- pacta-architecture-report -->';
72+
const fullBody = marker + '\n' + body;
73+
74+
// Find existing comment to update (idempotent)
75+
const { data: comments } = await github.rest.issues.listComments({
76+
owner: context.repo.owner,
77+
repo: context.repo.repo,
78+
issue_number: context.issue.number,
79+
});
80+
const existing = comments.find(c => c.body.startsWith(marker));
81+
82+
if (existing) {
83+
await github.rest.issues.updateComment({
84+
owner: context.repo.owner,
85+
repo: context.repo.repo,
86+
comment_id: existing.id,
87+
body: fullBody,
88+
});
89+
} else {
90+
await github.rest.issues.createComment({
91+
owner: context.repo.owner,
92+
repo: context.repo.repo,
93+
issue_number: context.issue.number,
94+
body: fullBody,
95+
});
96+
}
97+
98+
- name: Fail on New Violations
99+
if: inputs.fail-on-violations == 'true' && steps.pacta.outputs.new_violations != '0'
100+
shell: bash
101+
run: |
102+
echo "::error::Pacta found ${{ steps.pacta.outputs.new_violations }} new architectural violation(s)"
103+
exit 1

0 commit comments

Comments
 (0)