Skip to content

feat(local): add colima resize, cloudflare bootstrap, aws region/runtime#68

Merged
patrickleet merged 3 commits into
mainfrom
feat/local-listmonk-bootstrap
Jun 28, 2026
Merged

feat(local): add colima resize, cloudflare bootstrap, aws region/runtime#68
patrickleet merged 3 commits into
mainfrom
feat/local-listmonk-bootstrap

Conversation

@patrickleet

@patrickleet patrickleet commented Jun 28, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • hops local start now accepts --cpus (alias --cpu), --memory, --disk + --yes for non-interactive resize on existing VM.
  • New hops local resize --cpus N --memory N --disk N for non-destructive Colima VM resize (detects current via colima list --json, prevents disk shrink).
  • New hops local cloudflare (token from flag / env / AWS SM; applies provider + creds secret + ProviderConfig; --refresh support). Mirrors aws/zitadel/listmonk/github.
  • hops local aws gains --region, --runtime-config-name; always ensures region-aware DeploymentRuntimeConfig (normal + refresh paths).
  • Minor cleanups (formatting skipped in final rebase as superseded).

Branch rebased onto latest main for up-to-date base (previously based on stale feat branch).

Verification

  • cargo test: 104 passed
  • cargo check clean
  • Help text verified for new/updated commands

Tasks (GitKB)

  • Implements / closes [[tasks/hops-cli-local-resize]] (sizing + resize delivered; recovery flow split to follow-up)
  • Adds [[tasks/hops-cli-local-cloudflare]]
  • Adds [[tasks/hops-cli-local-registry-recover]] (follow-up)
  • Progress on [[tasks/hops-local-aws-watch]]

Commits (on feat/local-listmonk-bootstrap, rebased)

  • 9748493 feat(local): add colima sizing/resize and hops local cloudflare [[tasks/hops-cli-local-resize]]
  • 6fbbb96 feat(local): region + runtimeConfig support in hops local aws
  • (plus rebased 2e22f01 nodeport fix; older listmonk/DRC doctor work already merged to main via prior PRs)

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Removes the shared local-dev Crossplane DeploymentRuntimeConfig and replaces it with per-provider DRCs for Helm and Kubernetes. Adds hops local cloudflare, listmonk, resize, and doctor subcommands, parameterizes hops local start with size args, wires AWS region into DRC generation, adds a global --context flag, and switches provider install to use the push registry for runtime image references.

Changes

Local Dev Subcommands, Per-Provider DRC Split, and Doctor

