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.
7 files+121−150/7 viewed
| 53 | 53 | button.addEventListener("click", function () { | |
| 54 | 54 | if (action.id === "choose_workspace") return byId("runnerWorkspace").focus(); | |
| 55 | 55 | 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 | + | ); | |
| 63 | 74 | }); | |
| 64 | 75 | return button; | |
| 65 | 76 | } | |
| 66 | 77 | ||
| 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 | + | ||
| 67 | 99 | function element(tag, className, text) { | |
| 68 | 100 | var item = document.createElement(tag); | |
| 69 | 101 | if (className) item.className = className; |
| 711 | 711 | .runner-line .dot { | |
| 712 | 712 | margin-top: 0; | |
| 713 | 713 | } | |
| 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 | + | } |
| 314 | 314 | /// Looks for a newer runner now, and installs it as soon as its kinds of job are idle. | |
| 315 | 315 | const CHECK_UPDATES: Action = Action { id: "check_updates", label: "Check for runner updates" }; | |
| 316 | 316 | 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" }; | |
| 317 | 321 | const RESTART: Action = Action { id: "restart", label: "Restart" }; | |
| 318 | 322 | const SIGN_IN: Action = Action { id: "sign_in", label: "Sign in" }; | |
| 319 | 323 | const CHOOSE_WORKSPACE: Action = Action { id: "choose_workspace", label: "Choose workspace" }; | |
| ⋯ | |||
| 543 | 547 | Code::SandboxTaken => ( | |
| 544 | 548 | Tone::Warning, | |
| 545 | 549 | "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], | |
| 549 | 553 | ), | |
| 550 | 554 | Code::Updating => (Tone::Working, "Updating".into(), detail, some("The runner starts again as soon as it's done."), vec![]), | |
| 551 | 555 | Code::UpdateFailed => ( | |
| 221 | 221 | /// A kind of job was started: start what should run now, stopping nothing. | |
| 222 | 222 | Soon, | |
| 223 | 223 | 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, | |
| 224 | 227 | /// "Check for runner updates": look now, and install what is found | |
| 225 | 228 | /// even with "Download updates by themselves" off. | |
| 226 | 229 | Check, | |
| ⋯ | |||
| 568 | 571 | } | |
| 569 | 572 | "stop" => set_paused(app, true), | |
| 570 | 573 | "retry" | "restart" => retry(app), | |
| 574 | + | "remove_sandbox" => { | |
| 575 | + | *app.state::<Shared>().paused.lock().unwrap() = false; | |
| 576 | + | ask(app, Ask::RemoveSandbox); | |
| 577 | + | } | |
| 571 | 578 | "check_updates" => ask(app, Ask::Check), | |
| 572 | 579 | "sign_in" => crate::links::go(app, "/login"), | |
| 573 | 580 | "new_workspace" => crate::links::go(app, "/workspaces/new"), | |
| ⋯ | |||
| 931 | 938 | *at = Instant::now(); | |
| 932 | 939 | } | |
| 933 | 940 | } | |
| 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 | + | } | |
| 934 | 949 | Ask::Retry => { | |
| 935 | 950 | self.not_before = Instant::now(); | |
| 936 | 951 | self.failures = 0; | |
| 33 | 33 | "webviewInstallMode": { "type": "downloadBootstrapper" }, | |
| 34 | 34 | "nsis": { | |
| 35 | 35 | "installMode": "currentUser", | |
| 36 | + | "installerHooks": "./windows/hooks.nsh", | |
| 36 | 37 | "languages": ["English"] | |
| 37 | 38 | } | |
| 38 | 39 | }, |
| 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 |
| 253 | 253 | each one's registration beside it. | |
| 254 | 254 | ||
| 255 | 255 | 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. | |
| 260 | 263 | ||
| 261 | 264 | ### Registering | |
| 262 | 265 | ||
| ⋯ | |||
| 343 | 346 | | *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. | | |
| 344 | 347 | | *Not running: the sandbox can't run here* | Something else the sandbox needs, in its own words. | What it says. | | |
| 345 | 348 | | *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. | | |
| 347 | 350 | | *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. | | |
| 348 | 351 | | *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. | | |
| 349 | 352 | | *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.