Skip to content

Dev/ai summary dev

Dev/ai summary dev #21

name: qgs-ai-summary
# Post a concise, human-readable summary of the real changes to QGIS .qgs
# project files on a PR. scripts/qgs-diff.py builds a churn-free diff of the
# changed files; the GitHub Copilot CLI turns it into per-file bullet points;
# the result is posted as a single self-updating PR comment. Nothing derived
# is committed.
on:
pull_request:
paths:
- '**/*.qgs'
permissions:
contents: read
pull-requests: write
copilot-requests: write
concurrency:
group: qgs-ai-summary-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
summarise:
runs-on: ubuntu-latest
env:
MODEL: gpt-5.4
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Build churn-free diff
id: diff
run: |
WORK="$RUNNER_TEMP/qgs-ai"
mkdir -p "$WORK"
python3 scripts/qgs-diff.py diff --base "${{ github.base_ref }}" > "$WORK/diff.txt"
[ -s "$WORK/diff.txt" ] && echo "changed=1" >> "$GITHUB_OUTPUT" || echo "changed=0" >> "$GITHUB_OUTPUT"
- name: Set up Node for the Copilot CLI
if: steps.diff.outputs.changed == '1'
uses: actions/setup-node@v4
with:
node-version: 24
- name: Install Copilot CLI
if: steps.diff.outputs.changed == '1'
run: npm install -g @github/copilot
- name: Summarise with the Copilot CLI
id: ai
if: steps.diff.outputs.changed == '1'
env:
# Built-in workflow token — the Copilot CLI authenticates from this
# (via the copilot-requests permission), so no PAT/secret is needed.
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
WORK="$RUNNER_TEMP/qgs-ai"
cd "$WORK"
wc -l diff.txt
echo
echo "::group::diff (contains $(wc -l < diff.txt) lines)"
cat diff.txt
echo
echo "::endgroup::"
echo "::group::Generating summary with Copilot CLI (model $MODEL)"
PROMPT="$(printf '%s\n\n%s\n\n%s' \
'Use your file-reading with forceReadLargeFiles to read the entire file diff.txt in the current directory. It is small and unified with some change types already removed; diff headers (---, +++, @@) are present and may trip up the search tool, so read the file directly.' \
"$(cat "$GITHUB_WORKSPACE/scripts/assets/qgs-review-prompt.md")" \
'Write ONLY this markdown (no preamble or conclusion) to a file named summary.md in the current directory.')"
copilot \
--model "$MODEL" \
--no-ask-user \
--max-ai-credits 50 \
-p "$PROMPT" || true
cp "$WORK/summary.md" "$GITHUB_WORKSPACE/summary.md" 2>/dev/null || true
echo
echo "::endgroup::"
- name: Post sticky PR comment
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
PR: ${{ github.event.pull_request.number }}
CHANGED: ${{ steps.diff.outputs.changed }}
MODEL: ${{ env.MODEL }}
run: |
set -euo pipefail
MARKER='<!-- qgs-ai-summary -->'
{
echo "$MARKER"
echo "## 🗺️ QGIS project change summary"
echo
if [ "$CHANGED" = "1" ] && [ -s summary.md ]; then
cat summary.md
echo
echo "<sub>Generated by \`$MODEL\` via the GitHub Copilot CLI from a churn-free diff - verify against the file diff.</sub>"
else
echo "_No substantive QGIS project changes detected - only QGIS session churn._"
fi
} > comment.md
id=$(gh api "repos/$REPO/issues/$PR/comments" --paginate \
--jq ".[] | select(.body | contains(\"$MARKER\")) | .id" | head -n1)
if [ -n "$id" ]; then
gh api -X PATCH "repos/$REPO/issues/comments/$id" -F body=@comment.md >/dev/null
echo "updated comment $id"
else
gh api -X POST "repos/$REPO/issues/$PR/comments" -F body=@comment.md >/dev/null
echo "created comment"
fi