Layer / File(s) Summary
Per-provider DRC manifests and provider references
bootstrap/drc/helm.yaml, bootstrap/drc/kubernetes.yaml, bootstrap/drc/local-dev.yaml, bootstrap/providers/provider-helm.yaml, bootstrap/providers/provider-kubernetes.yaml
Removes the shared local-dev DRC; adds separate DeploymentRuntimeConfig + ClusterRoleBinding for each provider; updates spec.runtimeConfigRef.name in Helm and Kubernetes provider manifests accordingly.
Parameterized hops local start and new resize subcommand
src/commands/local/start.rs, src/commands/local/resize.rs
Replaces no-arg start::run with StartArgs/ColimaSizeArgs; adds Colima instance detection, disk-shrink validation, stop/restart resize logic, and per-provider DRC apply (DRC_K8S + DRC_HELM); adds ResizeArgs and its run entrypoint.
AWS region resolution and DRC wiring
src/commands/local/aws.rs
Adds --region/-r to AwsArgs; implements resolve_region/select_region with CLI/env/default precedence and character validation; extends build_credentials_ini with region; adds build_runtime_config_yaml; updates build_provider_yaml with runtimeConfigRef; refresh path now also applies the DRC.
New hops local cloudflare subcommand
src/commands/local/cloudflare.rs
Adds CloudflareArgs and run; resolves API token from CLI/env/AWS Secrets Manager with SSO login retry; extracts secret properties from JSON; waits for required CRDs; applies Provider, Secret, and ProviderConfig via kubectl apply; includes unit tests.
New hops local listmonk subcommand
src/commands/local/listmonk.rs
Adds ListmonkArgs and run; resolves endpoint/username/token from CLI/env/source Kubernetes secret; waits for ProviderConfig CRD; applies Provider, credentials Secret, and ProviderConfig; includes unit tests.
New hops local doctor subcommand
src/commands/local/doctor.rs
Adds run() that checks Crossplane deployments and two providers against expected per-provider DRC name, ClusterRoleBinding, and ProviderConfig using kubectl wrappers; collects results in a Doctor/Entry report and returns error on any failed check.
LocalCommands wiring: new variants, global --context, dispatcher
src/commands/local/mod.rs, src/commands/local/zitadel.rs
Expands module declarations; adds --context to LocalArgs; updates LocalCommands with typed Start(StartArgs), Resize, Doctor, Cloudflare, Listmonk variants; updates run() to set HOPS_KUBE_CONTEXT and dispatch all new arms; makes zitadel source_context required.
provider install: push registry runtime image ref
src/commands/provider/install.rs
Adds local_runtime_image_ref using REGISTRY_PUSH; passes push_runtime_ref instead of pull_runtime_ref to apply_provider_resources; adds unit test asserting REGISTRY_PULL is absent from the result.
Formatting-only changes
src/commands/auth/bootstrap.rs, src/commands/config/install.rs, src/commands/local/package_install.rs, src/commands/secrets/list.rs, src/commands/vars/mod.rs, src/commands/vars/sync.rs
Reformatting of log statements, function signatures, and import blocks with no logic changes.

Sequence Diagram(s)

sequenceDiagram
  participant CLI as hops local cloudflare
  participant resolver as resolve_api_token
  participant aws as AWS CLI (secretsmanager)
  participant kubectl as kubectl apply

  CLI->>resolver: resolve token (--api-token / CLOUDFLARE_API_TOKEN / AWS secret)
  resolver->>aws: get-secret-value --secret-id <id>
  aws-->>resolver: SecretString
  alt SSO error detected
    resolver->>aws: aws sso login --profile <profile>
    aws-->>resolver: ok
    resolver->>aws: get-secret-value (retry)
    aws-->>resolver: SecretString
  end
  resolver-->>CLI: api_token
  CLI->>kubectl: apply Provider YAML
  CLI->>kubectl: wait for CRDs (providerconfig, dnsrecord)
  CLI->>kubectl: apply Secret YAML
  CLI->>kubectl: apply ProviderConfig YAML
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • hops-ops/hops-cli#49: Overlaps with the zitadel.rs change making source_context required, as that PR introduced the Zitadel local provider bootstrap command.
  • hops-ops/hops-cli#51: Directly related — both PRs add/extend hops local listmonk with ListmonkArgs/run and wire LocalCommands::Listmonk in mod.rs.
  • hops-ops/hops-cli#53: Directly related — covers the per-provider DRC split (removing bootstrap/drc/local-dev.yaml), hops local doctor, and the global --context wiring in mod.rs.

Poem

