Changelog
View SourceAll notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
v0.4.2 (2026-10-16)
Changed
Detect the workspace projects from the
git ls-filesoutput when the workspace is in a git repositoryProjects ignored by git, e.g. through a
.gitignore, are no longer considered workspace projects, and the workspace tree is not scanned recursively. Projects in initialized git submodules and in nested git repositories, unless ignored, are included, and a warning is printed for uninitialized submodules. If the workspace is not in a git repository, or it is ignored, the directories are scanned as before.
Fixed
Do not count
quotelines as uncovered on Elixir 1.20+Elixir 1.20 wraps every
quotein an:elixir_quote.validate_quote/1call, so its line became executable. A macro used only by other modules of its project is expanded before the cover compilation, so itsquotelines could never be covered and the coverage of such projects dropped. Lines whose only code is that call are now excluded, as they were on earlier Elixir versions.
v0.4.1 (2026-10-07)
Fixed
- Mark projects as modified when their lockfile changes, even if it is outside of the project's path
v0.4.0 (2026-09-29)
Added
Add
Workspace.Checks.ValidateAffectedBycheckVerifies that the
:affected_bypaths of the projects match at least one file of the repository and are not within the project's own path. A mistyped or stale path would otherwise be silently ignored, and changes that should affect the project would not be detected.[ module: Workspace.Checks.ValidateAffectedBy, description: "all affected_by paths must be valid" ]Include
:affected_bypaths in the workspace graphEach distinct
:affected_bypath is now a:pathnode of the workspace graph, shared by all projects declaring it. Affected projects are computed through the graph, and the changed files matching each path are recorded in the new:affected_by_changesproject field.Paths are rendered by
mix workspace.graphin all formats, and paths with changed files are highlighted when--show-statusis set:$ mix workspace.graph --show-status :api ● └── :nif ● ├── native/common (path) ✚ └── proto/*.proto (path) :other ● └── native/common (path) ✚mix workspace.statusprints the matched paths and their changed files under each project, and they are included underaffected_by_changesin the JSON export of the projects:$ mix workspace.status Affected projects: :api api/mix.exs :nif nif/mix.exs affected by native/**/*.rs untracked native/src/lib.rs
Fixed
Fix
workspace.statusprinting absolute paths for changed files outside of the workspaceFix invalid
workspace.graph --format mermaidoutput for projects named after mermaid keywords, e.g.endFix
Workspace.Test.create_workspace/4ignoring the:projectsoption andwith_workspace/5not forwarding its optionsFix malformed
FNFandFNHfunction counts in LCOV coverage exportsFix
workspace.list --maintainerskipping projects added with--includeFix
workspace.graph --format dotomitting projects without any dependency or dependentFix
workspace.graph --focussilently printing an empty graph for unknown or excluded projectsFix invalid
workspace.graph --format dotoutput for projects named after DOT keywords, ids are now quotedFix
workspace.run --exportcrashing on task output that is not valid UTF-8Fix
workspace.run --exportnot writing the results when terminated by--early-stopFix
--env-varrejecting values containing=and upper casing the variable namesFix
DependenciesVersioncheck failing for options in a different order, git:tagor:refversions, or projects without depsFix
WorkspaceDepsPathscheck crashing on dependencies without a path, with a version requirement, or projects without depsFix
ValidateConfigPathcheck crashing if:expected_pathis not set, it is now requiredFix
ValidateConfigPathcheck failing for absolute configured or expected pathsFix changes of files with non ASCII or special characters in their names not being detected
Fix git warnings, e.g. about line endings or deprecated config options, hiding changed files or crashing workspace loading
Fix
--baseincluding files changed only on the base branch, changes are now computed against the merge base (base...head)Fix
:ignore_pathsalso ignoring paths sharing the same prefix, e.g.coverignoredcoverage_toolsSupport status related operations in repositories without commits
Detecting the uncommitted files relied on
git diff HEAD, which fails if the repository has no commits yet, so any status related operation, e.g.mix workspace.run --affected, raised. Staged files are now considered uncommitted in this case.Reset previous statuses on a forced
Workspace.Status.update/2A forced status update only marked the currently modified and affected projects, so statuses and changes from a previous update were kept, e.g. a project stayed modified after its changes were reverted, or when re-running the update against a different
:base.Detect changes of workspaces under symlinked paths
The git root was resolved to its real path, while project paths kept the symlinked form of the workspace path, so no changed file matched any project. For example, workspaces under
/varon macOS, which links to/private/var, had no modified or affected projects. The git root now keeps the form of the workspace path.Match
:affected_bypatterns without accessing the filesystemWildcard patterns were previously expanded with
Path.wildcard/1, so deleted files never matched them, e.g. removing a.rsfile under anative/**/*.rspattern did not mark the project as affected. Patterns are now matched directly against the changed paths.
v0.3.2 (2026-08-05)
Added
Add
--include/-ioption for union-based filteringThe
--includeoption allows you to add projects back to the filtered set, even if they were filtered out by other flags. This acts as a union operation, enabling powerful filtering combinations.Available in
workspace.runandworkspace.listtasks.Example use cases:
Run tests on affected projects but always include critical services:
mix workspace.run -t test --affected --include auth --include paymentGet all dependencies of a project plus the project itself:
mix workspace.list --dependent my_api --include my_api --format json
Note:
--excludealways has the highest priority - excluded projects cannot be re-included with--include.Add
--recursiveoption for transitive dependency filteringThe
--recursiveoption enables deep dependency traversal when used with--dependencyor--dependentflags, allowing you to work with all transitive dependencies instead of just first-level ones.Available in
workspace.runandworkspace.listtasks.Example use cases:
Get all projects that transitively depend on a shared library:
mix workspace.list --dependency shared_utils --recursiveRun tests on all transitive dependencies of an API service:
mix workspace.run -t test --dependent my_api --recursiveFind all projects affected by changes to a core dependency:
mix workspace.list --dependency core_lib --recursive --format json
By default (without
--recursive),--dependencyand--dependentonly consider direct (first-level) dependencies to maintain backward compatibility.
Fixed
Fix
--exclude-taghaving no effectThe tags provided through the command line were not normalized to atoms (or
{scope, tag}tuples for scoped tags), so they never matched the projects' tags and no project was excluded. This affected all tasks supporting the option, e.g.workspace.run,workspace.list,workspace.checkandworkspace.test.coverage.
v0.3.1 (2025-10-24)
Fixed
- Fix type violation warnings on Elixir 1.19
v0.3.0 (2025-10-13)
Added
- Add
:affected_byoption for explicit project dependenciesEnables projects to declare dependencies on files outside their directory structure, addressing common monorepo scenarios where projects depend on shared resources that cannot be detected through mix dependencies.In order to explicitly declare dependencies, you can now add in your:workspaceconfig in the project'smix.exs:
Use cases includedef project do [ app: :web, # ... other config workspace: [ affected_by: [ "../shared/config.ex", "../docs/**/*.md", "../rust/foo/" ] ] ] end- Cross-language dependencies (e.g., Rust NIFs depending on Rust crates)
- Shared configuration files across multiple projects
- Documentation changes that affect project builds
Deprecated
Add
--formatoption toworkspace.listwith support forjsonandprettyoutput formatsThe new
--formatoption provides a more flexible way to control output format:--format jsonoutputs JSON data (replaces the deprecated--jsonflag)--format prettyoutputs human-readable format (default)
The
--jsonoption is now deprecated and will be removed in version 0.4.0. Use--format jsonwith--outputinstead for the same functionality.
v0.2.2 (2025-07-10)
Added
workspace.run: store task output in the exportedjson.workspace.run: include the task duration in milliseconds in the exportedjson.workspace.list: support--base,--head,--affectedand---modifiedoptions.workspace.test.coverage: allow filtering by package path.
v0.2.1 (2025-03-14)
- Allow having multiple workspaces under the same git repo.
v0.2.0 (2025-02-07)
This version requires at least elixir v1.16
Added
workspace.run: support specifying execution order through the--optionflag.Till now
workspace.runwas executing the tasks in alphabetical order. A new--ordercli option is added that support setting it topreorder. This will perform a depth first search on the project graph and return the projects in post-order, e.g. outer leaves are returned first respecting the topology of your workspace.workspace.run: support filtering by root paths through the--pathflag.workspace.run: support filtering by--dependencyand--dependentsimilarly toworkspace.list.Support passing most repeated CLI arguments as a comma separated list, for example you can now do:
$ mix workspace.run -t format -p p1,p2,p3workspace.check: support running specific checks through the--checkoptionworkspace.check: support grouping checks.You can now configure the group of each check in your workspace config, with the
groupoption. Checks with the same group will be printed together on the CLI output, under a group header.Additionally you can specify
groups_for_checkswith which you can modify the default look and feel of each check group, for example:groups_for_checks: [ package: [ style: [:light_blue_background, :black], title: " 📦 Package checks" ], documentation: [ style: [:yellow_background, :black], title: " 📚 Documentation checks" ] ]workspace.list: support filtering by root paths through the--pathflag.Promoted helper testing utilities to a
Workspace.Testmodule.
Deprecated
- Check definitions without an
idis deprecated. ids can be used for filtering the checks that will be executed.
Removed
Workspace.Utils.Path.relative_to/2has been removed. After requiring at least elixir 1.16 you can now usePath.relative_to/3instead with theforce: trueoption.
Fixed
Escape base and head references in git commands.
workspace.test.coverage: respectignore_modulesfrom coverage report
v0.1.2 (2024-09-30)
Added
workspace.list: support filtering by dependents through the--dependentflag. You can now list all projects that are direct dependencies of a given project:mix workspace.list --dependent my_projectworkspace.list: support filtering by dependencies through the--dependency. Using this flag you can list only those projects that have the given direct dependency:mix workspace.list --dependency a_projectworkspace.list: add--maintainerfor filtering projects with the given maintainer
v0.1.1 (2024-07-04)
Added
workspace.run: add--exportoption for exporting execution results as ajsonfileworkspace.run: log execution time per projectworkspace.list: add--relative-pathsoption for exporting relative paths with respect to the workspace path instead of absolute paths (the default one).
Removed
workspace.run: remove--execution-modeflag
v0.1.0 (2024-05-13)
Initial release.