github-enrichment Design
Populates the GitHub* tables for GitHubRepository rows queued with needsEnrichment=true, via the GitHub REST API (go-github v68, GITHUB_PAT).
Overview
- Batch size: 10 repos per run (
GITHUB_ENRICH_BATCH, max 100) - Schedule: Every 15 minutes (
cron(*/15 * * * ? *)), schedule/task-def namego-github-enrichment-processor - Concurrency: None needed — the claim (bump
lastSyncedAt) plus oldest-first ordering keeps a straggling sibling off the same rows; zombieguard kills stale tasks - State: The queue IS the table —
GitHubRepository.needsEnrichment = trueordered bylastSyncedAt ASC. NoBulkDataDumpTrackerrows.
Queue Sources
GitHubRepository rows are queued (needsEnrichment=true) by:
- vdb-api
/v2/cli.sca— upserts a placeholder row from a scan’s GitHub git remote (keyed byfullName, autoincrement id), re-armed whenenrichedAtis >24h stale. vdb-api also runs a shallow inline goroutine (repo + languages + branches); this processor is the deep/catch-up pass. - enrich-googleosi —
CreateOrUpdateGitHubRepositoryinserts rows with GitHub’s numeric id when a deps.devSOURCE_REPOlink points at github.com.
Processing Flow
- Select oldest N queued repos (
needsEnrichment=true ORDER BY "lastSyncedAt" ASC), claim them by bumpinglastSyncedAt - Per repo,
EnrichGitHubRepoFull(internal/enrichment/github_repo_enrichment.go):GET /repos/{owner}/{repo}→UPDATE "GitHubRepository" ... WHERE "fullName"=$1(nodeId, counts, license, topics, URLs, timestamps; setsenrichedAt, clearsneedsEnrichment/enrichmentError). NotCreateOrUpdateGitHubRepository— itsON CONFLICT ("id")insert violates thefullNameunique for rows created with autoincrement ids.- Owner → upsert
GitHubUserorGitHubOrganization(bylogin), linkuserId/organizationId - Branches →
GitHubBranch+GitHubRepositoryBranchjunction; contributors →GitHubRepoContributor; languages →GitHubRepoLanguage;UpsertOpenSSFScorecardvia api.scorecard.dev - Releases (fully paginated, page cap 20) →
GitHubRelease+ embedded assets →GitHubReleaseAsset - Issues (1 page of 100, newest, PRs filtered out) →
GitHubIssue+ embedded labels →GitHubIssueLabel; repo-level comments (1 page) →GitHubIssueComment - PRs (1 page of 100) →
GitHubPullRequest; reviews for the latest 20 PRs →GitHubPullRequestReview - Workflows + runs (1 page each) →
GitHubWorkflow,GitHubWorkflowRun - Check suites on the default-branch head →
GitHubCheckSuite; check runs for up to 5 suites →GitHubCheckRun - Deployments (1 page) →
GitHubDeployment; statuses for the latest 20 →GitHubDeploymentStatus
- Sub-resources are best-effort (logged, never abort the repo); only a failed core repo fetch fails the repo
- Rate-limit guard: batch stops early when the PAT’s remaining requests drop below 500
Failure Policy
- Permanent (HTTP 404 / 410 / 451 — private, deleted, DMCA-blocked):
needsEnrichment=false+enrichmentErrorrecorded — dropped from the queue - Transient (403 rate/policy, 5xx, network):
enrichmentErrorrecorded, flag stays true; the claim already bumpedlastSyncedAt, so the row rotates to the back of the queue
Skipped (admin/push scope required)
GitHubCollaborator, GitHubWebhook, secret-scanning / Dependabot / CodeQL alerts — a public-repo PAT receives 403 for these.
Request Budget
≈35–60 GitHub API calls per repo → ~600/cycle at N=10, ~2,400/hour at 4 cycles — under the 5,000/hour PAT limit, with the rate floor as backstop. The GITHUB_PAT is shared with other GitHub-calling processors via Secrets Manager (go_task_secrets_github).
Tables Written
GitHubRepository— core metadata,enrichedAt,userId/organizationIdlinksGitHubUser/GitHubOrganization— repo ownerGitHubBranch,GitHubRepositoryBranch— branches + junctionGitHubRepoContributor,GitHubRepoLanguage— contributors, language bytesOpenSSFScorecard— scorecard via api.scorecard.devGitHubRelease,GitHubReleaseAsset— releases (full history) + assetsGitHubIssue,GitHubIssueLabel,GitHubIssueComment— issuesGitHubPullRequest,GitHubPullRequestReview— PRs + reviewsGitHubWorkflow,GitHubWorkflowRun— Actions workflows + runsGitHubCheckSuite,GitHubCheckRun— checks on the default-branch headGitHubDeployment,GitHubDeploymentStatus— deployments
Schema Note
GitHub’s modern entity ids exceed int4 (issue ids >4B, workflow-run ids >27B, check-suite ids >66B). The saas migration 20260610000002_github_activity_ids_bigint widened the activity-id columns (and ScannerRun.workflowRunId/checkRunId) to bigint. GitHubRepository.id remains int4 — revisit when GitHub repo ids approach 2³¹.
S3 Persistence
Not used. This processor does not currently archive payloads or quarantine failures to S3. Per the S3 Persistence Contract this is non-compliant — see the compliance matrix for the implementation roadmap.
⚠ Not in the compliance matrix — status needs verification.
Expected paths when implemented:
- Archive:
github-enrichment/files/{sha256}/{filename} - Quarantine:
failed-feeds/github-enrichment/{YYYY-MM-DD}/{reason}/{filename} - Likely reasons: (none documented)