name: spec-review
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: read
pull-requests: write
jobs:
spec-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Install req-cli
run: cargo install req-cli --locked
- name: Generate spec review
id: review
shell: bash
run: |
set -euo pipefail
mkdir -p .review-out
# Markdown report; non-zero exit only if validate errors,
# which we intentionally ignore here (the gate step handles
# that). This is the narrative layer.
req review --base "origin/${{ github.base_ref }}" \
> .review-out/spec-review.md || true
# Truncate to 60k chars; upload full report as artefact.
MAX=60000
BYTES=$(wc -c < .review-out/spec-review.md)
if [ "$BYTES" -gt "$MAX" ]; then
head -c "$MAX" .review-out/spec-review.md > .review-out/spec-review.short.md
echo "" >> .review-out/spec-review.short.md
echo "_… truncated at ${MAX} chars. Full report available as workflow artefact._" \
>> .review-out/spec-review.short.md
cp .review-out/spec-review.short.md .review-out/_for-comment.md
else
cp .review-out/spec-review.md .review-out/_for-comment.md
fi
- uses: actions/upload-artifact@v5
with:
name: spec-review
path: .review-out/spec-review.md
- name: Post or update PR comment
uses: actions/github-script@v7
env:
MARKER: "<!-- req-spec-review:bot -->"
with:
script: |
const fs = require('fs');
const marker = process.env.MARKER;
const body = marker + "\n\n" +
fs.readFileSync('.review-out/_for-comment.md', 'utf8');
const { owner, repo } = context.repo;
const issue_number = context.issue.number;
// Find an existing bot comment with our marker.
const { data: comments } = await github.rest.issues.listComments({
owner, repo, issue_number, per_page: 100,
});
const existing = comments.find(c =>
c.user.type === 'Bot' && c.body && c.body.includes(marker)
);
if (existing) {
await github.rest.issues.updateComment({
owner, repo, comment_id: existing.id, body,
});
core.info(`Updated comment ${existing.id}`);
} else {
await github.rest.issues.createComment({
owner, repo, issue_number, body,
});
core.info('Created new comment');
}