asgard 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.loki +4 -2
- data/CHANGELOG.md +29 -2
- data/CLAUDE.md +117 -0
- data/README.md +415 -136
- data/bin/asgard +1 -20
- data/examples/.loki +2 -0
- data/examples/db_subcommands.loki +74 -0
- data/examples/kitchen_sink.loki +164 -0
- data/examples/server_subcommands.loki +56 -0
- data/lib/asgard/base.rb +10 -8
- data/lib/asgard/tasks.rb +28 -0
- data/lib/asgard/version.rb +1 -1
- data/lib/asgard.rb +26 -13
- metadata +14 -22
data/examples/.loki
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# Demonstrates Thor subcommands with Asgard's depends_on chaining within
|
|
3
|
+
# the subcommand group. Inherits from Tasks for full Asgard DSL access.
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# asgard db # shows subcommand help
|
|
7
|
+
# asgard db migrate
|
|
8
|
+
# asgard db migrate 20240101120000 --dry-run
|
|
9
|
+
# asgard db rollback
|
|
10
|
+
# asgard db rollback 3
|
|
11
|
+
# asgard db seed --file db/seeds/staging.rb
|
|
12
|
+
# asgard db reset # runs: rollback → migrate → seed
|
|
13
|
+
# asgard db console --env staging
|
|
14
|
+
# asgard db status
|
|
15
|
+
|
|
16
|
+
class DBCommands < Tasks
|
|
17
|
+
desc "migrate [VERSION]", "Run pending migrations up to VERSION"
|
|
18
|
+
option :dry_run, aliases: "-n", type: :boolean, default: false, desc: "Print SQL without executing"
|
|
19
|
+
option :verbose, aliases: "-v", type: :boolean, default: false, desc: "Show each migration as it runs"
|
|
20
|
+
def migrate(version = nil)
|
|
21
|
+
target = version ? "to version #{version}" : "to latest"
|
|
22
|
+
puts "Migrating #{target}#{options[:dry_run] ? " (dry run)" : ""}..."
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
desc "rollback [STEPS]", "Roll back the last STEPS migrations (default: 1)"
|
|
26
|
+
option :dry_run, aliases: "-n", type: :boolean, default: false, desc: "Print SQL without executing"
|
|
27
|
+
def rollback(steps = "1")
|
|
28
|
+
puts "Rolling back #{steps} migration(s)#{options[:dry_run] ? " (dry run)" : ""}..."
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
desc "seed [FILE]", "Load seed data into the database"
|
|
32
|
+
option :env, type: :string, default: "development",
|
|
33
|
+
enum: %w[development staging production],
|
|
34
|
+
desc: "Environment to seed"
|
|
35
|
+
def seed(file = "db/seeds.rb")
|
|
36
|
+
puts "Seeding #{options[:env]} from #{file}..."
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# depends_on chains within the subcommand group:
|
|
40
|
+
# rollback → migrate → seed → reset
|
|
41
|
+
depends_on :rollback, :migrate, :seed
|
|
42
|
+
desc "reset", "Rollback all migrations, re-migrate, and reseed"
|
|
43
|
+
def reset
|
|
44
|
+
puts "Database reset complete."
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
long_desc <<~DESC
|
|
48
|
+
Opens an interactive SQL console connected to the configured database.
|
|
49
|
+
|
|
50
|
+
The console inherits credentials from the current environment's
|
|
51
|
+
database.yml (Rails) or DATABASE_URL.
|
|
52
|
+
|
|
53
|
+
Examples:\x5
|
|
54
|
+
asgard db console\x5
|
|
55
|
+
asgard db console --env staging
|
|
56
|
+
DESC
|
|
57
|
+
desc "console", "Open an interactive database console"
|
|
58
|
+
option :env, type: :string, default: "development",
|
|
59
|
+
enum: %w[development staging production],
|
|
60
|
+
desc: "Environment to connect to"
|
|
61
|
+
def console
|
|
62
|
+
puts "Opening #{options[:env]} database console..."
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
desc "status", "Show applied and pending migrations"
|
|
66
|
+
def status
|
|
67
|
+
puts "Checking migration status..."
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
class Tasks
|
|
72
|
+
desc "db SUBCOMMAND", "Manage the database"
|
|
73
|
+
subcommand "db", DBCommands
|
|
74
|
+
end
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# kitchen_sink.loki — demonstrates every Thor DSL feature available in Asgard.
|
|
3
|
+
#
|
|
4
|
+
# Task names deliberately avoid the gem's own .loki tasks (test, build, quality,
|
|
5
|
+
# install, release) so this file can be loaded alongside them without conflict.
|
|
6
|
+
|
|
7
|
+
class Tasks
|
|
8
|
+
# ── Asgard: var — static value and lazy lambda ─────────────────────────────
|
|
9
|
+
var :app_name, "my_app"
|
|
10
|
+
var :build_dir, -> { "builds/#{app_name}" }
|
|
11
|
+
|
|
12
|
+
# ── Asgard: dotenv — load environment variables ────────────────────────────
|
|
13
|
+
# Uncomment to activate:
|
|
14
|
+
# dotenv # loads .env
|
|
15
|
+
# dotenv ".env.local" # or a specific file
|
|
16
|
+
|
|
17
|
+
# ── Thor: class_option — option present on every task ──────────────────────
|
|
18
|
+
class_option :dry_run,
|
|
19
|
+
aliases: "-n",
|
|
20
|
+
type: :boolean,
|
|
21
|
+
default: false,
|
|
22
|
+
desc: "Print commands without executing them"
|
|
23
|
+
|
|
24
|
+
class_option :env,
|
|
25
|
+
type: :string,
|
|
26
|
+
default: "development",
|
|
27
|
+
enum: %w[development staging production],
|
|
28
|
+
desc: "Target environment"
|
|
29
|
+
|
|
30
|
+
# ── Thor: default_task — runs when no command is given ─────────────────────
|
|
31
|
+
default_task :greet
|
|
32
|
+
|
|
33
|
+
# ── Thor: map — short aliases for tasks ────────────────────────────────────
|
|
34
|
+
map "g" => :greet
|
|
35
|
+
map "ck" => :check
|
|
36
|
+
map "rp" => :report
|
|
37
|
+
map "pl" => :pipeline
|
|
38
|
+
|
|
39
|
+
# ── Basic task — no parameters ─────────────────────────────────────────────
|
|
40
|
+
desc "greet", "Say hello (default task when no command is given)"
|
|
41
|
+
def greet
|
|
42
|
+
puts "Hello from #{app_name} (#{options[:env]})!"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# ── Positional parameter with default ──────────────────────────────────────
|
|
46
|
+
desc "hello NAME", "Greet NAME; omit NAME to greet the world"
|
|
47
|
+
def hello(name = "World")
|
|
48
|
+
puts "Hello, #{name}!"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# ── Positional parameter with method_option ────────────────────────────────
|
|
52
|
+
desc "farewell NAME", "Say goodbye to NAME"
|
|
53
|
+
option :formal, aliases: "-f", type: :boolean, default: false, desc: "Use formal language"
|
|
54
|
+
def farewell(name = "friend")
|
|
55
|
+
msg = options[:formal] ? "Goodbye, #{name}." : "See ya, #{name}!"
|
|
56
|
+
puts msg
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# ── argument — formal positional with type metadata ────────────────────────
|
|
60
|
+
# WARNING: argument is a CLASS-LEVEL declaration that pollutes every task's
|
|
61
|
+
# usage line. Only use it when every task in the class shares the same input,
|
|
62
|
+
# or in a single-command CLI. Shown here as a commented-out reference only.
|
|
63
|
+
#
|
|
64
|
+
# argument :target,
|
|
65
|
+
# type: :string,
|
|
66
|
+
# default: "localhost",
|
|
67
|
+
# desc: "Deployment target host"
|
|
68
|
+
|
|
69
|
+
desc "notify RECIPIENT", "Send a notification to RECIPIENT"
|
|
70
|
+
def notify(recipient = "team")
|
|
71
|
+
puts "Notifying #{recipient}..."
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# ── method_option — all five option types ──────────────────────────────────
|
|
75
|
+
desc "compile", "Compile the project"
|
|
76
|
+
option :output, aliases: "-o", type: :string, default: "dist/", desc: "Output directory"
|
|
77
|
+
option :verbose, aliases: "-v", type: :boolean, default: false, desc: "Enable verbose output"
|
|
78
|
+
option :jobs, aliases: "-j", type: :numeric, default: 1, desc: "Number of parallel jobs"
|
|
79
|
+
option :tags, type: :array, desc: "Build tags to apply"
|
|
80
|
+
option :defines, type: :hash, desc: "Preprocessor defines (KEY:VALUE)"
|
|
81
|
+
def compile
|
|
82
|
+
puts "Compiling #{app_name} → #{options[:output]}"
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# ── required option + enum + banner ────────────────────────────────────────
|
|
86
|
+
desc "deploy ENV", "Deploy to ENV (default: staging)"
|
|
87
|
+
option :strategy,
|
|
88
|
+
type: :string,
|
|
89
|
+
required: true,
|
|
90
|
+
enum: %w[blue-green rolling canary],
|
|
91
|
+
desc: "Deployment strategy"
|
|
92
|
+
option :timeout,
|
|
93
|
+
type: :numeric,
|
|
94
|
+
default: 300,
|
|
95
|
+
banner: "SECONDS",
|
|
96
|
+
desc: "Abort deployment after SECONDS"
|
|
97
|
+
option :branch,
|
|
98
|
+
type: :string,
|
|
99
|
+
default: "main",
|
|
100
|
+
desc: "Git branch to deploy"
|
|
101
|
+
def deploy(env = "staging")
|
|
102
|
+
puts "Deploying #{app_name}@#{options[:branch]} to #{env}..."
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# ── long_desc — extended help shown by `asgard help report` ────────────────
|
|
106
|
+
long_desc <<~LONGDESC
|
|
107
|
+
Generates a project report covering test coverage, lint results,
|
|
108
|
+
and a dependency audit.
|
|
109
|
+
|
|
110
|
+
Pass --format to control output style. Use --since to scope the
|
|
111
|
+
report to changes after a given date.
|
|
112
|
+
|
|
113
|
+
Examples:\x5
|
|
114
|
+
asgard report --format html --since 2024-01-01\x5
|
|
115
|
+
asgard report --format json --output report.json\x5
|
|
116
|
+
asgard rp --format text
|
|
117
|
+
LONGDESC
|
|
118
|
+
desc "report", "Generate a project report"
|
|
119
|
+
option :format, type: :string, default: "text", enum: %w[text html json], desc: "Output format"
|
|
120
|
+
option :since, type: :string, banner: "DATE", desc: "Limit to changes after DATE"
|
|
121
|
+
option :output, type: :string, banner: "FILE", desc: "Write output to FILE"
|
|
122
|
+
def report
|
|
123
|
+
puts "Generating #{options[:format]} report..."
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# ── Asgard depends_on: sequential — analyze runs before spec ───────────────
|
|
127
|
+
desc "analyze", "Check code style and complexity"
|
|
128
|
+
def analyze = puts "Analyzing..."
|
|
129
|
+
|
|
130
|
+
depends_on :analyze
|
|
131
|
+
desc "spec", "Run the test suite (depends on: analyze)"
|
|
132
|
+
def spec = puts "Running specs..."
|
|
133
|
+
|
|
134
|
+
# ── Asgard depends_on: parallel — analyze and typecheck run concurrently ───
|
|
135
|
+
desc "typecheck", "Run the type checker"
|
|
136
|
+
def typecheck = puts "Type checking..."
|
|
137
|
+
|
|
138
|
+
depends_on [:analyze, :typecheck]
|
|
139
|
+
desc "check", "Run analyze and typecheck in parallel"
|
|
140
|
+
def check = puts "All checks passed."
|
|
141
|
+
|
|
142
|
+
# ── Asgard depends_on: mixed sequential + parallel ─────────────────────────
|
|
143
|
+
desc "pack", "Create distribution archive"
|
|
144
|
+
def pack = puts "Packing..."
|
|
145
|
+
|
|
146
|
+
# check → compile+spec (parallel) → pack → pipeline
|
|
147
|
+
depends_on :check, [:compile, :spec], :pack
|
|
148
|
+
desc "pipeline", "Full pipeline: check → compile+spec → pack"
|
|
149
|
+
def pipeline = puts "Pipeline complete."
|
|
150
|
+
|
|
151
|
+
# ── Thor: no_commands — public helper excluded from CLI and --help ──────────
|
|
152
|
+
no_commands do
|
|
153
|
+
def current_sha
|
|
154
|
+
`git rev-parse --short HEAD`.strip
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# ── private — also excluded from CLI and --help ────────────────────────────
|
|
159
|
+
private
|
|
160
|
+
|
|
161
|
+
def banner(msg)
|
|
162
|
+
puts "=== #{msg} ==="
|
|
163
|
+
end
|
|
164
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# Demonstrates Thor subcommands registered on the top-level Tasks class.
|
|
3
|
+
#
|
|
4
|
+
# The subcommand class inherits from Tasks so it has access to sh, shebang,
|
|
5
|
+
# var, depends_on, and the built-in --debug/--verbose class options.
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
# asgard server # shows subcommand help
|
|
9
|
+
# asgard server start
|
|
10
|
+
# asgard server start 4000 --workers 4 --daemon
|
|
11
|
+
# asgard server stop --force
|
|
12
|
+
# asgard server status
|
|
13
|
+
# asgard server restart 4000
|
|
14
|
+
|
|
15
|
+
class ServerCommands < Tasks
|
|
16
|
+
desc "start [PORT]", "Start the server on PORT (default: 3000)"
|
|
17
|
+
option :daemon, aliases: "-d", type: :boolean, default: false, desc: "Run as a background daemon"
|
|
18
|
+
option :workers, aliases: "-w", type: :numeric, default: 2, desc: "Number of worker processes"
|
|
19
|
+
option :log, type: :string, default: "log/server.log",
|
|
20
|
+
banner: "FILE", desc: "Write logs to FILE"
|
|
21
|
+
def start(port = "3000")
|
|
22
|
+
puts "Starting server on :%s with %d workers%s" % [
|
|
23
|
+
port,
|
|
24
|
+
options[:workers],
|
|
25
|
+
options[:daemon] ? " (daemon)" : ""
|
|
26
|
+
]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
desc "stop", "Stop the running server"
|
|
30
|
+
option :force, aliases: "-f", type: :boolean, default: false, desc: "Force-kill without draining"
|
|
31
|
+
option :wait, type: :numeric, default: 30, desc: "Seconds to wait for shutdown"
|
|
32
|
+
def stop
|
|
33
|
+
if options[:force]
|
|
34
|
+
puts "Force-stopping server..."
|
|
35
|
+
else
|
|
36
|
+
puts "Gracefully stopping server (timeout: #{options[:wait]}s)..."
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
desc "status", "Show server status and process info"
|
|
41
|
+
def status
|
|
42
|
+
puts "Checking server status..."
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# depends_on works inside subcommand groups — stop runs before start
|
|
46
|
+
depends_on :stop, :start
|
|
47
|
+
desc "restart [PORT]", "Restart the server on PORT (stop, then start)"
|
|
48
|
+
def restart(port = "3000")
|
|
49
|
+
puts "Server restarted on port #{port}."
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class Tasks
|
|
54
|
+
desc "server SUBCOMMAND", "Manage the application server"
|
|
55
|
+
subcommand "server", ServerCommands
|
|
56
|
+
end
|
data/lib/asgard/base.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require "thor"
|
|
4
4
|
require "set"
|
|
5
|
-
require "
|
|
5
|
+
require "dagwood"
|
|
6
6
|
|
|
7
7
|
module Asgard
|
|
8
8
|
class Base < Thor
|
|
@@ -57,15 +57,15 @@ module Asgard
|
|
|
57
57
|
graph
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
# Declare dependencies for the next
|
|
60
|
+
# Declare dependencies for the next task.
|
|
61
61
|
# Bare symbols run sequentially; arrays within the splat run in parallel.
|
|
62
62
|
#
|
|
63
63
|
# depends_on :build # sequential
|
|
64
64
|
# depends_on :build, :lint # both sequential
|
|
65
65
|
# depends_on [:build, :lint] # build and lint in parallel
|
|
66
66
|
# depends_on :setup, [:build, :lint], :test # setup, then build+lint, then test
|
|
67
|
-
def depends_on(*
|
|
68
|
-
@_pending_deps =
|
|
67
|
+
def depends_on(*tasks)
|
|
68
|
+
@_pending_deps = tasks
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
def var(name, value = nil, &block)
|
|
@@ -88,7 +88,7 @@ module Asgard
|
|
|
88
88
|
Dotenv.load(path) if File.exist?(path)
|
|
89
89
|
end
|
|
90
90
|
|
|
91
|
-
# Validate the full dep graph for cycles using
|
|
91
|
+
# Validate the full dep graph for cycles using Dagwood::DependencyGraph.
|
|
92
92
|
def validate_deps!
|
|
93
93
|
return if _deps.empty?
|
|
94
94
|
|
|
@@ -97,7 +97,7 @@ module Asgard
|
|
|
97
97
|
hash[task] = _deps.fetch(task, []).flatten
|
|
98
98
|
end
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
Dagwood::DependencyGraph.new(full_graph).order
|
|
101
101
|
rescue TSort::Cyclic => e
|
|
102
102
|
raise Asgard::CircularDependencyError, e.message
|
|
103
103
|
end
|
|
@@ -118,8 +118,10 @@ module Asgard
|
|
|
118
118
|
no_commands do
|
|
119
119
|
# Dispatch hook: resolves and runs all deps (in parallel where declared)
|
|
120
120
|
# before executing the target command. Thread-safe deduplication via
|
|
121
|
-
# the class-level _ran_tasks set ensures each
|
|
121
|
+
# the class-level _ran_tasks set ensures each task runs at most once.
|
|
122
122
|
def invoke_command(command, *args)
|
|
123
|
+
$DEBUG = true if options[:debug]
|
|
124
|
+
$VERBOSE = true if options[:verbose]
|
|
123
125
|
target = command.name.to_sym
|
|
124
126
|
|
|
125
127
|
should_run = self.class._ran_mutex.synchronize do
|
|
@@ -132,7 +134,7 @@ module Asgard
|
|
|
132
134
|
stages = self.class._deps[target]
|
|
133
135
|
if stages&.any?
|
|
134
136
|
graph = self.class._build_dep_graph(stages)
|
|
135
|
-
groups =
|
|
137
|
+
groups = Dagwood::DependencyGraph.new(graph).parallel_order
|
|
136
138
|
|
|
137
139
|
groups.each do |group|
|
|
138
140
|
if group.size > 1
|
data/lib/asgard/tasks.rb
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Tasks is the single conventional entry point for all .loki files.
|
|
4
|
+
# It is pre-defined by the gem so .loki files never need to declare a class.
|
|
5
|
+
# Auxiliary *.loki files define modules which are imported into Tasks.
|
|
6
|
+
class Tasks < Asgard::Base
|
|
7
|
+
class_option :debug,
|
|
8
|
+
type: :boolean,
|
|
9
|
+
default: false,
|
|
10
|
+
desc: "Enable debug mode ($DEBUG = true)"
|
|
11
|
+
|
|
12
|
+
class_option :verbose,
|
|
13
|
+
type: :boolean,
|
|
14
|
+
default: false,
|
|
15
|
+
desc: "Enable verbose output ($VERBOSE = true)"
|
|
16
|
+
|
|
17
|
+
desc "--version", "Show asgard version"
|
|
18
|
+
map "--version" => :_version
|
|
19
|
+
def _version
|
|
20
|
+
puts Asgard::VERSION
|
|
21
|
+
exit
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def debug? = $DEBUG
|
|
27
|
+
def verbose? = $VERBOSE
|
|
28
|
+
end
|
data/lib/asgard/version.rb
CHANGED
data/lib/asgard.rb
CHANGED
|
@@ -3,30 +3,43 @@
|
|
|
3
3
|
require_relative "asgard/version"
|
|
4
4
|
require_relative "asgard/shell"
|
|
5
5
|
require_relative "asgard/base"
|
|
6
|
+
require_relative "asgard/tasks"
|
|
6
7
|
|
|
7
8
|
module Asgard
|
|
8
9
|
class Error < StandardError; end
|
|
9
10
|
class CircularDependencyError < Error; end
|
|
10
11
|
|
|
11
|
-
# Search the current directory and its ancestors for task
|
|
12
|
-
# Returns
|
|
13
|
-
|
|
14
|
-
# Priority:
|
|
15
|
-
# 1. A single .loki file in the directory (default/hidden task file)
|
|
16
|
-
# 2. All *.loki files in the directory, sorted alphabetically
|
|
17
|
-
def self.find_task_files
|
|
12
|
+
# Search the current directory and its ancestors for a .loki task file.
|
|
13
|
+
# Returns the path string, or nil if not found.
|
|
14
|
+
def self.find_task_file
|
|
18
15
|
dir = Dir.pwd
|
|
19
16
|
loop do
|
|
20
|
-
|
|
21
|
-
return
|
|
22
|
-
|
|
23
|
-
matches = Dir.glob(File.join(dir, "*.loki")).sort
|
|
24
|
-
return matches unless matches.empty?
|
|
25
|
-
|
|
17
|
+
candidate = File.join(dir, ".loki")
|
|
18
|
+
return candidate if File.exist?(candidate)
|
|
26
19
|
parent = File.dirname(dir)
|
|
27
20
|
break if parent == dir
|
|
28
21
|
dir = parent
|
|
29
22
|
end
|
|
30
23
|
nil
|
|
31
24
|
end
|
|
25
|
+
|
|
26
|
+
# Load all *.loki files from dir in alphabetical order.
|
|
27
|
+
# Each file typically reopens class Tasks to add tasks.
|
|
28
|
+
# The .loki entry point is excluded — it is loaded separately by run!.
|
|
29
|
+
def self.load_loki(dir)
|
|
30
|
+
Dir.glob(File.join(dir, "*.loki")).sort.each { |f| load f }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Main entry point invoked by the asgard executable.
|
|
34
|
+
def self.run!(argv)
|
|
35
|
+
abort "asgard: unknown command '#{argv.first}'" if argv.first&.start_with?("_")
|
|
36
|
+
task_file = find_task_file or abort "asgard: no .loki file found in #{Dir.pwd}"
|
|
37
|
+
load_loki(File.dirname(task_file))
|
|
38
|
+
load task_file
|
|
39
|
+
Tasks.validate_deps!
|
|
40
|
+
Tasks._reset_ran!
|
|
41
|
+
Tasks.start(argv)
|
|
42
|
+
rescue CircularDependencyError => e
|
|
43
|
+
abort "asgard: circular dependency — #{e.message}"
|
|
44
|
+
end
|
|
32
45
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: asgard
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dewayne VanHoozer
|
|
@@ -9,20 +9,6 @@ bindir: bin
|
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
|
-
- !ruby/object:Gem::Dependency
|
|
13
|
-
name: logger
|
|
14
|
-
requirement: !ruby/object:Gem::Requirement
|
|
15
|
-
requirements:
|
|
16
|
-
- - ">="
|
|
17
|
-
- !ruby/object:Gem::Version
|
|
18
|
-
version: '0'
|
|
19
|
-
type: :runtime
|
|
20
|
-
prerelease: false
|
|
21
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
-
requirements:
|
|
23
|
-
- - ">="
|
|
24
|
-
- !ruby/object:Gem::Version
|
|
25
|
-
version: '0'
|
|
26
12
|
- !ruby/object:Gem::Dependency
|
|
27
13
|
name: thor
|
|
28
14
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -38,19 +24,19 @@ dependencies:
|
|
|
38
24
|
- !ruby/object:Gem::Version
|
|
39
25
|
version: '1.0'
|
|
40
26
|
- !ruby/object:Gem::Dependency
|
|
41
|
-
name:
|
|
27
|
+
name: dagwood
|
|
42
28
|
requirement: !ruby/object:Gem::Requirement
|
|
43
29
|
requirements:
|
|
44
30
|
- - "~>"
|
|
45
31
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '0
|
|
32
|
+
version: '1.0'
|
|
47
33
|
type: :runtime
|
|
48
34
|
prerelease: false
|
|
49
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
36
|
requirements:
|
|
51
37
|
- - "~>"
|
|
52
38
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '0
|
|
39
|
+
version: '1.0'
|
|
54
40
|
- !ruby/object:Gem::Dependency
|
|
55
41
|
name: dotenv
|
|
56
42
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -65,9 +51,9 @@ dependencies:
|
|
|
65
51
|
- - "~>"
|
|
66
52
|
- !ruby/object:Gem::Version
|
|
67
53
|
version: '3.0'
|
|
68
|
-
description:
|
|
69
|
-
|
|
70
|
-
importable task
|
|
54
|
+
description: A powerful Ruby-based task runner for any kind of project with task dependency
|
|
55
|
+
tracking and concurrent execution of designated tasks. Uses Thor for its rich CLI
|
|
56
|
+
options, var declarations, dotenv, sh/shebang helpers, and importable task files.
|
|
71
57
|
email:
|
|
72
58
|
- dewayne@vanhoozer.me
|
|
73
59
|
executables:
|
|
@@ -78,6 +64,7 @@ files:
|
|
|
78
64
|
- ".envrc"
|
|
79
65
|
- ".loki"
|
|
80
66
|
- CHANGELOG.md
|
|
67
|
+
- CLAUDE.md
|
|
81
68
|
- COMMITS.md
|
|
82
69
|
- LICENSE.txt
|
|
83
70
|
- README.md
|
|
@@ -85,9 +72,14 @@ files:
|
|
|
85
72
|
- bin/asgard
|
|
86
73
|
- bin/console
|
|
87
74
|
- bin/setup
|
|
75
|
+
- examples/.loki
|
|
76
|
+
- examples/db_subcommands.loki
|
|
77
|
+
- examples/kitchen_sink.loki
|
|
78
|
+
- examples/server_subcommands.loki
|
|
88
79
|
- lib/asgard.rb
|
|
89
80
|
- lib/asgard/base.rb
|
|
90
81
|
- lib/asgard/shell.rb
|
|
82
|
+
- lib/asgard/tasks.rb
|
|
91
83
|
- lib/asgard/version.rb
|
|
92
84
|
- sig/asgard.rbs
|
|
93
85
|
homepage: https://github.com/madbomber/asgard
|
|
@@ -113,5 +105,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
113
105
|
requirements: []
|
|
114
106
|
rubygems_version: 4.0.12
|
|
115
107
|
specification_version: 4
|
|
116
|
-
summary: A
|
|
108
|
+
summary: A powerful Ruby-based task runner
|
|
117
109
|
test_files: []
|