🐇 Hoppity hop through the YAML maze,
Per-provider configs set clusters ablaze!
A doctor now checks if the bindings align,
Cloudflare and Listmonk join the divine.
Resize, restart — Colima obeys,
This rabbit ships features in so many ways! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.90% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main local-development changes, especially Colima resizing, Cloudflare bootstrap, and AWS runtime/region updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/local-listmonk-bootstrap

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@patrickleet patrickleet force-pushed the feat/local-listmonk-bootstrap branch from 34d2fda to 6fbbb96 Compare June 28, 2026 02:09

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/commands/local/aws.rs`:
- Line 52: The refresh path in aws.rs applies the DRC but exits before updating
the Provider, so existing providers can keep a stale AWS region. Update the
refresh flow in the relevant command handler to also wire the Provider to the
refreshed runtime config by patching or reconciling the Provider when its
runtimeConfigRef.name does not match args.runtime_config_name. Use the existing
refresh/apply logic in the command implementation to ensure the Provider is
brought in sync before returning success.

In `@src/commands/local/doctor.rs`:
- Around line 170-181: The ClusterRoleBinding validation in ProviderExpectation
only checks ServiceAccount names, so a matching SA in the wrong namespace can
still pass. Update ProviderExpectation to carry the expected subject namespace,
then adjust the doctor validation around jsonpath and binding_ok to verify both
the ServiceAccount name and namespace for the binding identified by e.binding
and e.sa.
- Around line 238-251: `exists()` and `jsonpath()` currently swallow all
`kubectl` failures into `false`/`None`, so `doctor` can misreport
connectivity/auth problems as missing resources. Update the `doctor` flow in
`src/commands/local/doctor.rs` to perform an upfront cluster-access check before
calling these helpers, or have `exists`/`jsonpath` preserve the first `kubectl`
error and surface it in the report. Use the existing `run_cmd_output`, `exists`,
and `jsonpath` paths to locate the affected logic and ensure broken
kube-context/API failures are shown explicitly instead of drift.

In `@src/commands/local/start.rs`:
- Around line 80-89: The Colima instance selection logic is using the first JSON
item from the list output instead of the default profile, which can cause resize
and running-state checks to target the wrong VM when multiple profiles exist.
Update the code that processes the Colima array output in the local start flow
to identify and select the instance marked as the default profile, and make sure
the subsequent validation and start/stop checks use that chosen instance
consistently. Use the existing ColimaInstance type and the list/selection logic
around the Colima start/stop handling to locate the fix.
- Around line 307-323: The validation in validate_requested_size only checks for
disk shrinking, but it should also reject zero-sized resources before Colima is
invoked. Update this function to validate ColimaSizeArgs fields for --cpus,
--memory, and --disk, returning an error when any requested value is 0,
alongside the existing ColimaInstance::disk_gib shrink check. Keep the logic
centralized here so the start flow fails early with a clear message instead of
reaching the external command path.

In `@src/commands/local/zitadel.rs`:
- Around line 34-37: `ZitadelCommandArgs::source_context` is currently required
by clap for every invocation, even when `--access-token` or
`ZITADEL_ACCESS_TOKEN` is used and the source secret is never read. Make
`source_context` optional in the argument struct and move the requirement into
the source-secret fallback path in `src/commands/local/zitadel.rs`, so only the
code path that actually loads the secret enforces it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5ca3dc82-8faf-4a10-9ece-636db6c36f4f

📥 Commits

Reviewing files that changed from the base of the PR and between e2b8377 and 34d2fda.

📒 Files selected for processing (20)
  • bootstrap/drc/helm.yaml
  • bootstrap/drc/kubernetes.yaml
  • bootstrap/drc/local-dev.yaml
  • bootstrap/providers/provider-helm.yaml
  • bootstrap/providers/provider-kubernetes.yaml
  • src/commands/auth/bootstrap.rs
  • src/commands/config/install.rs
  • src/commands/local/aws.rs
  • src/commands/local/cloudflare.rs
  • src/commands/local/doctor.rs
  • src/commands/local/listmonk.rs
  • src/commands/local/mod.rs
  • src/commands/local/package_install.rs
  • src/commands/local/resize.rs
  • src/commands/local/start.rs
  • src/commands/local/zitadel.rs
  • src/commands/provider/install.rs
  • src/commands/secrets/list.rs
  • src/commands/vars/mod.rs
  • src/commands/vars/sync.rs
💤 Files with no reviewable changes (1)
  • bootstrap/drc/local-dev.yaml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/commands/local/aws.rs`:
