Skip to content

main -> enhance CI workflows - #323

Merged
saadqbal merged 21 commits into
mainfrom
develop
Jul 15, 2026
Merged

main -> enhance CI workflows#323
saadqbal merged 21 commits into
mainfrom
develop

Conversation

@saadqbal

@saadqbalsaadqbal commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Note

Medium Risk
Large CI surface area and new cross-repo gates (several skip until secrets exist), but runtime CLI exit semantics stay numeric-equivalent; release pipeline loses the dormant Homebrew bump path.

Overview
This PR expands CI and local make ci with pinned staticcheck, goimports grouping, blocking deadcode (allowlisted unreachables), and a per-file line budget, plus Dependabot for grouped gomod and monthly Actions updates.

It adds cross-repo drift workflows that compare pinned upstream refs to vendored contracts: backend API fixtures (internal/api/testdata + contracts_test.go), validator goldens vs data-ingestors, Helm chart invariants vs tracebloc/client, and an advisory HEAD-drift canary that files tracking issues when the pin goes stale. E2E also runs on develop pushes so scheduled jobs exercise the same tree as active development; install PATH persist reuses the client harness against this PR’s install.sh. A manual-only gremlins workflow documents the mutation-testing ritual in CONTRIBUTING.

Release drops the disabled Homebrew tap job and uses GitHub-generated release notes instead of CHANGELOG.md. Docs/README/navigation are refreshed; docs/json-output.md and a troubleshooting exit-code table document scripting contracts. CLI packages swap raw 1/130 exits for named constants from exitcodes.go (behavior unchanged).

Reviewed by Cursor Bugbot for commit 0bf4b9f. Bugbot is set up for automated code reviews on this repo. Configure here.

