asgard 0.2.0 → 0.3.0
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 +7 -9
- data/.rubocop.yml +157 -0
- data/CHANGELOG.md +49 -11
- data/CLAUDE.md +19 -9
- data/README.md +78 -53
- data/Rakefile +83 -4
- data/docs/api.md +86 -13
- data/docs/changelog.md +4 -0
- data/docs/dependencies.md +25 -25
- data/docs/environment.md +30 -14
- data/docs/examples.md +3 -3
- data/docs/getting-started.md +5 -6
- data/docs/helpers.md +34 -10
- data/docs/index.md +6 -6
- data/docs/options.md +2 -2
- data/docs/shell.md +11 -11
- data/docs/subcommands.md +9 -9
- data/docs/task-files.md +266 -113
- data/docs/tasks.md +17 -15
- data/docs/variables.md +267 -51
- data/examples/.env +4 -0
- data/examples/.loki +24 -2
- data/examples/concurrent.loki +5 -5
- data/examples/db_subcommands.loki +3 -3
- data/examples/env_usage.loki +27 -0
- data/examples/kitchen_sink.loki +48 -15
- data/examples/server_subcommands.loki +3 -3
- data/examples/subdir/.loki +12 -0
- data/examples/subdir/import_demo.loki +14 -0
- data/examples/subdir/import_up_demo.loki +18 -0
- data/lib/asgard/base.rb +125 -83
- data/lib/asgard/kernel_methods.rb +77 -0
- data/lib/asgard/shell.rb +8 -7
- data/lib/asgard/tasks.rb +0 -11
- data/lib/asgard/version.rb +1 -1
- data/lib/asgard.rb +2 -18
- metadata +13 -4
data/docs/dependencies.md
CHANGED
|
@@ -26,15 +26,15 @@ Bare symbols run one after another in the order declared:
|
|
|
26
26
|
|
|
27
27
|
```ruby
|
|
28
28
|
class Tasks
|
|
29
|
-
desc "
|
|
29
|
+
desc "Compile the project"
|
|
30
30
|
def build = sh "rake build"
|
|
31
31
|
|
|
32
32
|
depends_on :build
|
|
33
|
-
desc "
|
|
33
|
+
desc "Run the test suite"
|
|
34
34
|
def test = sh "rake test"
|
|
35
35
|
|
|
36
36
|
depends_on :test
|
|
37
|
-
desc "
|
|
37
|
+
desc "Publish the gem"
|
|
38
38
|
def release = sh "bundle exec rake release"
|
|
39
39
|
end
|
|
40
40
|
```
|
|
@@ -47,7 +47,7 @@ Multiple sequential dependencies in a single `depends_on` call run left to right
|
|
|
47
47
|
|
|
48
48
|
```ruby
|
|
49
49
|
depends_on :clean, :build, :test
|
|
50
|
-
desc "
|
|
50
|
+
desc "Clean, build, and test"
|
|
51
51
|
def package = sh "rake package"
|
|
52
52
|
```
|
|
53
53
|
|
|
@@ -59,14 +59,14 @@ Wrap symbols in an array to declare they can run concurrently. Asgard waits for
|
|
|
59
59
|
|
|
60
60
|
```ruby
|
|
61
61
|
class Tasks
|
|
62
|
-
desc "
|
|
62
|
+
desc "Check code style"
|
|
63
63
|
def lint = sh "bundle exec rubocop"
|
|
64
64
|
|
|
65
|
-
desc "
|
|
65
|
+
desc "Run type checks"
|
|
66
66
|
def typecheck = sh "bundle exec srb tc"
|
|
67
67
|
|
|
68
68
|
depends_on [:lint, :typecheck]
|
|
69
|
-
desc "
|
|
69
|
+
desc "Run tests (after lint and typecheck)"
|
|
70
70
|
def test = sh "bundle exec rake test"
|
|
71
71
|
end
|
|
72
72
|
```
|
|
@@ -85,16 +85,16 @@ Mix bare symbols and arrays in a single `depends_on` call. Execution proceeds st
|
|
|
85
85
|
|
|
86
86
|
```ruby
|
|
87
87
|
class Tasks
|
|
88
|
-
desc "
|
|
89
|
-
desc "
|
|
90
|
-
desc "
|
|
91
|
-
desc "
|
|
92
|
-
desc "
|
|
88
|
+
desc "Install dependencies"; def setup = sh "bundle install"
|
|
89
|
+
desc "Check code style"; def lint = sh "bundle exec rubocop"
|
|
90
|
+
desc "Compile assets"; def build = sh "rake assets:precompile"
|
|
91
|
+
desc "Run tests"; def test = sh "bundle exec rake test"
|
|
92
|
+
desc "Post to Slack"; def notify = sh "curl $SLACK_WEBHOOK -d '{\"text\":\"done\"}'"
|
|
93
93
|
|
|
94
94
|
# setup first, then lint+build in parallel, then test, then notify
|
|
95
95
|
depends_on :setup, [:lint, :build], :test, :notify
|
|
96
|
-
desc "
|
|
97
|
-
def ci =
|
|
96
|
+
desc "Full CI pipeline"
|
|
97
|
+
def ci = puts "CI complete"
|
|
98
98
|
end
|
|
99
99
|
```
|
|
100
100
|
|
|
@@ -124,19 +124,19 @@ Each task runs at most once per `asgard` invocation. If multiple tasks declare t
|
|
|
124
124
|
|
|
125
125
|
```ruby
|
|
126
126
|
class Tasks
|
|
127
|
-
desc "
|
|
127
|
+
desc "Install gems"
|
|
128
128
|
def setup = sh "bundle install"
|
|
129
129
|
|
|
130
130
|
depends_on :setup
|
|
131
|
-
desc "
|
|
131
|
+
desc "Run tests"
|
|
132
132
|
def test = sh "rake test"
|
|
133
133
|
|
|
134
134
|
depends_on :setup
|
|
135
|
-
desc "
|
|
135
|
+
desc "Check style"
|
|
136
136
|
def lint = sh "rubocop"
|
|
137
137
|
|
|
138
138
|
depends_on [:test, :lint]
|
|
139
|
-
desc "
|
|
139
|
+
desc "Test and lint (setup runs once)"
|
|
140
140
|
def ci = puts "done"
|
|
141
141
|
end
|
|
142
142
|
```
|
|
@@ -152,10 +152,10 @@ Asgard validates the full dependency graph using [Dagwood](https://rubygems.org/
|
|
|
152
152
|
```ruby
|
|
153
153
|
class Tasks
|
|
154
154
|
depends_on :b
|
|
155
|
-
desc "
|
|
155
|
+
desc "Task A"; def a = puts "a"
|
|
156
156
|
|
|
157
157
|
depends_on :a
|
|
158
|
-
desc "
|
|
158
|
+
desc "Task B"; def b = puts "b"
|
|
159
159
|
end
|
|
160
160
|
```
|
|
161
161
|
|
|
@@ -175,14 +175,14 @@ No backtrace is shown — just a single diagnostic line.
|
|
|
175
175
|
```ruby
|
|
176
176
|
# build.loki
|
|
177
177
|
class Tasks
|
|
178
|
-
desc "
|
|
178
|
+
desc "Compile"
|
|
179
179
|
def build = sh "rake build"
|
|
180
180
|
end
|
|
181
181
|
|
|
182
182
|
# test.loki
|
|
183
183
|
class Tasks
|
|
184
184
|
depends_on :build # build.loki must be loaded first
|
|
185
|
-
desc "
|
|
185
|
+
desc "Test"
|
|
186
186
|
def test = sh "rake test"
|
|
187
187
|
end
|
|
188
188
|
```
|
|
@@ -197,14 +197,14 @@ When `--auto-load` is used, `*.loki` files are loaded alphabetically, so `build.
|
|
|
197
197
|
|
|
198
198
|
```ruby
|
|
199
199
|
class DBCommands < Tasks
|
|
200
|
-
desc "
|
|
200
|
+
desc "Run migrations"
|
|
201
201
|
def migrate = sh "rails db:migrate"
|
|
202
202
|
|
|
203
|
-
desc "
|
|
203
|
+
desc "Load seed data"
|
|
204
204
|
def seed = sh "rails db:seed"
|
|
205
205
|
|
|
206
206
|
depends_on :migrate, :seed
|
|
207
|
-
desc "
|
|
207
|
+
desc "Migrate then seed"
|
|
208
208
|
def reset = puts "Done."
|
|
209
209
|
end
|
|
210
210
|
|
data/docs/environment.md
CHANGED
|
@@ -12,8 +12,8 @@ Call `dotenv` inside the class body (not inside a task method) to load the defau
|
|
|
12
12
|
class Tasks
|
|
13
13
|
dotenv # loads .env from the current working directory
|
|
14
14
|
|
|
15
|
-
desc "
|
|
16
|
-
def check =
|
|
15
|
+
desc "Print the app name from .env"
|
|
16
|
+
def check = puts env(:app_name)
|
|
17
17
|
end
|
|
18
18
|
```
|
|
19
19
|
|
|
@@ -46,17 +46,14 @@ end
|
|
|
46
46
|
`dotenv` is a **class-level** call — it executes at Ruby class-load time, not when a task is invoked. This means:
|
|
47
47
|
|
|
48
48
|
1. Variables are available in `ENV` before any task method runs.
|
|
49
|
-
2. They are
|
|
50
|
-
3. They are available during `depends_on` dependency resolution.
|
|
49
|
+
2. They are available during `depends_on` dependency resolution.
|
|
51
50
|
|
|
52
51
|
```ruby
|
|
53
52
|
class Tasks
|
|
54
53
|
dotenv
|
|
55
54
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
desc "migrate", "Run migrations"
|
|
59
|
-
def migrate = sh "DATABASE_URL=#{database_url} rails db:migrate"
|
|
55
|
+
desc "Run migrations"
|
|
56
|
+
def migrate = sh "DATABASE_URL=#{env(:database_url)} rails db:migrate"
|
|
60
57
|
end
|
|
61
58
|
```
|
|
62
59
|
|
|
@@ -79,20 +76,39 @@ This makes it safe to commit a `.env.local` line to your `.loki` without requiri
|
|
|
79
76
|
|
|
80
77
|
---
|
|
81
78
|
|
|
82
|
-
## Environment Variables vs.
|
|
79
|
+
## Environment Variables vs. Class Variables
|
|
83
80
|
|
|
84
|
-
Use `dotenv` to bring external configuration into `ENV
|
|
81
|
+
Use `dotenv` to bring external configuration into `ENV`. Use `@@` class variables for fixed values declared in the task file, and read from `ENV` directly in task bodies or helper methods when the value comes from the environment:
|
|
85
82
|
|
|
86
83
|
```ruby
|
|
87
84
|
class Tasks
|
|
88
85
|
dotenv
|
|
89
86
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
87
|
+
@@app_name ||= "myapp".freeze
|
|
88
|
+
|
|
89
|
+
desc "Start the server"
|
|
90
|
+
def start
|
|
91
|
+
port = ENV.fetch("PORT", "3000").to_i
|
|
92
|
+
sh "puma -b tcp://0.0.0.0:#{port} -w #{ENV.fetch('WORKERS', '2')}"
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
For `ENV` values used in multiple tasks, define a private helper method:
|
|
98
|
+
|
|
99
|
+
```ruby
|
|
100
|
+
class Tasks
|
|
101
|
+
dotenv
|
|
93
102
|
|
|
94
|
-
desc "
|
|
103
|
+
desc "Start the server"
|
|
95
104
|
def start = sh "puma -p #{port}"
|
|
105
|
+
|
|
106
|
+
desc "Show config"
|
|
107
|
+
def config = puts "#{@@app_name} on port #{port}"
|
|
108
|
+
|
|
109
|
+
private
|
|
110
|
+
|
|
111
|
+
def port = ENV.fetch("PORT", "3000").to_i
|
|
96
112
|
end
|
|
97
113
|
```
|
|
98
114
|
|
data/docs/examples.md
CHANGED
|
@@ -27,7 +27,7 @@ Alternatively, copy individual example files into your own project's directory.
|
|
|
27
27
|
|
|
28
28
|
The most comprehensive example — demonstrates every Thor DSL feature available in Asgard:
|
|
29
29
|
|
|
30
|
-
-
|
|
30
|
+
- `@@` class variables for shared configuration values
|
|
31
31
|
- `dotenv` (commented out, ready to activate)
|
|
32
32
|
- `class_option` with `:boolean` and `:string` types, including `enum`
|
|
33
33
|
- `default_task` — sets the default command when `asgard` is run with no arguments
|
|
@@ -56,7 +56,7 @@ asgard pipeline
|
|
|
56
56
|
|
|
57
57
|
---
|
|
58
58
|
|
|
59
|
-
##
|
|
59
|
+
## Server Subcommands
|
|
60
60
|
|
|
61
61
|
**Path:** `examples/server_subcommands.loki`
|
|
62
62
|
|
|
@@ -80,7 +80,7 @@ The `ServerCommands` class inherits from `Tasks`, giving it access to `sh`, `dep
|
|
|
80
80
|
|
|
81
81
|
---
|
|
82
82
|
|
|
83
|
-
##
|
|
83
|
+
## DB Subcommands
|
|
84
84
|
|
|
85
85
|
**Path:** `examples/db_subcommands.loki`
|
|
86
86
|
|
data/docs/getting-started.md
CHANGED
|
@@ -50,8 +50,8 @@ Open `.loki` in your editor and add a task:
|
|
|
50
50
|
|
|
51
51
|
```ruby
|
|
52
52
|
class Tasks
|
|
53
|
-
desc "
|
|
54
|
-
def hello =
|
|
53
|
+
desc "Say hello to the world"
|
|
54
|
+
def hello = puts "Hello, World!"
|
|
55
55
|
end
|
|
56
56
|
```
|
|
57
57
|
|
|
@@ -64,7 +64,6 @@ end
|
|
|
64
64
|
|
|
65
65
|
```bash
|
|
66
66
|
asgard hello
|
|
67
|
-
# echo "Hello, World!"
|
|
68
67
|
# Hello, World!
|
|
69
68
|
```
|
|
70
69
|
|
|
@@ -90,7 +89,7 @@ Positional parameters are declared directly in the method signature. Document th
|
|
|
90
89
|
class Tasks
|
|
91
90
|
desc "greet NAME", "Greet someone by name"
|
|
92
91
|
def greet(name = "World")
|
|
93
|
-
|
|
92
|
+
puts "Hello, #{name}!"
|
|
94
93
|
end
|
|
95
94
|
end
|
|
96
95
|
```
|
|
@@ -115,7 +114,7 @@ class Tasks
|
|
|
115
114
|
option :shout, aliases: "-s", type: :boolean, desc: "Uppercase the greeting"
|
|
116
115
|
def greet(name = "World")
|
|
117
116
|
msg = options[:shout] ? "HELLO, #{name.upcase}!" : "Hello, #{name}!"
|
|
118
|
-
|
|
117
|
+
puts msg
|
|
119
118
|
end
|
|
120
119
|
end
|
|
121
120
|
```
|
|
@@ -163,7 +162,7 @@ Inside a task body, use the `debug?` and `verbose?` predicates:
|
|
|
163
162
|
|
|
164
163
|
```ruby
|
|
165
164
|
def hello
|
|
166
|
-
|
|
165
|
+
puts "building..."
|
|
167
166
|
sh "make --debug" if debug?
|
|
168
167
|
end
|
|
169
168
|
```
|
data/docs/helpers.md
CHANGED
|
@@ -10,13 +10,13 @@ Methods declared after `private` are callable from any task in the same class bu
|
|
|
10
10
|
|
|
11
11
|
```ruby
|
|
12
12
|
class Tasks
|
|
13
|
-
desc "
|
|
13
|
+
desc "Compile and package"
|
|
14
14
|
def build
|
|
15
15
|
compile("src")
|
|
16
16
|
package(app_version)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
desc "
|
|
19
|
+
desc "Build and publish to RubyGems"
|
|
20
20
|
def release
|
|
21
21
|
build
|
|
22
22
|
sh "gem push pkg/myapp-#{app_version}.gem"
|
|
@@ -49,13 +49,13 @@ Thor's `no_commands` block marks public methods as excluded from CLI discovery.
|
|
|
49
49
|
|
|
50
50
|
```ruby
|
|
51
51
|
class Tasks
|
|
52
|
-
desc "
|
|
52
|
+
desc "Compile the project"
|
|
53
53
|
def build
|
|
54
54
|
puts "Revision: #{current_sha}"
|
|
55
55
|
sh "rake build"
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
-
desc "
|
|
58
|
+
desc "Deploy to production"
|
|
59
59
|
def deploy
|
|
60
60
|
puts "Deploying revision #{current_sha}..."
|
|
61
61
|
sh "cap production deploy"
|
|
@@ -73,8 +73,6 @@ class Tasks
|
|
|
73
73
|
end
|
|
74
74
|
```
|
|
75
75
|
|
|
76
|
-
`var`-declared variables are also implemented using `no_commands` internally, which is why they appear as callable methods but not as CLI commands.
|
|
77
|
-
|
|
78
76
|
---
|
|
79
77
|
|
|
80
78
|
## Choosing Between `private` and `no_commands`
|
|
@@ -93,6 +91,8 @@ For most helpers, `private` is the right choice. Use `no_commands` when the help
|
|
|
93
91
|
|
|
94
92
|
## Sharing Helpers Across Files
|
|
95
93
|
|
|
94
|
+
### Within a project
|
|
95
|
+
|
|
96
96
|
Extract shared helpers into a plain Ruby module and load it from `.loki` using `require_relative`:
|
|
97
97
|
|
|
98
98
|
```ruby
|
|
@@ -117,10 +117,10 @@ require_relative "shared/helpers"
|
|
|
117
117
|
class Tasks
|
|
118
118
|
include BuildHelpers
|
|
119
119
|
|
|
120
|
-
desc "
|
|
120
|
+
desc "Compile the project"
|
|
121
121
|
def build = compile("src")
|
|
122
122
|
|
|
123
|
-
desc "
|
|
123
|
+
desc "Create distribution archive"
|
|
124
124
|
def package = sh "tar czf #{dist_path(app_version)} bin/"
|
|
125
125
|
end
|
|
126
126
|
```
|
|
@@ -130,6 +130,30 @@ Because `include` in the class body makes the module methods available as instan
|
|
|
130
130
|
!!! tip
|
|
131
131
|
Helpers in a shared module can call `sh`, `shebang`, and other Asgard DSL methods because those are included in `Tasks` (via `Asgard::Base` and `Asgard::Shell`) and are available in `self` when the module method is invoked.
|
|
132
132
|
|
|
133
|
+
### Across projects with `import_up`
|
|
134
|
+
|
|
135
|
+
If helpers are defined as tasks in a shared `.loki` file, use `import_up` to load them from any sub-project without knowing the absolute path:
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
~/sandbox/
|
|
139
|
+
shared_helpers.loki ← defines helper tasks available to all sub-projects
|
|
140
|
+
projectA/
|
|
141
|
+
.loki
|
|
142
|
+
projectB/
|
|
143
|
+
.loki
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```ruby
|
|
147
|
+
# projectA/.loki (and identically in projectB/.loki)
|
|
148
|
+
import_up "shared_helpers.loki"
|
|
149
|
+
|
|
150
|
+
class Tasks
|
|
151
|
+
# shared tasks are already defined in Tasks by here
|
|
152
|
+
end
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`import_up` walks up from `Dir.pwd` until it finds `shared_helpers.loki`, then loads it. It returns `false` without raising if the file is not found, making it safe to use in projects where the shared file may not always be present.
|
|
156
|
+
|
|
133
157
|
---
|
|
134
158
|
|
|
135
159
|
## Helper Methods in Subcommands
|
|
@@ -138,10 +162,10 @@ Subcommand classes that inherit from `Tasks` also inherit all private helpers an
|
|
|
138
162
|
|
|
139
163
|
```ruby
|
|
140
164
|
class DeployCommands < Tasks
|
|
141
|
-
desc "
|
|
165
|
+
desc "Deploy to staging"
|
|
142
166
|
def staging = deploy_to("staging")
|
|
143
167
|
|
|
144
|
-
desc "
|
|
168
|
+
desc "Deploy to production"
|
|
145
169
|
def production = deploy_to("production")
|
|
146
170
|
|
|
147
171
|
private
|
data/docs/index.md
CHANGED
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
<li><strong>Task Dependencies</strong> — sequential, parallel, and mixed dependency graphs via <code>depends_on</code></li>
|
|
14
14
|
<li><strong>Concurrent Execution</strong> — parallel task groups run in native Ruby threads</li>
|
|
15
15
|
<li><strong>Subcommands</strong> — group related tasks under a named namespace</li>
|
|
16
|
-
<li><strong>Variables</strong> —
|
|
16
|
+
<li><strong>Variables</strong> — shared configuration via Ruby class variables (<code>@@name</code>), visible across all tasks and subcommands</li>
|
|
17
17
|
<li><strong>Shell Helpers</strong> — <code>sh</code> for any shell command or heredoc; <code>shebang</code> for polyglot scripts</li>
|
|
18
18
|
<li><strong>Dotenv Support</strong> — load <code>.env</code> files into the environment with <code>dotenv</code></li>
|
|
19
19
|
<li><strong>Auto-Discovery</strong> — <code>.loki</code> root marker searched from CWD upward through parent directories</li>
|
|
20
|
-
<li><strong>Multi-File Tasks</strong> — split tasks across <code>*.loki</code> files
|
|
20
|
+
<li><strong>Multi-File Tasks</strong> — split tasks across <code>*.loki</code> files loaded via <code>import</code></li>
|
|
21
21
|
<li><strong>Built-in Flags</strong> — <code>--version</code>, <code>--debug</code>, and <code>--verbose</code> available on every task</li>
|
|
22
22
|
</ul>
|
|
23
23
|
</td>
|
|
@@ -40,8 +40,8 @@ touch .loki
|
|
|
40
40
|
# Add your first task
|
|
41
41
|
cat >> .loki << 'EOF'
|
|
42
42
|
class Tasks
|
|
43
|
-
desc "
|
|
44
|
-
def hello =
|
|
43
|
+
desc "Say hello"
|
|
44
|
+
def hello = puts "Hello from Asgard!"
|
|
45
45
|
end
|
|
46
46
|
EOF
|
|
47
47
|
|
|
@@ -53,9 +53,9 @@ asgard hello
|
|
|
53
53
|
|
|
54
54
|
## How It Works
|
|
55
55
|
|
|
56
|
-
Asgard searches upward from your current directory for a `.loki` file. That file marks the project root. Additional `*.loki` files in the same directory can be loaded
|
|
56
|
+
Asgard searches upward from your current directory for a `.loki` file. That file marks the project root. Additional `*.loki` files in the same directory can be loaded via `import "*.loki"` at the top of `.loki`. All task files reopen `class Tasks`, which is pre-defined by the gem as a subclass of `Asgard::Base` (itself a Thor subclass).
|
|
57
57
|
|
|
58
|
-
The full Thor DSL is available: `desc`, `method_option`, `class_option`, `long_desc`, `argument`, `default_task`, `map`, and `subcommand` all work exactly as documented in Thor — with Asgard's own `depends_on`, `
|
|
58
|
+
The full Thor DSL is available: `desc`, `method_option`, `class_option`, `long_desc`, `argument`, `default_task`, `map`, and `subcommand` all work exactly as documented in Thor — with Asgard's own `depends_on`, `sh`, `shebang`, and `dotenv` layered on top.
|
|
59
59
|
|
|
60
60
|
---
|
|
61
61
|
|
data/docs/options.md
CHANGED
|
@@ -53,7 +53,7 @@ class Tasks
|
|
|
53
53
|
enum: %w[development staging production],
|
|
54
54
|
desc: "Target environment"
|
|
55
55
|
|
|
56
|
-
desc "
|
|
56
|
+
desc "Deploy the application"
|
|
57
57
|
def deploy
|
|
58
58
|
if options[:dry_run]
|
|
59
59
|
puts "Would deploy to #{options[:env]}"
|
|
@@ -62,7 +62,7 @@ class Tasks
|
|
|
62
62
|
end
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
-
desc "
|
|
65
|
+
desc "Run database migrations"
|
|
66
66
|
def migrate
|
|
67
67
|
sh "rails db:migrate RAILS_ENV=#{options[:env]}"
|
|
68
68
|
end
|
data/docs/shell.md
CHANGED
|
@@ -14,10 +14,10 @@ Pass a single-line string to run it via `system`:
|
|
|
14
14
|
|
|
15
15
|
```ruby
|
|
16
16
|
class Tasks
|
|
17
|
-
desc "
|
|
17
|
+
desc "Compile the project"
|
|
18
18
|
def build = sh "rake build"
|
|
19
19
|
|
|
20
|
-
desc "
|
|
20
|
+
desc "Remove build artifacts"
|
|
21
21
|
def clean = sh "rm -rf dist/ tmp/"
|
|
22
22
|
end
|
|
23
23
|
```
|
|
@@ -34,7 +34,7 @@ Pass a multiline string (e.g., a heredoc) to run it as a single `bash -c` script
|
|
|
34
34
|
|
|
35
35
|
```ruby
|
|
36
36
|
class Tasks
|
|
37
|
-
desc "
|
|
37
|
+
desc "Bootstrap the development environment"
|
|
38
38
|
def setup
|
|
39
39
|
sh <<~SHELL
|
|
40
40
|
brew install redis postgresql
|
|
@@ -54,10 +54,10 @@ Pass `silent: true` to suppress the command echo. The command still runs and sti
|
|
|
54
54
|
|
|
55
55
|
```ruby
|
|
56
56
|
class Tasks
|
|
57
|
-
desc "
|
|
57
|
+
desc "Compile (quiet)"
|
|
58
58
|
def build = sh "rake build", silent: true
|
|
59
59
|
|
|
60
|
-
desc "
|
|
60
|
+
desc "Print environment info without noise"
|
|
61
61
|
def info
|
|
62
62
|
sh "printenv | grep APP_", silent: true
|
|
63
63
|
end
|
|
@@ -71,7 +71,7 @@ end
|
|
|
71
71
|
```ruby
|
|
72
72
|
class Tasks
|
|
73
73
|
depends_on :test
|
|
74
|
-
desc "
|
|
74
|
+
desc "Test then release"
|
|
75
75
|
def release
|
|
76
76
|
sh "bundle exec rake release"
|
|
77
77
|
# Never reached if rake release fails
|
|
@@ -90,7 +90,7 @@ end
|
|
|
90
90
|
|
|
91
91
|
```ruby
|
|
92
92
|
class Tasks
|
|
93
|
-
desc "
|
|
93
|
+
desc "Run Python data analysis"
|
|
94
94
|
def analyze
|
|
95
95
|
shebang :python3, <<~PYTHON
|
|
96
96
|
import json
|
|
@@ -105,7 +105,7 @@ end
|
|
|
105
105
|
|
|
106
106
|
```ruby
|
|
107
107
|
class Tasks
|
|
108
|
-
desc "
|
|
108
|
+
desc "Build frontend assets with esbuild"
|
|
109
109
|
def bundle_assets
|
|
110
110
|
shebang :node, <<~JS
|
|
111
111
|
const esbuild = require("esbuild")
|
|
@@ -123,7 +123,7 @@ end
|
|
|
123
123
|
|
|
124
124
|
```ruby
|
|
125
125
|
class Tasks
|
|
126
|
-
desc "
|
|
126
|
+
desc "Transform data with Ruby"
|
|
127
127
|
def transform
|
|
128
128
|
shebang :ruby, <<~RUBY
|
|
129
129
|
require "json"
|
|
@@ -138,7 +138,7 @@ end
|
|
|
138
138
|
|
|
139
139
|
```ruby
|
|
140
140
|
class Tasks
|
|
141
|
-
desc "
|
|
141
|
+
desc "Run a bash provisioning script"
|
|
142
142
|
def provision
|
|
143
143
|
shebang :bash, <<~BASH
|
|
144
144
|
set -euo pipefail
|
|
@@ -192,7 +192,7 @@ You can mix both in the same task:
|
|
|
192
192
|
|
|
193
193
|
```ruby
|
|
194
194
|
class Tasks
|
|
195
|
-
desc "
|
|
195
|
+
desc "Run a mixed shell + Python pipeline"
|
|
196
196
|
def pipeline
|
|
197
197
|
sh "bundle exec rake build"
|
|
198
198
|
|
data/docs/subcommands.md
CHANGED
|
@@ -10,10 +10,10 @@ Define a subcommand class that inherits from `Tasks`, then register it on the to
|
|
|
10
10
|
|
|
11
11
|
```ruby
|
|
12
12
|
class DeployCommands < Tasks
|
|
13
|
-
desc "
|
|
13
|
+
desc "Deploy to staging"
|
|
14
14
|
def staging = sh "cap staging deploy"
|
|
15
15
|
|
|
16
|
-
desc "
|
|
16
|
+
desc "Deploy to production"
|
|
17
17
|
def production = sh "cap production deploy"
|
|
18
18
|
end
|
|
19
19
|
|
|
@@ -37,8 +37,8 @@ Inheriting from `Tasks` (rather than `Asgard::Base` or `Thor`) gives the subcomm
|
|
|
37
37
|
|
|
38
38
|
- `sh` and `shebang` shell helpers (from `Asgard::Shell`)
|
|
39
39
|
- `depends_on` for dependency declarations
|
|
40
|
-
- `var` for variables
|
|
41
40
|
- `dotenv` for environment loading
|
|
41
|
+
- `@@` class variables declared on `Tasks` (visible in all subclasses)
|
|
42
42
|
- The built-in `--debug` and `--verbose` class options
|
|
43
43
|
- The `debug?` and `verbose?` private predicates
|
|
44
44
|
- Any private helpers or `no_commands` methods defined on `Tasks`
|
|
@@ -54,14 +54,14 @@ Inheriting from `Tasks` (rather than `Asgard::Base` or `Thor`) gives the subcomm
|
|
|
54
54
|
|
|
55
55
|
```ruby
|
|
56
56
|
class DBCommands < Tasks
|
|
57
|
-
desc "
|
|
57
|
+
desc "Run pending migrations"
|
|
58
58
|
def migrate = sh "rails db:migrate"
|
|
59
59
|
|
|
60
|
-
desc "
|
|
60
|
+
desc "Load seed data"
|
|
61
61
|
def seed = sh "rails db:seed"
|
|
62
62
|
|
|
63
63
|
depends_on :migrate, :seed
|
|
64
|
-
desc "
|
|
64
|
+
desc "Migrate then seed"
|
|
65
65
|
def reset = puts "Done."
|
|
66
66
|
end
|
|
67
67
|
|
|
@@ -94,13 +94,13 @@ class ServerCommands < Tasks
|
|
|
94
94
|
sh "puma -p #{port} #{flags.join(' ')}"
|
|
95
95
|
end
|
|
96
96
|
|
|
97
|
-
desc "
|
|
97
|
+
desc "Stop the running server"
|
|
98
98
|
option :force, aliases: "-f", type: :boolean, default: false, desc: "Force-kill without draining"
|
|
99
99
|
def stop
|
|
100
100
|
options[:force] ? sh "pkill -9 puma" : sh "pumactl stop"
|
|
101
101
|
end
|
|
102
102
|
|
|
103
|
-
desc "
|
|
103
|
+
desc "Show server status"
|
|
104
104
|
def status = sh "pumactl stats"
|
|
105
105
|
|
|
106
106
|
depends_on :stop, :start
|
|
@@ -176,6 +176,6 @@ myproject/
|
|
|
176
176
|
db_subcommands.loki ← defines DBCommands
|
|
177
177
|
```
|
|
178
178
|
|
|
179
|
-
|
|
179
|
+
Because siblings loaded via `import "*.loki"` execute before `.loki`'s own class body, both `DBCommands` and `ServerCommands` are defined by the time `.loki` runs its `subcommand` calls.
|
|
180
180
|
|
|
181
181
|
See [`examples/server_subcommands.loki`](examples.md#server-subcommands) and [`examples/db_subcommands.loki`](examples.md#db-subcommands) for complete working examples.
|