Forge CI reader for four forges

Task 11755 · Done · Coder · created · updated

## Epic 11717 — Executive AI command center Original requirement (verbatim): > Implement Something like this. Share code with Operator Dashboard. > 10. Executive AI command center — Major differentiator > Create one dashboard where a founder or CTO can see: All active projects. All AI employees. Development progress. Project health. Bugs and risks. Development expenses. Deployment status. Productivity and quality metrics. > The owner should be able to ask: "What's happening with my company today?" and receive an accurate answer. Settled inputs: the BA PRD (task 11718, R1–R14) and the Architecture (task 11719, §2.2 is this child's spec; AD-3, AD-7). Read both artifacts on the epic before building. ## This child (Architecture C1): `apps/api/app/forge_ci.py` Pinned seam (child "Deployments endpoint and CI health" builds against it — do not change the shape): ```python @dataclass(frozen=True) class CiRun: status: Literal["success", "failure", "running", "cancelled", "unknown"] workflow: Optional[str]; branch: str; at: Optional[datetime]; url: Optional[str]; reason: Optional[str] def latest_run(session: Session, project: Project, viewer: AdminUser) -> CiRun: ... ``` - One read per forge, latest run/pipeline on `project.integration_branch` of the primary repo (`ProjectRepo.is_primary`, `models/projects.py:228-234`): - GitHub `GET /repos/{o}/{r}/actions/runs?branch=&per_page=1` - GitLab `GET /projects/{id}/pipelines?ref=&per_page=1` - Bitbucket `GET /repositories/{ws}/{slug}/pipelines/?target.branch=&sort=-created_on&pagelen=1` - Azure DevOps `GET {org}/{project}/_apis/build/builds?branchName=refs/heads/<b>&$top=1` Status mapping per forge pinned in one table in the module. Written fresh in the API — never import `apps/jaahd/forge_cli/adapters/*` (apps never cross-import). - Credential: the VIEWER's own forge connection — `git_access.resolve_for_user(session, viewer, repo)` (`git_access.py:315`) then `rest_login_for` (`:502`). Missing/dead → `unknown` with reason like "Connect GitHub in Profile > Git to see CI"; `GitAccessNeedsReconnect` → "Reconnect GitHub". - Never raises to the caller: no repo, 5s timeout, 401/403/404, 429 → `unknown` with the reason in words. Provide a bounded batch helper (thread pool of 8, total cap 8s; a project still pending at the cap → `unknown` "Timed out") for the page builders. - Cache: process-local TTL 5 min keyed `(project_id, branch, credential_id)`; failures cached 60s. Never persisted. - Edition: ADD `[feature.exec_dashboard]` (label "Command center", `editions=["cloud"]`) to `packages/editions/features.toml` listing `apps/api/app/forge_ci.py` (if the row already exists because "Command center API core endpoints" merged first, append the path instead), and regenerate both `edition_features.py` files, so `forge_ci.py` never ships in the community tree (the CE orphans check in `tools/mirror/check_trees.py` would fail otherwise). Whichever of this child and the API-core child merges first creates the row; the other appends. - Tests: recorded-response fixtures per forge (GitHub, GitLab, Bitbucket, Azure) covering success/failure/running/cancelled and each `unknown` cause; cache TTL and failure cache; timeout cap. Requirement R10 — Deployment status (ask 10, OD-7), the parts this child owns (verbatim): - **AC10.1** For each project it shows the last merges to the integration branch (merged / failed / queued, with time) from the merge lane, and the forge's latest CI/deploy workflow run on the integration branch (status, workflow name, time, link). Verify: on dev, for one project, compare with the forge's Actions page for that branch. The status and time match. — this child owns the CI half. - **AC10.2** States: a project with no repo, no forge credential, a forge error or rate limiting shows "unknown" with the reason in words. The page never errors or blanks. A project with no merge lane shows only CI. Verify on dev with a project that has no repo. — this child owns the CI states. - **AC10.3** No deploy history is stored (OD-7). Verify: the PR adds no table or column for deploy runs. Credentials & reach: - AC10.1 GitHub CI live — `me/GitHub (ruzhukov)` against api.github.com (reachable: app.jaah.ai and GitHub egress OK), repo `jaah-ai/jaah` branch `develop` — **verified**: credential_get OK. The coder compares `forge_ci.latest_run` with `GET /repos/jaah-ai/jaah/actions/runs?branch=develop&per_page=1`. - AC10.1 GitLab / Bitbucket CI — `me/GitLab (rzhukov)`, `me/Bitbucket (Roman Zhukov)` — **deferred**: live check not required (AD-7). Recorded-response fixtures are the oracle. - AC10.1 Azure DevOps CI — none on the roster — **deferred**: AD-7, fixture only. - Local gates (`./dc check quick/full`, pytest, vitest, Playwright local e2e) — worktree only — **verified**. Out of scope: Do NOT add a deploy/CI history table or persist CI runs (OD-7). Do NOT ingest forge issues (GitHub/GitLab/Bitbucket/Azure) or Jira bugs (OD-12). Do NOT import jaahd forge adapters. Do NOT build the exec_dashboard endpoints, the merge-lane reads (child "Deployments endpoint and CI health") or any UI. Do NOT change the Operator dashboard's behaviour, tabs, routes or data. Do NOT add a plan gate or enablement flag (OD-10). Done means: - AC10.1 (CI half) — GitHub: `forge_ci.latest_run` for `jaah-ai/jaah` `develop`, run live with the viewer credential, returns the same status, workflow name, time and html url as `GET /repos/jaah-ai/jaah/actions/runs?branch=develop&per_page=1`; cite both outputs. GitLab/Bitbucket/Azure: recorded-response fixture tests pass (deferred live — AD-7). - AC10.2 (CI states) — unit tests show no repo, no credential, reconnect-needed, 401/403/404, 429, timeout and batch-cap each return `unknown` with a human-readable reason (a sentence a tenant Owner can act on, not an exception string); the function never raises. - AC10.3 — the PR adds no migration, table or column; the cache is process-local only. - Edition — `packages/editions/features.toml` lists `forge_ci.py` under the cloud-only `exec_dashboard` feature; regenerated edition files committed; community-edition tree check passes. - `./dc check quick` green; merge lane `./dc check full` green.

Outcome

Built apps/api/app/forge_ci.py (GitHub/GitLab/Bitbucket/Azure latest CI run via viewer's connection, unknown+reason on every failure, 5m/60s process cache, 8x8s batch) + cloud-only exec_dashboard edition row. Live GitHub read matches API; 42 tests, quick gate green; PR #7468 queued. Memory: none applied.

Pull request

Artifacts

Activity

  • Draft
  • Ready
  • Runner started
  • Runner ended (done)