From 5a82bc8aa9f5026d3eec5a88993642941ab65fe1 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 5 Sep 2026 06:37:17 +0000 Subject: [PATCH] Add --branches flag to token create Pass allowed_branches on POST so tokens can be limited to named branches. Co-authored-by: Fang-Pen Lin --- src/cli.rs | 15 ++++++++++++++- src/client.rs | 4 ++++ tests/cli.rs | 16 ++++++++++++++++ tests/common/mod.rs | 1 + 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/cli.rs b/src/cli.rs index fbc8dfe..d3fa65c 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -158,6 +158,9 @@ enum TokenCommand { /// Comma-separated repo UUIDs for SELECTED_REPO. #[arg(long)] repository_ids: Option, + /// Comma-separated Amendable branch names this token may push. Empty means all branches. + #[arg(long)] + branches: Option, #[arg(long)] json: bool, }, @@ -244,12 +247,14 @@ fn execute(cli: Cli) -> Result<(), Error> { scope, grants, repository_ids, + branches, json, } => token_create( name.as_deref(), &scope, &grants, repository_ids.as_deref(), + branches.as_deref(), json, ), TokenCommand::Delete { token_id } => token_delete(&token_id), @@ -559,13 +564,21 @@ fn token_create( scope: &str, grants: &str, repository_ids: Option<&str>, + branches: Option<&str>, json: bool, ) -> Result<(), Error> { let cfg = Config::load()?; let grant_list = split_csv(grants); let repo_ids = repository_ids.map(split_csv); + let allowed_branches = branches.map(split_csv); let client = Client::new(&cfg.api_url, Some(cfg.require_token()?))?; - let created = client.create_access_token(name, scope, &grant_list, repo_ids.as_deref())?; + let created = client.create_access_token( + name, + scope, + &grant_list, + repo_ids.as_deref(), + allowed_branches.as_deref(), + )?; if json { print_json(&created)?; return Ok(()); diff --git a/src/client.rs b/src/client.rs index f5c8952..af4070a 100644 --- a/src/client.rs +++ b/src/client.rs @@ -187,6 +187,7 @@ impl Client { scope: &str, grants: &[String], repository_ids: Option<&[String]>, + allowed_branches: Option<&[String]>, ) -> Result { let mut body = serde_json::json!({ "name": name, @@ -196,6 +197,9 @@ impl Client { if let Some(ids) = repository_ids.filter(|v| !v.is_empty()) { body["repository_ids"] = serde_json::json!(ids); } + if let Some(branches) = allowed_branches.filter(|v| !v.is_empty()) { + body["allowed_branches"] = serde_json::json!(branches); + } self.request( reqwest::Method::POST, "/v1/access-tokens", diff --git a/tests/cli.rs b/tests/cli.rs index 3472678..04fe80b 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -145,6 +145,22 @@ fn token_create_and_list() { .assert() .success() .stdout(contains("NEWTOKENSHOWNONCE")); + harness + .cmd() + .args([ + "token", + "create", + "--name", + "main-only", + "--grants", + "GIT_HTTP_WRITE", + "--branches", + "main,release/1.0", + "--json", + ]) + .assert() + .success() + .stdout(contains("main").and(contains("release/1.0"))); harness .cmd() .args(["token", "list", "--json"]) diff --git a/tests/common/mod.rs b/tests/common/mod.rs index bcda469..0cd1d22 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -254,6 +254,7 @@ fn do_post( "name": body.get("name"), "scope": body.get("scope"), "grants": body.get("grants"), + "allowed_branches": body.get("allowed_branches").cloned().unwrap_or(json!([])), "token": "NEWTOKENSHOWNONCE", "repositories": [], });