Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t.sh
53 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

g1t can be checked against GitHub. The Conformance workflow, the same file in `.g1t/workflows/` and `.github/workflows/` (a test keeps them identical), runs by hand on either; each run's report records which runner variables were set and of what kind, every key of the contexts and the event payload with its type, how the workspace is laid out, and the values outputs, `GITHUB_ENV` and `GITHUB_PATH`, multi-line outputs, `working-directory`, job outputs, the matrix, a cache round trip, an artifact round trip, `hashFiles` and the expression functions give. `node scripts/conformance-diff.mjs github.json g1t.json` lists what GitHub has that g1t lacks or has otherwise, and what only g1t has. It reads no secrets. CONTRIBUTING says how to run it, and CI runs its tests.1#!/usr/bin/env node
2// Compares what the Conformance workflow (.g1t/workflows/conformance.yml)
3// saw on GitHub with what it saw on g1t: each run's `conformance-report`
4// artifact, conformance.json. What GitHub has and g1t lacks, or has of
5// another type, and every check whose value differs, is a difference, and
6// the exit code is 1. What g1t has beyond GitHub is listed, as g1t's own.
7//
8// node scripts/conformance-diff.mjs github.json g1t.json
9
10import { readFileSync } from "node:fs";
11
12/** The differences between `github`'s and `g1t`'s reports, by section. */
13export function compare(github, g1t) {
14 const found = { missing: [], different: [], extra: [] };
15 const mapping = (section, theirs = {}, ours = {}) => {
16 for (const [key, value] of Object.entries(theirs)) {
17 if (!(key in ours)) found.missing.push(`${section} ${key} (${value})`);
18 else if (ours[key] !== value) found.different.push(`${section} ${key}: GitHub ${JSON.stringify(value)}, g1t ${JSON.stringify(ours[key])}`);
19 }
20 for (const [key, value] of Object.entries(ours)) {
21 if (!(key in theirs)) found.extra.push(`${section} ${key} (${value})`);
22 }
23 };
24 mapping("variable", github.variables, g1t.variables);
25 mapping("layout", github.layout, g1t.layout);
26 for (const name of new Set([...Object.keys(github.contexts ?? {}), ...Object.keys(g1t.contexts ?? {})])) {
27 mapping(`${name}.`, github.contexts?.[name], g1t.contexts?.[name]);
28 }
29 mapping("event", github.event ?? {}, g1t.event ?? {});
30 mapping("check", github.checks, g1t.checks);
31 return found;
32}
33
34if (process.argv[1] && import.meta.url === new URL(`file://${process.argv[1]}`).href) {
35 const [githubFile, g1tFile] = process.argv.slice(2);
36 if (!githubFile || !g1tFile) {
37 console.error("usage: node scripts/conformance-diff.mjs github.json g1t.json");
38 process.exit(2);
39 }
40 const read = (file) => JSON.parse(readFileSync(file, "utf8"));
41 const found = compare(read(githubFile), read(g1tFile));
42 const section = (title, items) => {
43 if (items.length === 0) return;
44 console.log(`${title} (${items.length})`);
45 for (const item of items) console.log(` ${item}`);
46 };
47 section("On GitHub, not on g1t", found.missing);
48 section("Different on g1t", found.different);
49 section("Only on g1t", found.extra);
50 const failing = found.missing.length + found.different.length;
51 console.log(failing === 0 ? "g1t matches GitHub." : `${failing} differences from GitHub.`);
52 process.exit(failing === 0 ? 0 : 1);
53}