@@ -18,6 +18,11 @@ Terraform-specific steps.
1818| ` vars: ` /` env: ` and ` sources: ` /` generates: ` | [ Shape C] ( #shape-c-variables-and-up-to-date-checks ) |
1919| ` includes: ` (multi-file composition) | see [ Common Problems] ( #includes-multi-file-composition ) |
2020
21+ ` deps: ` maps to command-level ` dependencies.commands ` (concurrent by default, deduped -- the
22+ direct match). ` sources: ` /` generates: ` maps to step-level ` inputs.sources ` /` artifacts.paths `
23+ (implicit ` when: checksum.changed ` -- the direct match). Neither is a gap; both need the user to
24+ add the matching field during migration, since neither carries over automatically.
25+
2126## Shape A: Simple Tasks
2227
2328** Before:**
@@ -82,28 +87,19 @@ tasks:
8287 - terraform -chdir=terraform apply -var-file=envs/dev.tfvars
8388` ` `
8489
85- This is the most important problem in this migration. Task runs `deps:` at the same time by
86- default. Atmos custom-command and workflow steps run one after another by default. This is the
87- opposite default. If you turn `deps : [test, lint]` into two plain steps that run one after
88- another, the command becomes slower. It also changes what happens when one task fails. To keep
89- Task's default behavior, put the dependency tasks inside a `parallel` step :
90+ Task runs `deps:` at the same time by default. Atmos custom-command and workflow steps run one
91+ after another by default -- so a `deps:` entry is not a step and never becomes one. It maps to
92+ the command-level `dependencies.commands` field, which resolves through the same DAG scheduler as
93+ ` parallel ` /`matrix` `needs:` and runs concurrently by default -- matching Task's `deps:` behavior
94+ directly, not working around it with a hand-built `parallel` step :
9095
9196` ` ` yaml
9297commands:
9398 - name: deploy
9499 description: Plan and apply the given environment
100+ dependencies:
101+ commands: [test, lint]
95102 steps:
96- - name: checks
97- type: parallel
98- fail:
99- mode: wait_all
100- steps:
101- - name: test
102- type: shell
103- command: atmos test
104- - name: lint
105- type: shell
106- command: atmos lint
107103 - type: atmos
108104 command: terraform apply infra -s dev
109105` ` `
@@ -113,9 +109,17 @@ task's Terraform code to `components/terraform/infra/` (the default
113109` components.terraform.base_path` is `components/terraform`), then swap `infra` for whatever the
114110user actually names the component.
115111
116- If the Taskfile's `deps:` list needs its own internal order, add `needs:` to the steps inside the
117- ` parallel` block. Do not assume the tasks should run one after another just because that is
118- Atmos's default for steps outside a `parallel` or `matrix` block.
112+ ` dependencies.commands` also matches a behavior Task itself has that a hand-rolled `parallel`
113+ step does not : if two commands both depend on the same one -- for example both `test` and `lint`
114+ depending on `build` -- Atmos runs `build` exactly once and dedups it, the same as Task's own
115+ ` deps:` graph. A `parallel` step calling `atmos build` from two different places would run it
116+ twice. If one dependency itself depends on another (`lint` depends on `build`, and `deploy`
117+ depends on `test` and `lint`), declare that directly on `lint`'s own `dependencies.commands` --
118+ the scheduler resolves the whole transitive graph itself, still deduping `build` to a single run.
119+
120+ Reach for a `parallel` step instead of `dependencies.commands` only for concurrency inside a
121+ single command's own steps, not between named commands -- for example, running several shell
122+ commands side by side that were never their own Task tasks to begin with.
119123
120124# # Shape C: Variables and Up-to-Date Checks
121125
@@ -141,19 +145,33 @@ tasks:
141145 `default : " dev" ` . Task's Sprig ` default` filter becomes the plain `default:` field.
142146- Turn `env:` into an `env:` map. The two are almost identical.
143147
144- # ## The `sources`/`generates` gap
148+ # ## `sources: `/`generates:` becomes `inputs`/`artifacts`
145149
146- Task skips a task's `cmds:` when its `sources:` files match its `generates:` outputs. It checks
147- this with a file hash. Atmos steps always run. There is no built-in check for whether a file is
148- up to date. The `require`/`assert` step type does not fix this. It only checks that a file, tool,
149- or directory exists. It does not compare hashes or timestamps.
150+ Task skips a task's `cmds:` when its `sources:` files match its `generates:` outputs, checked by
151+ default with a content hash (Task also supports `method : timestamp` for an mtime-based check).
152+ The step-level `inputs.sources` and `artifacts.paths` fields are the direct match, with the same
153+ checksum-by-default/timestamp-as-an-option choice :
150154
151- If the user depends on `sources:`/`generates:` to skip a slow step, such as code generation, tell
152- them plainly that this behavior does not carry over. Then offer two honest choices :
155+ ` ` ` yaml
156+ commands:
157+ - name: build
158+ description: Compile the deployable artifact
159+ steps:
160+ - type: shell
161+ command: go build -o bin/handler ./cmd/handler
162+ inputs:
163+ sources: ["cmd/**/*.go"]
164+ artifacts:
165+ paths: ["bin/handler"]
166+ ` ` `
153167
154- 1. Accept that the step always runs. This is correct for most fast build steps.
155- 2. Add a hash or timestamp check inside the shell step itself. This is a script the user
156- maintains. It is not a built-in Atmos feature.
168+ With no explicit `when:`, declaring `inputs`/`artifacts` on a step is enough -- it implicitly
169+ means `when : checksum.changed`, and the step is skipped when the hash of the matched source files
170+ matches the hash recorded after the last successful run. This does not carry over on its own --
171+ add `inputs`/`artifacts` to the migrated step yourself, matching the Taskfile's own
172+ ` sources:` /`generates:` lists. The `require`/`assert` step type is a different, older step type --
173+ it only checks that a file, tool, or directory exists, not whether it is fresh, so it does not
174+ replace `inputs`/`artifacts`.
157175
158176# # Common Problems
159177
@@ -173,17 +191,20 @@ Pick the one that fits the content being split:
173191 " stacks/workflows" ` ) the first time the user's migration reaches a workflow, or ` atmos
174192 workflow <name>` fails with `'workflows.base_path' must be configured in 'atmos.yaml'`.
175193
176- # ## `sources`/`generates` has no built-in match
194+ # ## `sources`/`generates` maps to a different field than `steps`
177195
178- See [Shape C](#the-sourcesgenerates-gap) above. This is the largest real gap in this migration.
179- State it directly. Do not gloss over it.
196+ See [Shape C](#sourcesgenerates-becomes-inputsartifacts) above. It does not carry over
197+ automatically -- the user must add `inputs`/`artifacts` to the migrated step themselves. State
198+ that directly. Do not gloss over it, and do not claim it "just works" without the field.
180199
181200# # What Not To Do
182201
183- - Do not drop `sources:`/`generates:` caching without comment. State the change directly. Let
184- the user decide how, or whether, to replace it.
185- - Do not turn `deps:` into plain sequential steps without warning the user about the change in
186- default concurrency.
202+ - Do not drop `sources:`/`generates:` without adding the matching `inputs`/`artifacts` fields to
203+ the migrated step. It is a direct match, not a gap, but it does not carry over on its own.
204+ - Do not turn `deps:` into plain sequential steps, or into a hand-built `parallel` step, without
205+ first considering command-level `dependencies.commands` -- it is the direct match : concurrent
206+ by default, and it dedups a dependency shared by more than one command the same way Task's own
207+ ` deps:` graph does.
187208- Do not describe `require`/`assert` as a freshness or caching check. It only checks that
188209 something exists.
189210- Do not turn every `internal : true` task into its own discoverable command by default. If it is
0 commit comments