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/task-files.md
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
# Task Files
|
|
2
2
|
|
|
3
|
-
Asgard uses a convention-based file discovery system. A hidden `.loki` file marks the project root
|
|
3
|
+
Asgard uses a convention-based file discovery system. A hidden `.loki` file marks the project root. Everything else — loading sibling files, shared task libraries, monorepo-wide tasks — is controlled explicitly from inside your `.loki` file using the `import` and `import_up` Kernel methods.
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
## The `.loki` Root Marker
|
|
8
8
|
|
|
9
|
-
When you run `asgard`, it searches for a `.loki` file starting in the current working directory and walking upward through parent directories until it finds one or reaches the filesystem root. The first `.loki` file found marks the project root
|
|
10
|
-
|
|
11
|
-
This means you can run `asgard` from any subdirectory of your project and it will find your tasks:
|
|
9
|
+
When you run `asgard`, it searches for a `.loki` file starting in the current working directory and walking upward through parent directories until it finds one or reaches the filesystem root. The first `.loki` file found marks the project root and is the only file Asgard loads automatically.
|
|
12
10
|
|
|
13
11
|
```
|
|
14
12
|
myproject/
|
|
@@ -18,143 +16,223 @@ myproject/
|
|
|
18
16
|
# asgard still works from here
|
|
19
17
|
```
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
The `.loki` file can be completely empty. Its presence alone is sufficient to mark the project root. If it is empty and you have `*.loki` files, you must pass `--auto-load` when running `asgard` — otherwise Asgard has nothing to do.
|
|
19
|
+
The `.loki` file can be completely empty — its presence alone marks the project root. It can also contain task definitions, `import` calls, or any valid Ruby.
|
|
23
20
|
|
|
24
21
|
---
|
|
25
22
|
|
|
26
|
-
## Loading
|
|
23
|
+
## Loading Files with `import`
|
|
24
|
+
|
|
25
|
+
`import` is a Kernel method available everywhere in Ruby — at the top level of `.loki` files, inside class bodies, and inside task method bodies. It loads `.loki` files with `require`-like idempotency: a file is loaded at most once per process, no matter how many times `import` is called with the same path.
|
|
27
26
|
|
|
28
|
-
|
|
27
|
+
### Single file by absolute path
|
|
29
28
|
|
|
30
|
-
```
|
|
31
|
-
|
|
29
|
+
```ruby
|
|
30
|
+
import "/home/shared/gem_tasks.loki"
|
|
32
31
|
```
|
|
33
32
|
|
|
34
|
-
|
|
33
|
+
### Single file by relative path
|
|
35
34
|
|
|
36
|
-
**
|
|
35
|
+
Relative paths are resolved relative to the **caller's file location**, like `require_relative`:
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
```ruby
|
|
38
|
+
# .loki — relative to this file's directory
|
|
39
|
+
import "build.loki"
|
|
40
|
+
import "../shared/gem_tasks.loki"
|
|
41
|
+
import "tasks/ci.loki"
|
|
42
|
+
```
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
### All files in the same directory (glob)
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
```ruby
|
|
47
|
+
import "*.loki" # all *.loki files in the same directory as the calling file
|
|
48
|
+
```
|
|
44
49
|
|
|
45
|
-
|
|
50
|
+
`*.loki` never matches `.loki` (the dotfile entry point) — Ruby's `Dir.glob` excludes dotfiles from `*` patterns by default.
|
|
46
51
|
|
|
47
|
-
|
|
52
|
+
### All files recursively (recursive glob)
|
|
48
53
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
| `desc` metadata | Thor registers the new usage/description string, discarding the old one |
|
|
53
|
-
| `depends_on` stages | `method_added` captures the pending deps for the new definition; the earlier dep chain is replaced |
|
|
54
|
+
```ruby
|
|
55
|
+
import "**/*.loki" # every .loki file in this directory and all subdirectories
|
|
56
|
+
```
|
|
54
57
|
|
|
55
|
-
|
|
58
|
+
### Specific named files
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
```ruby
|
|
61
|
+
import "gem_tasks.loki"
|
|
62
|
+
import "ci_tasks.loki"
|
|
63
|
+
```
|
|
59
64
|
|
|
60
|
-
|
|
65
|
+
### Combining patterns
|
|
61
66
|
|
|
62
67
|
```ruby
|
|
63
|
-
#
|
|
68
|
+
# .loki
|
|
69
|
+
import "*.loki" # load all siblings
|
|
70
|
+
import "../shared/*.loki" # load a parent-level shared library
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Typical `.loki` entry point
|
|
74
|
+
|
|
75
|
+
```ruby
|
|
76
|
+
# .loki
|
|
77
|
+
import "*.loki" # load all sibling task files
|
|
78
|
+
|
|
64
79
|
class Tasks
|
|
65
|
-
|
|
66
|
-
def build
|
|
67
|
-
sh "rake build"
|
|
68
|
-
end
|
|
80
|
+
# any top-level task definitions or overrides
|
|
69
81
|
end
|
|
70
82
|
```
|
|
71
83
|
|
|
84
|
+
### Return value
|
|
85
|
+
|
|
86
|
+
`import` returns `true` if at least one file was newly loaded, `false` if all files were already loaded or no glob pattern matched any file. If a specific (non-glob) file does not exist, `import` raises `LoadError`.
|
|
87
|
+
|
|
72
88
|
```ruby
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
# Preserve the original under a private name before overwriting it.
|
|
76
|
-
no_commands { alias_method :_build_original, :build }
|
|
89
|
+
import("gem_tasks.loki") ? "loaded now" : "already loaded"
|
|
90
|
+
```
|
|
77
91
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Finding Files with `loki_up`
|
|
95
|
+
|
|
96
|
+
`loki_up(name = ".loki")` searches `Dir.pwd` and each ancestor directory for a file with the given name, returning its absolute path or `nil`. It does **not** load the file — it only finds it.
|
|
97
|
+
|
|
98
|
+
Despite the name, `loki_up` is not limited to `.loki` files — it will locate any file by name. This makes it useful for finding shared config files, `.env` files, or any other resource that lives somewhere up the directory tree:
|
|
99
|
+
|
|
100
|
+
```ruby
|
|
101
|
+
loki_up # finds .loki (the project root marker)
|
|
102
|
+
loki_up("gem_tasks.loki") # finds gem_tasks.loki in CWD or any ancestor
|
|
103
|
+
loki_up(".env") # finds the nearest .env file up the tree
|
|
104
|
+
loki_up("VERSION") # finds a VERSION file in CWD or any ancestor
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Use `loki_up` when you need the path for other purposes, or to check whether a file exists before deciding to load it:
|
|
108
|
+
|
|
109
|
+
```ruby
|
|
110
|
+
if (path = loki_up("gem_tasks.loki"))
|
|
111
|
+
import path
|
|
83
112
|
end
|
|
113
|
+
|
|
114
|
+
# Pass the located .env to dotenv — works from any subdirectory
|
|
115
|
+
dotenv loki_up(".env") || ".env"
|
|
84
116
|
```
|
|
85
117
|
|
|
86
|
-
`
|
|
118
|
+
`loki_up` accepts exact filenames only. Glob patterns are not expanded by `loki_up` — use `import_up` for glob-aware ancestor search.
|
|
87
119
|
|
|
88
|
-
|
|
89
|
-
The `_` prefix on the alias name (`_build_original`) follows Asgard's convention for non-user-facing methods and reinforces that it is an implementation detail, not a task to be invoked directly.
|
|
120
|
+
---
|
|
90
121
|
|
|
91
|
-
|
|
92
|
-
Using `alias_method` to bolt post-task behaviour onto an existing task is a code smell. It is fragile (load-order dependent), obscures intent, and makes the dependency chain invisible to Asgard's cycle-detection and deduplication logic.
|
|
122
|
+
## Loading Files Found up the Tree with `import_up`
|
|
93
123
|
|
|
94
|
-
|
|
124
|
+
`import_up(name = ".loki")` combines `loki_up` and `import` into a single call. It finds the file (or files) up the ancestor chain and loads them.
|
|
95
125
|
|
|
96
|
-
|
|
97
|
-
# build.loki
|
|
98
|
-
class Tasks
|
|
99
|
-
desc "build", "Compile the project"
|
|
100
|
-
def build = sh "rake build"
|
|
126
|
+
### Exact filename
|
|
101
127
|
|
|
102
|
-
|
|
103
|
-
|
|
128
|
+
```ruby
|
|
129
|
+
import_up "gem_tasks.loki"
|
|
130
|
+
```
|
|
104
131
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
132
|
+
Walks up from `Dir.pwd` until it finds `gem_tasks.loki`, then loads it. Returns `false` if not found anywhere.
|
|
133
|
+
|
|
134
|
+
### Glob pattern
|
|
135
|
+
|
|
136
|
+
```ruby
|
|
137
|
+
import_up "*.loki"
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Walks up from `Dir.pwd` and stops at the **first ancestor directory** that contains any `*.loki` files, loading all of them. It does not aggregate matches from multiple levels — it loads only the nearest match, then stops.
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
~/sandbox/
|
|
144
|
+
gem_tasks.loki ← loaded by import_up("*.loki") from ~/sandbox/myproject/sub/
|
|
145
|
+
ci_tasks.loki ← also loaded — same directory as the first match
|
|
146
|
+
myproject/
|
|
147
|
+
.loki
|
|
148
|
+
sub/
|
|
149
|
+
# Dir.pwd here; import_up("*.loki") finds ~/sandbox/*.loki files
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Return value
|
|
153
|
+
|
|
154
|
+
Returns `true` if any file was newly loaded, `false` if the file was not found or was already loaded.
|
|
155
|
+
|
|
156
|
+
### Conditional load
|
|
157
|
+
|
|
158
|
+
Since `import_up` returns `false` when a file is not found (rather than raising), it composes naturally with `||`:
|
|
110
159
|
|
|
111
|
-
|
|
160
|
+
```ruby
|
|
161
|
+
import_up("project_tasks.loki") || import_up("gem_tasks.loki")
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Idempotency
|
|
167
|
+
|
|
168
|
+
Both `import` and `import_up` track loaded files in Ruby's `$LOADED_FEATURES`. A second call with the same path is a no-op and returns `false`. This means:
|
|
169
|
+
|
|
170
|
+
- You can call `import "*.loki"` from both `.loki` and a shared task file without double-loading.
|
|
171
|
+
- `import_up("gem_tasks.loki")` from two different projects in the same process each load their nearest match once.
|
|
172
|
+
- Swapping `require` for `import` in a `.loki` file gives the same once-per-process guarantee.
|
|
112
173
|
|
|
113
174
|
---
|
|
114
175
|
|
|
115
|
-
##
|
|
176
|
+
## Verbose and Debug Feedback
|
|
116
177
|
|
|
117
|
-
|
|
178
|
+
`import` and `import_up` emit diagnostic messages to stderr when the `verbose?` or `debug?` flags are active (set via `--verbose` or `--debug` on the CLI, or by setting `$VERBOSE`/`$DEBUG` directly):
|
|
179
|
+
|
|
180
|
+
| Flag | `import` output | `import_up` output |
|
|
181
|
+
|---|---|---|
|
|
182
|
+
| `--verbose` | Prints each file path as it is loaded | Prints `name → /full/path` when found |
|
|
183
|
+
| `--debug` | Same as verbose, plus prints a skip message for already-loaded files | Same as verbose, plus prints `name not found` when the search comes up empty |
|
|
118
184
|
|
|
119
185
|
```
|
|
120
|
-
|
|
121
|
-
|
|
186
|
+
$ asgard --verbose build
|
|
187
|
+
import: /home/user/myproject/build.loki
|
|
188
|
+
import: /home/user/myproject/test.loki
|
|
122
189
|
```
|
|
123
190
|
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Loading Patterns
|
|
194
|
+
|
|
195
|
+
### Single-file project
|
|
196
|
+
|
|
197
|
+
All tasks in `.loki`, nothing else:
|
|
198
|
+
|
|
124
199
|
```ruby
|
|
125
200
|
# .loki
|
|
126
201
|
class Tasks
|
|
127
|
-
|
|
202
|
+
@@app ||= "myapp".freeze
|
|
128
203
|
|
|
129
|
-
desc "
|
|
204
|
+
desc "Compile the project"
|
|
130
205
|
def build = sh "rake build"
|
|
131
206
|
|
|
132
|
-
desc "
|
|
207
|
+
desc "Run the test suite"
|
|
133
208
|
def test = sh "rake test"
|
|
134
209
|
|
|
135
|
-
desc "
|
|
136
|
-
def release = sh "gem push pkg/#{app}-*.gem"
|
|
210
|
+
desc "Build and push the gem"
|
|
211
|
+
def release = sh "gem push pkg/#{@@app}-*.gem"
|
|
137
212
|
end
|
|
138
213
|
```
|
|
139
214
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
## Multi-File Layout
|
|
215
|
+
### Multi-file project
|
|
143
216
|
|
|
144
|
-
Split tasks across files by concern
|
|
217
|
+
Split tasks across files by concern. Load them all from `.loki` with a glob:
|
|
145
218
|
|
|
146
219
|
```
|
|
147
220
|
myproject/
|
|
148
|
-
.loki ← entry point
|
|
149
|
-
build.loki ← build
|
|
150
|
-
deploy.loki ←
|
|
221
|
+
.loki ← entry point; imports siblings
|
|
222
|
+
build.loki ← build tasks
|
|
223
|
+
deploy.loki ← deploy tasks
|
|
151
224
|
test.loki ← test tasks
|
|
152
225
|
```
|
|
153
226
|
|
|
227
|
+
```ruby
|
|
228
|
+
# .loki
|
|
229
|
+
import "*.loki"
|
|
230
|
+
```
|
|
231
|
+
|
|
154
232
|
```ruby
|
|
155
233
|
# build.loki
|
|
156
234
|
class Tasks
|
|
157
|
-
desc "
|
|
235
|
+
desc "Compile the project"
|
|
158
236
|
def build = sh "rake build"
|
|
159
237
|
end
|
|
160
238
|
```
|
|
@@ -163,7 +241,7 @@ end
|
|
|
163
241
|
# test.loki
|
|
164
242
|
class Tasks
|
|
165
243
|
depends_on :build
|
|
166
|
-
desc "
|
|
244
|
+
desc "Run the test suite"
|
|
167
245
|
def test = sh "bundle exec rake test"
|
|
168
246
|
end
|
|
169
247
|
```
|
|
@@ -172,83 +250,158 @@ end
|
|
|
172
250
|
# deploy.loki
|
|
173
251
|
class Tasks
|
|
174
252
|
depends_on :test
|
|
175
|
-
desc "
|
|
253
|
+
desc "Deploy to production"
|
|
176
254
|
def deploy = sh "cap production deploy"
|
|
177
255
|
end
|
|
178
256
|
```
|
|
179
257
|
|
|
180
|
-
|
|
181
|
-
# .loki — can be empty, or can register subcommands, add top-level vars, etc.
|
|
182
|
-
```
|
|
258
|
+
Files loaded via glob are sorted alphabetically by `Dir.glob`, so `build.loki` loads before `test.loki`. Tasks defined in earlier files are available to later files via `depends_on`.
|
|
183
259
|
|
|
184
|
-
|
|
260
|
+
### Controlled load order
|
|
185
261
|
|
|
186
|
-
|
|
187
|
-
When `--auto-load` is used, `*.loki` files are sorted alphabetically, so `build.loki` loads before `test.loki`, which means `depends_on :build` in `test.loki` correctly references a task that already exists.
|
|
262
|
+
When alphabetical order does not match your dependency order, import explicitly:
|
|
188
263
|
|
|
189
|
-
|
|
264
|
+
```ruby
|
|
265
|
+
# .loki
|
|
266
|
+
import "infra.loki" # must be first
|
|
267
|
+
import "build.loki" # depends on infra
|
|
268
|
+
import "deploy.loki" # depends on build
|
|
269
|
+
```
|
|
190
270
|
|
|
191
|
-
|
|
271
|
+
### Shared task library in a monorepo
|
|
192
272
|
|
|
193
|
-
|
|
273
|
+
Place shared tasks in a parent directory and load them from any sub-project:
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
~/sandbox/
|
|
277
|
+
gem_tasks.loki ← shared: build, install, release tasks for any gem
|
|
278
|
+
myproject/
|
|
279
|
+
.loki ← loads gem_tasks.loki via import_up
|
|
280
|
+
other_project/
|
|
281
|
+
.loki ← also loads gem_tasks.loki via import_up
|
|
282
|
+
```
|
|
194
283
|
|
|
195
284
|
```ruby
|
|
196
|
-
#
|
|
197
|
-
|
|
198
|
-
require_relative "ci.loki"
|
|
285
|
+
# myproject/.loki
|
|
286
|
+
import_up "gem_tasks.loki" # finds ~/sandbox/gem_tasks.loki
|
|
199
287
|
|
|
200
288
|
class Tasks
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
desc "full-ci", "Complete CI run"
|
|
204
|
-
def full_ci = sh "echo 'full CI complete'"
|
|
289
|
+
# project-specific overrides here
|
|
205
290
|
end
|
|
206
291
|
```
|
|
207
292
|
|
|
208
|
-
|
|
293
|
+
### Conditional shared library
|
|
209
294
|
|
|
210
|
-
|
|
211
|
-
|
|
295
|
+
```ruby
|
|
296
|
+
# .loki
|
|
297
|
+
import_up("ci_tasks.loki") || import_up("gem_tasks.loki")
|
|
298
|
+
```
|
|
212
299
|
|
|
213
|
-
|
|
300
|
+
Loads `ci_tasks.loki` if found up the tree, otherwise falls back to `gem_tasks.loki`.
|
|
214
301
|
|
|
215
|
-
|
|
302
|
+
### Subcommand classes across files
|
|
216
303
|
|
|
217
|
-
|
|
304
|
+
Define subcommand classes in separate files and register them in `.loki`:
|
|
218
305
|
|
|
219
306
|
```
|
|
220
307
|
myproject/
|
|
221
|
-
.loki
|
|
222
|
-
|
|
223
|
-
|
|
308
|
+
.loki
|
|
309
|
+
db.loki
|
|
310
|
+
server.loki
|
|
224
311
|
```
|
|
225
312
|
|
|
226
313
|
```ruby
|
|
227
|
-
#
|
|
314
|
+
# db.loki
|
|
228
315
|
class DBCommands < Tasks
|
|
229
|
-
desc "
|
|
316
|
+
desc "Run migrations"
|
|
230
317
|
def migrate = sh "rails db:migrate"
|
|
231
318
|
end
|
|
319
|
+
```
|
|
232
320
|
|
|
233
|
-
|
|
321
|
+
```ruby
|
|
322
|
+
# server.loki
|
|
234
323
|
class ServerCommands < Tasks
|
|
235
|
-
desc "
|
|
324
|
+
desc "Start the server"
|
|
236
325
|
def start = sh "rails server"
|
|
237
326
|
end
|
|
327
|
+
```
|
|
238
328
|
|
|
329
|
+
```ruby
|
|
239
330
|
# .loki
|
|
331
|
+
import "*.loki" # db.loki and server.loki load first
|
|
332
|
+
|
|
240
333
|
class Tasks
|
|
241
334
|
desc "db SUBCOMMAND", "Manage the database"; subcommand "db", DBCommands
|
|
242
335
|
desc "server SUBCOMMAND", "Manage the server"; subcommand "server", ServerCommands
|
|
243
336
|
end
|
|
244
337
|
```
|
|
245
338
|
|
|
339
|
+
Subcommand classes are available in `.loki` because siblings loaded via `import "*.loki"` execute before `.loki`'s own class body.
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
## Task Name Overloading
|
|
344
|
+
|
|
345
|
+
Because all `*.loki` files reopen the same `class Tasks`, two files can define a method with the same name. Ruby's class reopening semantics apply: the last definition loaded wins, silently replacing the earlier one.
|
|
346
|
+
|
|
347
|
+
Three things are overwritten when a task name is reused:
|
|
348
|
+
|
|
349
|
+
| What | Effect |
|
|
350
|
+
|---|---|
|
|
351
|
+
| `def method_name` | The Ruby method body — the earlier implementation is gone |
|
|
352
|
+
| `desc` metadata | Thor registers the new usage/description string, discarding the old one |
|
|
353
|
+
| `depends_on` stages | `method_added` captures the pending deps for the new definition; the earlier dep chain is replaced |
|
|
354
|
+
|
|
355
|
+
**Accidental overloading** is a silent bug. Keep task names unique across files.
|
|
356
|
+
|
|
357
|
+
!!! warning
|
|
358
|
+
There is no runtime error when a task is overloaded. If a task is not behaving as expected, check whether another `.loki` file defines the same method name and loads after it.
|
|
359
|
+
|
|
360
|
+
**Intentional overloading** lets you extend a task defined in an earlier file using `alias_method`:
|
|
361
|
+
|
|
362
|
+
```ruby
|
|
363
|
+
# build.loki (loaded first)
|
|
364
|
+
class Tasks
|
|
365
|
+
desc "Compile the project"
|
|
366
|
+
def build = sh "rake build"
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
# postbuild.loki (loaded after build.loki, alphabetically)
|
|
370
|
+
class Tasks
|
|
371
|
+
no_commands { alias_method :_build_original, :build }
|
|
372
|
+
|
|
373
|
+
desc "Compile the project and copy assets"
|
|
374
|
+
def build
|
|
375
|
+
_build_original
|
|
376
|
+
sh "cp -r dist/ public/"
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
!!! warning "Prefer `depends_on` over intentional overloading"
|
|
382
|
+
Using `alias_method` to bolt post-task behaviour onto an existing task is fragile and load-order dependent. The idiomatic alternative is `depends_on`:
|
|
383
|
+
|
|
384
|
+
```ruby
|
|
385
|
+
class Tasks
|
|
386
|
+
desc "Compile the project"
|
|
387
|
+
def build = sh "rake build"
|
|
388
|
+
|
|
389
|
+
desc "Copy build output to public/"
|
|
390
|
+
def copy_assets = sh "cp -r dist/ public/"
|
|
391
|
+
|
|
392
|
+
depends_on :build, :copy_assets
|
|
393
|
+
desc "Compile and copy assets"
|
|
394
|
+
def build_all; end
|
|
395
|
+
end
|
|
396
|
+
```
|
|
397
|
+
|
|
246
398
|
---
|
|
247
399
|
|
|
248
400
|
## Summary of Loading Rules
|
|
249
401
|
|
|
250
|
-
|
|
|
251
|
-
|
|
252
|
-
|
|
|
253
|
-
|
|
|
254
|
-
| `
|
|
402
|
+
| Method | Finds? | Loads? | Glob? | Ancestor search? |
|
|
403
|
+
|---|---|---|---|---|
|
|
404
|
+
| `loki_up(name)` | Yes | No | No | Yes |
|
|
405
|
+
| `import(path)` | No | Yes | Yes | No |
|
|
406
|
+
| `import_up(name)` | Yes | Yes | Yes | Yes |
|
|
407
|
+
| Asgard's `run!` | Yes | `.loki` only | No | Yes |
|
data/docs/tasks.md
CHANGED
|
@@ -10,12 +10,12 @@ A task with no parameters and no options:
|
|
|
10
10
|
|
|
11
11
|
```ruby
|
|
12
12
|
class Tasks
|
|
13
|
-
desc "
|
|
14
|
-
def hello =
|
|
13
|
+
desc "Say hello"
|
|
14
|
+
def hello = puts "Hello, World!"
|
|
15
15
|
end
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
`desc`
|
|
18
|
+
`desc` accepts either one or two strings. With one argument, the description is shown in `asgard help` and the usage string defaults to the method name. Pass two arguments when the usage string needs to document parameters — `desc "greet NAME", "Greet NAME by name"`.
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
asgard hello
|
|
@@ -31,7 +31,7 @@ Positional parameters are declared directly in the method signature. Document th
|
|
|
31
31
|
class Tasks
|
|
32
32
|
desc "greet NAME", "Greet NAME; omit NAME to greet the world"
|
|
33
33
|
def greet(name = "World")
|
|
34
|
-
|
|
34
|
+
puts "Hello, #{name}!"
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
```
|
|
@@ -51,7 +51,7 @@ Use `method_option` (alias: `option`) for named flags. Access them inside the me
|
|
|
51
51
|
|
|
52
52
|
```ruby
|
|
53
53
|
class Tasks
|
|
54
|
-
desc "
|
|
54
|
+
desc "Compile the project"
|
|
55
55
|
option :output, aliases: "-o", type: :string, default: "dist/", desc: "Output directory"
|
|
56
56
|
option :verbose, aliases: "-v", type: :boolean, default: false, desc: "Enable verbose output"
|
|
57
57
|
option :jobs, aliases: "-j", type: :numeric, default: 1, desc: "Number of parallel jobs"
|
|
@@ -117,7 +117,7 @@ asgard deploy production --strategy blue-green
|
|
|
117
117
|
|
|
118
118
|
```ruby
|
|
119
119
|
class Tasks
|
|
120
|
-
desc "
|
|
120
|
+
desc "Build the project"
|
|
121
121
|
option :env,
|
|
122
122
|
type: :string,
|
|
123
123
|
default: "development",
|
|
@@ -139,7 +139,7 @@ Thor validates the value against the enum and shows a helpful error if it doesn'
|
|
|
139
139
|
|
|
140
140
|
```ruby
|
|
141
141
|
class Tasks
|
|
142
|
-
desc "
|
|
142
|
+
desc "Wait for a service to become available"
|
|
143
143
|
option :timeout, type: :numeric, default: 30, banner: "SECONDS", desc: "Give up after SECONDS"
|
|
144
144
|
def wait
|
|
145
145
|
sh "wait-for-it --timeout #{options[:timeout]}"
|
|
@@ -169,7 +169,7 @@ class Tasks
|
|
|
169
169
|
asgard report --format json --output report.json\x5
|
|
170
170
|
asgard report --format text
|
|
171
171
|
DESC
|
|
172
|
-
desc "
|
|
172
|
+
desc "Generate a project report"
|
|
173
173
|
option :format, type: :string, default: "text", enum: %w[text html json], desc: "Output format"
|
|
174
174
|
option :since, type: :string, banner: "DATE", desc: "Limit to changes after DATE"
|
|
175
175
|
def report
|
|
@@ -191,7 +191,7 @@ end
|
|
|
191
191
|
class Tasks
|
|
192
192
|
default_task :greet
|
|
193
193
|
|
|
194
|
-
desc "
|
|
194
|
+
desc "Say hello (runs by default)"
|
|
195
195
|
def greet
|
|
196
196
|
puts "Hello from Asgard!"
|
|
197
197
|
end
|
|
@@ -202,6 +202,8 @@ end
|
|
|
202
202
|
asgard # same as: asgard greet
|
|
203
203
|
```
|
|
204
204
|
|
|
205
|
+
Without `default_task`, running `asgard` with no arguments displays the help message.
|
|
206
|
+
|
|
205
207
|
---
|
|
206
208
|
|
|
207
209
|
## Command Aliases
|
|
@@ -215,13 +217,13 @@ class Tasks
|
|
|
215
217
|
map "t" => "test"
|
|
216
218
|
map "b" => "build"
|
|
217
219
|
|
|
218
|
-
desc "
|
|
220
|
+
desc "Print the version"
|
|
219
221
|
def version = puts Asgard::VERSION
|
|
220
222
|
|
|
221
|
-
desc "
|
|
223
|
+
desc "Run tests"
|
|
222
224
|
def test = sh "bundle exec rake test"
|
|
223
225
|
|
|
224
|
-
desc "
|
|
226
|
+
desc "Build the gem"
|
|
225
227
|
def build = sh "bundle exec rake build"
|
|
226
228
|
end
|
|
227
229
|
```
|
|
@@ -249,14 +251,14 @@ class Tasks
|
|
|
249
251
|
desc: "Name to greet"
|
|
250
252
|
|
|
251
253
|
desc "hello NAME", "Say hello to NAME"
|
|
252
|
-
def hello =
|
|
254
|
+
def hello = puts "Hello, #{name}!"
|
|
253
255
|
end
|
|
254
256
|
```
|
|
255
257
|
|
|
256
258
|
For most multi-task `.loki` files, the simpler positional default pattern is safer:
|
|
257
259
|
|
|
258
260
|
```ruby
|
|
259
|
-
def hello(name = "World") =
|
|
261
|
+
def hello(name = "World") = puts "Hello, #{name}!"
|
|
260
262
|
```
|
|
261
263
|
|
|
262
264
|
---
|
|
@@ -267,7 +269,7 @@ def hello(name = "World") = sh "echo 'Hello, #{name}!'"
|
|
|
267
269
|
|
|
268
270
|
```ruby
|
|
269
271
|
class Tasks
|
|
270
|
-
desc "
|
|
272
|
+
desc "Compile the project"
|
|
271
273
|
def build
|
|
272
274
|
puts "Revision: #{current_sha}"
|
|
273
275
|
sh "rake build"
|