Files
codex/codex-rs/cli/tests/marketplace_upgrade.rs
willwang-openai 68c9556cdf Upgrade Git marketplaces from merged configuration (#42149)
## Why

Configured Git marketplaces may be defined outside the user config, but those definitions could not download or update their snapshots.

## What changed

- Select marketplace source, ref, and sparse-path settings from the effective merged configuration for startup synchronization and explicit upgrades.
- Preserve the initiating operation's configuration loader and overrides when reloading before activation.
- Roll back activation if the marketplace definition changed or configuration can no longer be loaded, without copying settings into the user config.

## Testing

- Cover system-defined marketplaces, CLI overrides, startup fallback after invalid user configuration, and rollback after configuration changes.

GitOrigin-RevId: 53d1eecf68a91ce2aa8430e5749d78697bfcd821
2026-09-01 22:37:26 +00:00

107 lines
3.2 KiB
Rust

use anyhow::Result;
use codex_core_plugins::installed_marketplaces::marketplace_install_root;
use codex_utils_absolute_path::AbsolutePathBuf;
use predicates::str::contains;
use pretty_assertions::assert_eq;
use serde_json::json;
use std::path::Path;
use tempfile::TempDir;
fn codex_command(codex_home: &Path) -> Result<assert_cmd::Command> {
let mut cmd = assert_cmd::Command::new(codex_utils_cargo_bin::cargo_bin("codex")?);
cmd.env("CODEX_HOME", codex_home);
Ok(cmd)
}
#[tokio::test]
async fn marketplace_upgrade_runs_under_plugin() -> Result<()> {
let codex_home = TempDir::new()?;
codex_command(codex_home.path())?
.args(["plugin", "marketplace", "upgrade"])
.assert()
.success()
.stdout(contains("No configured Git marketplaces to upgrade."));
Ok(())
}
#[tokio::test]
async fn marketplace_upgrade_json_prints_upgrade_outcome() -> Result<()> {
let codex_home = TempDir::new()?;
let source = TempDir::new()?;
let manifest = r#"{"name":"debug","plugins":[]}"#;
std::fs::create_dir_all(source.path().join(".agents/plugins"))?;
std::fs::write(
source.path().join(".agents/plugins/marketplace.json"),
manifest,
)?;
for args in [
vec!["init", "--quiet"],
vec!["add", "."],
vec![
"-c",
"user.name=Codex Tests",
"-c",
"user.email=codex@example.com",
"commit",
"-m",
"marketplace",
],
] {
let output = std::process::Command::new("git")
.current_dir(source.path())
.args(args)
.output()?;
anyhow::ensure!(
output.status.success(),
"git fixture failed: {}",
String::from_utf8_lossy(&output.stderr)
);
}
let source_arg = serde_json::to_string(&source.path().to_string_lossy())?;
let marketplace_override =
format!("marketplaces.debug={{source_type=\"git\",source={source_arg}}}");
let assert = codex_command(codex_home.path())?
.current_dir(codex_home.path())
.args(["--config", &marketplace_override])
.args(["plugin", "marketplace", "upgrade", "--json"])
.assert()
.success();
let stdout = assert.get_output().stdout.as_slice();
let actual: serde_json::Value = serde_json::from_slice(stdout)?;
let installed_root = AbsolutePathBuf::try_from(
marketplace_install_root(&codex_home.path().canonicalize()?).join("debug"),
)?;
assert_eq!(
actual,
json!({
"selectedMarketplaces": ["debug"],
"upgradedRoots": [installed_root],
"errors": [],
})
);
assert_eq!(
std::fs::read_to_string(installed_root.join(".agents/plugins/marketplace.json"))?,
manifest
);
assert!(!codex_home.path().join("config.toml").exists());
Ok(())
}
#[tokio::test]
async fn marketplace_upgrade_no_longer_runs_at_top_level() -> Result<()> {
let codex_home = TempDir::new()?;
codex_command(codex_home.path())?
.args(["marketplace", "upgrade"])
.assert()
.failure()
.stderr(contains("unrecognized subcommand 'upgrade'"));
Ok(())
}