Skip to content

Changelog

All notable changes to Asgard are documented here.

The format follows Keep a Changelog. Asgard adheres to Semantic Versioning.


Unreleased

Added

  • --doctor built-in CLI flag — diagnoses .loki resolution, import chains, and task definitions for the current directory. Handled directly in Asgard.run! (same pattern as --version), so it works even when a broken file, a circular/undefined dependency, or a silently redefined task would otherwise abort the whole process. Backed by the new Asgard::Doctor class. Includes a "Tasks by file" listing — every command grouped by the file it's defined in, as file:line, with any silently-overridden task annotated inline (OVERRIDDEN by ... / active — redefines ...). See API Reference.
  • helper DSL method — defines a method available in both class context (e.g. inside header) and instance context (inside task methods) with a single declaration. Eliminates the manual def self.name + no_commands { private def name = self.class.name } boilerplate. Supports positional arguments, keyword arguments, and block arguments. See Helper Methods.
  • Flay and Reek quality gatesflay_check checks for structural duplication (mass ≥ 150); reek checks code smells. Reviewed findings are grandfathered precisely, per method and detector, via reek --todo-generated exclude: entries in .reek.yml — a genuinely new smell still fails the gate even at an already-reviewed method.
  • test_verbose, console tasks — verbose test output and an IRB console with the gem loaded.
  • git.loki — per-repo push/pull/fetch tasks.
  • typos_check / typos_fix tasks — spell-checking via the external typos CLI (brew install typos-cli). Reports SKIP (not a failure) if typos isn't installed, with a one-line install hint.
  • fasterer_check task — performance-idiom suggestions from the fasterer gem, reported as WARN (non-blocking).
  • SKIP / WARN quality-gate statuses — alongside PASS/FAIL; only FAIL blocks quality.
  • Every quality gate now writes full detail to a <gate>_output.txt file (gitignored) and prints just a one-line summary to stdout.
  • asgard tree now shows the project header/footer, matching asgard help.
  • bundler_audit_check taskbundle-audit check --update against Gemfile.lock; FAIL on any known vulnerability.
  • quality_rails.loki — imported only when Rails is defined; ships brakeman_check as a Rails security-scan example. No wiring needed — quality discovers it automatically (see depends_on below).
  • depends_on accepts a Proc/lambda, not just a fixed list — resolved once, in validate_deps!, after every .loki file has loaded, instead of immediately. Solves "load order matters" for a dependency list that can't be known upfront, e.g. every task ending in _check across several files. See Dynamic Dependencies.
  • depends_on also accepts a blockdepends_on { ... } or depends_on do ... end, interchangeable with the Proc/lambda form above. Task arguments and a block can't be combined; doing so raises Asgard::Error.
  • The Proc/lambda/block result is now shape-validated once resolved — it must be an Array of Symbol/String (sequential) or Array of Symbol/String (parallel group) stages, nested no deeper. A bad shape raises a clear Asgard::Error naming the task and the offending value instead of a raw NoMethodError. See examples/depends_on_block/{good,bad}/.

Changed

  • quality task — discovers every *_check task at run time (via a depends_on Proc) rather than a fixed list, and runs them all in parallel with a colorized PASS/FAIL/WARN/SKIP summary and tally.
  • test, rubocop, reek renamed to test_check, rubocop_check, reek_check — consistency with the other gates is what makes quality's automatic discovery possible.
  • release task — prompts for confirmation unless -y/--yes is passed.
  • Asgard::Base and Asgard::Doctor split into mixinslib/asgard/base/{registry,dependency_graph,task_dsl,dispatch}.rb and lib/asgard/doctor/{task_sections,report}.rb. No behavior change; drops both classes' Reek TooManyMethods/TooManyInstanceVariables warnings to zero.

Fixed

  • bin/asgard — switched from require "asgard" to require_relative "../lib/asgard" so the executable always loads the library shipped alongside it, instead of whatever asgard gem happens to be installed separately.

Removed

  • reek_baseline / ensure_quality_dir tasks and .quality/ — superseded by precise per-method exclude: entries in .reek.yml (see the Reek gate entry above).
  • var DSL method — replaced by native Ruby class variables. Use @@name ||= "value".freeze in the class body. Class variables are visible in all task instance methods and in subcommand subclasses, making them the correct tool for shared configuration in a Thor-based task runner. See Variables.

0.2.0 — 2026-05-29

