Skip to content

Commit f7ebfd6

Browse files
laststylebender14autofix-ci[bot]tusharmath
authored
feat(update): update forge in bg (#2466)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Tushar Mathur <tusharmath@gmail.com>
1 parent 0dffe3e commit f7ebfd6

7 files changed

Lines changed: 71 additions & 10 deletions

File tree

crates/forge_domain/src/update.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::time::Duration;
22

3+
use derive_setters::Setters;
34
use merge::Merge;
45
use schemars::JsonSchema;
56
use serde::{Deserialize, Serialize};
@@ -23,7 +24,7 @@ impl From<UpdateFrequency> for Duration {
2324
}
2425
}
2526

26-
#[derive(Debug, Clone, Serialize, Deserialize, Merge, Default, JsonSchema)]
27+
#[derive(Debug, Clone, Serialize, Deserialize, Merge, Default, JsonSchema, Setters)]
2728
#[merge(strategy = merge::option::overwrite_none)]
2829
pub struct Update {
2930
pub frequency: Option<UpdateFrequency>,

crates/forge_main/src/cli.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ pub enum TopLevelCommand {
149149
/// VS Code integration commands.
150150
#[command(subcommand)]
151151
Vscode(VscodeCommand),
152+
153+
/// Update forge to the latest version.
154+
Update(UpdateArgs),
152155
}
153156

154157
/// Command group for custom command management.
@@ -719,6 +722,14 @@ pub enum VscodeCommand {
719722
InstallExtension,
720723
}
721724

725+
/// Update command arguments.
726+
#[derive(Parser, Debug, Clone)]
727+
pub struct UpdateArgs {
728+
/// Skip the confirmation prompt when applying updates.
729+
#[arg(long, default_value_t = false)]
730+
pub no_confirm: bool,
731+
}
732+
722733
#[cfg(test)]
723734
mod tests {
724735
use clap::Parser;
@@ -1704,4 +1715,24 @@ mod tests {
17041715
let expected = false;
17051716
assert_eq!(actual, expected);
17061717
}
1718+
1719+
#[test]
1720+
fn test_update_with_no_confirm() {
1721+
let fixture = Cli::parse_from(["forge", "update", "--no-confirm"]);
1722+
let actual = match fixture.subcommands {
1723+
Some(TopLevelCommand::Update(args)) => args.no_confirm,
1724+
_ => panic!("Expected Update command"),
1725+
};
1726+
assert!(actual);
1727+
}
1728+
1729+
#[test]
1730+
fn test_update_without_no_confirm() {
1731+
let fixture = Cli::parse_from(["forge", "update"]);
1732+
let actual = match fixture.subcommands {
1733+
Some(TopLevelCommand::Update(args)) => args.no_confirm,
1734+
_ => panic!("Expected Update command"),
1735+
};
1736+
assert!(!actual);
1737+
}
17071738
}

crates/forge_main/src/ui.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,11 @@ impl<A: API + ConsoleWriter + 'static, F: Fn() -> A + Send + Sync> UI<A, F> {
670670
}
671671
return Ok(());
672672
}
673+
TopLevelCommand::Update(args) => {
674+
let update = forge_domain::Update::default().auto_update(Some(args.no_confirm));
675+
on_update(self.api.clone(), Some(&update)).await;
676+
return Ok(());
677+
}
673678
}
674679
Ok(())
675680
}

crates/forge_main/src/update.rs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ use forge_api::{API, Update};
55
use forge_tracker::VERSION;
66
use update_informer::{Check, Version, registry};
77

8-
/// Runs the official installation script to update Forge, failing silently
9-
async fn execute_update_command(api: Arc<impl API>) {
8+
/// Runs the official installation script to update Forge, failing silently.
9+
/// When `auto_update` is true, exits immediately after a successful update
10+
/// without prompting the user.
11+
async fn execute_update_command(api: Arc<impl API>, auto_update: bool) {
1012
// Spawn a new task that won't block the main application
1113
let output = api
1214
.execute_shell_command_raw("curl -fsSL https://forgecode.dev/cli | sh")
@@ -20,12 +22,17 @@ async fn execute_update_command(api: Arc<impl API>) {
2022
}
2123
Ok(output) => {
2224
if output.success() {
23-
let answer = forge_select::ForgeSelect::confirm(
24-
"You need to close forge to complete update. Do you want to close it now?",
25-
)
26-
.with_default(true)
27-
.prompt();
28-
if answer.unwrap_or_default().unwrap_or_default() {
25+
let should_exit = if auto_update {
26+
true
27+
} else {
28+
let answer = forge_select::ForgeSelect::confirm(
29+
"You need to close forge to complete update. Do you want to close it now?",
30+
)
31+
.with_default(true)
32+
.prompt();
33+
answer.unwrap_or_default().unwrap_or_default()
34+
};
35+
if should_exit {
2936
std::process::exit(0);
3037
}
3138
} else {
@@ -75,7 +82,7 @@ pub async fn on_update(api: Arc<impl API>, update: Option<&Update>) {
7582
if let Some(version) = informer.check_version().ok().flatten()
7683
&& (auto_update || confirm_update(version).await)
7784
{
78-
execute_update_command(api).await;
85+
execute_update_command(api, auto_update).await;
7986
}
8087
}
8188

shell-plugin/lib/actions/core.zsh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ function _forge_action_new() {
2323

2424
# Start background sync job if enabled and not already running
2525
_forge_start_background_sync
26+
# Start background update check
27+
_forge_start_background_update
2628
else
2729
# Only show banner if no input text (starting fresh conversation)
2830
_forge_exec banner

shell-plugin/lib/dispatcher.zsh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ function _forge_action_default() {
7777

7878
# Start background sync job if enabled and not already running
7979
_forge_start_background_sync
80+
# Start background update check
81+
_forge_start_background_update
8082
}
8183

8284
function forge-accept-line() {

shell-plugin/lib/helpers.zsh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,16 @@ function _forge_start_background_sync() {
138138
} &!
139139
}
140140

141+
# Start background update check if not already running
142+
# Mirrors the background sync pattern to silently check for and apply updates
143+
function _forge_start_background_update() {
144+
{
145+
# Run update check in background
146+
# Close all output streams immediately to prevent any flashing
147+
# Redirect stdin to /dev/null to prevent hanging
148+
exec >/dev/null 2>&1 </dev/null
149+
setopt NO_NOTIFY NO_MONITOR
150+
$_FORGE_BIN update --no-confirm
151+
} &!
152+
}
153+

0 commit comments

Comments
 (0)