Skip to content

Fix shell quoting: use Python to build JSON request payload #20

Fix shell quoting: use Python to build JSON request payload

Fix shell quoting: use Python to build JSON request payload #20

name: FVUtils Weekly Report
on:
schedule:
- cron: '0 9 * * 1'
workflow_dispatch:
permissions:
contents: read
pull-requests: read
discussions: write
env:
MODEL: gpt-5-mini-high
jobs:
generate-news:
runs-on: ubuntu-latest
steps:
# ── Step 1: Identify active repos ────────────────────────────────────────
# Find fvutils repos that have had pushes in the past 7 days.
- name: Identify active repos
env:
GH_TOKEN: ${{ github.token }}
run: |
END_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
START_DATE=$(date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ)
echo "START_DATE=$START_DATE" >> $GITHUB_ENV
echo "END_DATE=$END_DATE" >> $GITHUB_ENV
echo "Scanning fvutils org for repos pushed since $START_DATE ..."
gh repo list fvutils --limit 100 --json name,pushedAt \
| jq -r --arg start "$START_DATE" \
'.[] | select(.pushedAt >= $start) | .name' \
> /tmp/active_repos.txt
echo "Active repos:"
cat /tmp/active_repos.txt
# ── Step 2: Collect details from active repos ────────────────────────────
# For each active repo, gather commits, merged PRs, and updated issues.
- name: Collect details from active repos
env:
GH_TOKEN: ${{ github.token }}
run: |
: > /tmp/activity.md # start fresh
while IFS= read -r repo; do
echo "## fvutils/$repo" >> /tmp/activity.md
echo "" >> /tmp/activity.md
# Commits
COMMITS=$(gh api \
"repos/fvutils/$repo/commits?since=${START_DATE}&until=${END_DATE}&per_page=50" \
--jq '.[] | "- \(.commit.message | split("\n")[0]) [\(.sha[0:7])]"' \
2>/dev/null || true)
if [ -n "$COMMITS" ]; then
echo "### Commits" >> /tmp/activity.md
echo "$COMMITS" >> /tmp/activity.md
echo "" >> /tmp/activity.md
fi
# Pull requests (merged or opened this week)
PRS=$(gh pr list --repo "fvutils/$repo" --state all \
--search "updated:>=$(echo $START_DATE | cut -c1-10)" \
--json number,title,state,author \
--jq '.[] | "- #\(.number) \(.title) [\(.state)] (@\(.author.login))"' \
2>/dev/null || true)
if [ -n "$PRS" ]; then
echo "### Pull Requests" >> /tmp/activity.md
echo "$PRS" >> /tmp/activity.md
echo "" >> /tmp/activity.md
fi
# Issues opened or updated this week
ISSUES=$(gh issue list --repo "fvutils/$repo" --state all \
--search "updated:>=$(echo $START_DATE | cut -c1-10)" \
--json number,title,state,author \
--jq '.[] | "- #\(.number) \(.title) [\(.state)] (@\(.author.login))"' \
2>/dev/null || true)
if [ -n "$ISSUES" ]; then
echo "### Issues" >> /tmp/activity.md
echo "$ISSUES" >> /tmp/activity.md
echo "" >> /tmp/activity.md
fi
done < /tmp/active_repos.txt
echo "--- collected activity ---"
cat /tmp/activity.md
# ── Step 3: Generate news item via gh api /models/$MODEL ─────────────────
# Pass the raw activity to gpt-5-mini-high and ask for a polished news item.
- name: Generate news item
env:
GH_TOKEN: ${{ github.token }}
run: |
WEEK_END=$(date -u '+%d %b %Y')
# Build the JSON payload with Python to avoid shell quoting issues
python3 - << PYEOF
import json, os

Check failure on line 102 in .github/workflows/fvutils-weekly-report.yaml

View workflow run for this annotation

GitHub Actions / .github/workflows/fvutils-weekly-report.yaml

Invalid workflow file

You have an error in your yaml syntax on line 102
activity = open('/tmp/activity.md').read()
week_end = "$WEEK_END"
model = "$MODEL"
prompt = (
"You are a technical writer for an open-source verification tools project.\n\n"
f"Below is raw weekly activity (commits, PRs, issues) from the fvutils GitHub org "
f"for the week ending {week_end}.\n\n"
+ activity +
"\n\nWrite a concise weekly news item suitable for the project website. "
"Include: a short overall summary paragraph, then a per-repo highlights section "
"using bullet points, and a brief \"What's next\" closing line. "
"Be factual, avoid hype, use past tense for completed work."
)
payload = {"model": model, "messages": [{"role": "user", "content": prompt}],
"max_tokens": 600, "temperature": 0.4}
with open('/tmp/request.json', 'w') as f:
json.dump(payload, f)
print("Request JSON written.")
PYEOF
gh api -X POST "/models/$MODEL/chat/completions" \
--input /tmp/request.json \
--jq '.choices[0].message.content' \
> /tmp/news_item.md 2>/tmp/api_error.txt \
|| {
echo "WARNING: GitHub Models API call failed:"
cat /tmp/api_error.txt
echo "Generating fallback news item..."
printf "## fvutils Weekly Highlights — week ending %s\n\n" "$WEEK_END" > /tmp/news_item.md
cat /tmp/activity.md >> /tmp/news_item.md
echo "" >> /tmp/news_item.md
echo "*Auto-generated from commit/PR/issue metadata — AI summarization unavailable.*" >> /tmp/news_item.md
}
echo "=== Generated news item ==="
cat /tmp/news_item.md
# ── Publish: post to fvutils/.github Discussions ─────────────────────────
- name: Post to Discussions
env:
GH_TOKEN: ${{ github.token }}
run: |
WEEK_NUM=$(date -u +%V)
YEAR=$(date -u +%Y)
TITLE="Weekly Highlights — Week $WEEK_NUM, $YEAR"
BODY=$(cat /tmp/news_item.md)
BODY="$BODY"$'\n\n---\n*Generated automatically by [fvutils-weekly-report](../actions/workflows/fvutils-weekly-report.yaml) using '"$MODEL"'.*'
gh api graphql -f query='
mutation($repositoryId: ID!, $categoryId: ID!, $title: String!, $body: String!) {
createDiscussion(input: {
repositoryId: $repositoryId
categoryId: $categoryId
title: $title
body: $body
}) {
discussion { id url title }
}
}
' \
-f repositoryId="R_kgDOHMTiUw" \
-f categoryId="DIC_kwDOHMTiU84C2BrA" \
-f title="$TITLE" \
-f body="$BODY" \
| jq -r '.data.createDiscussion.discussion | "Created: \(.title)\nURL: \(.url)"'