Changed

  • *.loki files are no longer auto-loaded by default. Pass --auto-load to asgard to load all *.loki files from the project root alphabetically before .loki. This is a breaking change for projects using the multi-file layout.
  • Added --auto-load as a built-in CLI flag in Tasks, visible in asgard help

0.1.2 — 2026-05-29

Added

  • --version built-in CLI flag — prints Asgard::VERSION and exits; implemented as a _-prefixed method in Tasks per the gem-owned naming convention
  • --debug and --verbose built-in class_option declarations on Tasks — set $DEBUG/$VERBOSE before any task runs via the invoke_command hook in Asgard::Base
  • debug? and verbose? private predicate helpers on Tasks — thin wrappers around $DEBUG and $VERBOSE for use inside task bodies
  • _ prefix convention for gem-owned methods in Tasks — built-in methods use _ prefix to distinguish them from user-defined tasks
  • run! guards against direct invocation of _-prefixed commands with a clean error message and exit 1
  • examples/ directory with working .loki files:
  • kitchen_sink.loki — demonstrates the full Thor DSL (all option types, long_desc, class_option, default_task, map, depends_on, var, no_commands, private)
  • server_subcommands.loki — subcommand group for server management
  • db_subcommands.loki — subcommand group for database management with depends_on chaining
  • concurrent.loki — demonstrates parallel task execution with interleaved thread output
  • README sections: Helper methods, Subcommands, Thor wrapper callout

Fixed

  • Replaced warn/exit 1 with abort throughout run!Kernel#warn is silenced when $VERBOSE = nil, which is the default in Ruby 4.0; abort writes to $stderr regardless

Changed

  • --debug and --verbose promoted from mapped tasks to class_option — they now work as modifiers alongside other commands (e.g. asgard build --debug) rather than as standalone commands
  • Removed all references to just task runner and recipe terminology; Asgard uses "task" throughout
  • depends_on parameter renamed from *recipes to *tasks for consistency

0.1.1 — 2026-05-28

Added

  • Parallel dependency execution — wrap deps in an array to run them concurrently: depends_on [:build, :lint] or depends_on :setup, [:build, :lint], :deploy
  • Asgard.run!(argv) — single entry point encapsulating find, load, validate, and start
  • Asgard.load_loki(dir) — auto-loads all *.loki files in a directory alphabetically
  • Tasks class pre-defined by the gem (class Tasks < Asgard::Base) — task files reopen it without restating the superclass
  • lib/asgard/tasks.rb — ships the pre-defined Tasks class

Changed

  • Replaced SimpleFlow dependency with Dagwood — purpose-built DAG library with no extra dependencies and no Ruby 4 compatibility issues
  • bin/asgard simplified to two lines: require "asgard" + Asgard.run!(ARGV)
  • Task file convention: .loki is the project root marker and entry point; *.loki files each reopen class Tasks and are auto-loaded before .loki
  • Asgard.find_task_files renamed to Asgard.find_task_file (singular — only .loki is the entry point)
  • depends_on now accepts mixed sequential/parallel stages; bare symbols run sequentially, arrays within the splat run in parallel
  • run! handles its own errors — missing .loki and circular dependencies produce a clean one-line message and exit 1 rather than a backtrace
  • Thread-safe dep deduplication via class-level _ran_tasks Set + Mutex replaces Thor's @_invocations
  • Removed import macro — task files use Ruby class reopening instead of modules

Removed

  • SimpleFlow dependency (replaced by Dagwood)
  • logger gem workaround (was only needed for SimpleFlow on Ruby 4)
  • *.loki glob fallback in find_task_file — only .loki is the auto-discovered entry point

0.1.0 — 2026-05-28

Added

  • Asgard::Base — Thor subclass providing the task DSL
  • depends_on — declare task dependencies; dependencies run at most once per invocation
  • var — declare static or lazy-evaluated variables available to all tasks
  • import — flat-merge a task module into the current class
  • dotenv — load a .env file into the environment
  • sh — run a shell command or multiline heredoc script; exits with the command's status on failure
  • shebang — write a script body to a tempfile and execute it with a given interpreter (:python3, :node, :ruby, :perl, :bash, :sh, or any custom interpreter)
  • Asgard.find_task_files — search current directory and ancestors for task files
  • Task file resolution: .loki takes priority; falls back to all *.loki files sorted alphabetically
  • asgard executable — finds task files, validates dependency graph, dispatches via Thor
  • Circular dependency detection via SimpleFlow::DependencyGraph at startup
  • 100% test coverage enforced via SimpleCov (95% minimum threshold)
  • Quality task in .loki runs flog after tests