iter-19: pull-zone bug fixes & CLI UX polish#21
Conversation
Fixes the two field-report blockers (Storage-Zone-backed pull-zone create, deserialize panic on Magic-Container-backed pull zones) plus credential bootstrap (storage-zone passwords) and a few polish items. - pull-zone create: --storage-zone-id and --zone-tier flags, ArgGroup enforces exactly-one origin - pull-zone update: --storage-zone-id (mutually exclusive with --origin-url) - bunny-api-core: forward-compat repr-enum deserialization via lossy Option<T> helper; OriginType=5=MagicContainerEndpoint added - DnsRecord.record_type now Option<DnsRecordType> - storage-zone get/list/create: Password / ReadOnlyPassword surfaced via redaction layer (default `<set, length=N>`, --reveal opts in) - container list/get/delete: top-level shortcuts aliasing `container app` - hoppy --version: embeds short git SHA + bunny-spec date via build.rs - help text: examples + long_help on pull-zone create, pull-zone hostname add, dns record add, storage-zone create Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Free Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughThis PR implements forward-compatible enum deserialization, makes pull-zone creation support storage-zone backing with clap ArgGroup validation, threads storage-zone secret redaction through CLI output (with ChangesForward-compatible enums, storage-zone backing, and credential redaction
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login. Comment |
There was a problem hiding this comment.
Pull request overview
This PR addresses several CLI blockers and UX improvements in hoppy (the async Rust bunny.net CLI), focusing on pull zone creation/update correctness, forward-compatible enum deserialization in the core API client, and safely surfacing Storage Zone credentials via the existing redaction layer.
Changes:
- Fix
pull-zone create/updateto support Storage-Zone-backed origins (--storage-zone-id) and add--zone-tier {premium,volume}with clap mutual-exclusion enforcement. - Make
bunny-api-coremore forward-compatible by lossy-deserializing unknown integer repr-enums toNone, and modelOriginType::MagicContainerEndpoint = 5. - Surface
StorageZone.Password/ReadOnlyPasswordin CLI JSON with default redaction (<set, length=N>) and--revealoverride; plus--versionprovenance viabuild.rsand container command aliases.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/snapshots/cli_storage_zone__storage_zone_list_json.snap | Snapshot updated to include redacted Password/ReadOnlyPassword fields. |
| tests/snapshots/cli_storage_zone__storage_zone_get_json.snap | Snapshot updated to include redacted Password/ReadOnlyPassword fields. |
| tests/snapshots/cli_storage_zone__storage_zone_create_json.snap | Snapshot updated to include redacted Password/ReadOnlyPassword fields. |
| tests/cli_storage_zone.rs | Adds CLI tests for default redaction vs --reveal for storage-zone get. |
| tests/cli_pull_zone.rs | Adds CLI tests for --storage-zone-id, --zone-tier, and clap ArgGroup error paths. |
| src/redact.rs | Adds JSON secret-field redaction walker + updates secret-field heuristic. |
| src/main.rs | Passes RedactConfig into storage-zone command handler. |
| src/commands/storage_zone.rs | Applies secret redaction to storage-zone JSON output and threads RedactConfig through. |
| src/commands/pull_zone.rs | Adds create/update support for StorageZoneId and zone tier mapping into request body. |
| src/commands/dns.rs | Handles DnsRecord.record_type: Option<_> in table rows with “Unknown” fallback. |
| src/commands/container.rs | Adds top-level container list/get/delete aliases to container app .... |
| src/cli.rs | Adds ZoneTier enum, pull-zone ArgGroup, expanded help text, container aliases, and long --version. |
| hoppy-knowledgebase/iterations/iteration-19-pullzone-bugfixes.md | Marks iter-19 completed and documents shipped changes/deferrals. |
| hoppy-knowledgebase/decision-log.md | Documents lossy-enum strategy, password redaction approach, ArgGroup choice, and build provenance. |
| hoppy-knowledgebase/api/bunny-api-quirks.md | Documents enum-growth behavior, storage-zone origin quirks, password redaction, DNS caveats. |
| fixtures/core/pullzone_get_magic_container.json | Adds regression fixture for Magic-Container-backed pull zones (OriginType: 5). |
| crates/bunny-api-core/tests/storagezone_api.rs | Updates tests to assert password round-trips at API-client layer. |
| crates/bunny-api-core/tests/pullzone_api.rs | Adds tests for Magic Container OriginType and unknown OriginType fallback behavior. |
| crates/bunny-api-core/tests/dns_api.rs | Updates DNS tests for record_type: Option<_>. |
| crates/bunny-api-core/src/types.rs | Adds OriginType=5, changes request/response modeling (Option enums + storage passwords serialize). |
| crates/bunny-api-core/src/serde_helpers.rs | New helper to lossy-deserialize unknown repr-enum integers into None. |
| crates/bunny-api-core/src/lib.rs | Exposes serde_helpers module publicly. |
| build.rs | New build script embedding short git SHA + “spec date” into --version long output. |
| if let OutputFormat::Json = format { | ||
| let json = serde_json::to_string_pretty(sz).expect("failed to serialize to JSON"); | ||
| let mut value = serde_json::to_value(sz).expect("failed to serialize StorageZone to JSON"); | ||
| redact_secrets_in_json(&mut value, redact_cfg); | ||
| let json = serde_json::to_string_pretty(&value).expect("failed to serialize to JSON"); | ||
| println!("{json}"); |
| let lower = name.to_lowercase(); | ||
| // Allowlist: a few `_key` suffixes are not secrets in this codebase. | ||
| const KEY_SUFFIX_NOT_SECRET: &[&str] = &[ | ||
| "zonesecuritykey", // PullZone — already gated separately |
| let spec_date = newest_spec_mtime().unwrap_or_else(|| "unknown".to_owned()); | ||
| println!("cargo:rustc-env=HOPPY_BUNNY_API_SPEC_DATE={spec_date}"); |
| println!("cargo:rerun-if-changed=specs"); | ||
| } | ||
|
|
- tests: tighten clap mutual-exclusion + required-arg stderr assertions - tests: assert AccessKey header on volume-tier and update mocks - tests: assert redaction placeholder shape (not just absence of secret) - tests: set application/json content-type on unknown-OriginType mock - tests: clarify comment on the MagicContainer regression test - build.rs: skip unreadable spec entries instead of aborting newest_spec_mtime - build.rs: only emit cargo:rerun-if-changed=.git/HEAD when the file exists - redact.rs: doc comment now matches the null/string handling actually implemented Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
pull-zone createnow supports--storage-zone-id(and--zone-tier {premium,volume}); a clapArgGroupenforces exactly-one-of--origin-url/--storage-zone-id.pull-zone updateadds--storage-zone-id(mutually exclusive with--origin-url).repr-enum deserialization inbunny-api-core— everyOption<EnumType>response field now falls back toNonefor unknown integers viaserde_helpers::deserialize_repr_option.OriginType::MagicContainerEndpoint = 5is now modelled, fixing the panic on Magic-Container-backed pull zones (pullzone get 5719318).DnsRecord.record_typeis nowOption<DnsRecordType>for the same reason.storage-zone get/list/createnow surfacesPassword/ReadOnlyPassword. Redacted by default (<set, length=N>); pass--revealto bypass. Operators no longer have to fall back tocurlfor credential bootstrap.hoppy container list/get/deletenow mirrorpull-zone listetc. (alias tocontainer app …);hoppy --versionnow embeds the short git SHA and bunny-spec date via a smallbuild.rs; long-form help with examples onpull-zone create,pull-zone hostname add,dns record add,storage-zone create.decision-log.mdandapi/bunny-api-quirks.mdcovering the lossy-enum strategy, the storage-password redaction, and the DNS Flatten/PullZone caveats; iter-19 plan marked completed with explicit deferrals.Test plan
cargo fmtcargo clippy --workspace --all-targets -- -D warningscargo test --workspacepull-zone create --storage-zone-idbody shape,--zone-tier volumebody shape, ArgGroup error paths (no flag / both flags),pull-zone update --storage-zone-id, Magic-Container PZ regression fixture (OriginType: 5), unknown-OriginType fallback,storage-zone getredacted vs--reveal.hoppy --versionprintshoppy 0.1.0 (sha=…, bunny-api-spec=YYYY-MM-DD).live-apifeature for future runs).🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
container list,container get,container delete--origin-urlvs--storage-zone-idplus--zone-tierImprovements
--revealto show plaintextDocumentation
Tests