Skip to main content

CHANGELOG.md

# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.3.1] - 2026-05-21

### Added

- Added executable fixture-app architecture examples covering PlantUML
  conformance, captured slices, function-level call metadata, reusable rules,
  and graph metrics against real compiled BEAM files.
- Included the fixture example docs, PlantUML diagram, and test module in the
  Hex package, with the fixture README listed in HexDocs examples.

## [0.3.0] - 2026-05-21

### Added

- `use ArchTest, app: ...` now automatically scopes assertion, layer, onion,
  and modulith checks.
- `use ArchTest, freeze: true` auto-freezes assertion wrappers, with stable
  structured violation baseline keys.
- `ArchTest.Collector.build_graph_from_paths/2`, import filters, and
  function-level `%ArchTest.Call{}` metadata via `calls/2` and
  `calls_from_path/2`.
- `ArchTest.Rule` helpers for reusable rules, ignore filters, assertion, and
  freeze integration.
- `ArchTest.Modulith.define_slices_by/2` for captured namespace slices.
- `ArchTest.PlantUML.enforce/2` for component diagram conformance.
- `ArchTest.Metrics.afferent/2`, `efferent/2`, `fan_in/2`, `fan_out/2`,
  and `dependency_depth/2`.
- `ArchTest.Layers.allow_layer_dependency/3` and
  `ArchTest.allow_layer_dependency/3` for explicit layer-direction exceptions.

### Changed

- Empty assertion subjects now fail by default. Use `allow_empty: true` when an
  empty subject is intentional.
- `should_have_module_count/2` accepts `min:` and `max:` aliases for
  `at_least:` and `at_most:`.
- `should_be_free_of_cycles/2` now supports both `ModuleSet` checks and
  `Modulith` slice-cycle checks, so documented modulith pipelines work.
- `ArchTest.Collector` filters now keep dependency graphs closed by removing
  excluded modules from both graph keys and dependency edges.
- `ArchTest.Collector.calls/2` and `calls_from_path/2` now filter callers and
  callees, ignore generated protocol/compiler noise, and report static remote
  captures plus static `apply/3` targets.
- Layer, onion, modulith, and convention helpers now consistently forward
  graph/scope options to the collector.
- `ArchTest.Metrics.martin/2` now computes each module against itself rather
  than treating the whole matched set as one package.
- `ArchTest.Metrics.coupling/2` now treats a binary namespace root and its
  descendants as one package, and counts distinct external dependencies.
- `ArchTest.Modulith.define_slices_by/2` now discovers slices from descendant
  modules and resolves concrete roots when wildcard segments precede `(*)`.
- `ArchTest.PlantUML.parse_edges/1` now ignores line comments and PlantUML
  block comments.

### Fixed

- `use ArchTest, app: ...` now correctly respects per-rule scope overrides for
  `should_have_module_count/2`.
- `use ArchTest, freeze: true` now baselines `should_have_module_count/2`
  failures and includes semantic scope options (`app`, `apps`, `paths`,
  `include`, `exclude`) in generated freeze IDs.
- Freeze update mode no longer baselines empty-subject control failures.
- `should_only_be_called_by/3` now fails on an empty protected object set by
  default, matching other subject-based assertions.
- `should_have_module_count/3` no longer treats assertion options such as
  `rule_id:` and `allow_empty:` as count constraints.
- `should_have_module_count/3` no longer treats collector scope options such as
  `apps:`, `paths:`, `include:`, `exclude:`, and `force:` as count constraints.
- Auto-freeze rule IDs for `should_have_module_count/3` no longer include
  non-semantic `graph:` data.
- Repeated `ArchTest.Rule.ignore/2` calls now accumulate filters instead of
  replacing previous filters for the same field.
- `use ArchTest` now exposes option-aware `define_layers/2`, `define_onion/2`,
  and `define_slices/2` helpers.
- Documentation examples were corrected for freeze usage, layer exceptions,
  collector options, metric helpers, and non-overlapping layer patterns.
- Added a 0.2 to 0.3 migration guide with upgrade steps and before/after code
  examples for app scoping, conventions, empty subjects, freeze baselines,
  layer patterns, modulith slices, and reusable rules.
- Igniter generators now emit `use ArchTest, app: ...`, use safer
  non-overlapping layer defaults, pass app scope to generated convention checks,
  and mark optional schema-placement checks with `allow_empty: true`.

## [0.2.1] - 2026-04-10

### Fixed

