Add marketplace command (#17087)

Added a new top-level `codex marketplace add` command for installing
plugin marketplaces into Codex’s local marketplace cache.

This change adds source parsing for local directories, GitHub shorthand,
and git URLs, supports optional `--ref` and git-only `--sparse` checkout
paths, stages the source in a temp directory, validates the marketplace
manifest, and installs it under
`$CODEX_HOME/marketplaces/<marketplace-name>`

Included tests cover local install behavior in the CLI and marketplace
discovery from installed roots in core. Scoped formatting and fix passes
were run, and targeted CLI/core tests passed.
This commit is contained in:
xli-oai
2026-04-10 19:18:37 -07:00
committed by GitHub
parent 58933237cd
commit f9a8d1870f
15 changed files with 1330 additions and 2 deletions

View File

@@ -0,0 +1,60 @@
use anyhow::Result;
use codex_core::plugins::marketplace_install_root;
use predicates::str::contains;
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)
}
fn write_marketplace_source(source: &Path, marker: &str) -> Result<()> {
std::fs::create_dir_all(source.join(".agents/plugins"))?;
std::fs::create_dir_all(source.join("plugins/sample/.codex-plugin"))?;
std::fs::write(
source.join(".agents/plugins/marketplace.json"),
r#"{
"name": "debug",
"plugins": [
{
"name": "sample",
"source": {
"source": "local",
"path": "./plugins/sample"
}
}
]
}"#,
)?;
std::fs::write(
source.join("plugins/sample/.codex-plugin/plugin.json"),
r#"{"name":"sample"}"#,
)?;
std::fs::write(source.join("plugins/sample/marker.txt"), marker)?;
Ok(())
}
#[tokio::test]
async fn marketplace_add_rejects_local_directory_source() -> Result<()> {
let codex_home = TempDir::new()?;
let source = TempDir::new()?;
write_marketplace_source(source.path(), "local ref")?;
codex_command(codex_home.path())?
.args(["marketplace", "add", source.path().to_str().unwrap()])
.assert()
.failure()
.stderr(contains(
"local marketplace sources are not supported yet; use an HTTP(S) Git URL, SSH Git URL, or GitHub owner/repo",
));
assert!(
!marketplace_install_root(codex_home.path())
.join("debug")
.exists()
);
Ok(())
}