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

The desktop app is 0.3.3: Settings opens again on Windows, and an update found as g1t starts installs itself. Since 0.3.0, Settings opened from the title bar's button or the site's account menu showed a white window and nothing else: both are synchronous commands, which run on the main thread, and on Windows a webview window made there deadlocks (Tauri's known issue), so the window appeared and its page never loaded. The settings window is now made on a thread of its own whoever asks, and Tauri hands the making to the event loop. And so that opening g1t again is all it takes to leave a copy that misbehaves, the app looks for a newer version as it starts, three seconds after the window rather than fifteen, and one it downloads within its first two minutes is installed straight away, g1t opening again on it, before anyone has begun working in it; a runner in the middle of a job is never cut short for it, and then the update waits for Restart to update as before. After that it looks every hour rather than every six, and what it finds still waits for a restart or quitting. The desktop guide's Updates section says so.

syntaqxcommitted Parent39342daBrowse files
6 files+73−170/6 viewed
+1−1
13301330
13311331 [[package]]
13321332 name = "g1t-desktop"
1333−version = "0.3.2"
1333+version = "0.3.3"
13341334 dependencies = [
13351335 "base64 0.22.1",
13361336 "ed25519-dalek",
+1−1
11 [package]
22 name = "g1t-desktop"
3−version = "0.3.2"
3+version = "0.3.3"
44 edition = "2024"
55 license = "MIT"
66 repository = "https://g1t.sh/flagon-io/g1t"
+7−0
416416 }
417417 }
418418
419+/// Whether the runner is running a job: what restarts g1t waits for it,
420+/// since restarting stops the runner and would cut the job short.
421+pub fn busy(app: &AppHandle) -> bool {
422+ let now = app.state::<Shared>().now.lock().unwrap().clone();
423+ now.code == Code::Busy || now.sandbox.as_ref().is_some_and(|status| status.job().is_some())
424+}
425+
419426 /// The tray's line: `Runner: Waiting for jobs`, at most 60 characters.
420427 pub fn headline(view: &View) -> String {
421428 let line = format!("Runner: {}", view.diagnosis.title);
+13−0
227227 }
228228 return;
229229 }
230+ // Made on a thread of its own, whoever asks. Settings opens from
231+ // synchronous commands too (the title bar's button, the site's account
232+ // menu), which run on the main thread, and on Windows a window made
233+ // there deadlocks: it appears, white, and its page never loads. From
234+ // another thread, Tauri hands the making to the event loop and waits.
235+ let app = app.clone();
236+ let spawned = std::thread::Builder::new().name("g1t-settings-window".into()).spawn(move || build(&app, check));
237+ if let Err(error) = spawned {
238+ eprintln!("g1t: the settings window could not open: {error}");
239+ }
240+}
241+
242+fn build(app: &AppHandle, check: bool) {
230243 // A window still loading has no listener yet: the address asks instead.
231244 let page = if check { "settings.html?check" } else { "settings.html" };
232245 let custom = crate::frame::started(app);
+40−11
1−//! Updates. The app asks g1t.sh/downloads/desktop/latest.json soon after
2−//! it starts and every six hours after, downloads a newer version in the
3−//! background, and then says so: a notification, and the tray's "Restart
4−//! to update". Nothing is installed under someone mid-sentence; the
5−//! restart, or quitting, installs it. The manifest is signed with g1t's
1+//! Updates. The app asks g1t.sh/downloads/desktop/latest.json as it
2+//! starts and every hour after, and downloads a newer version in the
3+//! background. One found as it starts is installed straight away, and g1t
4+//! opens again on it, before anyone has begun working in it: so a person
5+//! whose copy misbehaves only has to open g1t again to be on the newest,
6+//! fixed one (unless the runner is in the middle of a job, which is never
7+//! cut short; then it waits like any other). One found later says so, with
8+//! a notification and the tray's "Restart to update", since nothing is
9+//! installed under someone mid-sentence; the restart, or quitting,
10+//! installs it. The manifest is signed with g1t's
611 //! release key, built into the app, and a download whose signature does
712 //! not check out is thrown away (scripts/desktop-release.mjs).
813
2126 bytes: Vec<u8>,
2227 }
2328
24−const FIRST_CHECK: Duration = Duration::from_secs(15);
25−const EVERY: Duration = Duration::from_secs(6 * 60 * 60);
29+/// The first look waits only for the window to be up.
30+const FIRST_CHECK: Duration = Duration::from_secs(3);
31+const EVERY: Duration = Duration::from_secs(60 * 60);
32+/// An update downloaded this soon after g1t started is installed at once:
33+/// nobody has begun working in it yet.
34+const AT_START: Duration = Duration::from_secs(2 * 60);
2635
27−/// Checks soon after the start, then every six hours, unless settings
28−/// turned that off; a person can still check from the menu.
36+/// Checks as g1t starts, installing what it finds then, and every hour
37+/// after, unless settings turned that off; a person can still check from
38+/// the menu.
2939 pub fn schedule(app: AppHandle) {
3040 tauri::async_runtime::spawn(async move {
41+ let started = std::time::Instant::now();
3142 tokio::time::sleep(FIRST_CHECK).await;
43+ let mut first = true;
3244 loop {
3345 if config::settings(&app).auto_update {
34− let _ = check(&app, false).await;
46+ let at_start = first && started.elapsed() < AT_START;
47+ let found = look(&app, false, at_start).await;
48+ if at_start && let Some(version) = found.ok().as_deref().and_then(|answer| answer.strip_prefix("ready:")).map(str::to_owned) {
49+ if crate::runner::busy(&app) {
50+ tell(&app, "g1t is ready to update", &format!("Version {version} is downloaded. Restart g1t from the tray to use it."));
51+ } else {
52+ tell(&app, "Updating g1t", &format!("g1t opens again on version {version} in a moment."));
53+ restart(&app);
54+ }
55+ }
3556 }
57+ first = false;
3658 tokio::time::sleep(EVERY).await;
3759 }
3860 });
6183 /// the tray or the site, who is told the answer either way; the timer
6284 /// says nothing unless there is something to install.
6385 pub async fn check(app: &AppHandle, asked: bool) -> Result<String, String> {
86+ look(app, asked, false).await
87+}
88+
89+/// [`check`]; `at_start` says nothing of a download, which is installed at once.
90+async fn look(app: &AppHandle, asked: bool, at_start: bool) -> Result<String, String> {
6491 if let Some(version) = ready(app) {
6592 if asked {
6693 tell(app, "g1t is ready to update", &format!("Version {version} is downloaded. Restart g1t to use it."));
93120 *app.state::<config::State>().update.lock().unwrap() = Some(Ready { version: version.clone(), update, bytes });
94121 tray::update_ready(&version);
95122 let _ = app.emit_to(settings::SETTINGS, settings::READY_EVENT, version.clone());
96− tell(app, "g1t is ready to update", &format!("Version {version} is downloaded. Restart g1t from the tray to use it."));
123+ if !at_start {
124+ tell(app, "g1t is ready to update", &format!("Version {version} is downloaded. Restart g1t from the tray to use it."));
125+ }
97126 Ok(format!("ready:{version}"))
98127 }
99128 Err(error) => {
+11−4
340340 ## Updates
341341
342342 The app asks `g1t.sh/downloads/desktop/latest.json` for a newer version
343−shortly after it starts and every six hours, and downloads one in the
344−background. It never installs under you: a notification and the tray's
345−**Restart to update** say it is ready, and the restart, or quitting,
346−installs it.
343+as it starts and every hour, and downloads one in the background.
344+
345+- **As it starts**, a newer version is installed straight away, and g1t
346+ opens again on it a moment later, before you have begun working in it.
347+ If something in the app misbehaves, quitting and opening g1t again is
348+ enough to be on the newest version. The one exception is your runner
349+ in the middle of a job, which is never cut short: then the update waits
350+ like any other.
351+- **Later on**, it never installs under you: a notification and the
352+ tray's **Restart to update** say it is ready, and the restart, or
353+ quitting, installs it.
347354
348355 To see where your copy stands, choose **Check for updates…** in the Help
349356 menu or the tray, or **Check for updates** in [the settings](#settings).

Comments

Sign in to comment.