- **Compilation without Igniter** — mix task files no longer fail with `module Igniter.Mix.Task is not loaded` when Igniter is not a dependency. All task modules are now wrapped in `Code.ensure_loaded?(Igniter.Mix.Task)` guards so they are only defined when Igniter is available.

## [0.2.0] - 2026-03-08

### Added

- **Igniter Mix tasks** — 8 generators for common architecture patterns:
  - `mix igniter.install arch_test` / `mix arch_test.install` — basic arch test file with cycle check
  - `mix arch_test.gen.phoenix` — opinionated Phoenix setup (layers + naming + conventions)
  - `mix arch_test.gen.layers` — classic web → context → repo layered architecture
  - `mix arch_test.gen.onion` — onion / hexagonal architecture (domain → application → adapters → web)
  - `mix arch_test.gen.modulith` — bounded-context slice isolation
  - `mix arch_test.gen.naming` — naming convention rules (no Managers, schema placement)
  - `mix arch_test.gen.conventions` — code hygiene checks (no `IO.puts`, `dbg`, bare `raise`)
  - `mix arch_test.gen.freeze` — freeze baseline for gradual adoption
- **Optional Igniter dependency**`{:igniter, "~> 0.7", only: [:dev, :test], optional: true, runtime: false}`

## [0.1.2] - 2026-03-07

### Added

- `Modulith.all_modules_covered_by/3` — asserts that every module under a
  namespace pattern belongs to a declared slice. Modules that escape slice
  coverage cause an explicit test failure instead of being silently ignored.
  Supports `:except` (list of glob patterns) and `:graph` (for testability).
  Also delegated from `ArchTest` as `all_modules_covered_by/2,3`.

## [0.1.1] - 2026-03-07

### Fixed

- OTP version compatibility: tests now use stable fixture modules instead of OTP-version-sensitive stdlib internals, fixing failures on OTP 26/27
- All credo `--strict` issues resolved (implicit try, `Enum.map_join`, negated if/else, nesting depth, cyclomatic complexity)

## [0.1.0] - 2026-03-06

Initial release.

### Added

- **Dependency assertions**`should_not_depend_on/2`, `should_only_depend_on/2`, `should_not_be_called_by/2`, `should_only_be_called_by/2`, `should_not_transitively_depend_on/2`, `should_be_free_of_cycles/1`, `should_not_exist/1`
- **Naming assertions**`should_reside_under/2`, `should_have_name_matching/2`, `should_have_module_count/2`
- **Behaviour / protocol assertions**`should_implement_behaviour/2`, `should_not_implement_behaviour/2`, `should_implement_protocol/2`, `should_not_implement_protocol/2`
- **Module attribute assertions**`should_have_attribute/2`, `should_not_have_attribute/2`, `should_have_attribute_value/3`, `should_not_have_attribute_value/3`
- **Function assertions**`should_export/3`, `should_not_export/3`, `should_have_public_functions_matching/2`, `should_not_have_public_functions_matching/2`, `should_use/2`, `should_not_use/2`
- **Layered architecture**`define_layers/1` + `enforce_direction/1`, `define_onion/1` + `enforce_onion_rules/1`
- **Modulith / bounded-context isolation**`define_slices/1`, `allow_dependency/3`, `enforce_isolation/1`, `should_not_depend_on_each_other/1`
- **`ArchTest.Conventions`** — pre-built checks: `no_io_puts_in/2`, `no_process_sleep_in/2`, `no_application_get_env_in/2`, `no_dbg_in/2`, `no_raise_string_in/2`, `no_plug_in/2`, `all_public_functions_documented/2`
- **`ArchTest.Metrics`** — afferent/efferent coupling, instability, abstractness, distance from main sequence (Martin metrics)
- **`ArchTest.Freeze`** — violation baseline freezing for gradual adoption; `ARCH_TEST_UPDATE_FREEZE=true` mode
- **`ArchTest.ModuleSet`** — fluent module selection DSL: glob patterns, `excluding/2`, `union/2`, `intersection/2`, `satisfying/1`
- **`ArchTest.Pattern`** — glob pattern compiler with `*` (single segment) and `**` (multi-segment) wildcards
- **`ArchTest.Collector`** — BEAM-native dependency graph builder via OTP `:xref`; works on compiled bytecode, no source parsing
- **Conventions support for both legacy and modern BEAM debug formats** — handles both `:abstract_code` (OTP < 24) and `:debug_info_v1` with `:elixir_erl` backend (Elixir 1.14+)