Releases: hops-ops/hops-cli
v0.32.1
v0.32.0
What's changed in v0.32.0
-
chore(deps): update rust crate log to v0.4.32 (#50) (by @renovate[bot])
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
-
chore(deps): update rust crate uuid to v1.23.2 (#52) (by @renovate[bot])
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
-
feat: mount distributed_cli for hops service (drop local adapter) (#56) (by @patrickleet)
- feat: mount distributed_cli for
hops serviceinstead of a local adapter
hops servicenow re-exports distributed_cli's command surface rather than
carrying its own scaffold/describe/schema adapter: the Service variant holds
distributed_cli::ServiceArgs and dispatches with distributed_cli::run. Deletes
src/commands/service (the former ~930-line adapter) and swaps the dependency from
distributed_tooling to distributed_cli.This makes hops a thin, optional front-end: new flags/commands added in
distributed_cli (e.g.schema --format atlas) reachhops serviceon a plain
cargo update, with no code changes here.Temporary git dep on the distributed branch until distributed_cli is published;
swap to a registry version once distributed PR #74 releases.- chore: depend on published distributed_cli 1.6 from crates.io
distributed PR #74 merged and released distributed_cli 1.6.x, so replace the
temporary git dependency with the registry version. No git source or branch
tracking;hops serviceresolves the command surface from the published crate.Closes #58
- feat: mount distributed_cli for
See full diff: v0.31.0...v0.32.0
v0.31.0
What's changed in v0.31.0
-
feat: add distributed service scaffold commands (#55) (by @patrickleet)
- feat: add distributed service scaffold commands
Implements [[tasks/hops-service-create-microsvc-scaffold]].
Updates [[customize-hops-service-scaffold-and-schema-output]].
Updates [[gitops-knative-service-scaffold]].
Updates [[replace-model-booleans-with-repeatable-model]].
Updates [[add-service-bus-flag]].
Updates [[make-service-read-models-opt-in]].
Updates [[rename-service-create-to-scaffold]].
Updates [[add-service-scaffold-github-workflows]].
- refactor: back service scaffold with distributed_tooling crate
Replace the ~2100-line in-CLI generation logic (ScaffoldNames/ModelScaffold/
MessageHandler, all the *_rs / *_yaml templates, Knative broker/trigger
inference, GitHub workflow rendering) with a thin adapter over the new
distributed_tooling crate. The CLI now:- keeps the clap surface (ScaffoldArgs + Framework/Transport/Store/Bus/
GitopsPromote enums) and maps it to distributed_tooling::ServiceScaffoldSpec
via From impls; - computes output_dir + the relative distributed dependency path as before;
- calls generate_service_scaffold(), writes each GeneratedFile (creating parents,
honoring FileMode::Executable), prints warnings, and runs the
EnsureGithubRepository post-create action via the existing gh logic; - keeps describe/schema and the manifest compile-harness unchanged.
Generation rules now live in (and are tested by) distributed_tooling. Verified
byte-for-byte identical output against the previous implementation across five
variants (HTTP, model+read-models, Knative+bus+gitops+promote, full GitHub, and
preview-only) — the only intended difference is the generated service.rs builder
(Service::new().with_repo(repo)).Dependency uses the meta-repo sibling path (../distributed/distributed_tooling);
a git dependency will replace it for released/standalone builds.cli mod.rs: 2589 -> 930 lines.
Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com
- fix(ci): depend on distributed_tooling via git instead of a local path
The
../distributed/distributed_toolingpath dep only resolves in the meta-repo
sibling layout; standalone hops-cli CI checks out only this repo, so the build
failed reading the missing Cargo.toml. distributed is public, so a plain HTTPS
git dep resolves with no secrets. Tracks the PR #53 branch until the crate is
published to crates.io.Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
- chore: depend on published distributed_tooling 1.5 from crates.io
distributed v1.5.0 published distributed_tooling, so drop the temporary
git-branch dependency in favor of the registry version. No git source or
secrets needed; the crate only pulls in serde_json.Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com
Co-authored-by: Claude Opus 4.8 (1M context) noreply@anthropic.com
See full diff: v0.30.0...v0.31.0
v0.30.0
What's changed in v0.30.0
-
feat(local): label
hops provider installresources so doctor knows they're intentional (#54) (by @patrickleet)hops provider installnow stampsapp.kubernetes.io/managed-by: hops-provider-install
on the Provider, DeploymentRuntimeConfig, and ClusterRoleBinding it manages. A
custom install (e.g. a forked provider built from source) uses the
<provider>-runtimeDRC convention rather than the bootstraplocal-dev-<provider>
DRC, whichhops local doctorpreviously reported as drift.hops local doctornow reads that label: a labeled provider is checked against the
install convention (<provider>-runtimeDRC,<provider>-cluster-adminbinding,
SA<provider>) and reported as a "custom install" with its package, instead of
false drift — while still verifying cluster-admin and still flagging real drift
(runtimeConfigRef=default / missing cluster-admin) in both modes.Co-authored-by: Claude Opus 4.8 (1M context) noreply@anthropic.com
See full diff: v0.29.0...v0.30.0
v0.29.0
What's changed in v0.29.0
-
feat(local): per-provider DRCs,
hops local doctor, and global --context (#53) (by @patrickleet)Split the shared
local-devDeploymentRuntimeConfig into per-provider DRCs
(local-dev-kubernetes, local-dev-helm), each with its own cluster-admin
ServiceAccount + ClusterRoleBinding, and point each provider's runtimeConfigRef
at its own DRC. A shared DRC let one provider's runtime image/SA silently
clobber the other's pod.Add
hops local doctor: verifies whathops local startset up — crossplane,
both providers (installed / healthy / runtimeConfigRef pinned to its own DRC /
DRC present / cluster-admin binding / ProviderConfig) and the registry — and
reports drift with a non-zero exit + remediation. Catches a provider whose
runtimeConfigRef reverted todefault, dropping its cluster-admin SA (which
breaks observing XRs through the in-cluster ProviderConfig).Add a global
--contextflag tohops localso every subcommand can target a
context (e.g.hops local aws --refresh --profile hops --context colima), given
before or after the subcommand. Plumbs through HOPS_KUBE_CONTEXT_ENV like
config/provider install.Co-authored-by: Claude Opus 4.8 (1M context) noreply@anthropic.com
See full diff: v0.28.0...v0.29.0
v0.28.0
What's changed in v0.28.0
-
feat(local): add
hops local listmonk+ make --source-context required (#51) (by @patrickleet)Mirrors
hops local zitadel/hops local github. Bootstraps the
hops-ops/provider-listmonk Crossplane provider + a cluster-scoped
ProviderConfig pointing at a Listmonk instance via Basic-Auth
credentials (JSON Secret).Credential resolution waterfall:
- Explicit --endpoint / --username / --token flags
- LISTMONK_{ENDPOINT,USERNAME,TOKEN} env vars
- Read from the chart-bootstrapped Secret on a source cluster
(with keysusername+token— the shape produced by
listmonk-chart v0.2.0's post-install api-user-bootstrap hook)
Endpoint is derived from the source Secret name when not explicitly
set:<release>-provider-creds→ in-cluster service
http://<release>.<source-namespace>.svc.cluster.local:9000.Default upjet provider package: ghcr.io/hops-ops/provider-listmonk:v0.0.3.
Also drops the
pat-localdefault from--source-contexton BOTH
this command andhops local zitadel— that hardcoded value bakes
the implementer's personal cluster name into a tool meant for
multiple users. Required positional flag now; users explicitly pass
their own source context.Verified end-to-end on pat-local 2026-05-25:
- Provider install + Healthy
- ProviderConfig applied
- UserRole MR reconciled (Crossplane → upjet → TF provider →
Listmonk REST API → users / roles table) - User MR reconciled with cross-resource userRoleIdRef → numeric
userRoleId (typed-reference resolution works end-to-end) - AppSettings MR reconciled (no-op write of current values; round-
trip lossless)
See full diff: v0.27.0...v0.28.0
v0.27.0
What's changed in v0.27.0
-
feat: add local zitadel provider bootstrap (#49) (by @patrickleet)
-
feat: add local zitadel provider bootstrap
-
fix: preserve zitadel domain ports
-
See full diff: v0.26.1...v0.27.0
v0.26.1
What's changed in v0.26.1
-
chore(deps): update rust crate openssl-sys to v0.9.116 (#43) (by @renovate[bot])
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
-
chore(deps): update rust crate tokio to v1.52.3 (#44) (by @renovate[bot])
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
-
chore(deps): update unbounded-tech/workflow-vnext-tag action to v1.21.3 (#45) (by @renovate[bot])
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
-
chore(deps): update unbounded-tech/workflows-rust action to v2.3.0 (#46) (by @renovate[bot])
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
-
chore(deps): update rust crate tar to v0.4.46 (#47) (by @renovate[bot])
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
-
fix(deps): update rust crate serde_json to v1.0.150 (#48) (by @renovate[bot])
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
See full diff: v0.26.0...v0.26.1
v0.26.0
What's changed in v0.26.0
-
feat(secrets): three-bucket list with platform-pushed section, symmetric managed-by tagging (by @patrickleet)
hops secrets sync awsnow writeshops.ops.com.ai/managed-by=sync
alongside the existinghops.ops.com.ai/secret=true, mirroring the
managed-by=pushsecrettag that AuthStack-style Crossplane stacks
attach to ESO-pushed AWS SM entries. Bucketing insecrets list
becomes a positive match instead of "secret=true minus everything
else."secrets listgains a "Platform-pushed secrets" section between the
existing "Managed secrets" and "Other AWS secrets" sections. Routing
byhops.ops.com.ai/managed-by:- sync (or absent + secret=true for legacy entries) → Managed
- pushsecret → Platform-pushed
- everything else → Other
Platform-pushed columns: Name | Owner | Cluster | Namespace | KMS Key |
Status.Owneris derived from the explicithops.ops.com.ai/kind+
hops.ops.com.ai/nametags (renders e.g.AuthStack/pat-local); falls
back to scanning for the olderhops.ops.com.ai/<kind.lower>=<name>
label for entries pushed before the explicit tags were added.has_managed_secret_tag()(used bysync --cleanupto decide which
remote secrets to consider for deletion) was tightened to require
eithermanaged-by=syncOR no managed-by tag at all. Previously it
matched anysecret=trueentry, which would have swept up PushSecret-
managed entries the moment we addedsecret=trueto that flow.Existing managed secrets show
remote tags differin the list output
until the nexthops secrets sync awswrites the new managed-by tag.
No data is at risk — the migration is just additive.Pairs with the AuthStack PushSecret commit + the SecretStack
push/*IAM grant.
See full diff: v0.25.1...v0.26.0
v0.25.1
What's changed in v0.25.1
-
fix(provider install): never reuse a Provider's existing DRC ref (by @patrickleet)
apply_provider_resources now always names the DRC -runtime
instead of inheriting the existing Provider's spec.runtimeConfigRef.name.
A previous "avoid orphaning the DRC" heuristic blindly reused whatever
DRC the upstream Provider already referenced, then overwrote that DRC
with the new install's image — silently corrupting any other Provider
that happened to reference the same DRC.Repro (the bug that surfaced this): provider-helm and provider-kubernetes
both referenced DRC "local-dev"; a later 'hops provider install helm'
wrote local-dev with the helm dev image, leaving provider-kubernetes
pinned to that DRC and therefore running the helm binary in a pod
labeled as kubernetes.After the fix:
- Each install creates an owned DRC named <existing_provider>-runtime
- If the existing Provider already pointed at a differently-named DRC,
a log::warn surfaces the migration ("switching to owned DRC ...; the
old DRC is not deleted") so leftovers are discoverable - The orphaned DRC is left in place; it may still be referenced by
another Provider, and deletion is the operator's call
Validated end-to-end on colima: 'hops provider install --repo
jonasz-lasut/provider-helm' migrated provider-helm from local-dev to
crossplane-contrib-provider-helm-runtime, helm pod healthy on
v1.999.2, provider-kubernetes (after clearing its stale local-dev ref)
healthy on upstream provider-kubernetes:v1.2.0.Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
See full diff: v0.25.0...v0.25.1