build: centralize the pinned opencode version (#1075)

Keep OpenCode version selection predictable by reading a single repo-wide constant and packaging that pin into orchestrator builds. Remove env and latest-release fallbacks so desktop, workers, snapshots, and CI stay aligned.

Co-authored-by: Omar McAdam <omar@OpenWork-Studio.localdomain>
This commit is contained in:
Omar McAdam
2026-03-20 12:30:24 -07:00
committed by GitHub
parent a9bf75da0a
commit db10a7b5ba
30 changed files with 186 additions and 392 deletions

View File

@@ -63,6 +63,25 @@ fn openwork_dev_mode_enabled() -> bool {
env_truthy("OPENWORK_DEV_MODE").unwrap_or(cfg!(debug_assertions))
}
fn pinned_opencode_version() -> String {
let constants = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../../constants.json"));
let parsed: serde_json::Value =
serde_json::from_str(constants).expect("constants.json must be valid JSON");
parsed["opencodeVersion"]
.as_str()
.expect("constants.json must include opencodeVersion")
.trim()
.trim_start_matches('v')
.to_string()
}
fn pinned_opencode_install_command() -> String {
format!(
"curl -fsSL https://opencode.ai/install | bash -s -- --version {} --no-modify-path",
pinned_opencode_version()
)
}
#[derive(Default)]
struct OutputState {
stdout: String,
@@ -250,7 +269,7 @@ pub fn engine_install() -> Result<ExecResult, String> {
ok: false,
status: -1,
stdout: String::new(),
stderr: "Guided install is not supported on Windows yet. Install OpenCode via Scoop/Chocolatey or https://opencode.ai/install, then restart OpenWork.".to_string(),
stderr: "Guided install is not supported on Windows yet. Install the OpenWork-pinned OpenCode version manually, then restart OpenWork.".to_string(),
});
}
@@ -263,7 +282,7 @@ pub fn engine_install() -> Result<ExecResult, String> {
let output = std::process::Command::new("bash")
.arg("-lc")
.arg("curl -fsSL https://opencode.ai/install | bash")
.arg(pinned_opencode_install_command())
.env("OPENCODE_INSTALL_DIR", install_dir)
.output()
.map_err(|e| format!("Failed to run installer: {e}"))?;
@@ -363,8 +382,9 @@ pub fn engine_start(
);
let Some(program) = program else {
let notes_text = notes.join("\n");
let install_command = pinned_opencode_install_command();
return Err(format!(
"OpenCode CLI not found.\n\nInstall with:\n- brew install anomalyco/tap/opencode\n- curl -fsSL https://opencode.ai/install | bash\n\nNotes:\n{notes_text}"
"OpenCode CLI not found.\n\nInstall with:\n- {install_command}\n\nNotes:\n{notes_text}"
));
};

View File

@@ -15,6 +15,24 @@ use crate::types::{ExecResult, WorkspaceOpenworkConfig};
use crate::workspace::state::load_workspace_state;
use tauri::{AppHandle, Manager, State};
fn pinned_opencode_install_command() -> String {
let constants = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/../../../constants.json"
));
let parsed: serde_json::Value =
serde_json::from_str(constants).expect("constants.json must be valid JSON");
let version = parsed["opencodeVersion"]
.as_str()
.expect("constants.json must include opencodeVersion")
.trim()
.trim_start_matches('v');
format!(
"curl -fsSL https://opencode.ai/install | bash -s -- --version {} --no-modify-path",
version
)
}
#[derive(serde::Serialize)]
pub struct CacheResetResult {
pub removed: Vec<String>,
@@ -244,8 +262,9 @@ fn resolve_opencode_program(
program.ok_or_else(|| {
let notes_text = notes.join("\n");
let install_command = pinned_opencode_install_command();
format!(
"OpenCode CLI not found.\n\nInstall with:\n- brew install anomalyco/tap/opencode\n- curl -fsSL https://opencode.ai/install | bash\n\nNotes:\n{notes_text}"
"OpenCode CLI not found.\n\nInstall with:\n- {install_command}\n\nNotes:\n{notes_text}"
)
})
}

View File

@@ -57,7 +57,7 @@ Skills add new capabilities. Plugins add advanced features like scheduling or br
OpenWork is a GUI for OpenCode. Everything that works in OpenCode works here.
Most reliable setup today:
1) Install OpenCode from opencode.ai
1) Install the OpenWork-pinned OpenCode version
2) Configure providers there (models and API keys)
3) Come back to OpenWork and start a session