- Line 52: The refresh path in aws.rs applies the DRC but exits before updating
the Provider, so existing providers can keep a stale AWS region. Update the
refresh flow in the relevant command handler to also wire the Provider to the
refreshed runtime config by patching or reconciling the Provider when its
runtimeConfigRef.name does not match args.runtime_config_name. Use the existing
refresh/apply logic in the command implementation to ensure the Provider is
brought in sync before returning success.

In `@src/commands/local/doctor.rs`:
- Around line 170-181: The ClusterRoleBinding validation in ProviderExpectation
only checks ServiceAccount names, so a matching SA in the wrong namespace can
still pass. Update ProviderExpectation to carry the expected subject namespace,
then adjust the doctor validation around jsonpath and binding_ok to verify both
the ServiceAccount name and namespace for the binding identified by e.binding
and e.sa.
- Around line 238-251: `exists()` and `jsonpath()` currently swallow all
`kubectl` failures into `false`/`None`, so `doctor` can misreport
connectivity/auth problems as missing resources. Update the `doctor` flow in
`src/commands/local/doctor.rs` to perform an upfront cluster-access check before
calling these helpers, or have `exists`/`jsonpath` preserve the first `kubectl`
error and surface it in the report. Use the existing `run_cmd_output`, `exists`,
and `jsonpath` paths to locate the affected logic and ensure broken
kube-context/API failures are shown explicitly instead of drift.

In `@src/commands/local/start.rs`:
- Around line 80-89: The Colima instance selection logic is using the first JSON
item from the list output instead of the default profile, which can cause resize
and running-state checks to target the wrong VM when multiple profiles exist.
Update the code that processes the Colima array output in the local start flow
to identify and select the instance marked as the default profile, and make sure
the subsequent validation and start/stop checks use that chosen instance
consistently. Use the existing ColimaInstance type and the list/selection logic
around the Colima start/stop handling to locate the fix.
- Around line 307-323: The validation in validate_requested_size only checks for
disk shrinking, but it should also reject zero-sized resources before Colima is
invoked. Update this function to validate ColimaSizeArgs fields for --cpus,
--memory, and --disk, returning an error when any requested value is 0,
alongside the existing ColimaInstance::disk_gib shrink check. Keep the logic
centralized here so the start flow fails early with a clear message instead of
reaching the external command path.

In `@src/commands/local/zitadel.rs`:
- Around line 34-37: `ZitadelCommandArgs::source_context` is currently required
by clap for every invocation, even when `--access-token` or
`ZITADEL_ACCESS_TOKEN` is used and the source secret is never read. Make
`source_context` optional in the argument struct and move the requirement into
the source-secret fallback path in `src/commands/local/zitadel.rs`, so only the
code path that actually loads the secret enforces it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5ca3dc82-8faf-4a10-9ece-636db6c36f4f

📥 Commits

Reviewing files that changed from the base of the PR and between e2b8377 and 34d2fda.

📒 Files selected for processing (20)
  • bootstrap/drc/helm.yaml
  • bootstrap/drc/kubernetes.yaml
  • bootstrap/drc/local-dev.yaml
  • bootstrap/providers/provider-helm.yaml
  • bootstrap/providers/provider-kubernetes.yaml
  • src/commands/auth/bootstrap.rs
  • src/commands/config/install.rs
  • src/commands/local/aws.rs
  • src/commands/local/cloudflare.rs
  • src/commands/local/doctor.rs
  • src/commands/local/listmonk.rs
  • src/commands/local/mod.rs
  • src/commands/local/package_install.rs
  • src/commands/local/resize.rs
  • src/commands/local/start.rs
  • src/commands/local/zitadel.rs
  • src/commands/provider/install.rs
  • src/commands/secrets/list.rs
  • src/commands/vars/mod.rs
  • src/commands/vars/sync.rs
💤 Files with no reviewable changes (1)
  • bootstrap/drc/local-dev.yaml
🛑 Comments failed to post (6)
src/commands/local/aws.rs (1)

52-52: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Ensure refresh wires the Provider to the refreshed runtime config.

