Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
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.

gatetest-action.tsBlame99 lines · 1 contributor
abfa9adClaude1/**
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
15import { eq } from "drizzle-orm";
16import type { ActionHandler } from "../action-registry";
17import { db } from "../../db";
18import { repositories, users } from "../../db/schema";
19import { runGateTestScan } from "../gate";
20
21async 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
48export const gatetestAction: ActionHandler = {
49 name: "gluecron/gatetest",
50 version: "v1",
51 async run(ctx): Promise<import("../action-registry").ActionResult> {
52 try {
f3e1873Claude53 // 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) {
abfa9adClaude58 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};