Changelog
August 25, 2026 · View on GitHub
All notable changes to this project are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
[1.1.3] - 2026-08-25
Patch — positional archive naming (cluster anchored at the tail).
Changed
- Capture / archive naming: the cluster is now the absolute tail of the
archive basename, anchored positionally by the terminal
-YYYYMMDD-HHMMSStimestamp. The free-form--messageand the-since-<duration>marker now precede the timestamp, so the cluster can contain arbitrary characters (DO-style hosts, UUIDs, dashes, dots, evendevelop) without downstream parsing ambiguity. The consuming gfs parser (groot-share) reads the cluster by position (everything after the timestamp), so both sides must ship together — pair with gfs0.7.0. - README / man pages / BSD ports: version badge and packaging pins synced to 1.1.3.
[1.1.2] - 2026-08-18
Security patch — Go 1.26.6 stdlib CVEs; golangci-lint v2.12.2.
Security
- Go 1.26.5 → 1.26.6 in
go.modandDockerfilebuilder image (stdlib CVEs cleared by govulncheck): GO-2026-6087 (net/url), GO-2026-6091 (html/template), GO-2026-6090 (crypto/tls), GO-2026-6089 / GO-2026-5026 (net/http), GO-2026-6088 (encoding/xml), GO-2026-5972 (encoding/asn1).
Changed
- CI / lint:
make lintand the GitHub Actions lint job now run golangci-lint v2 (.golangci.yml: govet, staticcheck, ineffassign, misspell, revive, unused) instead of barego vet. Cyclomatic complexity remains a separatemake gocyclogate. Pin bumped to v2.12.2 (Go 1.26-built binary; v2.5.0 failed CI with exit 3 against oldergo 1.26.5). - README / man pages / BSD ports: version badge, image pin, and packaging synced to 1.1.2. Go version badge synced to 1.26.6.
- Grype: directory scan also excludes local
./.tmp-go/**so leftover test binaries do not failmake security.
Docs
- Groot family: README, SPEC, and AGENTS now point at companion repos groot-selfhosted, groot-trigger, groot-share (gfs), and groot-share-selfhosted.
[1.1.1] - 2026-08-11
Patch — path expansion, concurrent-safe capture naming, S3 credential trim.
Changed
- Capture / archive naming:
sessionBaseis now<file_prefix>-<short>-<timestamp>[…]where<short>is the lowercase random suffix fromrun_id, so concurrent collects in the same second do not collide on a sharedoutput_dir. - README / man pages / BSD ports: version badge and packaging pins synced to 1.1.1.
- VHS demo (
docs/demo.gif): regenerated sogroot --versionshows 1.1.1.
Fixed
kubeconfigpath expansion:~and${VAR}now expand forkubeconfig(YAML),KUBECONFIG, and--kubeconfig— same rules asoutput_dir. Multipath lists expand per entry. SFTPidentity_file/known_hosts_filepaths expand too.- S3 credentials trim:
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, andAWS_SESSION_TOKENare trimmed before signing (avoids Contabo/S3-compatibleSignatureDoesNotMatchfrom trailing spaces when pasting keys).
Docs
- Link
examples/upload/s3.ymlto groot-selfhosted Contabo Object Storage playbook (run/examples/s3-contabo/). - ROADMAP backlog #97 WebDAV/Nextcloud; ignore local GSD research cache under
.planning/.
[1.1.0] - 2026-08-10
Added
- offline
groot analyze(1.1.x #69): heuristic hints (CrashLoopBackOff, OOMKilled, ImagePullBackOff, NotReady, Evicted) from a collected.tar.gzwithout kubeconfig or cluster access; emits executive Markdown, structured JSON, or a budgeted LLM-ready paste pack. - golden fixture corpus (1.1.x #69): committed source-tree scenarios under
testing/fixtures/archives/(healthy, crashloop, oom, imagepull, missing-manifest) with CI golden tests locking executive and LLM Markdown output. --max-decompressedflag (1.1.x #69): override the default 16GiB total decompressed archive cap ongroot analyzeandgroot inspect.
Changed
- arcread / analyze / inspect (1.1.x #69): raise default max decompressed archive total from 512MiB to 16GiB so typical large collects can be indexed.
- analyze evidence (1.1.x #69): raise analyze-local read cap for TSV /
resources.txt/ pods-wide from 2MiB to 32MiB (still under the 64MiB per-member arcread cap) so large namespace inventories are not skipped. - README / BSD ports / man pages: version badge and package pins synced to 1.1.0.
Fixed
- kind E2E archive check: avoid
tar | grep -qunderpipefail(SIGPIPE false negative fore2e-groot/resources.txton GitHub Actions); silence/dev/ttyprobe noise when there is no controlling TTY.
[1.0.6] - 2026-08-04
Packaging + docs patch — man(1)/nfpm/BSD, CONTRIBUTING collector guide, expanded examples. No CLI or config contract changes.
Added
- man(1) + packaging (1.1.x #96 / GH #2): ship
contrib/man/man1/groot.1andkubectl-groot.1; GoReleaser archives + nfpm (.deb/.rpm) install man pages; Homebrew caskmanpages:; FreeBSD/OpenBSD ports install the same pages;make man-syncbumps.THfromVERSION. - CONTRIBUTING collector guide (1.1.x #47): how jobs are wired (
buildJobs/k8s_exec/k8srunner), when to preferextra_kubectl, test layers, and a PR checklist. - Examples beyond profiles (1.1.x #46):
examples/README.mdindex; notify smokes (Slack/Teams/generic/PagerDuty); upload skeletons (S3/GCS/SFTP); collection (targets/extra_kubectl, redact); GKE/AKS managed profiles.
Changed
- README / BSD ports: version badge and package pins synced to 1.0.6.
- VHS demo (
docs/demo.gif): regenerated at v1.0.6 sogroot --versionmatches the release.
[1.0.5] - 2026-08-01
Docs patch — Homebrew 6+ tap trust guidance; no CLI or config contract changes.
Changed
- Docs (Homebrew 6+): README install block documents tap trust — prefer fully qualified
brew install --cask hrodrig/groot/groot; explain unrelated “Skipping … not trusted” warnings during auto-update. - README / BSD ports: version badge and package pins synced to 1.0.5.
- VHS demo (
docs/demo.gif): regenerated at v1.0.5 sogroot --versionmatches the release.
[1.0.4] - 2026-07-29
Security patch — google.golang.org/grpc v1.82.1 (Dependabot #1) and OpenTelemetry v1.44.0; no CLI or config contract changes.
Security
- Dependencies: bump
google.golang.org/grpcto v1.82.1 (Dependabot #1 / GHSA-hrxh-6v49-42gf — xDS RBAC + HTTP/2 Rapid Reset). Transitive via GCS client; groot does not expose a gRPC server. - Dependencies: bump
go.opentelemetry.io/otel(andmetric/trace/sdk) to v1.44.0 — closes grype GO-2026-5158 / GHSA-5wrp-cwcj-q835 (baggage header length). Transitive via GCS; govulncheck reports no vulnerable call path in groot.
Fixed
-v/--version: no longer prints emptyError:plus full Usage after the version line (cobra treatedErrVersionPrintedas a PreRun failure). Align with kzero: rootSilenceUsage/SilenceErrors;mainprints real errors to stderr.- macOS Gatekeeper: Homebrew cask post-install clears quarantine on
kubectl-grootas well asgroot; README documents bothxattrone-liners.
Changed
- ROADMAP: Kimi review — band status table + close dates, Current focus (in flight), explicit 1.0.0 contract surface, Band 4 themes + community signals, expanded Known gaps / Non-goals, stronger SPEC triad note. Product stance:
streamout of philosophy;watchreframed as triggered collect → upload → notify (#55). - README: version badge and container pull pin updated to v1.0.4.
- BSD ports:
PORTVERSION/DISTNAMEsynced to 1.0.4.
[1.0.3] - 2026-07-12
Maintenance patch — post-audit hygiene (#88–#95); groot notify test adds one CLI subcommand (no config schema change).
Fixed
- Container image default CMD prints
--helpinstead of runningcollectagainst the bundled sample config (groot.yml.sampleremains in the image for copy/reference).(1.0.3 #88)
Security
- Dependencies: bump
golang.org/x/cryptoto v0.54.0 (and transitivegolang.org/x/net,golang.org/x/sys,golang.org/x/text) — grype GO-2026-5932 hygiene; govulncheck reports no vulnerable call paths.(1.0.3 #94)
Changed
- Tests:
internal/cmdTestMainremoves staleout/groot-capture-*dirs after package tests (gitignored artifacts from local cmd runs).(1.0.3 #91) --version/-v: always returns throughErrVersionPrintedandExecuteContext(noos.Exit(0)in library code).(1.0.3 #92)- Docs: Kubernetes client QPS 50 / burst 100 vs
collection.worker_concurrency; YAML-tunable rate limit remains roadmap #67.(1.0.3 #93) - README: version badge and container pull pin updated to v1.0.3.
- BSD ports:
PORTVERSION/DISTNAMEsynced to 1.0.3. - VHS demo (
docs/demo.gif): refreshed at v1.0.3 (groot notify testin tape).
Added
- Tests: fake SMTP server coverage for email notifier (plain, STARTTLS, implicit TLS, AUTH PLAIN, FanOut integration).
(1.0.3 #89) - Tests: GCS upload via
fake-gcs-server+STORAGE_EMULATOR_HOST; coversgcsClientOptions, success path, cancel, missing archive.(1.0.3 #90) groot notify test— send a synthetic summary to all enabled notify channels without running collect or contacting the cluster;--event notify.test|success|failure; exit 4 on delivery failure.(1.0.3 #95)- Docs: Mailgun/SMTP notify smoke runbook (
docs/notify-smoke-test.md) andexamples/notify/mailgun-smoke.yml.(1.0.3 #95)
[1.0.2] - 2026-07-11
Maintenance patch — distroless Debian 13 runtime base (no CLI or config contract changes).
Changed
- Container runtime base:
gcr.io/distroless/static-debian12:nonroot→static-debian13:nonrootinDockerfileandDockerfile.release(Debian 12 EOL; distroless defaults to trixie). - README: version badge and container pull pin updated to v1.0.2.
- BSD ports:
PORTVERSION/DISTNAMEsynced to 1.0.2.
[1.0.1] - 2026-07-10
Security patch — Go toolchain 1.26.5 (no CLI or config contract changes).
Security
- Go 1.26.4 → 1.26.5 in
go.modandDockerfilebuilder image: CVE-2026-39822 (osroot escape via symlink + trailing slash) and CVE-2026-42505 (crypto/tlsECH privacy leak).
Changed
- README: version badge and container pull pin updated to v1.0.1.
- VHS demo (
docs/demo.gif): refreshed at v1.0.1. - BSD ports:
PORTVERSION/DISTNAMEsynced to 1.0.1.
[1.0.0] - 2026-07-03
Stable contract release (Band 3 — plan-1.0.0.md).
Added
config_versionin YAML with loader validation;1is supported, absent/0= legacy pre-1.0 configs (1.0.0 #30).archive_layout_versioninextras/manifest.jsonon every new collect (1.0.0 #34).groot collect --output jsonemitsSummaryJSON on success;validate/inspectalready supported--output jsonfrom 0.9.x (1.0.0 #40).- Golden inspect fixture test for archive regression without a cluster (1.0.0 #87).
- Governance:
.github/CODEOWNERS, issue templates, PR template (1.0.0 #48).
Changed
pkg/→internal/module layout; groot is a CLI, not a public Go SDK — no CLI flag changes (1.0.0 #35).- SFTP upload:
known_hosts_fileis required when SFTP is enabled unlessallow_insecure_host_key: true(testing only). Previously defaulted to insecure host key verification. - VHS demo (
docs/demo.gif): regenerated at v1.0.0 (groot --version, validate, completion, sample config). - README hero (
docs/assets/groot-readme-hero.png): refreshed for v1.0 (stable contract, structured output, inspect).
Fixed
- Notifier HTTP client: per-instance retry config (no global mutable state).
- Archive tar walk: close file descriptors per file (no FD leak on large trees).
- Control-plane pod list: log API failures instead of silent omission.
- Manifest paths: cache directory walk between pre/post-archive manifest writes.
- SIGINT/SIGTERM: graceful context cancellation from
main. - SFTP config: validate
userat load time.
Migration
- New configs: set
config_version: 1at the top ofgroot.yml. - Legacy configs without
config_versioncontinue to load unchanged. - New archives include
archive_layout_version: 1inextras/manifest.json. - SFTP operators: set
upload.sftp.known_hosts_file(orGROOT_UPLOAD_SFTP_KNOWN_HOSTS) before upgrading if you relied on implicit insecure host keys.
[0.9.2] - 2026-06-29
Fixed
- OpenBSD release build:
diskfree_openbsd.gousesF_bsize/F_blocks/F_bavailfield names; GoReleaserGOOS=openbsdtargets compile after v0.9.1 release failure.
Changed
- VHS demo (
docs/demo.gif): tape runsmake install; regenerate withPATH="$(go env GOPATH)/bin:$PATH" vhs docs/demo.tapeso Homebrew/system installs do not shadow the repo binary; shows 0.9.x subcommands (validate,completion).
[0.9.1] - 2026-06-29
Fixed
- Windows release build: split
diskFreeintodiskfree_unix.go(syscall.Statfs) anddiskfree_windows.go(GetDiskFreeSpaceEx) so GoReleaser cross-compiles forGOOS=windowsaftergroot validatedisk preflight landed in v0.9.0.
[0.9.0] - 2026-06-28
Fixed
- Helm
helm_releasestarget matching (0.9.x #79):matchesTargetsByLabelsnow honours Helm-canonical labels (app.kubernetes.io/instanceandapp.kubernetes.io/name) and rejects pods whoseapp.kubernetes.io/managed-bydeclares a non-Helm owner (Kustomize, Operators). Legacy Helm 2 (heritage=Tiller+release=<name>) is also recognised. NewhelmMatcheshelper with 12 case-driven unit tests covering modern, legacy, non-Helm rejection, and edge cases;matchesTargetsByLabelsnow routes Helm targets through it.
Added
- kubectl-groot plugin (0.9.x #64, #85): same
cmd/groot/main.gonow ships as bothgrootandkubectl-grootfrom GoReleaser (builds:second entry,binary: kubectl-groot; archives, nfpms, container images, and Homebrew cask all include both binaries in the same artefacts). Newpkg/cmd/plugin.goexposesIsPluginInvocation()(basename match onkubectl-grootor explicitGROOT_FORCE_KUBECTL_PLUGIN=1);FormatVersionswaps the banner betweengrootandkubectl-grootso logs tell which entry point fired (greeting staysI am Grootfor both).make install-kubectl-pluginlays the binary down askubectl-grooton a$PATH-residentPREFIXand refuses otherwise. Krew plugin manifest lives atcontrib/krew/groot.yamlwith a manual submission runbook atcontrib/krew/SUBMISSION.md. README has a full plugin-install section with Homebrew, local build, and Krew examples. 12 new unit tests inpkg/cmd/plugin_test.go+ 2 version-banner tests inpkg/cmd/version_test.go. - Shell completion (0.9.x #80): new
groot completion <bash|zsh|fish|powershell>subcommand wraps Cobra's generators with strict arg validation. Defaults to writing the script to stdout so it installs with a redirect (e.g.groot completion zsh > "${fpath[1]}/_groot",groot completion bash | sudo install -m 0644 /dev/stdin /etc/bash_completion.d/groot); errors and unsupported-shell messages go to stderr. Listed in root--help. 8 unit tests inpkg/cmd/completion_test.go. - Exit code taxonomy (0.9.x #82): stable codes for scripting —
0success,1config validation (YAML /--since/ missing config file),2Kubernetes client or API error,3collect aborted (timeout / archive failure),4notify delivery failed;5reserved for partial-job-failure--strictopt-in. Newpkg/cmd/exitcode.godefinesExitError,ExitCodeOf, and the fiveExit*constants;pkg/cmd/root.goRunE funnels every error throughNewExitErrorso the code is preserved across%wwrappers.cmd/groot/main.go:exitCodenow delegates tocmd.ExitCodeOf(was binary 0/1). SPEC §3 documents the contract. 9 unit tests inpkg/cmd/exitcode_test.go+ 3 end-to-end tests inpkg/cmd/exitcode_cli_test.go+ 3 e2e tests for--strict. groot validateandgroot inspect <archive>(0.9.x #31, #83):pkg/collector/preflight.goaddsService.Preflight(ctx) PreflightResult(config + cluster handshake + RBACauth can-imatrix + disk space, configurable viacollection.min_free_bytes/collection.warn_free_bytes, defaults 256 MiB fail / 1 GiB warn). Newgroot validatesubcommand prints the findings as text or JSON, exits 1 on config/disk/RBAC failure or 2 on Kubernetes-API failure.pkg/collector/inspect.goaddsInspectArchive(path)(no cluster; readsextras/manifest.jsonfrom a.tar.gz). Newgroot inspect <archive>subcommand summarises an archive. 9 preflight tests + 5 inspect tests + 8 render tests + 7 e2e CLI tests.groot collect --summaryand signal-first jobs (0.9.x #42, #84):--summaryflag writes a one-screen block after a successful collect (total / success / failed jobs, archive path, duration, plus counts of pods inCrashLoopBackOff/ImagePullBackOff/OOMKilled/PendingviaService.CountUnhealthyPods). Signal-first job ordering is on by default (useSetHighSignalFirst(false)to disable); movesevents-warning,events-all,cluster-info,nodes-wide,pods-allto the head of the queue so operators see actionable signal in seconds. 6 summary tests + 4 reorder tests + 3 tally tests.run_id+archive_sha256in manifest (0.9.x #81):Service.Runnow generates a stable per-run identifier (formatYYYYMMDDTHHMMSSZ-<base32>) and SHA-256 of the final.tar.gz; both surface inextras/manifest.jsonasrun_idandarchive_sha256. The manifest is re-emitted after the archive is hashed so the checksum always agrees with the bytes on disk.Summary.RunIDpropagated to notify{{run_id}}placeholder; S3/GCS upload metadata tags includerun_id; SFTP remote filename includesrun_idsuffix. 4 unit tests inpkg/collector/runid_test.go.
Changed
- Planning triad refocus: trimmed Band 3 to 1.0.0 contract only (#30, #34, #35, #40, #48, #87); new Band 0.9.x for operator wins (plan-0.9.0.md: #31, #42, #60, #64, #79–#86); deferred multi-cluster, stream, analyze, and 30+ items to Band 4 backlog. SPEC scope sections aligned. (ROADMAP planning)
[0.8.0] - 2026-06-17
Added
- Workload resource RCA extras (0.8.x #39):
extras/workload-resources.tsv— per-container CPU/memory requests and limits for every pod, plus controller owner kind/name.extras/all-pods-rca.tsvadds pod-levelcpu_request,cpu_limit,memory_request, andmemory_limitcolumns (summed across init + app containers) alongside usage metrics and log paths.
[0.7.2] - 2026-06-17
Changed
- Node log capture: primary host logs via
…/proxy/logs/messages→nodes/<node>.log; optional kubelet Node Log Query →nodes/<node>-kubelet.log. Both job types are optional so managed clusters without log query (e.g. AKS) no longer report spurious job failures. --versionoutput: printsgroot vX.Y.Z (commit=… branch=… built=…)(aligned with vision). Newgroot versionsubcommand.
[0.7.1] - 2026-06-16
Added
cluster_nameconfig and in-cluster archive naming: optionalcluster_name:overrides the archive basename cluster segment. When empty, Groot resolves kubeconfig cluster metadata, thenkube-public/cluster-info, then the API server host, beforeunknown-cluster. Helps in-cluster CronJobs and on-demand pods without kubeconfig context.
[0.7.0] - 2026-06-15
Added
- SFTP post-collect upload (band 2 #36):
upload.sftppushes.tar.gzto a remote Linux host over SSH (public-key only,known_hostsverification,BatchMode). Env:GROOT_UPLOAD_SFTP_*. Same failure semantics as S3/GCS. Relay playbook → groot-selfhostedrun/examples/airgapped-relay/. - Airgapped relay playbook (band 2 #37):
run/examples/airgapped-relay/in groot-selfhosted — end-to-end topology bastion → SFTP → rclone → OneDrive, systemd watcher, SSH hardening. No groot code. - Container image SBOM (band 2 #38): OCI attestation enabled on
dockers_v2(sbom: true); release workflow uses buildxdocker-containerdriver.
[0.6.1] - 2026-06-15
Changed
- Documentation: product vs operator repo split — Helm chart and flat CronJob manifests moved to groot-selfhosted; README, SPEC links, and
AGENTS.mdclarify product scope. No CLI behavior change. - Homebrew cask (
0.6.x #25): post-install hook clears macOS quarantine (xattr -dr) on staged binary.
[0.6.0] - 2026-06-06
Added
- Homebrew cask tap (
0.6.x #25):homebrew_casksin GoReleaser; release basenamesgroot_vX.Y.Z_*({{ .Tag }}); cask in homebrew-groot +scripts/update-homebrew-cask.sh; README install block. - SBOM (
0.6.x #26): SPDX-JSON (archives) + CycloneDX-JSON (binaries) via GoReleasersboms:. - Cosign signing (
0.6.x #27): keylesssignsforchecksums.txt+docker_signsfor GHCR images;cosign-installerandid-token: writein release workflow. - Post-collect upload (
0.6.x #28):upload:config (S3 + GCS),pkg/uploader/,--no-upload/GROOT_NO_UPLOAD; runs after notify; upload errors do not fail collect. - BSD ports (
0.6.x #29):contrib/freebsd/+contrib/openbsd/port/(kzero/pgwd repackage pattern); FreeBSD/OpenBSD release tarballs via GoReleaser;make port-*-sync+make dist-*. docs/plan-0.6.0.md: implementation plan for v0.6.0 (roadmap 0.6.x items #25–#29).
Changed
- Release artifact basenames break scripts that assumed
groot_0.5.0_*; new form isgroot_v0.6.0_*(README basename note). HOMEBREW_TAP_TOKENpassed to GoReleaser inrelease.yml.- Docs hygiene post-v0.5.0: positioning copy and ROADMAP refresh (also noted under [0.5.0]).
[0.5.0] - 2026-06-06
Added
- Notify on failure (
0.5.x #19):notify.on_failuresends optional alerts when collect aborts (on_abort, defaulttrue) or when completed collects havefailed >= min_failed_jobs(default1). Respects--no-notify/GROOT_NO_NOTIFY. Partial-failure alerts are in addition to the normal success notify. - Rich generic webhooks (
0.5.x #20):notify.generic.extra_fields,body_template(JSON with{{summary}},{{total}},{{failed}},{{event}}, … placeholders), and optional HMAC-SHA256 signing (hmac_secret,hmac_header, envGROOT_NOTIFY_GENERIC_HMAC_SECRET). - Email / SMTP (
0.5.x #21):notify.emailchannel (STARTTLS on port 587 by default; implicit TLS viause_tls). Env:GROOT_NOTIFY_EMAIL_HOST,_USERNAME,_PASSWORD,_FROM,_TO. - Notify HTTP retry (
0.5.x #24):notify.retry(max_attempts,initial_backoff,max_backoff) retries transient 5xx and network errors for webhook and PagerDuty HTTP clients. - Optional secret redaction (
0.5.x #23):collection.redact_secrets(defaultfalse) scans collected*.logfiles with built-in patterns plus optionalredact_patternsregex list; replaces matches with[REDACTED]. - In-cluster deploy (
0.5.x #22): Helm chart atdeploy/helm/groot/(CronJob, ClusterRole, ServiceAccount, ConfigMap, optional PVC for/out) and flat manifests atdeploy/k8s/cronjob.yaml. Image:ghcr.io/hrodrig/groot. docs/plan-0.5.0.md: implementation plan for v0.5.0 (roadmap 0.5.x items #19–#24).
Changed
- Positioning copy: README, SPEC, ROADMAP, and CLI
Short/Longdescribe GROOT as a read-only log and context collector (not a diagnostics/diagnosis tool); ROADMAP honest gaps refreshed pre-0.5.x; #25 documents Homebrew cask + pgwd/kzero release basename convention. configs/groot.yml.sampleandSampleYAML()document new notify, retry, on_failure, and redaction keys.docs/SPECIFICATIONS.md: §4 notify schema, §7 failure alerts and retry, §9 configuration examples, §8 in-cluster deploy; redaction in §5.README.md: notifications (email, HMAC, on_failure), in-cluster deploy, secret redaction, correctedfile_prefix/ output naming; usage examples for--list-jobs, redaction, failure notify.deploy/: expanded READMEs with Helm and flat-manifest examples.docs/README.md: index for plan-0.5.0 and quick links to 0.5.x topics.docs/ROADMAP.md: 0.5.x band closed; Current focus → 0.6.x.
[0.4.1] - 2026-06-06
Fixed
Dockerfilebuilder image: bumpgolangbase from 1.26.3 to 1.26.4 to matchgo.mod; restores Security workflow Grype image build (go mod downloadwas failing withrequires go >= 1.26.4).
Changed
- README: fixed-tag download examples and
go installpin updated to v0.4.1.
[0.4.0] - 2026-06-05
Added
- Archive manifest (
0.4.x #15): every successful collect writesextras/manifest.jsoninside the archive withgroot_version,groot_commit,collected_at,duration_seconds,session_base,archive_basename,file_prefix,cluster(context/cluster/user/server),jobs(total/success/failed), and a sortedpaths[]listing of the captured files. CLI build metadata is injected from the linker viaSetBuildInfo. groot collect --list-jobs(0.4.x #18): prints planned collection jobs (name, output file, args,optional) and exits without writing the capture tree, without creating the.tar.gz, and without firing notify. Useful as an operator preview before a real run.- Broader
extra_kubectlresources (0.4.x #13):k8srunnergetanddescribenow supportconfigmap/cm,pvc,service/svc,ingress/ing, and the apps workloadsdeployment/deploy,replicaset/rs,statefulset/sts,daemonset/ds.get --raw <path>remains the escape hatch for CRDs and generic reads.explainandwaitare still rejected. - Job / CronJob log targets (
0.4.x #14):collection.targets.<ns>acceptsjobsandcronjobslists in addition todeployments/statefulsets/daemonsets/helm_releases. Pod matching uses the same label keys as Deployments (app.kubernetes.io/name,app.kubernetes.io/instance,app) plusjob-namefor Job pods. - Kind E2E in CI (
0.4.x #17): new optional GitHub Actions jobtest-e2e-kindrunsmake test-e2e-kindwithcontinue-on-error: trueso flakes and Docker variance don't block merges while the budget stabilizes. docs/plan-0.4.0.md: implementation plan for v0.4.0 (roadmap 0.4.x items #12–#18), merge order, and release checklist.
Changed
file_prefixis now used in naming (0.4.x #12):config.file_prefix(defaultgroot-capture) drives both the capture directory and the.tar.gzarchive basename. Capture folder becomes<file_prefix>-<timestamp>[-since-<slug>]; archive becomes<sessionBase>-<cluster>[-<message>].tar.gz. Empty value falls back to the default.- Docs hygiene (
0.4.x #16):pkg/config/sample.go(SampleYAML()) andconfigs/groot.yml.sampleare now in sync; comments no longer say "kubectl" — wording reflects the client-go runtime.docs/SPECIFICATIONS.mdupdated for--list-jobs,file_prefix, Job/CronJob targets, archive manifest, and the broaderextra_kubectlresource set.
Fixed
pkg/cmd.ResetPersistentCLInow also resetscollectCmdflags, preventing--list-jobs(and other collect-local flags) from leaking across tests in the same package.
[0.3.2] - 2026-06-05
Security
- Address GO-2026-5026 / CVE-2026-39821 (
golang.org/x/netIDNA Punycode) by upgradinggolang.org/x/netto v0.55.0 and relatedgolang.org/x/*modules viago mod tidy.
Changed
- Go toolchain directive 1.26.3 → 1.26.4 in
go.mod.
[0.3.1] - 2026-05-14
Release note: v0.3.0 was never published (no git tag and no GitHub Release). v0.3.1 is the first tagged release on that line of work: it includes everything listed under [0.3.0] below, plus the 0.3.1 items in this section. When upgrading or auditing, treat the [0.3.0] section as shipped starting with v0.3.1.
develop commits (audit): after 9c3a6c2 (feat(collector): pod RCA table…), 65b6df5 (fix(config): do not auto-load /etc/groot/groot.yml.sample), then c9788e2 (Release v0.3.0 — client-go diagnostics, security, changelog — sets VERSION / docs for 0.3.0, still without a v0.3.0 tag). Further commits on develop finish 0.3.1 (kind E2E, README, VHS demo, docs/badges.md, VERSION bump). Only v0.3.1 was tagged from main at the merge tip.
Added
testing/: kind-based E2E (make test-e2e-kind, aliase2e-kind),testing/scripts/test-e2e-kind.sh,testing/k8s/e2e-workload.yaml, andtesting/README.md(Docker probe with optionalGROOT_DOCKER_WAIT_SECS, optional archive copy viaGROOT_E2E_ARCHIVE, emptynodes/note for the slim config).docs/e2e-kind.md;scripts/e2e-kind.shforwards totesting/scripts/test-e2e-kind.sh(mapsKIND_CLUSTER_NAMEtoGROOT_E2E_CLUSTERwhen set).
[0.3.0] - 2026-05-14
Not released: this version appears in the changelog for traceability, but there was no v0.3.0 tag—see the note at [0.3.1].
Added
CHANGELOG.mdfor release notes.pkg/k8srunner: allowlisted read-only diagnostics executed via client-go (argv shaped like familiar kubectl verbs, without the kubectl binary).pkg/kubetest: minimal fake Kubernetes API HTTP server for tests.- Unit tests for
k8srunner,kubeloader, andkubetest; merged coverage gate remains at 80% with headroom.
Changed
- Kubernetes collection uses client-go / metrics APIs end-to-end; no
kubectlbinary is required at runtime. - Per-namespace
resources.txtcaptures namespace-scoped workload objects as JSON sections (pods, services, Deployments, ReplicaSets, StatefulSets, DaemonSets) instead of a singlekubectl get alltext dump. collection.extra_kubectlvalidation: allowlist matches implementation (get,describe,top,logs,api-resources,api-versions,version,cluster-info,config view …,auth can-i …only).Runner.Metricsismetricsversioned.Interfaceso tests can inject a metrics fake client.- Dependency bumps aligned with govulncheck / grype:
golang.org/x/netv0.53.0,golang.org/x/oauth2v0.27.0, and relatedgolang.org/x/*modules viago mod tidy.
Fixed
config viewhandling: acceptconfig viewwith no extra tokens; apply-o/--outputflags from argv afterview(previously used the wrong slice and required an extra argument).
Removed
pkg/kubemock(unused kubectl shim for tests).
Security
- Address GO-2026-4918 (
golang.org/x/netHTTP/2) and GHSA-6v2p-p543-phr9 (golang.org/x/oauth2) by upgrading the affected modules.