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

Stopping the desktop app's runner when it runs jobs in Docker removes the containers, networks and volumes of the job it had, rather than leaving them running until the runner next starts and sweeps them; and Retry after a failed update tries the update again without restarting a runner that is working.

syntaqxcommitted Parent60c0d16Browse files
2 files+38−60/2 viewed
+15−6
549549 Ask::Retry => {
550550 self.not_before = Instant::now();
551551 self.failures = 0;
552− if self.run.as_ref().is_some_and(|run| !run.listening || matches!(self.code(), Code::UpdateFailed | Code::Offline)) {
553− self.halt();
554− }
555− if self.code() == Code::UpdateFailed {
556− self.next_update = Instant::now();
552+ match self.code() {
553+ // The runner is fine: only the update is tried again.
554+ Code::UpdateFailed => self.next_update = Instant::now(),
555+ Code::Offline => self.halt(),
556+ _ if self.run.as_ref().is_some_and(|run| !run.listening) => self.halt(),
557+ _ => {}
557558 }
558559 }
559560 Ask::Token { workspace, token } => {
677678 launcher::down(&native::binary(&folder(&self.app)), &native_dir(&self.app, run.backend));
678679 native::stop(child);
679680 }
680− (Process::Child(child), _) => native::stop(child),
681+ // The image's runner is always a container; a child here is only ever g1t-runner's.
682+ (Process::Child(child), Engine::Sysbox) => native::stop(child),
683+ (Process::Child(child), Engine::Native { docker }) => {
684+ native::stop(child);
685+ // A job's container outlives the runner killed under it: removed now, not at its next start.
686+ if docker {
687+ native::sweep(&native_dir(&self.app, run.backend));
688+ }
689+ }
681690 }
682691 let _ = std::fs::remove_file(folder(&self.app).join("pid"));
683692 }
+23−0
158158 let _ = child.wait();
159159 }
160160
161+/// Removes the containers, networks and volumes of the jobs of the runner
162+/// registered in `dir`, as `g1t-runner` does itself when it starts: each
163+/// carries the label `sh.g1t.runner=<its id>`.
164+pub fn sweep(dir: &Path) {
165+ #[derive(Deserialize)]
166+ struct Registered {
167+ runner: String,
168+ }
169+ let Some(registered) = std::fs::read(dir.join("config.json")).ok().and_then(|bytes| serde_json::from_slice::<Registered>(&bytes).ok()) else { return };
170+ let label = format!("label=sh.g1t.runner={}", registered.runner);
171+ for (list, remove) in [
172+ (vec!["ps", "-aq", "--filter", &label], vec!["rm", "-f", "-v"]),
173+ (vec!["network", "ls", "-q", "--filter", &label], vec!["network", "rm"]),
174+ (vec!["volume", "ls", "-q", "--filter", &label], vec!["volume", "rm", "-f"]),
175+ ] {
176+ let Ok(out) = quiet("docker").args(&list).stderr(Stdio::null()).output() else { return };
177+ let ids: Vec<String> = String::from_utf8_lossy(&out.stdout).split_whitespace().map(str::to_owned).collect();
178+ if !ids.is_empty() {
179+ let _ = quiet("docker").args(&remove).args(&ids).stdout(Stdio::null()).stderr(Stdio::null()).status();
180+ }
181+ }
182+}
183+
161184 /// A runner the app started before and did not stop (it was ended
162185 /// without quitting): stopped, if that process is still `g1t-runner`.
163186 pub fn reap(pid: u32) {

Comments

Sign in to comment.