-
Notifications
You must be signed in to change notification settings - Fork 3
171 lines (152 loc) Β· 5.62 KB
/
musubi-reusable.yml
File metadata and controls
171 lines (152 loc) Β· 5.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
name: MUSUBI Reusable Workflow
permissions:
contents: read
issues: write
pull-requests: write
on:
workflow_call:
inputs:
command:
description: 'MUSUBI command to run'
type: string
default: 'validate'
feature:
description: 'Feature name to analyze'
type: string
required: false
fail-on-gaps:
description: 'Fail if gaps found'
type: boolean
default: false
constitution-check:
description: 'Run constitutional check'
type: boolean
default: true
post-comment:
description: 'Post comment on PR'
type: boolean
default: true
outputs:
validation-result:
description: 'Validation result'
value: ${{ jobs.musubi.outputs.validation-result }}
coverage:
description: 'Coverage percentage'
value: ${{ jobs.musubi.outputs.coverage }}
gaps-count:
description: 'Number of gaps'
value: ${{ jobs.musubi.outputs.gaps-count }}
permissions:
contents: read
pull-requests: write
jobs:
musubi:
name: MUSUBI Validation
runs-on: ubuntu-latest
outputs:
validation-result: ${{ steps.validate.outputs.result }}
coverage: ${{ steps.analyze.outputs.coverage }}
gaps-count: ${{ steps.gaps.outputs.count }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
- name: Install Dependencies
run: npm ci || npm install
- name: Install MUSUBI
run: npm install -g musubi-sdd
- name: Constitutional Check
id: constitution
if: inputs.constitution-check
run: |
echo "ποΈ Constitutional Governance Check"
if [ -f "steering/rules/constitution.md" ]; then
npx musubi validate --constitution && echo "result=passed" >> $GITHUB_OUTPUT || echo "result=failed" >> $GITHUB_OUTPUT
else
echo "β οΈ No constitution.md found"
echo "result=skipped" >> $GITHUB_OUTPUT
fi
- name: Validate
id: validate
if: contains(fromJson('["validate", "all"]'), inputs.command)
run: |
echo "β
Running Validation"
if npx musubi validate ${{ inputs.feature && format('--feature {0}', inputs.feature) || '' }}; then
echo "result=passed" >> $GITHUB_OUTPUT
else
echo "result=failed" >> $GITHUB_OUTPUT
exit 1
fi
- name: Analyze
id: analyze
if: contains(fromJson('["analyze", "all"]'), inputs.command)
run: |
echo "π Running Analysis"
RESULT=$(npx musubi analyze --format json ${{ inputs.feature && format('--feature {0}', inputs.feature) || '' }} 2>/dev/null || echo '{"coverage":0}')
COVERAGE=$(echo "$RESULT" | jq -r '.coverage // 0')
echo "coverage=$COVERAGE" >> $GITHUB_OUTPUT
echo "Coverage: $COVERAGE%"
- name: Check Gaps
id: gaps
if: contains(fromJson('["gaps", "trace", "all"]'), inputs.command)
run: |
echo "π Checking Traceability Gaps"
RESULT=$(npx musubi gaps --format json ${{ inputs.feature && format('--feature {0}', inputs.feature) || '' }} 2>/dev/null || echo '{"gaps":[]}')
COUNT=$(echo "$RESULT" | jq '.gaps | length // 0')
echo "count=$COUNT" >> $GITHUB_OUTPUT
echo "Gaps: $COUNT"
if [ "$COUNT" -gt 0 ] && [ "${{ inputs.fail-on-gaps }}" = "true" ]; then
echo "β Gaps found, failing"
npx musubi gaps ${{ inputs.feature && format('--feature {0}', inputs.feature) || '' }}
exit 1
fi
- name: Generate Report
id: report
run: |
cat << 'EOF' > musubi-report.md
## π MUSUBI SDD Report
| Check | Status |
|-------|--------|
| Constitutional | ${{ steps.constitution.outputs.result || 'N/A' }} |
| Validation | ${{ steps.validate.outputs.result || 'N/A' }} |
| Coverage | ${{ steps.analyze.outputs.coverage || 'N/A' }}% |
| Gaps | ${{ steps.gaps.outputs.count || 'N/A' }} |
---
*Generated by [MUSUBI SDD](https://github.com/your-org/musubi)*
EOF
echo "path=musubi-report.md" >> $GITHUB_OUTPUT
- name: Comment on PR
if: github.event_name == 'pull_request' && inputs.post-comment
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const report = fs.readFileSync('musubi-report.md', 'utf8');
// Find existing comment
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});
const botComment = comments.find(c =>
c.user.type === 'Bot' && c.body.includes('MUSUBI SDD Report')
);
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: report
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: report
});
}