Release v0.25.4
Docker Image
The Docker image for this release has been published to DockerHub:
Repository: gooddata/gooddata-goodchanges
Tags:
gooddata/gooddata-goodchanges:0.25.4gooddata/gooddata-goodchanges:latest
Pull Commands
# Pull specific version
docker pull gooddata/gooddata-goodchanges:0.25.4
# Pull latest
docker pull gooddata/gooddata-goodchanges:latestRun Command
docker run --rm gooddata/gooddata-goodchanges:0.25.4 [command]Standalone Binaries
Download the binary for your platform from the assets below.
| Platform | Architecture | Asset |
|---|---|---|
| Linux | x86_64 | goodchanges-linux-amd64.tar.gz |
| Linux | ARM64 | goodchanges-linux-arm64.tar.gz |
| macOS | Intel | goodchanges-darwin-amd64.tar.gz |
| macOS | Apple Silicon | goodchanges-darwin-arm64.tar.gz |
| Windows | x86_64 | goodchanges-windows-amd64.zip |
| Windows | ARM64 | goodchanges-windows-arm64.zip |
All platforms
goodchanges-darwin-amd64.tar.gzgoodchanges-darwin-amd64.tar.gz.sha256goodchanges-darwin-arm64.tar.gzgoodchanges-darwin-arm64.tar.gz.sha256goodchanges-linux-amd64.tar.gzgoodchanges-linux-amd64.tar.gz.sha256goodchanges-linux-arm64.tar.gzgoodchanges-linux-arm64.tar.gz.sha256goodchanges-windows-amd64.zipgoodchanges-windows-amd64.zip.sha256goodchanges-windows-arm64.zipgoodchanges-windows-arm64.zip.sha256
Install (Linux/macOS)
# Example: download and install linux/amd64
curl -sL https://github.com/gooddata/gooddata-goodchanges/releases/download/v0.25.4/goodchanges-linux-amd64.tar.gz | tar xz
chmod +x goodchanges-linux-amd64
sudo mv goodchanges-linux-amd64 /usr/local/bin/goodchangesChangelog
0.25.4 - 2026-08-07
Fixed
- Intra-file taint propagation now matches symbol names as whole identifiers instead of raw substrings. The dependency/usage checks used
strings.Contains(body, name), so a symbol whose name is a substring of another was falsely linked — e.g. removing the unusedchooseActiontainted the surviving, usedchooseActionByIndex(its body "contains" the stringchooseAction), which then propagated to a spec and flaggedgdc-dashboards-e2efor a dead-code deletion. All six propagation sites (astdiff.gointra-file graph, plus the seed/importer/usage propagation inanalyzer.go) now require the name to appear flanked by non-identifier characters ([A-Za-z0-9_$]) via a sharedcontainsIdentifierhelper; non-identifier tokens like the*wildcard keep the substring behaviour. Strictly more precise (it only drops matches that were substrings inside a larger identifier — never a real usage), so no false negatives.
0.25.3 - 2026-08-07
Fixed
- Replaced the fine-grained path's whole-file
*fallback with import-time-aware detection, so an empty symbol diff no longer floods every importer. Previously, when a changed file produced no symbol-level diff,FindAffectedFilestainted the entire file with*— so a comment-only edit, a formatting change, a type-only change, or reordering imports in a widely-imported helper flagged all its consumers. That blanket is removed; a change now wildcards a file only when something that actually runs at import time changed:- a top-level side-effect statement (
console.log(...),describe(...),test(...), etc.) — already detected viahasSideEffectStmtChanges; - a bare side-effect import (
import "./x") added, removed, or re-pointed.
- a top-level side-effect statement (
- Named-import re-pointing is now handled precisely instead of via the blanket. When a binding keeps its name but resolves to a different module/export (
import { x } from "./a"→"./b", or{ a as x }→{ b as x }), its usages don't change textually and the symbol diff missed them; those usages are now tainted directly. Reordering imports and re-pointing a type-only import (import type, whenincludeTypesis off) correctly taint nothing. Import statement type-only-ness is now tracked ontsparse.Import.
Together these keep genuine import-time changes flagged while eliminating the large false-positive class where a comment or dead-code edit to a shared file re-ran every dependent target.
- Removing an unused export no longer floods every importer with taint. A deleted symbol was logged but never recorded as a change, so the per-file AST diff returned no affected symbols — and in the fine-grained path (
FindAffectedFiles) an empty diff falls through to tainting the whole file with*. Deleting one unused export from a widely-imported helper (e.g.ERROR_MESSAGEfromgdc-ldm-modeler-e2e'splaywright/helpers/selectors.ts) therefore tainted every file that imported it, flagging all ~48 dependent specs. Deleted symbols are now recorded as changed and propagate by name, so a removed export taints exactly the files that imported that symbol: an unused one taints nobody, while a removed used export still flags its importers (no false negative). The deleted names are appended after intra-file propagation (which walks only surviving symbols) and before the whole-file side-effect fallback, so a deletion-only change is carried precisely instead of being widened.
0.25.1 - 2026-08-07
Fixed
- Destructuring default initializers are now included in a binding's taint span. A binding's default (
const { a = compute() } = obj,const [a = fallbackVal] = arr) is a real second dependency — it supplies the value when the destructured slot isundefined— but it lives on the pattern (LHS), disjoint from the mapped source (RHS), so the element-wise span recorded in 0.25.0 covered only the source and excluded the default. A symbol used only inside such a default therefore escapedfindTaintedSymbolsByUsage— a false negative. The binding's span is now widened to cover the default expression as well as its mapped source. (Narrow in scope: only bites when a tainted symbol appears solely in a binding default and nowhere else in the file, but false negatives are always worth closing.)
0.25.0 - 2026-08-03
Changed
- Destructured bindings are now attributed element-wise when the initializer is an array or object literal, refining the whole-initializer attribution added in 0.24.13. Previously every binding in
const [a, b] = [tainted(), safe()](orconst { a, b } = { a: tainted(), b: safe() }) shared the entire initializer's span, so a change touching only one element tainted all the bindings — a false positive. Each binding is now mapped to its corresponding element (by index for array literals, by key for object literals, following nested patterns), and only falls back to the shared initializer span when mapping can't be done statically: a non-literal initializer (a call/identifier/member access — e.g.createStore(), where all bindings genuinely share the dependency), rest bindings (...rest), spreads, computed keys, or out-of-range indices. Net effect:adepends ontainted()andbonsafe(), so a change tosafe()no longer flags consumers ofa.
0.24.13 - 2026-08-01
Fixed
- Destructuring variable declarations (
const { a, b } = expr/const [a, b] = expr) are now decomposed into their individual bindings for both symbol and export extraction. PreviouslygetDeclNameonly handled plain identifiers and returned""for binding patterns, so destructured names were registered as neither symbols nor exports — they simply didn't exist in the file model. That silently broke taint propagation through a very common pattern: e.g.export const { store, startSagas, … } = createStore()ingdc-analytical-designer-runtime'sreduxStore.ts. A runtime change to the reducers feedingcreateStoretaintedcreateStore, but the taint could not reachstore/startSagas/…, so the package reported 0 affected exports and nothing propagated to the AD module/harness (or the dashboards harness that embeds it) — a false negative. Each destructured binding is now emitted as a symbol/export; renames ({ a: b }→b), rest elements (...x), nested patterns and array holes are handled. To stay precise, a binding's symbol span is the initializer expression (not the whole statement), so the sibling binding names don't bleed into the compared body and cross-link in the AST diff — each binding is attributed exactly to the initializer it destructures.
0.24.12 - 2026-07-30
Fixed
- App taint propagation (added in 0.24.1) no longer over-flags downstream targets. An affected app was seeded into the upstream-taint map — tainting everything that imports it — whenever it was merely reachable in the affected set, i.e. a transitive dependent of any touched package. So a change to a library an app depends on flagged that app's harness/host consumers even when the change affected no export the app actually imports (e.g. removing unused exports from
gdc-analytical-designer-runtimeflaggedgdc-analytical-designer-harness,gdc-dashboards-harness, andgdc-host-application). The wholesale-taint seed is now gated on the app being genuinely affected — the same conditions its own target detection uses: directly changed (has changed files), a changed lockfile dependency, or an actual tainted import from upstream (HasTaintedImportsForGlob). Apps that are only transitively reachable but import nothing that changed no longer propagate taint; real changes to exports an app imports still propagate as before. The per-package upstream-taint filter is also factored into a sharedbuildPkgUpstreamTainthelper used by both the library and app paths.
0.24.11 - 2026-07-30
Changed
- Upgrade vendored typescript-go to
37357ae666e7
0.24.10 - 2026-07-30
Fixed
- Symbol-level AST diff no longer marks an unchanged declaration as changed when a neighboring declaration is edited or removed. Each symbol's body text was extracted starting at
stmt.Pos(), which in the TS AST includes the symbol's leading trivia (the preceding comments and blank lines). Deleting a sibling — or otherwise changing what comes before a symbol — re-attaches the intervening comment (e.g. a// SECTIONheader) to the next symbol, so its extracted body differed between the old and new versions and it was reported as a runtime change. That false "change" then spread through the intra-file reference graph and out via the library's exports, over-tainting downstream consumers. Symbol start lines are now taken from the first real token (scanner.SkipTrivia), excluding leading comments/blank lines from the compared body. Example: removing three unusedcreateSelectorexports frombootstrap_selector.tspreviously tainted nine untouched sibling selectors (and everything reachable from them); it now taints none.
0.24.9 - 2026-07-30
Changed
- Renamed the
LOG_LEVEL=BASIC/DEBUGsummary lineAffected e2e packages (N):toAffected targets (N):. The list has always contained resolved.goodchangesrc.jsontargets (unit-test targets, app/harness targets, etc.), not just e2e packages, so the label now reflects its actual contents. Log wording only — the JSON result on stdout is unchanged.
0.24.8 - 2026-07-23
Changed
- Upgrade vendored typescript-go to
9696f950a1bb
0.24.7 - 2026-07-23
Changed
- Upgrade vendored typescript-go to
0d0b387e08e8
0.24.6 - 2026-07-23
Changed
- Upgrade vendored typescript-go to
8457ea62d288
0.24.5 - 2026-07-23
Changed
- Upgrade vendored typescript-go to
a7ae3a14e910
0.24.4 - 2026-07-23
Changed
- Upgrade vendored typescript-go to
375d2b910dc3
0.24.3 - 2026-07-23
Changed
- Upgrade vendored typescript-go to
49b85c922aed
0.24.2 - 2026-07-23
Changed
- Upgrade vendored typescript-go to
0fa4110e4e0e
[0.24.1] - 2026-07-21
Fixed
- Affected apps now propagate taint to packages that import them. When a package is not a library, its per-symbol export analysis is skipped — but it was also seeding no taint at all, so the taint chain died at the app boundary. A consumer importing from an affected app (e.g. a thin harness that dynamically imports its app package:
() => import("gdc-analytical-designer-module")) saw a clean upstream-taint map and was never flagged, so app/harness targets sitting behind an intermediate app went undetected. Now an affected app is tainted wholesale: all of its entrypoint exports are seeded into the upstream-taint map (mirroring the existing global-changeDirsfull-taint seeding for libraries), so downstream importers match via the normal import graph — including bare/dynamic side-effect imports (empty import names), which match on any non-empty symbol set for the package. Example: a change ingdc-analytical-designer-runtimenow correctly reachesgdc-analytical-designer-harnessthrough the intermediategdc-analytical-designer-moduleapp.
0.24.0 - 2026-06-08
Added
- CSS/SCSS taint now bridges into JS imports for the "JS-bundled CSS" pattern (most
libs/gdc-*). Previously, a changed SCSS file propagated through cross-library@usechains (e.g.gdc-dashboards-runtime/src/styles/app.scss@uses@gooddata/sdk-ui-dashboard) but the taint lived in a separate__css__:namespace that was only matched against style imports. A consumer that pulls the styles in purely via a JavaScript import —import { Root } from "gdc-dashboards-runtime", whereRoot.tsxdoesimport "./styles/app.scss"— never matched, so prod-affecting CSS changes failed to trigger app targets likegdc-dashboards. Now, while analysing each library (withINCLUDE_CSS=1), a local style file is treated as tainted if it@uses the styles of a CSS-tainted upstream package; any TS file that side-effect-imports that style file inherits taint on its exported symbols, which then rides the normal TS import graph into JS consumers. The__css__closure is computed before library analysis (and threaded through the per-package upstream-taint filter) so it is available during seeding. This implements Stage 3 ofproperly-support-tree-shaken-scss-or-scss-modules.md;package.jsonsideEffectsgating is still to come.
0.23.0 - 2026-06-07
Removed
- Breaking: The
appfield on target definitions in.goodchangesrc.json(the "app-relationship" feature) and itsIGNORE_APP_RELATIONSHIPenv var are removed. Targets are no longer triggered just because a referenced app is affected — linking e2e targets to applications is the caller's responsibility, done after change detection. While this was helpful to us initially, it was later decided to be outside the scope of the change detector, which should be repository agnostic. It also conflated two distinct questions ("which apps need testing" vs "which e2e libs changed directly"), and forced a second invocation withIGNORE_APP_RELATIONSHIPto surface fine-grained detections the app check would otherwise hide. Theappfield is now silently ignored if present. Also removed the now-unusedanalyzer.HasTaintedImportshelper.
0.22.0 - 2026-06-07
Changed
LOG_LEVEL=BASICoutput is now prefixed with[BASIC]on every line, mirroring the existing[DEBUG]prefix.log.Basicfnow prepends[BASIC]and appends the trailing newline itself (matchingDebugf), so callers no longer carry their own\n. Output is otherwise unchanged.
0.21.3 - 2026-06-07
Fixed
LOG_LEVEL=BASIC(and theBASIC-gated output underDEBUG) emitted nothing.mainset the localflagLogfromLOG_LEVELbut only ever assignedlog.Debug, neverlog.Basic, so the package-levelBasicflag stayedfalseand everylog.Basicf(...)call was silently swallowed.log.Basicis now set fromflagLog, restoring the progress/affected-package logging on stderr while the JSON result stays on stdout.
0.21.2 - 2026-06-01
Fixed
- Targets that reference an
app(e.g. e2e targets with"app": "gdc-analytical-designer") are now triggered when that app is affected via a changed dependency. WhenTARGETSwas set, the relevant-package set was seeded only from each matched target's own package and its transitive dependencies — but a target'sappis a logical relationship, not an npm dependency, so the app and its dependency subtree (e.g. the runtime library whose change is meant to trigger the e2e target) were excluded from analysis, produced no taint, and the app-taint check always came up empty. The seed set now also includestd.App(unlessIGNORE_APP_RELATIONSHIPis set), so the app and its dependencies are analyzed and the app-taint check fires.
0.21.1 - 2026-05-31
Fixed
- Aliased named imports (
import { X as Y }) now propagate taint correctly. The import parser only captured the local binding name (Y) and discarded the original imported name (X), so taint matching — which keys on the name the source module exports — never matched, and propagation stopped at the renamed hop. Imports now carry both names: the source-side name is used to match exported/affected symbols, and the local name is used to scan the importing file's body for usage. This fixes cases likeimport { Root as InnerRoot }where a change toRootfailed to reach the importing file's exports (and therefore its entrypoint and dependent targets).
0.21.0 - 2026-05-02
Added
- Top-level
typefield in.goodchangesrc.json("library"or"app"). When set, overrides the automatic library-vs-app inference frompackage.json. Invalid values cause a fatal error at startup.
0.20.0 - 2026-05-01
Changed
LOG_LEVEL=BASICoutput now goes to stderr instead of stdout. Stdout is reserved for the JSON result, so pipinggoodchanges | jq …works with logging enabled.
0.19.4 - 2026-04-29
Changed
- Upgrade vendored typescript-go to
56ab4af42157
0.19.3 - 2026-04-28
Changed
- Upgrade vendored typescript-go to
3499951dbc49
0.19.2 - 2026-04-24
Fixed
- Bare dynamic
import("pkg")calls (e.g.() => import("pkg")passed to a loader, orconst mod = await import("pkg")used opaquely without property access) are now recorded as side-effect imports, so taint on the target package propagates to the importing file. Previously only the three pattern forms (var+property-access, destructure,.thencallback) produced anImportrecord, leaving bare calls invisible to taint propagation.
0.19.1 - 2026-04-23
Fixed
- Global
changeDirstaint now enumerates every export from each entrypoint (including recursively viaexport * from "./local") instead of seeding a"*"wildcard. Downstream packages consume exports by exact name, so the wildcard never matched named imports — taint stopped at the first hop and targets transitively dependent on the tainted library were missed.
0.19.0 - 2026-04-20
Added
IGNORE_APP_RELATIONSHIPenv var. When set, theappfield in target configs is ignored — targets are no longer triggered just because their corresponding app is tainted (only direct changes, lockfile changes, and tainted workspace imports apply).
0.18.1 - 2026-04-13
Changed
- Upgrade vendored typescript-go to
24753aa4bf38
0.18.0 - 2026-04-10
Added
- Global
changeDirsfield in.goodchangesrc.json(top-level, next toignores). Matching files taint all exports (libraries) and trigger all targets in the package.
0.17.1 - 2026-04-10
Fixed
- Detect runtime side-effect statements (e.g.
console.log()) in entrypoint/barrel files as affecting all exports — previously these were misclassified as "comments/imports only" and seeded zero taint
0.17.0 - 2026-04-04
Changed
- Breaking: Lockfile dep change detection now parses old and new pnpm-lock.yaml as YAML (gopkg.in/yaml.v3) instead of diffing text lines. Compares resolved versions for direct deps per importer, and BFS-walks the snapshots section to detect transitive dep version changes — a transitive change taints the direct dep that pulled it in.
0.16.7 - 2026-04-04
Changed
- Upgrade vendored typescript-go to
c0703e66b68b
0.16.6 - 2026-04-04
Changed
- Upgrade vendored typescript-go to
02bf7c9f25a4
0.16.5 - 2026-04-04
Changed
- Upgrade vendored typescript-go to
7d9b07b896c1
0.16.4 - 2026-04-04
Changed
- Upgrade vendored typescript-go to
df62f5db69a2
0.16.3 - 2026-04-04
Changed
- Upgrade vendored typescript-go to
65056016dd8a
0.16.2 - 2026-04-04
Changed
- Upgrade vendored typescript-go to
df56d26717f7
0.16.1 - 2026-04-04
Changed
- Upgrade vendored typescript-go to
7f8f645fc008
0.16.0 - 2026-04-04
Changed
- Breaking: Merged
targetandvirtual-targettypes into a unified target definition. Thetypefield is removed. All targets now supportapp,targetName,changeDirs, lockfile detection, and fine-grained mode.targetNamedefaults to the package name when not set.changeDirsdefaults to**/*when not set.
0.15.3 - 2026-02-23
Fixed
- Add intra-file taint propagation after seeding phase in both
AnalyzeLibraryPackageandFindAffectedFiles, so that symbols referencing other tainted symbols in the same file are also marked as tainted before BFS starts
0.15.2 - 2026-02-20
Fixed
- Fix
export const/export letdeclarations not being added to the exports list in the TS parser, causing locally declared exported variables (e.g.export const allScenarios = [...]) to be invisible during entrypoint taint checking
0.15.1 - 2026-02-17
Changed
- Upgrade vendored typescript-go to
daa761e5c641
0.15.0 - 2026-02-17
Added
- lockfileVersion change detection: when
lockfileVersionchanges in a subspace's pnpm-lock.yaml, all projects in that subspace are treated as having all external deps changed, and all library exports are wildcard-tainted. This propagates transitively through the existing dependency graph and taint analysis. ParseLockfileVersionusing proper YAML parsing (gopkg.in/yaml.v3) to compare old vs new lockfile versions
0.14.2 - 2026-02-16
Added
- Comprehensive debug logging across all analyzer functions: FindAffectedFiles, FindEntrypoints, CollectEntrypointExports, HasTaintedImports, HasTaintedImportsForGlob, FindCSSTaintedPackages, and import resolution (resolve.go)
0.14.1 - 2026-02-16
Changed
- Upgrade vendored typescript-go to
7b198ca5c705
0.14.0 - 2026-02-14
Added
- JSON import taint propagation: changed
.jsonfiles now taint TS/JS files that import them, with symbol-level granularity based on usage of the imported binding
0.13.0 - 2026-02-14
Added
- Per-target
ignoresfield in target definitions. Per-target ignores are additive with the globalignoresand only apply to the specific target's detection.
0.12.0 - 2026-02-14
Changed
- Breaking:
.goodchangesrc.jsonnow uses atargetsarray instead of a single top-level target definition. Each entry intargetsis a target object withtype,app,targetName, andchangeDirs. Theignoresfield remains at the top level (shared across all targets).
0.11.2 - 2026-02-14
Fixed
- Fine-grained detection now seeds taint from changed CSS/SCSS files within the project (with CSS module granularity for
*.module.scss/*.module.css)
0.11.1 - 2026-02-14
Changed
- Fine-grained detection now uses symbol-level taint propagation matching library analysis: AST diffs identify changed symbols, import graph tracks name mappings, BFS only propagates to importers of actually changed symbols, with intra-file and re-export handling
0.11.0 - 2026-02-14
Added
-v/--versionflag prints the embedded version from theVERSIONfile
0.10.0 - 2026-02-14
Added
- Fine-grained
changeDirsentries now support an optionalfilterfield to narrow output results (e.g.{"glob": "src/**/*", "filter": "src/**/*.test.ts", "type": "fine-grained"}analyzes all files but only returns affected test files)
0.9.5 - 2026-02-14
Changed
- Fine-grained changeDirs now AST-diff changed files against the merge base; whitespace-only or comment-only changes no longer cascade through importers
0.9.4 - 2026-02-14
Fixed
- Fine-grained BFS propagation now follows re-exports (
export { X } from "./foo",export * from "./foo") so barrel files no longer break the chain
0.9.3 - 2026-02-14
Fixed
- Fine-grained changeDirs now detect lockfile dependency changes (
pnpm-lock.yamlupgrades taint files importing the affected external dep)
0.9.2 - 2026-02-14
Changed
- CSS module imports (
*.module.scss/*.module.css) with named bindings now use granular taint: only symbols that reference the imported binding are tainted, instead of all exports in the file
0.9.1 - 2026-02-14
Fixed
- Changed CSS/SCSS files within a library now taint TS files that relatively import them (e.g.
import "./styles.scss"taints all exports of the importing file)
0.9.0 - 2026-02-14
Changed
- Breaking:
changeDirsentries now use glob patterns instead of directory paths ("glob"field replaces"path") - Glob matching uses doublestar:
*matches files in current dir,**/*matches all nested files,**/*.stories.tsxmatches specific patterns - Ignores override glob matches: if a file matches a glob but is also in
ignores, it is excluded - Fine-grained changeDirs only match TS/TSX source files
0.8.0 - 2026-02-14
Changed
- When
TARGETSis set, compute relevant package set (active targets + transitive dependencies) and skip change detection, library analysis, and transitive dependent walks for irrelevant packages
0.7.1 - 2026-02-14
Fixed
- Load all
.goodchangesrc.jsonconfigs once at startup instead of re-reading from disk per changed file and again during target detection
0.7.0 - 2026-02-14
Changed
- Skip expensive target detection (file scanning, taint import checks) for targets excluded by
TARGETSfilter
0.6.0 - 2026-02-14
Added
- Optional
TARGETSenv var to filter output by target name (comma-delimited, supports*wildcard globs)
0.5.1 - 2026-02-14
Fixed
- Fix ignore globs not supporting
**patterns (e.g.scenarios/**/*.md) by replacingfilepath.Matchwithdoublestar.Match
0.5.0 - 2026-02-13
Added
- Fine-grained virtual target detection:
changeDirsentries can specify"type": "fine-grained"to collect specific affected files instead of triggering a full run - New
FindAffectedFilesanalyzer function for transitive file-level taint propagation within directories - Output format changed from
[]stringto[]{"name", "detections?"}for richer target information
Changed
changeDirsconfig field is now an array of objects ({"path": "...", "type?": "..."}) instead of plain strings
0.4.0 - 2026-02-13
Changed
- Parallelize library analysis within the same topological level using goroutines
0.3.0 - 2026-02-13
Added
install.shscript for downloading and installing standalone binaries with SHA-256 verification
0.2.5 - 2026-02-13
Changed
- Upgrade vendored typescript-go to
f058889a79ed
0.2.4 - 2026-02-12
Changed
- Trim release binaries to 6 targets: linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64, windows/arm64
0.2.3 - 2026-02-12
Added
- SHA-256 hash files (
.sha256) for every release binary
0.2.2 - 2026-02-12
Fixed
- Fix runner label for GitHub release job (
runners-cxa-xlarge, notcxa-xlarge)
0.2.1 - 2026-02-12
Changed
- Use cxa-xlarge runner for GitHub release job (cross-compiling 32 binaries)
- Docker images limited to linux/amd64 and linux/arm64 only (other platforms served via standalone binaries)
0.2.0 - 2026-02-12
Added
- Cross-platform standalone binaries attached to GitHub releases (32 targets)
- Support for Linux, macOS, Windows, FreeBSD, OpenBSD, NetBSD, Solaris, Illumos, AIX, DragonFlyBSD
Changed
- Docker build uses Go cross-compilation instead of QEMU emulation for faster multi-platform builds
0.1.0 - 2026-02-11
Added
- Initial release
- AST-level change detection for Rush monorepo libraries using vendored typescript-go parser
- Taint propagation through workspace dependency graph (unlimited BFS hops)
- Target and virtual target support via
.goodchangesrc.jsonconfiguration - Lockfile dependency change detection (pnpm-lock.yaml)
- Optional CSS/SCSS taint tracking and propagation through
@use/@importchains - Optional type-only change detection (interfaces, type aliases, annotations)
- Multi-stage Docker build
- Automated vendor upgrade workflow