Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bbac11b

Browse files
author
8sync-dev
committed
feat(up): --to <tag> pin/downgrade + document stable rollback
`8sync up --to v0.6.10` downloads that specific release asset instead of latest. Enables: (a) reproducible deployment across team machines, (b) explicit rollback after a regression, (c) the recommended 'restore HyDE-only stable baseline' recipe. selfup::install_tag(tag) shares the same atomic-replace flow as run_self_update (curl → /tmp → chmod 755 → rename). Strips/adds 'v' prefix so both 'v0.6.10' and '0.6.10' work. docs/known-issues.md now leads with the stable rollback recipe so any user landing on the doc sees: 8sync up --to v0.6.10 && 8sync setup --reset-shells v0.6.11.
1 parent 8b845f6 commit bbac11b

6 files changed

Lines changed: 91 additions & 12 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ resolver = "2"
33
members = ["crates/cli"]
44

55
[workspace.package]
6-
version = "0.6.10"
6+
version = "0.6.11"
77
edition = "2021"
88
license = "MIT"
99
authors = ["8sync-dev <[email protected]>"]

crates/cli/src/main.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ enum Cmd {
5050

5151
/// Full update: 8sync + omp + system pkgs (pacman/AUR) + rustup + flatpak. See `8sync up -h`.
5252
#[command(alias = "update")]
53-
Up,
53+
Up(verbs::up::Args),
5454

5555
/// Health-check; report what's installed and what's missing
5656
Doctor,
@@ -102,7 +102,7 @@ fn main() -> Result<()> {
102102
let cli = Cli::parse();
103103
if !matches!(
104104
cli.cmd,
105-
Some(Cmd::Up) | Some(Cmd::Setup(_)) | Some(Cmd::Help)
105+
Some(Cmd::Up(_)) | Some(Cmd::Setup(_)) | Some(Cmd::Help)
106106
) {
107107
verbs::selfup::auto_check_notice();
108108
}
@@ -112,7 +112,7 @@ fn main() -> Result<()> {
112112
Ok(())
113113
}
114114
Some(Cmd::Setup(a)) => verbs::setup::run(a),
115-
Some(Cmd::Up) => verbs::up::run(),
115+
Some(Cmd::Up(a)) => verbs::up::run(a),
116116
Some(Cmd::Doctor) => verbs::doctor::run(),
117117
Some(Cmd::Here(a)) => verbs::here::run(a),
118118
Some(Cmd::Ai(a)) => verbs::ai::run(a),

crates/cli/src/verbs/selfup.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,33 @@ pub fn run_self_update(force: bool) -> Result<bool> {
130130
ui::ok(&format!("installed {} → {}", tag, bin_dst.display()));
131131
Ok(true)
132132
}
133+
134+
/// Install a specific tag (e.g. `v0.6.10`). Used by `8sync up --to <tag>`
135+
/// for reproducibility / explicit downgrade.
136+
pub fn install_tag(tag: &str) -> Result<bool> {
137+
ui::step(&format!("Self-update → pinned tag {}", tag));
138+
let tag = tag.strip_prefix('v').map(|t| format!("v{}", t)).unwrap_or_else(|| format!("v{}", tag));
139+
let asset_url = format!(
140+
"https://github.com/{}/{}/releases/download/{}/{}{}{}",
141+
REPO_OWNER, REPO_NAME, tag, ASSET_PREFIX, tag, ASSET_SUFFIX
142+
);
143+
let bin_dst = dirs::home_dir()
144+
.ok_or_else(|| anyhow!("no home dir"))?
145+
.join(".local/bin/8sync");
146+
std::fs::create_dir_all(bin_dst.parent().unwrap())?;
147+
let tmp = bin_dst.with_extension(format!("new.{}", std::process::id()));
148+
ui::info(&format!("$ curl -fsSL --max-time 120 -o {} {}", tmp.display(), asset_url));
149+
let status = Command::new("curl")
150+
.args(["-fsSL", "--max-time", "120", "-o", tmp.to_str().unwrap(), &asset_url])
151+
.status()?;
152+
if !status.success() {
153+
let _ = std::fs::remove_file(&tmp);
154+
bail!("download failed: {}", asset_url);
155+
}
156+
use std::os::unix::fs::PermissionsExt;
157+
std::fs::set_permissions(&tmp, std::fs::Permissions::from_mode(0o755))?;
158+
std::fs::rename(&tmp, &bin_dst)?;
159+
let _ = std::fs::write(last_seen_tag_file(), &tag);
160+
ui::ok(&format!("installed {} → {}", tag, bin_dst.display()));
161+
Ok(true)
162+
}

crates/cli/src/verbs/up.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,37 @@
1-
// `8sync up` — update the 8sync binary from the latest GitHub Release.
1+
// `8sync up` — update the 8sync binary from a GitHub Release.
22
//
3-
// Decoupled from omp on purpose: omp self-updates via `omp update` (or its
4-
// own installer). Touching it here would silently change a runtime the user
5-
// is actively in the middle of a chat with. System pkgs (pacman/AUR) are
6-
// untouched too — user runs `paru -Syu` on their own schedule.
3+
// Default: pull the latest tag. With `--to <tag>` pin a specific release
4+
// for reproducibility / downgrade (e.g. `8sync up --to v0.6.10` to roll
5+
// every machine to the known-stable HyDE-only baseline).
6+
//
7+
// Decoupled from omp on purpose: omp self-updates via `omp update`. System
8+
// pkgs (pacman/AUR) untouched — user runs `paru -Syu` on their own schedule.
79

810
use anyhow::Result;
11+
use clap::Args as ClapArgs;
12+
913
use crate::{ui, verbs::selfup};
1014

11-
pub fn run() -> Result<()> {
15+
#[derive(ClapArgs, Debug)]
16+
#[command(
17+
after_help = indoc::indoc! {"
18+
EXAMPLES
19+
8sync up update to the latest GitHub Release
20+
8sync up --to v0.6.10 pin/downgrade to a specific tag
21+
"}
22+
)]
23+
pub struct Args {
24+
/// Pin to a specific release tag (e.g. `v0.6.10`). Default: latest.
25+
#[arg(long, value_name = "TAG")]
26+
pub to: Option<String>,
27+
}
28+
29+
pub fn run(a: Args) -> Result<()> {
1230
ui::header("8sync up");
13-
let updated = selfup::run_self_update(true)?;
31+
let updated = match a.to {
32+
Some(tag) => selfup::install_tag(&tag)?,
33+
None => selfup::run_self_update(true)?,
34+
};
1435
if updated {
1536
ui::info("done — re-run any 8sync command to pick up the new binary");
1637
}

docs/known-issues.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,31 @@
1+
# 🛟 Stable baseline rollback (any user, any time)
2+
3+
The known-stable baseline is **v0.6.10+ on HyDE-only, no overlay**. To
4+
return any machine to this state regardless of what was attempted before:
5+
6+
```sh
7+
# Already have 8sync
8+
8sync up --to v0.6.10
9+
8sync setup --reset-shells
10+
11+
# Add --purge-packages to also pacman -Rns caelestia-shell, quickshell, aubio
12+
8sync setup --reset-shells --purge-packages
13+
```
14+
15+
Fresh install (no 8sync yet):
16+
17+
```sh
18+
curl -fsSL -o ~/.local/bin/8sync \
19+
https://github.com/8-Sync-Dev/su-code/releases/download/v0.6.10/8sync-v0.6.10-linux-x86_64 \
20+
&& chmod +x ~/.local/bin/8sync \
21+
&& 8sync setup --reset-shells
22+
```
23+
24+
`--reset-shells` is idempotent: safe to re-run; safe on a machine that
25+
never had end-4 / caelestia installed in the first place.
26+
27+
---
28+
129
# Known issues & resolutions
230

331
Living log of HyDE / Caelestia / end-4 conflicts we've hit and the fix that

0 commit comments

Comments
 (0)