CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history
gatetest-action.ts
Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.
| abfa9ad | 1 | /** |
| 2 | * `gluecron/gatetest@v1` — runs the external GateTest scanner against the | |
| 3 | * current commit and surfaces its pass/fail as the step exit code. | |
| 4 | * | |
| 5 | * Wraps `runGateTestScan` from `src/lib/gate.ts` (owned by another agent — | |
| 6 | * read-only import here). In dev where `GATETEST_URL` isn't configured the | |
| 7 | * step short-circuits with exitCode 0 so workflows don't fail spuriously. | |
| 8 | * | |
| 9 | * `with:` inputs are accepted but only a subset are honored in v1: | |
| 10 | * url, apiKey, timeout — reserved for future overrides. Today the action | |
| 11 | * always uses the process-wide config. The inputs are parsed defensively | |
| 12 | * so user typos don't break the run. | |
| 13 | */ | |
| 14 | ||
| 15 | import { eq } from "drizzle-orm"; | |
| 16 | import type { ActionHandler } from "../action-registry"; | |
| 17 | import { db } from "../../db"; | |
| 18 | import { repositories, users } from "../../db/schema"; | |
| 19 | import { runGateTestScan } from "../gate"; | |
| 20 | ||
| 21 | async function lookupOwnerAndRepo( | |
| 22 | repoId: string | |
| 23 | ): Promise<{ owner: string; repo: string } | null> { | |
| 24 | try { | |
| 25 | const [row] = await db | |
| 26 | .select({ | |
| 27 | name: repositories.name, | |
| 28 | ownerId: repositories.ownerId, | |
| 29 | }) | |
| 30 | .from(repositories) | |
| 31 | .where(eq(repositories.id, repoId)) | |
| 32 | .limit(1); | |
| 33 | if (!row) return null; | |
| 34 | ||
| 35 | const [u] = await db | |
| 36 | .select({ username: users.username }) | |
| 37 | .from(users) | |
| 38 | .where(eq(users.id, row.ownerId)) | |
| 39 | .limit(1); | |
| 40 | if (!u) return null; | |
| 41 | ||
| 42 | return { owner: u.username, repo: row.name }; | |
| 43 | } catch { | |
| 44 | return null; | |
| 45 | } | |
| 46 | } | |
| 47 | ||
| 48 | export const gatetestAction: ActionHandler = { | |
| 49 | name: "gluecron/gatetest", | |
| 50 | version: "v1", | |
| 51 | async run(ctx): Promise<import("../action-registry").ActionResult> { | |
| 52 | try { | |
| f3e1873 | 53 | // Dev-mode short-circuit: when the operator hasn't opted into GateTest |
| 54 | // by setting GATETEST_URL, skip quietly. We read the env var directly | |
| 55 | // (not via `config`) because `config.gatetestUrl` falls back to a | |
| 56 | // default URL, which would defeat the intent of "unset = skip". | |
| 57 | if (!process.env.GATETEST_URL) { | |
| abfa9ad | 58 | return { |
| 59 | exitCode: 0, | |
| 60 | stdout: "GateTest not configured — skipping", | |
| 61 | outputs: { status: "skipped" }, | |
| 62 | }; | |
| 63 | } | |
| 64 | ||
| 65 | const lookup = await lookupOwnerAndRepo(ctx.repoId); | |
| 66 | if (!lookup) { | |
| 67 | return { | |
| 68 | exitCode: 1, | |
| 69 | stderr: `GateTest: unable to resolve repository ${ctx.repoId}`, | |
| 70 | }; | |
| 71 | } | |
| 72 | ||
| 73 | const ref = ctx.ref || "refs/heads/main"; | |
| 74 | const sha = ctx.commitSha || ""; | |
| 75 | const result = await runGateTestScan(lookup.owner, lookup.repo, ref, sha); | |
| 76 | ||
| 77 | const stdout = `GateTest: ${result.passed ? "PASS" : "FAIL"} — ${result.details}`; | |
| 78 | return { | |
| 79 | exitCode: result.passed || result.skipped ? 0 : 1, | |
| 80 | stdout, | |
| 81 | outputs: { | |
| 82 | status: result.skipped | |
| 83 | ? "skipped" | |
| 84 | : result.passed | |
| 85 | ? "passed" | |
| 86 | : "failed", | |
| 87 | details: result.details, | |
| 88 | }, | |
| 89 | }; | |
| 90 | } catch (err) { | |
| 91 | return { | |
| 92 | exitCode: 1, | |
| 93 | stderr: | |
| 94 | "GateTest action error: " + | |
| 95 | (err instanceof Error ? err.message : String(err)), | |
| 96 | }; | |
| 97 | } | |
| 98 | }, | |
| 99 | }; |