The refresh path applies the DRC but returns before applying or patching the Provider. Existing providers without runtimeConfigRef.name == args.runtime_config_name will not receive the refreshed AWS region despite the success log.

🐛 Proposed fix
     if args.refresh {
         log::info!(
             "Applying AWS provider runtime '{}' for region '{}'...",
             args.runtime_config_name,
             region
         );
         kubectl_apply_stdin(&build_runtime_config_yaml(
             &args.runtime_config_name,
             &region,
         ))?;
+
+        log::info!(
+            "Ensuring provider-family-aws uses runtime '{}'...",
+            args.runtime_config_name
+        );
+        kubectl_apply_stdin(&build_provider_yaml(
+            &args.provider_name,
+            &args.provider_package,
+            &args.runtime_config_name,
+        ))?;
 
         log::info!(
             "Refreshing secret '{}/{}' with generated credentials...",

Also applies to: 75-84

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/commands/local/aws.rs` at line 52, The refresh path in aws.rs applies the
DRC but exits before updating the Provider, so existing providers can keep a
stale AWS region. Update the refresh flow in the relevant command handler to
also wire the Provider to the refreshed runtime config by patching or
reconciling the Provider when its runtimeConfigRef.name does not match
args.runtime_config_name. Use the existing refresh/apply logic in the command
implementation to ensure the Provider is brought in sync before returning
success.
src/commands/local/doctor.rs (2)

170-181: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Validate the ClusterRoleBinding subject namespace too.

Line 175 only checks ServiceAccount names. A binding to the same SA name in the wrong namespace will still pass here even though the provider will not get the pinned identity. Add the expected subject namespace to ProviderExpectation and verify both fields.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/commands/local/doctor.rs` around lines 170 - 181, The ClusterRoleBinding
validation in ProviderExpectation only checks ServiceAccount names, so a
matching SA in the wrong namespace can still pass. Update ProviderExpectation to
carry the expected subject namespace, then adjust the doctor validation around
jsonpath and binding_ok to verify both the ServiceAccount name and namespace for
the binding identified by e.binding and e.sa.

238-251: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Surface kube-context/API failures before reporting drift.

exists() and jsonpath() turn every kubectl error into false/None. If the selected context is broken or the API is unreachable, doctor will report a pile of missing resources and suggest rerunning hops local start instead of showing the real connectivity/auth failure. Add an upfront cluster-access check or preserve the first kubectl error in the report.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/commands/local/doctor.rs` around lines 238 - 251, `exists()` and
`jsonpath()` currently swallow all `kubectl` failures into `false`/`None`, so
`doctor` can misreport connectivity/auth problems as missing resources. Update
the `doctor` flow in `src/commands/local/doctor.rs` to perform an upfront
cluster-access check before calling these helpers, or have `exists`/`jsonpath`
preserve the first `kubectl` error and surface it in the report. Use the
existing `run_cmd_output`, `exists`, and `jsonpath` paths to locate the affected
logic and ensure broken kube-context/API failures are shown explicitly instead
of drift.
src/commands/local/start.rs (2)

80-89: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Select the default Colima profile instead of the first JSON item.

For array output, Line 373 picks the first instance, but subsequent colima start/stop calls target the default profile. With multiple Colima profiles, resize validation and running-state checks can use the wrong VM.

🐛 Proposed fix
 #[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
 pub(crate) struct ColimaInstance {
+    #[serde(default)]
+    name: String,
     #[serde(default)]
     status: String,
@@
-    if let Ok(instances) = serde_json::from_str::<Vec<ColimaInstance>>(trimmed) {
-        return Ok(instances.into_iter().next());
+    if let Ok(instances) = serde_json::from_str::<Vec<ColimaInstance>>(trimmed) {
+        return Ok(select_default_colima_instance(instances));
     }
@@
 }
+
+fn select_default_colima_instance(instances: Vec<ColimaInstance>) -> Option<ColimaInstance> {
+    let mut first = None;
+    for instance in instances {
+        if instance.name == "default" {
+            return Some(instance);
+        }
+        if first.is_none() {
+            first = Some(instance);
+        }
+    }
+    first
+}

Also applies to: 362-374

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/commands/local/start.rs` around lines 80 - 89, The Colima instance
selection logic is using the first JSON item from the list output instead of the
default profile, which can cause resize and running-state checks to target the
wrong VM when multiple profiles exist. Update the code that processes the Colima
array output in the local start flow to identify and select the instance marked
as the default profile, and make sure the subsequent validation and start/stop
checks use that chosen instance consistently. Use the existing ColimaInstance
type and the list/selection logic around the Colima start/stop handling to
locate the fix.

307-323: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject zero-sized Colima resources before invoking Colima.

--cpus 0, --memory 0, and --disk 0 currently pass parsing and fail later in the external command path. Validate them alongside the disk-shrink check.

🐛 Proposed fix
 fn validate_requested_size(
     size: &ColimaSizeArgs,
     instance: Option<&ColimaInstance>,
 ) -> Result<(), Box<dyn Error>> {
+    if size.cpus == Some(0) {
+        return Err("Colima CPUs must be greater than 0".into());
+    }
+    if size.memory == Some(0) {
+        return Err("Colima memory must be greater than 0GiB".into());
+    }
+    if size.disk == Some(0) {
+        return Err("Colima disk must be greater than 0GiB".into());
+    }
+
     if let (Some(requested), Some(current)) =
         (size.disk, instance.and_then(ColimaInstance::disk_gib))
     {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

fn validate_requested_size(
    size: &ColimaSizeArgs,
    instance: Option<&ColimaInstance>,
) -> Result<(), Box<dyn Error>> {
    if size.cpus == Some(0) {
        return Err("Colima CPUs must be greater than 0".into());
    }
    if size.memory == Some(0) {
        return Err("Colima memory must be greater than 0GiB".into());
    }
    if size.disk == Some(0) {
        return Err("Colima disk must be greater than 0GiB".into());
    }

    if let (Some(requested), Some(current)) =
        (size.disk, instance.and_then(ColimaInstance::disk_gib))
    {
        if requested < current {
            return Err(format!(
                "Colima disk cannot be shrunk from {current}GiB to {requested}GiB. Use --disk {current} or larger, or destroy and recreate the VM."
            )
            .into());
        }
    }

    Ok(())
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/commands/local/start.rs` around lines 307 - 323, The validation in
validate_requested_size only checks for disk shrinking, but it should also
reject zero-sized resources before Colima is invoked. Update this function to
validate ColimaSizeArgs fields for --cpus, --memory, and --disk, returning an
error when any requested value is 0, alongside the existing
ColimaInstance::disk_gib shrink check. Keep the logic centralized here so the
start flow fails early with a clear message instead of reaching the external
command path.
src/commands/local/zitadel.rs (1)

34-37: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline src/commands/local/zitadel.rs --view expanded
rg -n -C3 'access_token|ZITADEL_ACCESS_TOKEN|source_context|source secret|source cluster' src/commands/local/zitadel.rs

Repository: hops-ops/hops-cli

Length of output: 4451


Make --source-context conditional on the source-secret fallback path. source_context is required by clap on every invocation here, so --access-token ... and ZITADEL_ACCESS_TOKEN callers still have to pass a source cluster context even though those paths never read the secret. Keep it optional at parse time and require it only when falling back to the source secret.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/commands/local/zitadel.rs` around lines 34 - 37,
`ZitadelCommandArgs::source_context` is currently required by clap for every
invocation, even when `--access-token` or `ZITADEL_ACCESS_TOKEN` is used and the
source secret is never read. Make `source_context` optional in the argument
struct and move the requirement into the source-secret fallback path in
`src/commands/local/zitadel.rs`, so only the code path that actually loads the
secret enforces it.

@patrickleet patrickleet merged commit 3889108 into main Jun 28, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant