Daily Project Digest #7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Daily Project Digest | |
| on: | |
| schedule: | |
| - cron: '0 7 * * *' # 07:00 UTC daily | |
| workflow_dispatch: {} # Allow manual trigger | |
| permissions: | |
| issues: write | |
| jobs: | |
| digest: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| fetch-depth: 0 # Full history for git log | |
| - name: Gather repository data | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| REPO="${{ github.repository }}" | |
| YESTERDAY=$(date -u -d '1 day ago' +%Y-%m-%dT00:00:00Z) | |
| TODAY=$(date -u +%Y-%m-%d) | |
| YESTERDAY_DATE=$(date -u -d '1 day ago' +%Y-%m-%d) | |
| echo "=== Gathering data for $YESTERDAY_DATE ===" >&2 | |
| # --- Stars and Forks --- | |
| gh api "repos/$REPO" --jq '{ | |
| stars: .stargazers_count, | |
| forks: .forks_count, | |
| open_issues: .open_issues_count, | |
| watchers: .subscribers_count | |
| }' > /tmp/repo-stats.json | |
| # --- Commits in last 24h --- | |
| git log --since="$YESTERDAY" --format='- [`%h`](https://github.com/'"$REPO"'/commit/%H) %s (%an)' > /tmp/commits.txt || true | |
| # --- Pull requests merged in last 24h --- | |
| gh pr list --repo "$REPO" --state merged --search "merged:>=$YESTERDAY_DATE" \ | |
| --json number,title,author,mergedAt,url --limit 50 \ | |
| --jq '.[] | "- [#\(.number)](\(.url)) \(.title) (@\(.author.login))"' \ | |
| > /tmp/merged-prs.txt || true | |
| # --- Pull requests opened in last 24h --- | |
| gh pr list --repo "$REPO" --state open --search "created:>=$YESTERDAY_DATE" \ | |
| --json number,title,author,url --limit 50 \ | |
| --jq '.[] | "- [#\(.number)](\(.url)) \(.title) (@\(.author.login))"' \ | |
| > /tmp/opened-prs.txt || true | |
| # --- Currently open PRs --- | |
| gh pr list --repo "$REPO" --state open \ | |
| --json number,title,author,url --limit 50 \ | |
| --jq '.[] | "- [#\(.number)](\(.url)) \(.title) (@\(.author.login))"' \ | |
| > /tmp/open-prs.txt || true | |
| # --- Issues opened in last 24h --- | |
| gh issue list --repo "$REPO" --state open --search "created:>=$YESTERDAY_DATE" \ | |
| --json number,title,author,url,labels --limit 50 \ | |
| --jq '.[] | "- [#\(.number)](\(.url)) \(.title) (@\(.author.login))"' \ | |
| > /tmp/opened-issues.txt || true | |
| # --- Issues closed in last 24h --- | |
| gh issue list --repo "$REPO" --state closed --search "closed:>=$YESTERDAY_DATE" \ | |
| --json number,title,url --limit 50 \ | |
| --jq '.[] | "- [#\(.number)](\(.url)) \(.title)"' \ | |
| > /tmp/closed-issues.txt || true | |
| # --- Currently open issues --- | |
| OPEN_ISSUE_COUNT=$(gh issue list --repo "$REPO" --state open --limit 1 --json number --jq 'length') | |
| echo "$OPEN_ISSUE_COUNT" > /tmp/open-issue-count.txt | |
| # --- Dependency updates (go.sum changes) --- | |
| git diff --name-only HEAD~5..HEAD 2>/dev/null | grep -E "go\.(mod|sum)" > /tmp/dep-changes.txt || true | |
| # --- CI status of latest run --- | |
| gh run list --repo "$REPO" --branch main --limit 3 \ | |
| --json conclusion,name,updatedAt,url \ | |
| --jq '.[] | "- \(.conclusion // "in_progress") — \(.name) [\(.updatedAt)](\(.url))"' \ | |
| > /tmp/ci-status.txt || true | |
| - name: Build digest | |
| run: | | |
| YESTERDAY_DATE=$(date -u -d '1 day ago' +%Y-%m-%d) | |
| TODAY=$(date -u +%Y-%m-%d) | |
| STARS=$(jq -r '.stars' /tmp/repo-stats.json) | |
| FORKS=$(jq -r '.forks' /tmp/repo-stats.json) | |
| WATCHERS=$(jq -r '.watchers' /tmp/repo-stats.json) | |
| OPEN_ISSUES=$(cat /tmp/open-issue-count.txt) | |
| cat > /tmp/digest-data.txt <<DATAEOF | |
| # Daily Project Digest: $TODAY | |
| ## Repository Stats | |
| | Metric | Count | | |
| |--------|-------| | |
| | Stars | $STARS | | |
| | Forks | $FORKS | | |
| | Watchers | $WATCHERS | | |
| | Open issues | $OPEN_ISSUES | | |
| ## Commits (last 24h) | |
| $(cat /tmp/commits.txt 2>/dev/null | head -30) | |
| $([ ! -s /tmp/commits.txt ] && echo "_No commits in the last 24 hours._") | |
| ## Pull Requests Merged (last 24h) | |
| $(cat /tmp/merged-prs.txt 2>/dev/null) | |
| $([ ! -s /tmp/merged-prs.txt ] && echo "_No PRs merged._") | |
| ## Pull Requests Opened (last 24h) | |
| $(cat /tmp/opened-prs.txt 2>/dev/null) | |
| $([ ! -s /tmp/opened-prs.txt ] && echo "_No new PRs._") | |
| ## Currently Open PRs | |
| $(cat /tmp/open-prs.txt 2>/dev/null) | |
| $([ ! -s /tmp/open-prs.txt ] && echo "_No open PRs._") | |
| ## Issues Opened (last 24h) | |
| $(cat /tmp/opened-issues.txt 2>/dev/null) | |
| $([ ! -s /tmp/opened-issues.txt ] && echo "_No new issues._") | |
| ## Issues Closed (last 24h) | |
| $(cat /tmp/closed-issues.txt 2>/dev/null) | |
| $([ ! -s /tmp/closed-issues.txt ] && echo "_No issues closed._") | |
| ## CI Status (latest runs on main) | |
| $(cat /tmp/ci-status.txt 2>/dev/null) | |
| ## Dependency Changes (last 5 commits) | |
| $(cat /tmp/dep-changes.txt 2>/dev/null) | |
| $([ ! -s /tmp/dep-changes.txt ] && echo "_No dependency changes._") | |
| DATAEOF | |
| - name: Generate AI summary | |
| env: | |
| OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} | |
| run: | | |
| if [ -z "$OPENROUTER_API_KEY" ]; then | |
| echo "::warning::OPENROUTER_API_KEY not set, posting raw digest" | |
| cp /tmp/digest-data.txt /tmp/digest-final.md | |
| exit 0 | |
| fi | |
| jq -n --rawfile data /tmp/digest-data.txt '{ | |
| model: "nvidia/nemotron-3-super-120b-a12b:free", | |
| messages: [ | |
| { | |
| role: "system", | |
| content: "You are a project digest assistant for mxcli, a Go CLI tool for reading and modifying Mendix application projects (.mpr files). Generate a concise daily digest from the raw data provided. Structure your response as:\n\n1. **Highlights** (1-3 bullet points of the most important changes)\n2. **Code Changes** (summarize commits by theme, not individually)\n3. **Pull Requests** (merged, opened, pending review)\n4. **Issues** (new, closed, total open)\n5. **Repository Health** (stars, forks, CI status)\n6. **Action Items** (anything that needs attention: failing CI, stale PRs, unanswered issues)\n\nKeep it concise — this is a daily scan, not a detailed report. Use markdown formatting." | |
| }, | |
| { | |
| role: "user", | |
| content: $data | |
| } | |
| ], | |
| max_tokens: 3000, | |
| temperature: 0.3 | |
| }' > /tmp/ai-request.json | |
| HTTP_CODE=$(curl -s -w "%{http_code}" -o /tmp/ai-response.json -X POST \ | |
| -H "Authorization: Bearer $OPENROUTER_API_KEY" \ | |
| -H "Content-Type: application/json" \ | |
| -d @/tmp/ai-request.json \ | |
| https://openrouter.ai/api/v1/chat/completions) | |
| if [ "$HTTP_CODE" = "200" ]; then | |
| SUMMARY=$(jq -r '.choices[0].message.content // empty' /tmp/ai-response.json) | |
| if [ -n "$SUMMARY" ]; then | |
| echo "$SUMMARY" > /tmp/digest-final.md | |
| else | |
| cp /tmp/digest-data.txt /tmp/digest-final.md | |
| fi | |
| else | |
| echo "::warning::OpenRouter returned HTTP $HTTP_CODE, using raw digest" | |
| cp /tmp/digest-data.txt /tmp/digest-final.md | |
| fi | |
| - name: Post digest as issue | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| TODAY=$(date -u +%Y-%m-%d) | |
| { | |
| cat /tmp/digest-final.md | |
| echo "" | |
| echo "---" | |
| echo "*Daily digest generated automatically — [workflow source](${{ github.server_url }}/${{ github.repository }}/blob/main/.github/workflows/daily-digest.yml)*" | |
| } > /tmp/issue-body.md | |
| gh issue create \ | |
| --repo "${{ github.repository }}" \ | |
| --title "Daily Digest: $TODAY" \ | |
| --body-file /tmp/issue-body.md \ | |
| --label "digest" |