diff --git a/.github/workflows/monitor-upstream.yml b/.github/workflows/monitor-upstream.yml new file mode 100644 index 000000000..f2dfd250c --- /dev/null +++ b/.github/workflows/monitor-upstream.yml @@ -0,0 +1,124 @@ +name: Monitor Upstream Changes + +on: + schedule: + - cron: '0 8 * * *' # Run daily at 08:00 UTC + workflow_dispatch: # Allow manual triggering + +permissions: + contents: read + issues: write + +jobs: + check-upstream: + runs-on: ubuntu-latest + + steps: + - name: Checkout fork + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Fetch upstream + run: | + git remote add upstream https://github.com/microsoft/graphrag.git + git fetch upstream main + + - name: Compute outstanding changes + run: | + COUNT=$(git rev-list --count HEAD..upstream/main 2>/dev/null || echo "0") + echo "$COUNT" > /tmp/commit-count.txt + git log --oneline --no-merges -50 HEAD..upstream/main > /tmp/commit-list.txt 2>/dev/null || true + + - name: Create or update tracking issue + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + + const count = parseInt(fs.readFileSync('/tmp/commit-count.txt', 'utf8').trim(), 10); + const rawList = fs.readFileSync('/tmp/commit-list.txt', 'utf8').trim(); + + // Ensure the tracking label exists + try { + await github.rest.issues.getLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + name: 'upstream-tracking', + }); + } catch { + await github.rest.issues.createLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + name: 'upstream-tracking', + color: '0075ca', + description: 'Tracks outstanding changes from the upstream microsoft/graphrag repository', + }); + } + + const now = new Date().toUTCString(); + const comparisonUrl = + 'https://github.com/microsoft/graphrag/compare/main...sharpninja:graphrag:main'; + + const commitSection = + count === 0 + ? '_No outstanding commits — fork is up to date with upstream._' + : '```\n' + rawList + '\n```'; + + const body = + `@sharpninja\n\n` + + `## Outstanding Changes from \`microsoft/graphrag\`\n\n` + + `**${count} commit(s) pending** as of ${now}\n\n` + + `### Recent upstream commits not yet in this fork\n\n` + + commitSection + '\n\n' + + `---\n` + + `[View full comparison on GitHub](${comparisonUrl})\n\n` + + `*This issue is updated automatically every day by the [Monitor Upstream Changes]` + + `(../../actions/workflows/monitor-upstream.yml) workflow.*`; + + const title = `\uD83D\uDD04 Upstream Tracking: ${count} pending change(s) from microsoft/graphrag`; + + // Find an existing open tracking issue + const existing = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + labels: 'upstream-tracking', + per_page: 1, + }); + + if (existing.data.length > 0) { + const issueNumber = existing.data[0].number; + + // Update the issue body and title + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + title, + body, + }); + + // Add a comment so @sharpninja receives a new notification + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: + `@sharpninja **Update ${now}**: ` + + `**${count}** outstanding change(s) from upstream detected.\n\n` + + `[View full comparison](${comparisonUrl})`, + }); + + console.log(`Updated issue #${issueNumber}`); + } else { + const created = await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title, + body, + labels: ['upstream-tracking'], + }); + + console.log(`Created issue #${created.data.number}`); + }