saadqbaland others added 17 commits July 14, 2026 18:02
…op-319
chore: back-merge main → develop after #319 promote
…ert (cli#289) (#312)
New advisory workflow (head-drift-canary.yml), cron + dispatch only, never
blocking: checks data-ingestors develop HEAD (NOT the pin) two ways —
1. goldens check vs HEAD: sync-validator-goldens.sh --check against a
checkout of HEAD, catching verdict/value changes the next pin bump
would have to adopt.
2. mirrored-source drift: git content comparison (pin vs HEAD) over the
upstream surface internal/push + internal/schema mirror (validators/,
modalities/, coercion/columns/constants/validators_mapping,
csv_ingestor/record_processor/base/preflight, file_transfer,
schema_inference, database, schema/) — catching the di#365 class: a
new or extended upstream validator with no corpus case, invisible to
the goldens check by definition.
On either signal it opens or comments on a SINGLE tracking issue keyed by
the head-drift-canary marker label (label auto-created idempotently);
all-clear runs just emit a notice. Drift never reds the run — the job
captures the goldens verdict instead of failing on it. An unreachable pin
SHA (rewritten upstream history) is reported as drift too.
Verified locally against real history: the path-list diff at the OLD pin
7b4ecac flags exactly the di#358+di#365 surface (9 files incl.
mask_id_validator.py, image_validator.py); at the current pin 8f89aec it
is empty. Issue-body construction exercised with sample env; goldens
check vs HEAD ran green locally. actionlint clean.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ct (#297) (#314)
data delete is the destructive, script-invoked verb with zero JSON
support today. Add --output-json mirroring data_list.go's contract
exactly:
- RunE splits streams the same way (human -> stderr via
printerForWriter, JSON -> stdout) and, like data ingest's
implies---no-input, never wires a prompter in JSON mode — a scripted
delete must say --yes (or --dry-run) explicitly, else it fails
closed (exit 3).
- runDataDelete gains the jsonEmitted + deferred-error-writer pattern
(Bugbot #53 lineage): every failure return emits
{status:"error", error, exit_code} so stdout is never empty; the
error shape is byte-compatible with writeDataListErrorJSON's.
- Terminal statuses: deleted / dry-run / declined — all exit 0 like
the human flow, so scripts branch on status. The payload carries the
case-RESOLVED table spelling (backend#1027), namespace, release,
database, pvc_paths and removed_paths ([] never null).
- Exit codes unchanged; documented in the command Long text.
docs/json-output.md (new): which commands emit JSON (version, data
ingest, data list, data delete), the one-object-on-stdout rule, the
shared error shape, exit-code lockstep, and the additive-only
stability promise. doctor/resources/auth status extension deferred
pending epic OQ5.
Tests: success (case-resolved spelling + stream separation), dry-run
([] not null), confirm-declined, early failure (exit 2), off-TTY
refusal (exit 3), late teardown failure (exit 7), and a wiring-level
test pinning that --output-json never prompts.
Fixes#297
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…act tests (#291) (#317)
WS-D.2 of the CLI hardening epic (backend#1106): the unit tests feed
internal/api hand-written JSON, which pins the CLI's expectations but
drifts silently when the backend renames a field — the new body decodes
green and callers get Go zero values (empty account, id 0, adopted never
true). This closes that class end to end:
- scripts/sync-backend-fixtures.sh (cloned from sync-schema.sh's shape)
vendors the REAL serialized responses for all 9 endpoints the CLI calls
— generated + shape-asserted in backend CI
(metaApi/tests/test_cli_response_contracts.py, backend#1108) — from
tracebloc/backend at scripts/.backend-ref into internal/api/testdata/.
Backend is private, so it fetches via the authenticated contents API
(BACKEND_CONTRACTS_TOKEN / GH_TOKEN / gh auth token).
- NEW pinned scripts/.backend-ref (backend#1009 pattern): an unrelated
backend commit can't red every open CLI PR; adopting upstream shapes is
a deliberate SHA bump + re-sync.
- internal/api/contracts_test.go replays every fixture through the
client's real decode paths: load-bearing fields must decode non-zero,
the RFC 8628 error enums must map to their sentinels, 200-adopt vs
201-mint must drive the adopted flag, 426 must carry min_version, and
the 409 bodies must carry the fields conflictMessage parses. A manifest
completeness check fails when a synced fixture has no assertions.
- backend-fixtures-drift.yml runs the --check in CI; skips with a warning
until a read-only BACKEND_CONTRACTS_TOKEN secret exists (backend is
private; the default GITHUB_TOKEN can't read it).
Fixtures live in backend CI as plain pytest output — no backend PR ever
blocks on the CLI.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…l) (#303)
Pure moves of whole top-level declarations out of the 1539-line data.go,
same package cli, zero behavior change:
- data_ingest_cmd.go — newDataIngestCmd (flag surface incl. hidden
deprecated aliases) + runDataIngestArgs
- data_ingest_local.go — sortedKeys / expandHome / statDatasetPath +
printLocalSummary + runLocalPreflight
- data_ingest_cluster.go — runIngestionRun + shouldReclaimStaging +
printClusterSummary + test seams +
destTableExists + existingTableAction
- data_ingest_output.go — pushJSONResult/pushJSONSummary +
writePushJSON/writePushErrorJSON +
classifyPushOutcome (kept together with
writePushJSON — mutation-hardened lockstep)
data.go keeps the data group command, the deprecation-alias notice, and
runDataIngest itself (extracted separately in cli#283). Only new text is
each file's header comment + package/import clauses; every moved section
was verified verbatim against the pre-split file. data_test.go is
untouched and compiles unchanged.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…it di#358 (cli#286) (#305)
* chore(schema): bump data-ingestors pin to develop HEAD 8f89aec (cli#286)
Adopts the 6 upstream commits since the 7b4ecac (di#359) pin:
- di#358 — require-and-enforce semseg mask_id validator (backend#816)
- di#365 — min_size values validated as positive ints at construction (#348)
- di#369 — orphan-row reconcile before retry ingest (write path only)
- di#366 — content-comparison e2e (tests only)
- di#368 — ingest correlation id (write path only)
- the 0.7.0 version bump
Both sync scripts re-run against the new pin:
- scripts/sync-schema.sh: ingest.v1.json + layout.v1.json byte-identical
(no upstream schema change in the range) — no diff.
- scripts/sync-validator-goldens.sh: regenerated against the REAL
validators at 8f89aec — byte-identical goldens, so no verdict or
value-level drift for the existing corpus. di#358 only adds the semseg
MaskIdColumnValidator (no semseg parity cases yet) and di#365 only
changes verdicts for malformed min_size values the corpus never emits.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs(push): adopt di#365 min_size contract + audit CheckMaskIdColumn vs merged di#358 (cli#286)
di#365 adoption (ValidateImages/spec): the upstream ImageResolutionValidator
now validates min_size VALUES at construction — each side must be a positive
integer (integer-valued floats coerced; strings/bool/None/non-integral floats
rejected as a config error instead of surfacing as a phantom corrupt-image
error). No CLI code change is needed: ParseMinSize's WxH grammar (Atoi + >0)
is the equivalent gate at flag-parse time, so spec.file_options.min_size can
only ever carry the positive ints upstream accepts. Documented on
SpecArgs.MinSize + ValidateImages, and TestParseMinSize now pins the float
boundary ('16.5x32', '32.0x32' both rejected).
di#358 audit (CheckMaskIdColumn vs the merged MaskIdColumnValidator at
8f89aec) — semantics verified point for point, no divergence found:
- exact-lowercase 'mask_id' required after whitespace strip (ReadCSVHeader
trims like CSVIngestor's columns.str.strip())
- case/whitespace variant → rename hint (matchColumnIndex ≙ _match_column)
- empty scan tests the RAW untrimmed cell against NA_SENTINELS (naSentinels
is byte-identical, 12 tokens) + whitespace-only/missing — not trimmed-then-
matched (the #239/#240 padded-sentinel null-set trap)
- mid-read error fails closed on both sides
- duplicate stripped-equal headers: both sides inspect the FIRST exact match
- schema-declaration half satisfied by construction (buildImage always
declares mask_id VARCHAR(255)); csv_options dialect threading N/A (CLI
stages comma-separated UTF-8)
Recorded as a doc block on CheckMaskIdColumn.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…ise (#299) (#300)
Decision recorded on the epic (Lukas, 2026-07-14): GitHub Releases plus
the cosign-verified install.sh are the install path. Drop both deferred
follow-ups rather than keep advertising them:
- delete the disabled bump-homebrew-tap job from release.yml (and the
header bullet promising it)
- delete scripts/homebrew-formula.rb.tmpl
- README: state the install path plainly; annotate the roadmap row
- RELEASE_CHECKLIST: remove the tap one-time-setup + vanity-URL
sections, the tap verify bullet, and the brew install alternative
Everything is recoverable from git history if a customer ever asks.
Kept deliberately: the cosign pre-install hint (brew install cosign),
delete.go's brew-managed-binary uninstall hints, and RFC-0001 history —
those are not distribution promises.
Fixes#299
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* ci: run e2e on develop pushes; ratchet + extend coverage floors
Scheduled workflows execute the default branch's tree (main), which
trails develop by ~46 commits — discovery_e2e_test.go,
delete_e2e_test.go, and the delete-teardown job don't exist there, so
the nightly never actually ran them. Add push: branches: [develop] to
e2e.yml so the suite runs against the tree it was written for.
Ratchet the coverage floors to just under current develop numbers and
add the two missing load-bearing packages:
internal/cli 68 -> 80 (current 82.9%)
internal/submit 72 -> 78 (current 80.4%)
internal/push NEW 87 (current 89.0%)
internal/cluster NEW 75 (current 78.5%)
Verified locally: ./scripts/coverage-floor.sh passes all four floors.
Fixes#293Fixes#294
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(ci): cluster floor 73 — CI runner measures 74.6%, not the local 78.5%
internal/cluster coverage is environment-dependent: the
kubeconfig-resolution paths only execute on a machine that has a real
~/.kube/config, so a dev laptop reads 78.5% while the bare ubuntu
runner reads 74.6% (first CI run on this PR). The floor gates on CI,
so it must be set against the CI number: 73 (= actual - 1), not the
ticket's proposed 75.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…unDataIngest (#321)
runDataIngest was 586 lines; every pre-cluster step and the cluster
pre-flight now live in two named stanza functions, moved verbatim:
- resolveLocalInput (data_ingest_local.go) — steps 0–4 + the P3 content
preflight: flag guard, banner, guided prompts, ~-expansion +
existence-first check, table-name/category/misapplied-flag validation,
layout walk, per-category spec resolution, spec synthesis + schema
validation, local summary. Mutates a in place (via *runDataIngestArgs)
so the --output-json defer and the cluster steps see the resolved spec
exactly as before.
- connectIngestTarget (data_ingest_cluster.go) — steps 5–8a: kubeconfig
resolve, release + PVC discovery, verbose cluster summary, and the
destination-table guard (incl. the folded interactive replace decision,
which still flips a.Overwrite).
The jsonEmitted/named-return defer dance stays INSIDE runDataIngest,
next to the err it reads — both extracted functions feed that named
return, so the error-JSON contract is unchanged. The dry-run stop (which
sets jsonEmitted) also stays inside.
Only in-stanza edits are what the new signatures force: multi-value
returns on error paths, := to = where a named result already exists, and
&a -> a where a is already a pointer. Step order, output order, and exit
codes are untouched.
data.go: 693 -> 240 lines; runDataIngest: 586 -> 138.
Safety net: the #187 outcome-matrix table test + #264 mutation pins pass
untouched; full suite green under -race; coverage floors hold (82.7%).
Co-authored-by: Lukas Wuttke <lukas@tracebloc.io>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…mand docs table (#315)
* refactor(cli): name every exit-code site + cross-command docs table
internal/cli/exitcodes.go names every exit code the CLI produces; every
non-test &exitError construction site now uses a named constant instead
of a bare number. exit.go keeps owning the extraction — this is a naming
sweep, not a redesign; all numeric values are unchanged (and documented
as frozen: they're the scripting contract customers branch on).
Site census (the ticket's count of 138 grep hits includes one doc
comment in exit.go; 137 are real construction sites):
61x1, 25x2, 23x3, 7x4, 4x5, 1x6, 5x7, 2x8, 4x9, 2x130,
2x kubeconfigExitCode(...) (the helper now returns named constants),
1x variable (runLocalPreflight's BadFlag fold, now built from
constants). Zero numeric literals remain at non-test sites.
Codes that grew more than one per-command meaning get one constant per
MEANING sharing the value (2: exitBadInput / doctor's exitChecksFailed;
5: exitAuth / data delete's exitNoSuchDataset; 7: exitStagingFailed /
exitTeardownFailed / exitQueryFailed), so each site reads honestly.
docs/troubleshooting.md gains the cross-command exit-code table (code,
meaning, producing commands, constant name), sourced from the per-command
long-help blocks — data ingest's (data_ingest_cmd.go, pre-split
data.go:236-252) is the fullest.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci: file-budget line-count ratchet (scripts/file-budget.sh) wired into make ci + build.yml (#316)
* refactor(cli): extract resolveLocalInput + connectIngestTarget from runDataIngest
runDataIngest was 586 lines; every pre-cluster step and the cluster
pre-flight now live in two named stanza functions, moved verbatim:
- resolveLocalInput (data_ingest_local.go) — steps 0–4 + the P3 content
preflight: flag guard, banner, guided prompts, ~-expansion +
existence-first check, table-name/category/misapplied-flag validation,
layout walk, per-category spec resolution, spec synthesis + schema
validation, local summary. Mutates a in place (via *runDataIngestArgs)
so the --output-json defer and the cluster steps see the resolved spec
exactly as before.
- connectIngestTarget (data_ingest_cluster.go) — steps 5–8a: kubeconfig
resolve, release + PVC discovery, verbose cluster summary, and the
destination-table guard (incl. the folded interactive replace decision,
which still flips a.Overwrite).
The jsonEmitted/named-return defer dance stays INSIDE runDataIngest,
next to the err it reads — both extracted functions feed that named
return, so the error-JSON contract is unchanged. The dry-run stop (which
sets jsonEmitted) also stays inside.
Only in-stanza edits are what the new signatures force: multi-value
returns on error paths, := to = where a named result already exists, and
&a -> a where a is already a pointer. Step order, output order, and exit
codes are untouched.
data.go: 693 -> 240 lines; runDataIngest: 586 -> 138.
Safety net: the #187 outcome-matrix table test + #264 mutation pins pass
untouched; full suite green under -race; coverage floors hold (82.7%).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor(cli): name every exit-code site + cross-command docs table
internal/cli/exitcodes.go names every exit code the CLI produces; every
non-test &exitError construction site now uses a named constant instead
of a bare number. exit.go keeps owning the extraction — this is a naming
sweep, not a redesign; all numeric values are unchanged (and documented
as frozen: they're the scripting contract customers branch on).
Site census (the ticket's count of 138 grep hits includes one doc
comment in exit.go; 137 are real construction sites):
61x1, 25x2, 23x3, 7x4, 4x5, 1x6, 5x7, 2x8, 4x9, 2x130,
2x kubeconfigExitCode(...) (the helper now returns named constants),
1x variable (runLocalPreflight's BadFlag fold, now built from
constants). Zero numeric literals remain at non-test sites.
Codes that grew more than one per-command meaning get one constant per
MEANING sharing the value (2: exitBadInput / doctor's exitChecksFailed;
5: exitAuth / data delete's exitNoSuchDataset; 7: exitStagingFailed /
exitTeardownFailed / exitQueryFailed), so each site reads honestly.
docs/troubleshooting.md gains the cross-command exit-code table (code,
meaning, producing commands, constant name), sourced from the per-command
long-help blocks — data ingest's (data_ingest_cmd.go, pre-split
data.go:236-252) is the fullest.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci: file-budget line-count ratchet (scripts/file-budget.sh)
Clones the coverage-floor.sh pattern for file size: path:max_lines pairs,
checked by wc -l, portable to bash 3.2, with the same malformed-entry
guard — plus a missing-file guard so a moved/renamed budgeted file makes
the stale list loud instead of silently un-budgeting it.
Ceilings are a RATCHET: only ever lowered as files shrink; raising one is
a deliberate, reviewed edit to the checked-in script. Seeds sit just
above today's reality (develop + the WS-B split):
internal/push/preflight.go:1650 (now 1635)
internal/cli/data.go:500 (now 240 post cli#282/#283)
internal/cli/client.go:1050 (now 1027)
internal/cli/home.go:850 (now 841)
Wired into `make ci` (new file-budget target, keeping the Makefile's
"make ci green => CI green" invariant) and into build.yml's lint job as
one surgical step. Exercised all three failure paths locally (over
budget, missing file, malformed entry) — each exits 1 with a ::error::
annotation; shellcheck clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci(file-budget): seed preflight.go at true size (Bugbot #316 HIGH)
The ratchet seeded internal/push/preflight.go at 1650, but the file is
1655 lines (wc -l, same count the gate uses) and the check is strict-
greater — so `make file-budget` would fail the moment this landed on
develop. Raise the ceiling to 1700, the next round-50 ratchet value just
above actual, matching how the other seeds sit above their files
(client.go 1050>1027, home.go 850>849, data.go 500>240). Also correct
the header comment to reality (preflight ~1655, home ~849); it wrongly
read ~1635 / ~841.
Proof: `bash scripts/file-budget.sh` now passes (preflight 1655 <= 1700).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* test: SwapSeam helper + advisory gremlins mutation workflow
internal/testutil.SwapSeam(t, ptr, stub) replaces the hand-rolled
save/stub/restore blocks around package-level seam variables: swap,
then LIFO-restore via t.Cleanup. Generic, so non-function seams
(timeouts) work too. Converted the three blocks in internal/submit
(watch_test.go x2, run_watch_test.go x1); internal/push has none.
The ~26 blocks in internal/cli are deliberately left for the
decomposition work to pick up; converting them here would collide.
mutation.yml formalizes the gremlins ritual that produced #262-#264:
workflow_dispatch only, one package per run, advisory (lived mutants
never fail the job — no thresholds). Prints a survivors-to-triage
summary, uploads the JSON report, and CONTRIBUTING.md documents how
survivors get triaged into pinning-test issues.
Fixes#295
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci: harden gremlins mutation workflow (Bugbot #306)
- Reject a zero timeout-coefficient. The digit check accepted `0`/`00`,
which collapses gremlins' per-mutant timeout so survivors report TIMED
OUT instead of KILLED/LIVED — the exact failure mode this input guards
against. Now require a positive integer (> 0), matching the error text.
- Add `set -o pipefail` to the run step. The implicit default shell is
`bash -e {0}` (no pipefail), so `gremlins | tee` masked a non-zero
gremlins exit behind tee's 0, letting a broken suite pass the job —
contradicting the workflow's "tool/test health fails the run" contract.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…i#287) (#308)
* ci: goldens-drift job — validator goldens vs data-ingestors @ pin (cli#287)
New dedicated workflow (goldens-drift.yml): checks out
tracebloc/data-ingestors at the pinned ref (scripts/.data-ingestors-ref),
installs its runtime requirements, and runs
scripts/sync-validator-goldens.sh --check — failing any PR whose committed
parity goldens have drifted from the REAL validators at the pin. Closes
the wired-into-no-CI hole: until now the goldens were only regenerated by
hand, so a corpus/generator/pin change could land with stale goldens and
CI stayed green.
Triggers: PRs touching internal/push/**, the pin, or the sync harness;
weekly Monday cron as a backstop; manual dispatch.
Cross-repo access: data-ingestors is currently PUBLIC (verified via gh),
so the default workflow token suffices — the cli#62 precedent
(install-path-persist.yml) also checks out a sibling repo with no secret.
The job still prefers an org secret CROSS_REPO_READ_TOKEN when present and
skips-with-warning (never hard-fails) if the repo becomes unreadable, so a
future privatization flips to 'create the secret' instead of redding every
open PR.
Deps: pip install -r data-ingestors/requirements.txt, not just
pandas+pillow — the generator's import chain also needs sqlalchemy,
tenacity, ijson et al (verified in a clean venv; pandas+pillow alone fails
on import). requirements.txt is all light pure-python wheels.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci: goldens-drift probe falls back to github.token on invalid PAT (cli#287)
A set-but-invalid CROSS_REPO_READ_TOKEN (expired / wrong scope) made the
readability probe pick only the PAT, fail, and skip the whole drift check
while data-ingestors is still public and the default token would work.
Probe now tries the PAT, and if it fails falls back to github.token before
marking access failed — only skip-with-warning when BOTH fail. It emits a
`use_pat` selector so the checkout uses exactly the token the probe
validated, keeping the two in lockstep. Still read-only, least-privilege,
skip-not-hard-fail.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…rt the 8 CLI-assumed invariants (#311)
* ci: pinned-ref chart-invariant gate against tracebloc/client
The CLI hardcodes 8 invariants about the tracebloc/client chart —
discovery labels + jobs-manager Deployment name forms, the jobs-manager
Service on 8080, the client-pvc mount at /data/shared, the
ingestion-authz ConfigMap + "ingestor" SA fallback, the
INGESTOR_IMAGE_DIGEST env, the requests-proxy Deployment, and the
POST /internal/submit-ingestion-run port. A chart rename ships green in
both repos and breaks discovery/doctor/ingest in the field.
New scripts/.client-ref pins the client commit the gate renders (the
scripts/.data-ingestors-ref pattern, backend#1009): chart-drift.yml
checks out tracebloc/client at that ref, helm-templates it with the same
CI values the client repo's own drift job uses, and
scripts/chart-invariants asserts every invariant with a mapping back to
the CLI constant it protects. Triggers: PRs touching internal/cluster/**
or internal/doctor/** (or the gate's own files, weekly cron, manual
dispatch. The client-side half extends that repo's
scripts/tests/check-drift.sh so renaming chart PRs fail at the source.
Refs #290 (WS-D.1, backend#1106)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
EOF
)
* fix(chart-gate): assert the SELECTED jobs-manager Service exposes 8080
Invariant 3 passed if any jobs-manager/<release>-jobs-manager Service
exposed 8080, but pickJobsManagerService (internal/cluster/discover.go)
selects the unprefixed "jobs-manager" first by existence, ignoring ports.
With both Services rendered and only the non-selected one on 8080, the gate
passed while the CLI would port-forward to the wrong target. Now the gate
mirrors that precedence and checks the selected Service. Adds a regression
case covering the both-Services-only-sibling-has-8080 scenario.
Fixes a Cursor Bugbot finding on #311.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…release policy (#307)
* docs: truth pass — README/nav-map/checklist match the v0.8 surface; release policy (#296)
Every claim re-verified against the actual command tree (go run
./cmd/tracebloc --help + each subcommand on develop @ 5af9a80):
README:
- v0.3.0 status blurb -> v0.8.0 latest release + a lifecycle command
table (login/logout/auth, client/status, resources show+set,
data ingest/list/delete/validate, cluster info, doctor, delete,
version/completion/home screen); notes what landed post-v0.8.0
- 15-of-16 tasks -> all 16 (semantic_segmentation shipped in #247;
registry verified: 16x CLISupported, zero false)
- roadmap tail: 9-of-10-modalities + v0.2/v0.3 story -> v0.2-v0.8
arc; semseg removed from Next (done); cloud-source kept (backed
by RFC-0002 + the in-help 1 GiB cap copy)
- links the navigation map
docs/cli-navigation.md:
- stale-basis disclaimer removed (was develop @ 27c5392)
- resources set (#241) + status-aware home screen (#244) un-dashed —
both merged; proposed classDef dropped
- nonexistent home-screen-spec.md references removed (point at #244)
- doctor node: top-level doctor shipped, cluster doctor = hidden
alias (pinned by TestClusterCmd_DoctorIsHiddenAlias)
- known-gaps list pruned to what is still true (offboard partial
teardown still exits 0 — re-verified in delete.go)
scripts/RELEASE_CHECKLIST.md:
- 5-line release policy: trigger = customer-visible merge or weekly,
owner = DevEx squad (role, not person)
- EKS smoke: dataset push -> data ingest; v0.1-ticket pre-flight
genericized
release.yml: header comment claimed release notes come from
CHANGELOG.md — no such file exists; it's generate_release_notes: true.
Fixes#296
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: refresh README latest-release refs v0.8.0 -> v0.9.1 (#296)
Addresses Asad's review on #307: this truth pass predated the v0.9.0
and v0.9.1 cuts, so a few version claims went stale.
- Status blurb: "v0.8.0 is the latest release" -> "v0.9.1 is the
latest release".
- The post-v0.8.0 "ships with the next release" framing for
resources / status-aware home screen / top-level doctor /
semantic_segmentation -> "Shipped in v0.9.0" (they released in
v0.9.0, no longer "next").
- Roadmap tail: "Since the v0.8.0 cut, develop gained ..." -> a
"v0.9 added ...; v0.9.1 is the current latest" entry, extending
the v0.2-v0.8 arc.
Historical v0.8.0 references (the v0.8.0 cut, cluster doctor in
v0.8.0) kept as deliberate contrasts. Homebrew tap stays dropped
(#300) - no reintroduction.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…> 67 cases) (#310)
Every schema category now ends with >=1 parity case; every mirrored
preflight check ends with >=1 valid + >=1 violation case (cli#288, WS-C.3
of tracebloc/backend#1106).
New coverage, in the ticket's priority order:
- object_detection (4): CheckAnnotationPairing both directions +
a documented PascalVOCXMLValidator under-preview (objdet-bad-xml).
- semantic_segmentation (4): CheckMaskPairing (missing mask, non-_mask
name) + semseg-missing-mask-id — a PIN-SCOPED divergence: the CLI
previews the backend#816 mask_id contract, but the pinned ingestor
(7b4ecac, di#359) predates di#358's MaskIdColumnValidator, so its
preflight accepts. Flip to reject/reject at the cli#286 pin bump.
- keypoint_detection (3): happy path (Annotation/Visibility JSON),
kp-res-mismatch pinning the image-family commons cover keypoint too,
+ a documented KeypointAnnotationValidator under-preview.
- text formats (13): token_classification (BIO ok / missing label
column / bad-tag under-preview), sentence_pair_classification
(ok+value-parity / uniform-label / malformed-pair under-preview),
mlm, clm, seq2seq, embeddings happy paths + emb-malformed and
mlm-missing-files (IngestableRecords file cross-check has no text
mirror), text-clf-label-uniform.
- tabular_regression / TSF / TTE (8): happy paths, tabreg-label-uniform
as an over-reject guard (no diversity gate for regression on either
side), tabreg-label-missing (the read-time divergence twin), and
documented under-previews: TSF global time order, TSF fixed-timestamp
schema rule, TTE negative-time.
Goldens regenerated from the REAL ingestor validators at the pinned ref
(scripts/gen-validator-goldens.py; existing 35 entries byte-identical).
runGoPreflight now populates LocalLayout.Sidecars (annotations/, masks/,
texts/, sequences/) the way production Discover does — without it the
object_detection/semseg pairing previews would see an empty sidecar set.
Fixes#288
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…58) (#322)
The goldens-drift check went red on develop once cli#286 bumped the
data-ingestors pin past di#358, whose MaskIdColumnValidator now REQUIRES
mask_id to be a *declared schema column* (an undeclared mask_id is dropped
at ingest -> stored table lacks it -> the training client raises
FileNotFoundError, backend#816).
Root cause was in the goldens harness, not the CLI or the ingestor: the
CLI's real semseg ingest declares the mask_id column (spec.go sets
schema={'mask_id':'VARCHAR(255)'}), but gen-validator-goldens.py only
injected a schema for tabular/time-series categories. So it drove the
validators WITHOUT the schema the CLI sends, and MaskIdColumnValidator
spuriously rejected every semseg case (incl. semseg-ok). Fix: mirror
spec.go for semantic_segmentation cases (an explicit per-case schema still
wins, so the reject-path cases keep exercising the contract).
Also flips semseg-missing-mask-id's ingestor_verdict accept->reject: it has
no mask_id column, so post-di#358 the ingestor correctly rejects it (both
sides now agree). This is exactly the reconciliation the case's own note
predicted at pin-bump time. Regenerated goldens; only that one entry
changes. 'validator goldens in sync'; internal/push parity tests green.
Part of tracebloc/backend#1106 (WS-C validator mirrors).
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Adds a label-gated (+nightly) CI job that catches a PATH-persistence
regression in this repo's scripts/install.sh from the CLI side, pre-merge:
a change that persists PATH only where a fresh non-login shell can't read it
(the class that shipped green originally) fails CI before it merges. The
fresh-shell harness is the single source of truth in tracebloc/client
(scripts/tests/path-persist.sh); this job checks it out and points it at the
PR's install.sh.
Tracks the harness on client's develop (it has since merged there),
resolving the original pin-to-feature-branch TODO. Part of #737.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
@LukasWodka

Copy link
Copy Markdown
Contributor

👋 Heads-up — Code review queue is at 47 / 30

Above the WIP limit. The team convention is to review existing PRs before opening new work.

Open PRs currently in Code review (oldest first):

Pull from review before opening new work. (This is a nudge from the kanban WIP check, not a block.)

Comment threadinternal/api/contracts_test.go
LukasWodka
LukasWodka previously approved these changes Jul 14, 2026
@saadqbal
saadqbal requested a review from LukasWodkaJuly 14, 2026 17:22
…findings (#302)
* ci: re-enable staticcheck (pinned standalone) + fix the 5 non-ST1005 findings
Pinned staticcheck@2025.1.1 joins the standalone lint set in both the
Makefile lint target and build.yml's lint job (-checks all,-ST1005),
mirroring the errcheck/ineffassign pin pattern. The golangci-lint OOM
story that originally disabled it is stale for the standalone binary:
a full run is ~12s wall locally.
Findings fixed (the full non-ST1005 set):
- ST1008: runSet (resources_set_test) returns (string, error), error last
- ST1003: CheckMaskIdColumn -> CheckMaskIDColumn (+ call sites/comments)
- ST1003: errors_as -> errorsAs, io_eof_or_similar -> ioEOFOrSimilar
- ST1020: CoreFloorText doc comment starts with the function name
ST1005 stays excluded: it flags ~58 customer-visible error strings that
need a wording review, not a mechanical sweep — separate follow-up.
Rebased onto develop: union-merged the lint job with develop's govulncheck
job (#278), coverage-floor step (#301) and deadcode advisory gate; kept the
audit comment #286 added above CheckMaskID*Column. The 'going back to the
action' comment in build.yml is KEPT (not deleted) — #6 is still open on
develop, so golangci-lint-action stays disabled and that rationale still
holds. Detached the four data_ingest_*.go header comments (#303 split) plus
exitcodes.go's (#284, which develop merged after this branch was cut) from
the package clause so the newly-enabled staticcheck gate is ST1000-clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci: goimports -local gate + Dependabot config (gomod weekly, actions monthly) (#304)
* ci: goimports -local gate + Dependabot config (gomod weekly, actions monthly)
goimports -local github.com/tracebloc/cli now blocks in both loops:
build.yml's lint job (pinned goimports@v0.48.0, same x/tools version as
the deadcode pin) and the Makefile's fmt-check target, with make fmt
extended to auto-fix. .golangci.yml already declared this grouping via
local-prefixes but nothing enforced it — 4 files had drifted (data.go,
data_test.go, ingestion_run_test.go, resources_set_test.go), fixed here
with import-grouping-only diffs.
.github/dependabot.yml extends the org's backend-only Dependabot pilot:
gomod weekly (k8s.io/* + sigs.k8s.io/* grouped, golang.org/x/* grouped),
github-actions monthly. Unlike backend's security-only config, the CLI
takes real version updates — customers install this binary, so staying
current is security posture (see #276). Org-wide rollout decision
flagged to Asad on the PR.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci: canonicalize import grouping in data_test.go for the goimports gate
Regroups imports into the layout goimports -local github.com/tracebloc/cli
emits (stdlib / third-party / tracebloc-local). gofmt and goimports only
sort within existing blank-line groups, so the manual groups passed
fmt-check as-is but were not the canonical single-block output; Bugbot and
our precheck both flagged the divergence. Verified idempotent under the
pinned goimports v0.48.0 and green on make fmt-check + go build ./...
Rebased onto ci/279 (post-#303 data.go split): data.go's import block is
already canonical from the #303 split, so its canonicalization here is a
no-op and dropped — this commit now regroups data_test.go only.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* ci: flip deadcode gate to blocking; delete the 3 dead #127 leftovers (#313)
* ci: goimports -local gate + Dependabot config (gomod weekly, actions monthly)
goimports -local github.com/tracebloc/cli now blocks in both loops:
build.yml's lint job (pinned goimports@v0.48.0, same x/tools version as
the deadcode pin) and the Makefile's fmt-check target, with make fmt
extended to auto-fix. .golangci.yml already declared this grouping via
local-prefixes but nothing enforced it — 4 files had drifted (data.go,
data_test.go, ingestion_run_test.go, resources_set_test.go), fixed here
with import-grouping-only diffs.
.github/dependabot.yml extends the org's backend-only Dependabot pilot:
gomod weekly (k8s.io/* + sigs.k8s.io/* grouped, golang.org/x/* grouped),
github-actions monthly. Unlike backend's security-only config, the CLI
takes real version updates — customers install this binary, so staying
current is security posture (see #276). Org-wide rollout decision
flagged to Asad on the PR.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci: canonicalize import grouping in data_test.go for the goimports gate
Regroups imports into the layout goimports -local github.com/tracebloc/cli
emits (stdlib / third-party / tracebloc-local). gofmt and goimports only
sort within existing blank-line groups, so the manual groups passed
fmt-check as-is but were not the canonical single-block output; Bugbot and
our precheck both flagged the divergence. Verified idempotent under the
pinned goimports v0.48.0 and green on make fmt-check + go build ./...
Rebased onto ci/279 (post-#303 data.go split): data.go's import block is
already canonical from the #303 split, so its canonicalization here is a
no-op and dropped — this commit now regroups data_test.go only.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci: flip deadcode gate to blocking; delete the 3 dead #127 leftovers
The deadcode CI step loses continue-on-error (and the Makefile target
its '|| true'): both now run scripts/deadcode-check.sh, which fails on
any function unreachable from ./cmd/tracebloc that isn't declared in
scripts/deadcode-allowlist.txt. The tool itself always exits 0, so the
old advisory step never could have blocked — the gate keys on output.
Deleted (verified still dead with the pinned deadcode@v0.48.0):
- config.clearAll + its three dedicated tests (TestClearAll,
TestClearAll_HomeError, TestClear) — logout uses Save, nothing else
ever called it
- push.allCategoryIDs — moved verbatim into category_registry_test.go
(the registry-pinning tests legitimately iterate every id; the
shipped binary shouldn't carry the helper)
- submit.isSubmitError — moved into client_test.go as the test-local
assertion helper it always was (orphaned 'errors' import dropped)
Allowlisted with reasons (the 4 legit findings): Status.String +
JobOutcome.String (fmt-reflection Stringers) and ReadLabelValues +
inferColumnType (di#349 test-only parity harnesses). Stale allowlist
entries warn without failing; line numbers are stripped so edits that
shift code don't red the gate.
Coverage floors still clear after the test deletions (cli 82.9% >= 68,
submit 80.3% >= 72).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…n list contracts (#324)
assertProvisionedClient asserts every ProvisionedClient field decodes
non-zero — the silent-drift class. That is right for the three hand-pinned
single fixtures (create/adopt/patch), but TestContractListClientsPaginated
applied it to every row of a real synced list (edge_device_list.json).
status==0 is STATUS_OFFLINE and cluster_id is "Empty on legacy /
not-yet-backfilled clients" (client.go), so the next re-sync of a list that
includes an offline or unanchored row would fail CI even though decoding is
correct. This is the Cursor Bugbot "contract test rejects valid values"
finding on #323.
Add assertDecodesFrom, used per-row by the list test. It catches BOTH silent
drift directions without rejecting legitimate zeros:
- struct-tag drift (a Go json tag renamed): the wire still carries the old
key with a value while the struct decodes zero -> value mismatch -> caught.
- backend rename/drop on re-sync (the wire field renamed, fixture reseeded):
the old key vanishes, so a pure value compare reads zero on both sides. A
presence assertion on the always-present keys (id/first_name/username/
namespace/status) catches this. cluster_id is presence-optional (legit
empty), its rename stays covered by the strict single-fixture tests.
status==0 is tolerated (key present, value 0). The single pinned fixtures
keep the strict non-zero helper.
Also harden TestContractListClientAdmins (surfaced by the same-class sweep):
email is a domain-guaranteed identifier -> assert present + wire-match (a
renamed email tag decodes "" -> caught); name is a display name that can be
legitimately blank -> assert wire-fidelity only, not non-empty.
Proven by mutation: struct-tag rename and backend key-rename both fail the
list test; an offline/unanchored fixture row passes; a blank admin name
passes; an admin email-key rename fails.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread.github/workflows/head-drift-canary.yml Outdated
LukasWodka added a commit that referenced this pull request Jul 14, 2026
The HEAD-drift canary set drift=true on ANY non-zero exit from
sync-validator-goldens.sh --check. But that exit also covers harness
failures -- missing deps, a bad DATA_INGESTORS_DIR, a generator crash -- so the
tracking issue reported "DRIFT -- verdicts/values changed" even when parity was
never evaluated, sending someone down the pin-bump playbook for an infra bug.
(Cursor Bugbot, Medium, surfaced on the #323 promotion.)
sync-validator-goldens.sh --check now uses reserved exit codes so consumers
can tell the two apart:
0 in sync
2 HARNESS ERROR -- could not regenerate; parity NOT evaluated (not drift)
3 DRIFT -- verdicts / read-path values changed
The required goldens-drift check is unaffected (it reds on any non-zero).
The canary maps those codes and, crucially, adapts the ENTIRE tracking issue to
the signal via a pin_actionable flag (real drift OR source diff OR unreachable
pin):
- exit 3 / source diff / bad pin -> drift framing: pin-bump Playbook, the
"HEAD has drifted" title, and the "close when the pin bump lands" footer.
- exit 2 / unexpected, harness-only -> harness framing: NO pin-bump Playbook,
a "could not run (harness error)" title, and a "fix the harness, do NOT
bump the pin" footer.
The "All clear" step now requires evaluated=true so it cannot mask a harness
failure.
Verified: --check with no data-ingestors exits 2 with a HARNESS ERROR message
and does not mutate goldens.json; the reporting script, run under both a
harness-only and a real-drift scenario, produces the correct row / playbook /
footer / title each time; actionlint + shellcheck clean; YAML valid.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
LukasWodka added a commit that referenced this pull request Jul 14, 2026
The HEAD-drift canary set drift=true on ANY non-zero exit from
sync-validator-goldens.sh --check. But that exit also covers harness
failures -- missing deps, a bad DATA_INGESTORS_DIR, a generator crash -- so the
tracking issue reported "DRIFT -- verdicts/values changed" even when parity was
never evaluated, sending someone down the pin-bump playbook for an infra bug.
(Cursor Bugbot, Medium, surfaced on the #323 promotion.)
sync-validator-goldens.sh --check now uses reserved exit codes so consumers
can tell the two apart:
0 in sync
2 HARNESS ERROR -- could not regenerate; parity NOT evaluated (not drift)
3 DRIFT -- verdicts / read-path values changed
The required goldens-drift check is unaffected (it reds on any non-zero).
The canary adapts the WHOLE tracking issue to the signal via a pin_actionable
flag (real drift OR source diff OR unreachable pin):
- pin_actionable -> drift framing: the pin-bump Playbook, the "HEAD has
drifted" title, and the "close when the pin bump lands" footer.
- harness-only (evaluated=false, no source diff, pin reachable) -> harness
framing: NO Playbook, a "could not run (harness error)" title, and a "fix
the harness, do NOT bump the pin" footer.
The harness-error note is purely factual (no bump/don't-bump wording) so it
never contradicts the Playbook when a harness error co-occurs with a real
source diff. The title is recomputed from the current signal and refreshed on
EVERY run (issue edit, not only create) so a persistent issue's title never
lags the latest failure mode. "All clear" requires evaluated=true so it cannot
mask a harness failure.
Verified: --check with no data-ingestors exits 2 with a HARNESS ERROR message
and does not mutate goldens.json; the reporting script, exercised across
harness-only, harness+source-diff, real-drift, and existing-vs-new-issue
scenarios, produces a self-consistent row / note / playbook / footer / title
each time; actionlint + shellcheck clean; YAML valid.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The HEAD-drift canary set drift=true on ANY non-zero exit from
sync-validator-goldens.sh --check. But that exit also covers harness
failures -- missing deps, a bad DATA_INGESTORS_DIR, a generator crash -- so the
tracking issue reported "DRIFT -- verdicts/values changed" even when parity was
never evaluated, sending someone down the pin-bump playbook for an infra bug.
(Cursor Bugbot, Medium, surfaced on the #323 promotion.)
sync-validator-goldens.sh --check now uses reserved exit codes so consumers
can tell the two apart:
0 in sync
2 HARNESS ERROR -- could not regenerate; parity NOT evaluated (not drift)
3 DRIFT -- verdicts / read-path values changed
The required goldens-drift check is unaffected (it reds on any non-zero).
The canary adapts the WHOLE tracking issue to the signal via a pin_actionable
flag (real drift OR source diff OR unreachable pin):
- pin_actionable -> drift framing: the pin-bump Playbook, the "HEAD has
drifted" title, and the "close when the pin bump lands" footer.
- harness-only (evaluated=false, no source diff, pin reachable) -> harness
framing: NO Playbook, a "could not run (harness error)" title, and a "fix
the harness, do NOT bump the pin" footer.
The harness-error note is purely factual (no bump/don't-bump wording) so it
never contradicts the Playbook when a harness error co-occurs with a real
source diff. The title is recomputed from the current signal and refreshed on
EVERY run (issue edit, not only create) so a persistent issue's title never
lags the latest failure mode. "All clear" requires evaluated=true so it cannot
mask a harness failure.
Verified: --check with no data-ingestors exits 2 with a HARNESS ERROR message
and does not mutate goldens.json; the reporting script, exercised across
harness-only, harness+source-diff, real-drift, and existing-vs-new-issue
scenarios, produces a self-consistent row / note / playbook / footer / title
each time; actionlint + shellcheck clean; YAML valid.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@LukasWodka

Copy link
Copy Markdown
Contributor

@BugBot run

Comment thread.github/workflows/head-drift-canary.yml Outdated
Comment thread.github/workflows/goldens-drift.yml
…-ingestors jobs (#326)
Two Cursor Bugbot findings surfaced on the #323 promotion re-review of the
data-ingestors drift jobs:
1. Invalid PAT breaks canary checkout (Medium). head-drift-canary.yml passed
`secrets.CROSS_REPO_READ_TOKEN || github.token` straight to actions/checkout.
`||` only falls back when the secret is EMPTY, so a set-but-expired /
mis-scoped PAT reds the weekly canary even though data-ingestors is public
and github.token would work. Ported goldens-drift.yml's reachability probe:
a `git ls-remote` check picks the PAT only when it actually works and falls
back to the default token otherwise (use_pat output, kept in lockstep with
the checkout). goldens-drift.yml already had this probe.
2. Pin ref lacks shape guard (Low). goldens-drift.yml and head-drift-canary.yml
read scripts/.data-ingestors-ref and (for goldens-drift) pass it straight to
actions/checkout after only an emptiness check, unlike chart-drift.yml which
validates ref shape. Added the same guard to both: SHA / branch / tag
characters only and no "..", so a malformed pin fails with a clear error
instead of an opaque checkout failure.
Verified: the shape guard accepts the real pin, branch/tag/SHA refs, and
rejects "..", shell metacharacters, and empty; the probe's no-token path
selects github.token; actionlint + shellcheck clean; YAML valid.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@LukasWodka

Copy link
Copy Markdown
Contributor

@BugBot run

@cursorcursorBot 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.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 0bf4b9f. Configure here.

@saadqbal
saadqbal merged commit 4ce0e52 into mainJul 15, 2026
41 of 42 checks passed
saadqbal added a commit that referenced this pull request Jul 16, 2026
* chore(deps): bump softprops/action-gh-release from 2 to 3
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 2 to 3.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](softprops/action-gh-release@v2...v3)
---
updated-dependencies:
- dependency-name: softprops/action-gh-release
dependency-version: '3'
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
* chore: back-merge main → develop after #323 promote (#335)
* chore(deps): bump the k8s group with 3 updates (#331)
Bumps the k8s group with 3 updates: [k8s.io/api](https://github.com/kubernetes/api), [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) and [k8s.io/client-go](https://github.com/kubernetes/client-go).
Updates `k8s.io/api` from 0.36.1 to 0.36.2
- [Commits](kubernetes/api@v0.36.1...v0.36.2)
Updates `k8s.io/apimachinery` from 0.36.1 to 0.36.2
- [Commits](kubernetes/apimachinery@v0.36.1...v0.36.2)
Updates `k8s.io/client-go` from 0.36.1 to 0.36.2
- [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md)
- [Commits](kubernetes/client-go@v0.36.1...v0.36.2)
---
updated-dependencies:
- dependency-name: k8s.io/api
dependency-version: 0.36.2
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: k8s
- dependency-name: k8s.io/apimachinery
dependency-version: 0.36.2
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: k8s
- dependency-name: k8s.io/client-go
dependency-version: 0.36.2
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: k8s
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Asad Iqbal (Saadi) <asad.dsoft@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore(deps): bump github.com/schollz/progressbar/v3 (#333)
Bumps [github.com/schollz/progressbar/v3](https://github.com/schollz/progressbar) from 3.19.0 to 3.19.1.
- [Release notes](https://github.com/schollz/progressbar/releases)
- [Commits](schollz/progressbar@v3.19.0...v3.19.1)
---
updated-dependencies:
- dependency-name: github.com/schollz/progressbar/v3
dependency-version: 3.19.1
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Asad Iqbal (Saadi) <asad.dsoft@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore(deps): bump helm/kind-action from 1.10.0 to 1.14.0 (#328)
Bumps [helm/kind-action](https://github.com/helm/kind-action) from 1.10.0 to 1.14.0.
- [Release notes](https://github.com/helm/kind-action/releases)
- [Commits](helm/kind-action@v1.10.0...v1.14.0)
---
updated-dependencies:
- dependency-name: helm/kind-action
dependency-version: 1.14.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Asad Iqbal (Saadi) <asad.dsoft@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore(deps): bump actions/add-to-project from 1.0.2 to 2.0.0 (#327)
Bumps [actions/add-to-project](https://github.com/actions/add-to-project) from 1.0.2 to 2.0.0.
- [Release notes](https://github.com/actions/add-to-project/releases)
- [Commits](actions/add-to-project@v1.0.2...v2.0.0)
---
updated-dependencies:
- dependency-name: actions/add-to-project
dependency-version: 2.0.0
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Asad Iqbal (Saadi) <asad.dsoft@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* chore(deps): bump actions/stale from 9 to 10 (#332)
Bumps [actions/stale](https://github.com/actions/stale) from 9 to 10.
- [Release notes](https://github.com/actions/stale/releases)
- [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md)
- [Commits](actions/stale@v9...v10)
---
updated-dependencies:
- dependency-name: actions/stale
dependency-version: '10'
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Asad Iqbal (Saadi) <asad.dsoft@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* fix(ci): point Dependabot at develop, not main (#336)
All work in this repo flows feature → develop → main (promote PRs).
Dependabot defaults to the repo default branch (main), so the first
batch of bumps (#327#334) targeted main directly — bypassing develop
and set to regress on the next promote (develop carries the older deps).
Set target-branch: "develop" on both ecosystems so bumps ride the normal
review + promote path.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* ci: bump artifact actions to v7 (upload + download together) (#337)
Supersedes Dependabot #329, which bumped actions/upload-artifact 4→7 but
left actions/download-artifact@v4 in release.yml's publish job. GitHub
requires matching upload/download majors — a v7↔v4 pair breaks the
release artifact merge (download-artifact can't read v7-format uploads).
Bump all four refs together: upload-artifact in build.yml, mutation.yml,
release.yml, and download-artifact in release.yml. CI/release-only; no
CLI-binary change.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* Merge pull request #339 from tracebloc/fix/338-heartbeat-single-client
fix(cli): home heartbeat fetches one client, not the whole account (#338)
* chore(deps): bump github.com/spf13/cobra from 1.8.1 to 1.10.2 (#340)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.8.1 to 1.10.2.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](spf13/cobra@v1.8.1...v1.10.2)
---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
dependency-version: 1.10.2
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for freeto 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.

2 participants

@saadqbal@LukasWodka