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

Commit

A computer with a sandbox the desktop app has no record of making can be put right with one button. The app said "this computer has another sandbox" and told the person to run `g1t-runner sandbox down --delete`, which looks in the default folder rather than the app's own, so it removed nothing. Most often the sandbox was the app's own from before it was uninstalled with its data deleted and installed again: deleting the app's folder left the WSL distribution behind. Now the message's button is Remove it and start again: it asks first, then removes the sandbox with its VM and registration from the app's own folder and starts a sandbox of the app's own, registered with the workspace. Uninstalling on Windows with Delete the application data ticked removes the sandbox too (an installer hook; not on an update, which keeps everything). And in the Runner window a pressed fix shows a spinner and stays pressed until the status that follows, rather than looking dead until something happens. The desktop guide says so.

syntaqxcommitted Parent14f96e9Browse files
7 files+121−150/7 viewed
+39−7
5353 button.addEventListener("click", function () {
5454 if (action.id === "choose_workspace") return byId("runnerWorkspace").focus();
5555 if (action.id === "choose_backend") return byId("runnerBackend").focus();
56− invoke("runner_control", { action: action.id }).then(function () {
57− if (action.id.indexOf("copy_") !== 0) return;
58− button.textContent = "Copied";
59− setTimeout(function () {
60− button.textContent = action.label;
61− }, 2000);
62− }, fail);
56+ if (action.id === "remove_sandbox" && !window.confirm(REMOVE_SANDBOX)) return;
57+ var copying = action.id.indexOf("copy_") === 0;
58+ // Busy until the status that follows draws the buttons again, so a
59+ // press is seen to do something; given back if nothing comes.
60+ if (!copying) working(button);
61+ invoke("runner_control", { action: action.id }).then(
62+ function () {
63+ if (!copying) return;
64+ button.textContent = "Copied";
65+ setTimeout(function () {
66+ button.textContent = action.label;
67+ }, 2000);
68+ },
69+ function (error) {
70+ done(button, action.label);
71+ fail(error);
72+ },
73+ );
6374 });
6475 return button;
6576 }
6677
78+ var REMOVE_SANDBOX =
79+ "Remove this computer's sandbox? Its VM and registration go, and g1t makes its own in their place, registered with your workspace. Its old runners stay listed on g1t until you remove them there.";
80+
81+ // A button at work: a spinner and its label, pressed no more until it is done.
82+ function working(button) {
83+ button.disabled = true;
84+ button.classList.add("busy");
85+ button.setAttribute("aria-busy", "true");
86+ var label = button.textContent;
87+ setTimeout(function () {
88+ if (button.isConnected) done(button, label);
89+ }, 20000);
90+ }
91+
92+ function done(button, label) {
93+ button.disabled = false;
94+ button.classList.remove("busy");
95+ button.removeAttribute("aria-busy");
96+ button.textContent = label;
97+ }
98+
6799 function element(tag, className, text) {
68100 var item = document.createElement(tag);
69101 if (className) item.className = className;
+26−0
711711 .runner-line .dot {
712712 margin-top: 0;
713713 }
714+/* A button at work: a small spinner before its label until the status that follows. */
715+button.busy {
716+ cursor: progress;
717+}
718+button.busy::before {
719+ content: "";
720+ display: inline-block;
721+ width: 0.75em;
722+ height: 0.75em;
723+ margin-right: 0.5em;
724+ vertical-align: -0.1em;
725+ border: 2px solid currentColor;
726+ border-right-color: transparent;
727+ border-radius: 50%;
728+ animation: spin 0.8s linear infinite;
729+}
730+@keyframes spin {
731+ to {
732+ transform: rotate(360deg);
733+ }
734+}
735+@media (prefers-reduced-motion: reduce) {
736+ button.busy::before {
737+ animation: none;
738+ }
739+}
+7−3
314314 /// Looks for a newer runner now, and installs it as soon as its kinds of job are idle.
315315 const CHECK_UPDATES: Action = Action { id: "check_updates", label: "Check for runner updates" };
316316 const CHECK_AGAIN: Action = Action { id: "check_updates", label: "Check again" };
317+/// Removes the sandbox this computer has (`sandbox down --delete`, in the
318+/// app's own folder for it) and starts the app's own: what the command a
319+/// person would type does, without needing to know where that folder is.
320+const REMOVE_SANDBOX: Action = Action { id: "remove_sandbox", label: "Remove it and start again" };
317321 const RESTART: Action = Action { id: "restart", label: "Restart" };
318322 const SIGN_IN: Action = Action { id: "sign_in", label: "Sign in" };
319323 const CHOOSE_WORKSPACE: Action = Action { id: "choose_workspace", label: "Choose workspace" };
543547 Code::SandboxTaken => (
544548 Tone::Warning,
545549 "Not running: this computer has another sandbox".into(),
546− some("This computer already has a g1t-runner sandbox that g1t didn't make, such as one started with `g1t-runner sandbox up`, and it has room for one."),
547− some("Remove it with `g1t-runner sandbox down --delete`, then Retry; its runners stay listed on g1t until you remove them there. Or keep it, and turn off running jobs in g1t."),
548− vec![RETRY, LEARN_MORE],
550+ some("This computer already has a g1t-runner sandbox that this copy of g1t has no record of making, such as one from before g1t was installed again, or one started with `g1t-runner sandbox up`. A computer has room for one."),
551+ some("Remove it and start again: g1t removes it, with the jobs' VM and its registration, and makes its own, registered with your workspace. Its old runners stay listed on g1t, offline, until you remove them there. Or keep it, and turn off running jobs in g1t."),
552+ vec![REMOVE_SANDBOX, LEARN_MORE],
549553 ),
550554 Code::Updating => (Tone::Working, "Updating".into(), detail, some("The runner starts again as soon as it's done."), vec![]),
551555 Code::UpdateFailed => (
+15−0
221221 /// A kind of job was started: start what should run now, stopping nothing.
222222 Soon,
223223 Retry,
224+ /// "Remove it and start again": the sandbox this computer has, removed
225+ /// with its registration, and the app's own made in its place.
226+ RemoveSandbox,
224227 /// "Check for runner updates": look now, and install what is found
225228 /// even with "Download updates by themselves" off.
226229 Check,
568571 }
569572 "stop" => set_paused(app, true),
570573 "retry" | "restart" => retry(app),
574+ "remove_sandbox" => {
575+ *app.state::<Shared>().paused.lock().unwrap() = false;
576+ ask(app, Ask::RemoveSandbox);
577+ }
571578 "check_updates" => ask(app, Ask::Check),
572579 "sign_in" => crate::links::go(app, "/login"),
573580 "new_workspace" => crate::links::go(app, "/workspaces/new"),
931938 *at = Instant::now();
932939 }
933940 }
941+ Ask::RemoveSandbox => {
942+ self.set(Code::Starting, detail("Removing this computer's sandbox."));
943+ self.halt();
944+ self.forget_sandbox();
945+ self.failures = 0;
946+ self.not_before = Instant::now();
947+ self.set(Code::Starting, detail("Starting a sandbox of g1t's own."));
948+ }
934949 Ask::Retry => {
935950 self.not_before = Instant::now();
936951 self.failures = 0;
+1−0
3333 "webviewInstallMode": { "type": "downloadBootstrapper" },
3434 "nsis": {
3535 "installMode": "currentUser",
36+ "installerHooks": "./windows/hooks.nsh",
3637 "languages": ["English"]
3738 }
3839 },
+25−0
1+; Hooks into the Windows installer Tauri makes (tauri.conf.json,
2+; bundle.windows.nsis.installerHooks).
3+;
4+; Uninstalling with "Delete the application data" ticked takes the runner's
5+; sandbox with it: its WSL distribution (g1t-sandbox) is registered with
6+; Windows apart from the app's folder, so deleting the folder alone left it
7+; behind, and g1t installed again found a sandbox it had no record of. Not
8+; on an update (/UPDATE), which uninstalls the old version to install the
9+; new one and keeps everything. The runner's folder is in local data, or in
10+; roaming data where an older version set it up; either is seen to.
11+
12+!macro G1T_REMOVE_SANDBOX ROOT
13+ ${If} ${FileExists} "${ROOT}\sh.g1t.desktop\runner\bin\g1t-runner.exe"
14+ nsExec::Exec '"${ROOT}\sh.g1t.desktop\runner\bin\g1t-runner.exe" sandbox down --delete --state-dir "${ROOT}\sh.g1t.desktop\runner\sandbox"'
15+ Pop $0
16+ ${EndIf}
17+!macroend
18+
19+!macro NSIS_HOOK_PREUNINSTALL
20+ ${If} $DeleteAppDataCheckboxState = 1
21+ ${AndIf} $UpdateMode <> 1
22+ !insertmacro G1T_REMOVE_SANDBOX "$LOCALAPPDATA"
23+ !insertmacro G1T_REMOVE_SANDBOX "$APPDATA"
24+ ${EndIf}
25+!macroend
+8−5
253253 each one's registration beside it.
254254
255255 On Windows the sandbox is the WSL distribution `g1t-sandbox`, of which a
256−computer has one. If you made one yourself with `g1t-runner sandbox up`,
257−the app leaves it alone and says *this computer has another sandbox*:
258−remove it with `g1t-runner sandbox down --delete` for the app to make its
259−own, or keep it and turn the app's runner off.
256+computer has one. If this copy of g1t has no record of making the one
257+there (you made it with `g1t-runner sandbox up`, or g1t was uninstalled
258+with its data deleted and installed again), the app leaves it alone and
259+says *this computer has another sandbox*: **Remove it and start again**
260+removes it, with its VM and registration, and makes the app's own; or keep
261+it and turn the app's runner off. Uninstalling g1t with **Delete the
262+application data** ticked removes the sandbox too.
260263
261264 ### Registering
262265
343346 | *Not running: the sandbox's image didn't check out* | The image that downloaded isn't the one the release signed (its signature or SHA-256), so it wasn't used. | It downloads it again by itself. If it keeps happening, something between your computer and g1t, such as a proxy or antivirus, is changing downloads: **Report** it. |
344347 | *Not running: the sandbox can't run here* | Something else the sandbox needs, in its own words. | What it says. |
345348 | *Not running: the sandbox failed* | The sandbox stopped, or didn't start, with its reason. | It starts again by itself, waiting longer each time. **Retry**, or **View log**. |
346−| *Not running: this computer has another sandbox* | A sandbox you made with `g1t-runner sandbox up`; a computer has one. | Remove it with `g1t-runner sandbox down --delete`, then **Retry**; or keep it, and turn the app's runner off. |
349+| *Not running: this computer has another sandbox* | A sandbox this copy of g1t has no record of making: one you made with `g1t-runner sandbox up`, or one left from before g1t was installed again. A computer has one. | **Remove it and start again**, which asks first; its old runners stay listed on g1t, offline, until you remove them there. Or keep it, and turn the app's runner off. |
347350 | *Not running: this g1t-runner has no sandbox* | The app's `g1t-runner` is from before the sandbox. | It downloads a newer one by itself; **Retry** looks now. |
348351 | *Windows jobs: Not available*: *Windows Sandbox is off*, *Windows needs an update* | Windows Sandbox is off, this Windows is Home, or it is older than 24H2. Linux jobs still run. | On Pro, Enterprise or Education, turn on Windows Sandbox (**Open Windows features**) and restart, or update Windows. |
349352 | *Windows jobs: Problem*: *Its runner didn't start* or *Its runner stopped* | The runner for Windows jobs didn't start, with why, or stopped by itself, while Linux jobs run. | It is started again by itself in a few minutes; **Retry** now, or **View log**. |

Comments

Sign in to comment.