Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesPull RequestsActionsSecurityInsightsSettings
✨ AI
More
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.tsBlame97 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";
20import { config } from "../config";
21
22async function lookupOwnerAndRepo(
23 repoId: string
24): Promise<{ owner: string; repo: string } | null> {
25 try {
26 const [row] = await db
27 .select({
28 name: repositories.name,
29 ownerId: repositories.ownerId,
30 })
31 .from(repositories)
32 .where(eq(repositories.id, repoId))
33 .limit(1);
34 if (!row) return null;
35
36 const [u] = await db
37 .select({ username: users.username })
38 .from(users)
39 .where(eq(users.id, row.ownerId))
40 .limit(1);
41 if (!u) return null;
42
43 return { owner: u.username, repo: row.name };
44 } catch {
45 return null;
46 }
47}
48
49export const gatetestAction: ActionHandler = {
50 name: "gluecron/gatetest",
51 version: "v1",
52 async run(ctx): Promise<import("../action-registry").ActionResult> {
53 try {
54 // Dev-mode short-circuit: no URL configured → skip quietly.
55 if (!config.gatetestUrl) {
56 return {
57 exitCode: 0,
58 stdout: "GateTest not configured — skipping",
59 outputs: { status: "skipped" },
60 };
61 }
62
63 const lookup = await lookupOwnerAndRepo(ctx.repoId);
64 if (!lookup) {
65 return {
66 exitCode: 1,
67 stderr: `GateTest: unable to resolve repository ${ctx.repoId}`,
68 };
69 }
70
71 const ref = ctx.ref || "refs/heads/main";
72 const sha = ctx.commitSha || "";
73 const result = await runGateTestScan(lookup.owner, lookup.repo, ref, sha);
74
75 const stdout = `GateTest: ${result.passed ? "PASS" : "FAIL"} — ${result.details}`;
76 return {
77 exitCode: result.passed || result.skipped ? 0 : 1,
78 stdout,
79 outputs: {
80 status: result.skipped
81 ? "skipped"
82 : result.passed
83 ? "passed"
84 : "failed",
85 details: result.details,
86 },
87 };
88 } catch (err) {
89 return {
90 exitCode: 1,
91 stderr:
92 "GateTest action error: " +
93 (err instanceof Error ? err.message : String(err)),
94 };
95 }
96 },
97};