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
62 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.

Merge the desktop app's settings and runner in the main window: the runner is a dot beside the title bar's Settings button with a menu of its own (its state, each kind of job and what it runs, Start and Stop, updates, the log), Settings opens as a dialog in the window with its sections down the side, the separate windows stay only for when the site isn't showing, and every button that asks the app for something shows it is working until something happens.1import assert from "node:assert/strict";
2import { test } from "node:test";
3
4import { type DesktopSettingsView, KEPT, checkFailed, hostOf, sectionOf, settingsOf, updateLine } from "./desktop-settings.ts";
5
6function view(over: Partial<DesktopSettingsView> = {}): DesktopSettingsView {
7 return {
8 startHidden: true,
9 closeToTray: true,
10 notifications: true,
11 flash: true,
12 badge: true,
13 systemTitleBar: false,
14 zoom: 1.1,
15 autoUpdate: true,
16 runner: true,
17 runnerBackend: "sandboxed",
18 runnerWorkspace: "acme",
19 runnerCapabilities: { linux: true, windows: false, macos: true },
20 openAtLogin: true,
21 version: "0.3.6",
22 platform: "windows",
23 server: "https://g1t.sh/",
24 updateReady: null,
25 checkedAt: null,
26 titleBarChanged: false,
27 customFrame: true,
28 runnerView: {} as DesktopSettingsView["runnerView"],
29 ...over,
30 };
31}
32
33test("a change is saved over the settings as the app has them, and nothing else", () => {
34 // The zoom changed from the menu while the dialog was open: turning the badge off keeps it.
35 const saved = settingsOf(view({ zoom: 1.5 }), { badge: false });
36 assert.equal(saved.badge, false);
37 assert.equal(saved.zoom, 1.5);
38 assert.deepEqual(saved.runnerCapabilities, { linux: true, windows: false, macos: true });
39 // Only what the app keeps goes back: not what it only shows.
40 assert.deepEqual(Object.keys(saved).sort(), [...KEPT].sort());
41});
42
43test("the app opens the section it names, or the first", () => {
44 assert.equal(sectionOf("updates"), "updates");
45 assert.equal(sectionOf("runner"), "runner");
46 assert.equal(sectionOf("plan9"), "general");
47 assert.equal(sectionOf(null), "general");
48});
49
50test("updates say where this copy stands", () => {
51 assert.match(updateLine(view({ updateReady: "0.3.7" })), /^Version 0\.3\.7 is downloaded/);
52 assert.match(updateLine(view({ checkedAt: Date.now() })), /^Up to date\. Last checked today at /);
53 assert.match(updateLine(view()), /checks on its own shortly/);
54 assert.equal(updateLine(view({ autoUpdate: false })), "Checking on its own is off.");
55});
56
57test("a failed check says why in a line", () => {
58 assert.match(checkFailed("error sending request for url"), /Could not reach g1t\.sh/);
59 assert.match(checkFailed(new Error("")), /Could not reach g1t\.sh/);
60 assert.equal(checkFailed("the signature is wrong"), "Could not check: the signature is wrong");
61 assert.equal(hostOf("https://g1t.example.com/"), "g1t.example.com");
62});

This file's history is long; its oldest lines are credited to the oldest commit read.