From d3b3c6b0c44ef180c333523beeb3a1b03334c1a9 Mon Sep 17 00:00:00 2001 From: Sion Smith Date: Fri, 11 Sep 2026 12:42:00 +0100 Subject: [PATCH 1/5] chore(release): v0.1.0 Bump the workspace version to 0.1.0, add the 0.1.0 changelog section, drop the path-dependency version pin (only needed for crates.io publishing), and make the CLI version tests derive the expected string from CARGO_PKG_VERSION. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_019WDt3RRcPRUR3oxsBjiGio --- CHANGELOG.md | 5 +++++ Cargo.lock | 6 +++--- Cargo.toml | 4 ++-- crates/zdk-cli/tests/cli.rs | 10 +++++----- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 50a7a63..f33fdd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ the GitHub Release body, so every release PR must add one. Unreleased work goes ## [Unreleased] +## [0.1.0] - 2026-09-11 + ### Added - **Authentication** (`zdk auth`): OAuth authorization code with PKCE on a single-use loopback listener (`--port`, `--no-browser` with a paste-back flow, `--redirect-uri`, `--expires-in`), client credentials for CI (`--client-credentials`, `--store-secret`), and the legacy API-token ramp (`--api-token`) that prints a one-line countdown to the 27 Oct 2026 / 30 Apr 2027 deadlines. `status`, `whoami`, `refresh [--force]`, `logout [--no-revoke]`, `test`, `token --format raw|bearer|json`, and `scopes list|show|check|preset` over the 52-scope catalogue with the `agent`, `admin`, `readonly` and `exporter` presets. Pre-emptive refresh at 80 % of the token lifetime with rotation persisted before use; local scope pre-flight (`SCOPE_MISSING`, exit 4) before any request. @@ -25,3 +27,6 @@ the GitHub Release body, so every release PR must add one. Unreleased work goes - **Output**: `table` on a terminal, `json` when piped, plus `ndjson`, `csv`, `tsv`, `yaml` and `raw`; `--fields`/`--exclude` projection, `--compact`, `--sideload` joins, an embedded jq filter (`--jq`), and one-line JSON errors on stderr with stable `code` strings and exit codes; `zdk --help-json` for tool-definition generation. - **Shell integration**: `zdk completions bash|zsh|fish|powershell|elvish` and `zdk man --to DIR` (one page per subcommand), both shipped in release archives. - **Distribution**: 7-target release pipeline (macOS arm64/x64, Linux musl arm64/x64 and glibc x64, Windows x64/arm64) with build-provenance attestations, `checksums-sha256.txt`, Homebrew tap and Scoop bucket updates. + +[Unreleased]: https://github.com/osodevops/zendesk-cli/compare/v0.1.0...HEAD +[0.1.0]: https://github.com/osodevops/zendesk-cli/releases/tag/v0.1.0 diff --git a/Cargo.lock b/Cargo.lock index 0e1faa4..2d61fc1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4126,7 +4126,7 @@ checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" [[package]] name = "xtask" -version = "0.0.0" +version = "0.1.0" dependencies = [ "anyhow", "chrono", @@ -4249,7 +4249,7 @@ dependencies = [ [[package]] name = "zdk-core" -version = "0.0.0" +version = "0.1.0" dependencies = [ "arc-swap", "argon2", @@ -4301,7 +4301,7 @@ dependencies = [ [[package]] name = "zendesk-cli" -version = "0.0.0" +version = "0.1.0" dependencies = [ "assert_cmd", "chrono", diff --git a/Cargo.toml b/Cargo.toml index f8f90e3..11f01d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ members = ["crates/zdk-core", "crates/zdk-cli", "xtask"] default-members = ["crates/zdk-core", "crates/zdk-cli"] [workspace.package] -version = "0.0.0" +version = "0.1.0" edition = "2024" rust-version = "1.88" license = "MIT" @@ -15,7 +15,7 @@ keywords = ["zendesk", "cli", "oauth", "support", "ai-agent"] categories = ["command-line-utilities"] [workspace.dependencies] -zdk-core = { path = "crates/zdk-core", version = "0.0.0" } +zdk-core = { path = "crates/zdk-core" } # add `version` when publishing to crates.io # CLI clap = { version = "4.6", features = ["derive", "env", "string", "wrap_help"] } diff --git a/crates/zdk-cli/tests/cli.rs b/crates/zdk-cli/tests/cli.rs index 8a7f7fa..da3df72 100644 --- a/crates/zdk-cli/tests/cli.rs +++ b/crates/zdk-cli/tests/cli.rs @@ -37,12 +37,12 @@ fn version_flag_and_command() { .arg("--version") .assert() .success() - .stdout(predicate::str::is_match(r"^zdk 0\.0\.0\n$").expect("re")); + .stdout(predicate::str::is_match(r"^zdk \d+\.\d+\.\d+\n$").expect("re")); h.zdk() .args(["version", "-o", "table"]) .assert() .success() - .stdout("zdk 0.0.0\n"); + .stdout(concat!("zdk ", env!("CARGO_PKG_VERSION"), "\n")); // Piped (the default here) means JSON. let out = h .zdk() @@ -52,7 +52,7 @@ fn version_flag_and_command() { .get_output() .stdout .clone(); - assert_eq!(json(&out)["version"], "0.0.0"); + assert_eq!(json(&out)["version"], env!("CARGO_PKG_VERSION")); } #[test] @@ -67,7 +67,7 @@ fn version_json_has_target_and_spec_versions() { .stdout .clone(); let v = json(&out); - assert_eq!(v["version"], "0.0.0"); + assert_eq!(v["version"], env!("CARGO_PKG_VERSION")); assert!(v["target"].as_str().is_some_and(|t| t.contains('-')), "{v}"); assert!(v["spec_versions"].is_array(), "{v}"); } @@ -85,7 +85,7 @@ fn help_json_is_a_walkable_tree() { .clone(); let v = json(&out); assert_eq!(v["binary"], "zdk"); - assert_eq!(v["version"], "0.0.0"); + assert_eq!(v["version"], env!("CARGO_PKG_VERSION")); let subs = v["subcommands"].as_array().expect("subcommands"); let config = subs .iter() From 71065f31a0e9c2739ffd6cd41cadcac2a4ed9c7a Mon Sep 17 00:00:00 2001 From: Sion Smith Date: Fri, 11 Sep 2026 12:51:08 +0100 Subject: [PATCH 2/5] ci(deny): allow version-less path dependencies for workspace members Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_019WDt3RRcPRUR3oxsBjiGio --- deny.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deny.toml b/deny.toml index 78c7680..6e60662 100644 --- a/deny.toml +++ b/deny.toml @@ -38,6 +38,8 @@ license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }] [bans] multiple-versions = "allow" wildcards = "deny" +# Workspace members are path dependencies without a version until crates.io publishing. +allow-wildcard-paths = true [sources] unknown-registry = "deny" From f5bba4357f941e04cf69ab41d35ea77088f15d5e Mon Sep 17 00:00:00 2001 From: Sion Smith Date: Fri, 11 Sep 2026 12:51:47 +0100 Subject: [PATCH 3/5] chore(release): keep the zdk-core path pin at the workspace version and guard it Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_019WDt3RRcPRUR3oxsBjiGio --- Cargo.toml | 2 +- .../check-release-version.cpython-314.pyc | Bin 0 -> 15251 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 scripts/__pycache__/check-release-version.cpython-314.pyc diff --git a/Cargo.toml b/Cargo.toml index 11f01d4..33e50f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ keywords = ["zendesk", "cli", "oauth", "support", "ai-agent"] categories = ["command-line-utilities"] [workspace.dependencies] -zdk-core = { path = "crates/zdk-core" } # add `version` when publishing to crates.io +zdk-core = { path = "crates/zdk-core", version = "0.1.0" } # keep equal to [workspace.package] version (guarded by scripts/check-release-version.py) # CLI clap = { version = "4.6", features = ["derive", "env", "string", "wrap_help"] } diff --git a/scripts/__pycache__/check-release-version.cpython-314.pyc b/scripts/__pycache__/check-release-version.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..16b43f5f6610f00518a1f00b4f3b32eb821ef575 GIT binary patch literal 15251 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 literal 0 HcmV?d00001 From 0cd6b5121a0ac98db8eb2743e8e3cb5f654c3223 Mon Sep 17 00:00:00 2001 From: Sion Smith Date: Fri, 11 Sep 2026 12:52:27 +0100 Subject: [PATCH 4/5] ci(guard): verify internal path-dependency version pins match the workspace version Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_019WDt3RRcPRUR3oxsBjiGio --- scripts/check-release-version.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/scripts/check-release-version.py b/scripts/check-release-version.py index 71c2c9e..b8075c5 100755 --- a/scripts/check-release-version.py +++ b/scripts/check-release-version.py @@ -171,6 +171,25 @@ def verify_changelog_version(version: str) -> None: fail(f"CHANGELOG.md is missing a `## [{version}]` release section (it becomes the release body).") +def verify_internal_dep_pins(version: str) -> None: + """[workspace.dependencies] path entries for workspace members carry a `version` + (crates.io requires it); it must equal the workspace version or `cargo update` + and publishing break in confusing ways.""" + root = parse_toml(Path("Cargo.toml").read_text(encoding="utf-8"), "Cargo.toml") + members = load_workspace_member_names() + stale: list[str] = [] + for name, spec in root.get("workspace", {}).get("dependencies", {}).items(): + if isinstance(spec, dict) and "path" in spec and name in members: + pinned = spec.get("version") + if isinstance(pinned, str) and pinned.lstrip("=^") != version: + stale.append(f"{name} pins {pinned}") + if stale: + fail( + f"[workspace.dependencies] path pins are out of sync with {version}: " + f"{', '.join(stale)}. Edit the `version = ...` on those entries in Cargo.toml." + ) + + def tag_exists(tag: str) -> bool: result = subprocess.run( ["git", "rev-parse", "--verify", "--quiet", f"refs/tags/{tag}"], @@ -225,6 +244,7 @@ def main() -> None: fail(f"[workspace.package] version must increase (base: {base_version}, head: {head_version}).") verify_lockfile_version(head_version) + verify_internal_dep_pins(head_version) verify_changelog_version(head_version) if args.mode == "guard" and args.event_name == "pull_request" and tag_exists(tag): From 7f2a6f0a23e8a089a18df631e8ddfeb8653a91db Mon Sep 17 00:00:00 2001 From: Sion Smith Date: Fri, 11 Sep 2026 12:52:42 +0100 Subject: [PATCH 5/5] chore: untrack Python bytecode and ignore __pycache__ Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_019WDt3RRcPRUR3oxsBjiGio --- .gitignore | 4 ++++ .../check-release-version.cpython-314.pyc | Bin 15251 -> 0 bytes 2 files changed, 4 insertions(+) delete mode 100644 scripts/__pycache__/check-release-version.cpython-314.pyc diff --git a/.gitignore b/.gitignore index d5f4934..b58b77d 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,7 @@ tokens.enc # OS artifacts .DS_Store Thumbs.db + +# Python bytecode from running scripts/*.py locally +__pycache__/ +*.pyc diff --git a/scripts/__pycache__/check-release-version.cpython-314.pyc b/scripts/__pycache__/check-release-version.cpython-314.pyc deleted file mode 100644 index 16b43f5f6610f00518a1f00b4f3b32eb821ef575..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15251 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