tasktree 0.0.2__tar.gz → 0.0.3__tar.gz

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.
Files changed (40) hide show
  1. {tasktree-0.0.2 → tasktree-0.0.3}/.github/workflows/test.yml +1 -1
  2. {tasktree-0.0.2 → tasktree-0.0.3}/PKG-INFO +148 -12
  3. {tasktree-0.0.2 → tasktree-0.0.3}/README.md +147 -11
  4. {tasktree-0.0.2 → tasktree-0.0.3}/pyproject.toml +1 -1
  5. tasktree-0.0.3/requirements/future/docker-task-environments.md +1002 -0
  6. tasktree-0.0.3/requirements/future/shell-environment-requirements.md +392 -0
  7. {tasktree-0.0.2 → tasktree-0.0.3}/src/tasktree/cli.py +35 -89
  8. {tasktree-0.0.2 → tasktree-0.0.3}/src/tasktree/executor.py +202 -16
  9. {tasktree-0.0.2 → tasktree-0.0.3}/src/tasktree/hasher.py +4 -1
  10. {tasktree-0.0.2 → tasktree-0.0.3}/src/tasktree/parser.py +108 -5
  11. {tasktree-0.0.2 → tasktree-0.0.3}/tests/integration/test_cli_options.py +149 -1
  12. {tasktree-0.0.2 → tasktree-0.0.3}/tests/integration/test_dependency_execution.py +4 -4
  13. {tasktree-0.0.2 → tasktree-0.0.3}/tests/integration/test_missing_outputs.py +7 -7
  14. {tasktree-0.0.2 → tasktree-0.0.3}/tests/integration/test_working_directory.py +1 -1
  15. {tasktree-0.0.2 → tasktree-0.0.3}/tests/unit/test_executor.py +375 -5
  16. {tasktree-0.0.2 → tasktree-0.0.3}/tests/unit/test_parser.py +90 -0
  17. {tasktree-0.0.2 → tasktree-0.0.3}/.github/workflows/release.yml +0 -0
  18. {tasktree-0.0.2 → tasktree-0.0.3}/.gitignore +0 -0
  19. {tasktree-0.0.2 → tasktree-0.0.3}/CLAUDE.md +0 -0
  20. {tasktree-0.0.2 → tasktree-0.0.3}/example/source.txt +0 -0
  21. {tasktree-0.0.2 → tasktree-0.0.3}/example/tasktree.yaml +0 -0
  22. {tasktree-0.0.2 → tasktree-0.0.3}/src/__init__.py +0 -0
  23. {tasktree-0.0.2 → tasktree-0.0.3}/src/tasktree/__init__.py +0 -0
  24. {tasktree-0.0.2 → tasktree-0.0.3}/src/tasktree/graph.py +0 -0
  25. {tasktree-0.0.2 → tasktree-0.0.3}/src/tasktree/state.py +0 -0
  26. {tasktree-0.0.2 → tasktree-0.0.3}/src/tasktree/tasks.py +0 -0
  27. {tasktree-0.0.2 → tasktree-0.0.3}/src/tasktree/types.py +0 -0
  28. {tasktree-0.0.2 → tasktree-0.0.3}/tasktree.yaml +0 -0
  29. {tasktree-0.0.2 → tasktree-0.0.3}/tests/integration/test_clean_state.py +0 -0
  30. {tasktree-0.0.2 → tasktree-0.0.3}/tests/integration/test_end_to_end.py +0 -0
  31. {tasktree-0.0.2 → tasktree-0.0.3}/tests/integration/test_input_detection.py +0 -0
  32. {tasktree-0.0.2 → tasktree-0.0.3}/tests/integration/test_nested_imports.py +0 -0
  33. {tasktree-0.0.2 → tasktree-0.0.3}/tests/integration/test_state_persistence.py +0 -0
  34. {tasktree-0.0.2 → tasktree-0.0.3}/tests/unit/test_cli.py +0 -0
  35. {tasktree-0.0.2 → tasktree-0.0.3}/tests/unit/test_graph.py +0 -0
  36. {tasktree-0.0.2 → tasktree-0.0.3}/tests/unit/test_hasher.py +0 -0
  37. {tasktree-0.0.2 → tasktree-0.0.3}/tests/unit/test_state.py +0 -0
  38. {tasktree-0.0.2 → tasktree-0.0.3}/tests/unit/test_tasks.py +0 -0
  39. {tasktree-0.0.2 → tasktree-0.0.3}/tests/unit/test_types.py +0 -0
  40. {tasktree-0.0.2 → tasktree-0.0.3}/uv.lock +0 -0
@@ -12,7 +12,7 @@ jobs:
12
12
  strategy:
13
13
  fail-fast: false
14
14
  matrix:
15
- os: [ubuntu-latest, macos-latest, windows-latest]
15
+ os: [ubuntu-latest, macos-latest]
16
16
  python-version: ['3.11', '3.12']
17
17
 
18
18
  steps:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tasktree
3
- Version: 0.0.2
3
+ Version: 0.0.3
4
4
  Summary: A task automation tool with incremental execution
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: click>=8.1.0
@@ -72,11 +72,12 @@ tt --list # Show all available tasks
72
72
 
73
73
  Task Tree only runs tasks when necessary. A task executes if:
74
74
 
75
- - Its definition (command, outputs, working directory) has changed
75
+ - Its definition (command, outputs, working directory, environment) has changed
76
76
  - Any input files have changed since the last run
77
77
  - Any dependencies have re-run
78
78
  - It has never been executed before
79
79
  - It has no inputs or outputs (always runs)
80
+ - The execution environment has changed (CLI override or environment config change)
80
81
 
81
82
  ### Automatic Input Inheritance
82
83
 
@@ -105,17 +106,25 @@ All state lives in `.tasktree-state` at your project root. Stale entries are aut
105
106
  ```yaml
106
107
  task-name:
107
108
  desc: Human-readable description (optional)
108
- deps: [other-task] # Task dependencies
109
- inputs: [src/**/*.go] # Explicit input files (glob patterns)
110
- outputs: [dist/binary] # Output files (glob patterns)
111
- working_dir: subproject/ # Execution directory (default: project root)
112
- args: [param1, param2:path=default] # Task parameters
113
- cmd: go build -o dist/binary # Command to execute
109
+ deps: [other-task] # Task dependencies
110
+ inputs: [src/**/*.go] # Explicit input files (glob patterns)
111
+ outputs: [dist/binary] # Output files (glob patterns)
112
+ working_dir: subproject/ # Execution directory (default: project root)
113
+ env: bash-strict # Execution environment (optional)
114
+ args: [param1, param2:path=default] # Task parameters
115
+ cmd: go build -o dist/binary # Command to execute
114
116
  ```
115
117
 
116
118
  ### Commands
117
119
 
118
- Multi-line commands using YAML literal blocks:
120
+ **Single-line commands** are executed directly via the configured shell:
121
+
122
+ ```yaml
123
+ build:
124
+ cmd: cargo build --release
125
+ ```
126
+
127
+ **Multi-line commands** are written to temporary script files for proper execution:
119
128
 
120
129
  ```yaml
121
130
  deploy:
@@ -125,7 +134,9 @@ deploy:
125
134
  rsync -av dist/ server:/opt/app/
126
135
  ```
127
136
 
128
- Or folded blocks for long single-line commands:
137
+ Multi-line commands preserve shell syntax (line continuations, heredocs, etc.) and support shebangs on Unix/macOS.
138
+
139
+ Or use folded blocks for long single-line commands:
129
140
 
130
141
  ```yaml
131
142
  compile:
@@ -136,6 +147,58 @@ compile:
136
147
  -L lib -lm
137
148
  ```
138
149
 
150
+ ### Execution Environments
151
+
152
+ Configure custom shell environments for task execution:
153
+
154
+ ```yaml
155
+ environments:
156
+ default: bash-strict
157
+
158
+ bash-strict:
159
+ shell: bash
160
+ args: ['-c'] # For single-line: bash -c "command"
161
+ preamble: | # For multi-line: prepended to script
162
+ set -euo pipefail
163
+
164
+ python:
165
+ shell: python
166
+ args: ['-c']
167
+
168
+ powershell:
169
+ shell: powershell
170
+ args: ['-ExecutionPolicy', 'Bypass', '-Command']
171
+ preamble: |
172
+ $ErrorActionPreference = 'Stop'
173
+
174
+ tasks:
175
+ build:
176
+ # Uses 'default' environment (bash-strict)
177
+ cmd: cargo build --release
178
+
179
+ analyze:
180
+ env: python
181
+ cmd: |
182
+ import sys
183
+ print(f"Analyzing with Python {sys.version}")
184
+ # ... analysis code ...
185
+
186
+ windows-task:
187
+ env: powershell
188
+ cmd: |
189
+ Compress-Archive -Path dist/* -DestinationPath package.zip
190
+ ```
191
+
192
+ **Environment resolution priority:**
193
+ 1. CLI override: `tt --env python build`
194
+ 2. Task's `env` field
195
+ 3. Recipe's `default` environment
196
+ 4. Platform default (bash on Unix, cmd on Windows)
197
+
198
+ **Platform defaults** when no environments are configured:
199
+ - **Unix/macOS**: bash with `-c` args
200
+ - **Windows**: cmd with `/c` args
201
+
139
202
  ### Parameterised Tasks
140
203
 
141
204
  Tasks can accept arguments with optional defaults:
@@ -202,12 +265,19 @@ Input and output patterns support standard glob syntax:
202
265
 
203
266
  ### How State Works
204
267
 
205
- Each task is identified by a hash of its definition (command, outputs, working directory). State tracks:
268
+ Each task is identified by a hash of its definition. The hash includes:
206
269
 
270
+ - Command to execute
271
+ - Output patterns
272
+ - Working directory
273
+ - Argument definitions
274
+ - Execution environment
275
+
276
+ State tracks:
207
277
  - When the task last ran
208
278
  - Timestamps of input files at that time
209
279
 
210
- Tasks are re-run when their definition changes or inputs are newer than the last run.
280
+ Tasks are re-run when their definition changes, inputs are newer than the last run, or the environment changes.
211
281
 
212
282
  ### What's Not In The Hash
213
283
 
@@ -222,6 +292,72 @@ Changes to these don't invalidate cached state:
222
292
 
223
293
  At the start of each invocation, state is checked for invalid task hashes and non-existent ones are automatically removed. Delete a task from your recipe file and its state disappears the next time you run `tt <cmd>`
224
294
 
295
+ ## Command-Line Options
296
+
297
+ Task Tree provides several command-line options for controlling task execution:
298
+
299
+ ### Execution Control
300
+
301
+ ```bash
302
+ # Force re-run (ignore freshness checks)
303
+ tt --force build
304
+ tt -f build
305
+
306
+ # Run only the specified task, skip dependencies (implies --force)
307
+ tt --only deploy
308
+ tt -o deploy
309
+
310
+ # Override environment for all tasks
311
+ tt --env python analyze
312
+ tt -e powershell build
313
+ ```
314
+
315
+ ### Information Commands
316
+
317
+ ```bash
318
+ # List all available tasks
319
+ tt --list
320
+ tt -l
321
+
322
+ # Show detailed task definition
323
+ tt --show build
324
+
325
+ # Show dependency tree (without execution)
326
+ tt --tree deploy
327
+
328
+ # Show version
329
+ tt --version
330
+ tt -v
331
+
332
+ # Create a blank recipe file
333
+ tt --init
334
+ ```
335
+
336
+ ### State Management
337
+
338
+ ```bash
339
+ # Remove state file (reset task cache)
340
+ tt --clean
341
+ tt --clean-state
342
+ tt --reset
343
+ ```
344
+
345
+ ### Common Workflows
346
+
347
+ ```bash
348
+ # Fresh build of everything
349
+ tt --force build
350
+
351
+ # Run a task without rebuilding dependencies
352
+ tt --only test
353
+
354
+ # Test with a different shell/environment
355
+ tt --env python test
356
+
357
+ # Force rebuild and deploy
358
+ tt --force deploy production
359
+ ```
360
+
225
361
  ## Example: Full Build Pipeline
226
362
 
227
363
  ```yaml
@@ -58,11 +58,12 @@ tt --list # Show all available tasks
58
58
 
59
59
  Task Tree only runs tasks when necessary. A task executes if:
60
60
 
61
- - Its definition (command, outputs, working directory) has changed
61
+ - Its definition (command, outputs, working directory, environment) has changed
62
62
  - Any input files have changed since the last run
63
63
  - Any dependencies have re-run
64
64
  - It has never been executed before
65
65
  - It has no inputs or outputs (always runs)
66
+ - The execution environment has changed (CLI override or environment config change)
66
67
 
67
68
  ### Automatic Input Inheritance
68
69
 
@@ -91,17 +92,25 @@ All state lives in `.tasktree-state` at your project root. Stale entries are aut
91
92
  ```yaml
92
93
  task-name:
93
94
  desc: Human-readable description (optional)
94
- deps: [other-task] # Task dependencies
95
- inputs: [src/**/*.go] # Explicit input files (glob patterns)
96
- outputs: [dist/binary] # Output files (glob patterns)
97
- working_dir: subproject/ # Execution directory (default: project root)
98
- args: [param1, param2:path=default] # Task parameters
99
- cmd: go build -o dist/binary # Command to execute
95
+ deps: [other-task] # Task dependencies
96
+ inputs: [src/**/*.go] # Explicit input files (glob patterns)
97
+ outputs: [dist/binary] # Output files (glob patterns)
98
+ working_dir: subproject/ # Execution directory (default: project root)
99
+ env: bash-strict # Execution environment (optional)
100
+ args: [param1, param2:path=default] # Task parameters
101
+ cmd: go build -o dist/binary # Command to execute
100
102
  ```
101
103
 
102
104
  ### Commands
103
105
 
104
- Multi-line commands using YAML literal blocks:
106
+ **Single-line commands** are executed directly via the configured shell:
107
+
108
+ ```yaml
109
+ build:
110
+ cmd: cargo build --release
111
+ ```
112
+
113
+ **Multi-line commands** are written to temporary script files for proper execution:
105
114
 
106
115
  ```yaml
107
116
  deploy:
@@ -111,7 +120,9 @@ deploy:
111
120
  rsync -av dist/ server:/opt/app/
112
121
  ```
113
122
 
114
- Or folded blocks for long single-line commands:
123
+ Multi-line commands preserve shell syntax (line continuations, heredocs, etc.) and support shebangs on Unix/macOS.
124
+
125
+ Or use folded blocks for long single-line commands:
115
126
 
116
127
  ```yaml
117
128
  compile:
@@ -122,6 +133,58 @@ compile:
122
133
  -L lib -lm
123
134
  ```
124
135
 
136
+ ### Execution Environments
137
+
138
+ Configure custom shell environments for task execution:
139
+
140
+ ```yaml
141
+ environments:
142
+ default: bash-strict
143
+
144
+ bash-strict:
145
+ shell: bash
146
+ args: ['-c'] # For single-line: bash -c "command"
147
+ preamble: | # For multi-line: prepended to script
148
+ set -euo pipefail
149
+
150
+ python:
151
+ shell: python
152
+ args: ['-c']
153
+
154
+ powershell:
155
+ shell: powershell
156
+ args: ['-ExecutionPolicy', 'Bypass', '-Command']
157
+ preamble: |
158
+ $ErrorActionPreference = 'Stop'
159
+
160
+ tasks:
161
+ build:
162
+ # Uses 'default' environment (bash-strict)
163
+ cmd: cargo build --release
164
+
165
+ analyze:
166
+ env: python
167
+ cmd: |
168
+ import sys
169
+ print(f"Analyzing with Python {sys.version}")
170
+ # ... analysis code ...
171
+
172
+ windows-task:
173
+ env: powershell
174
+ cmd: |
175
+ Compress-Archive -Path dist/* -DestinationPath package.zip
176
+ ```
177
+
178
+ **Environment resolution priority:**
179
+ 1. CLI override: `tt --env python build`
180
+ 2. Task's `env` field
181
+ 3. Recipe's `default` environment
182
+ 4. Platform default (bash on Unix, cmd on Windows)
183
+
184
+ **Platform defaults** when no environments are configured:
185
+ - **Unix/macOS**: bash with `-c` args
186
+ - **Windows**: cmd with `/c` args
187
+
125
188
  ### Parameterised Tasks
126
189
 
127
190
  Tasks can accept arguments with optional defaults:
@@ -188,12 +251,19 @@ Input and output patterns support standard glob syntax:
188
251
 
189
252
  ### How State Works
190
253
 
191
- Each task is identified by a hash of its definition (command, outputs, working directory). State tracks:
254
+ Each task is identified by a hash of its definition. The hash includes:
192
255
 
256
+ - Command to execute
257
+ - Output patterns
258
+ - Working directory
259
+ - Argument definitions
260
+ - Execution environment
261
+
262
+ State tracks:
193
263
  - When the task last ran
194
264
  - Timestamps of input files at that time
195
265
 
196
- Tasks are re-run when their definition changes or inputs are newer than the last run.
266
+ Tasks are re-run when their definition changes, inputs are newer than the last run, or the environment changes.
197
267
 
198
268
  ### What's Not In The Hash
199
269
 
@@ -208,6 +278,72 @@ Changes to these don't invalidate cached state:
208
278
 
209
279
  At the start of each invocation, state is checked for invalid task hashes and non-existent ones are automatically removed. Delete a task from your recipe file and its state disappears the next time you run `tt <cmd>`
210
280
 
281
+ ## Command-Line Options
282
+
283
+ Task Tree provides several command-line options for controlling task execution:
284
+
285
+ ### Execution Control
286
+
287
+ ```bash
288
+ # Force re-run (ignore freshness checks)
289
+ tt --force build
290
+ tt -f build
291
+
292
+ # Run only the specified task, skip dependencies (implies --force)
293
+ tt --only deploy
294
+ tt -o deploy
295
+
296
+ # Override environment for all tasks
297
+ tt --env python analyze
298
+ tt -e powershell build
299
+ ```
300
+
301
+ ### Information Commands
302
+
303
+ ```bash
304
+ # List all available tasks
305
+ tt --list
306
+ tt -l
307
+
308
+ # Show detailed task definition
309
+ tt --show build
310
+
311
+ # Show dependency tree (without execution)
312
+ tt --tree deploy
313
+
314
+ # Show version
315
+ tt --version
316
+ tt -v
317
+
318
+ # Create a blank recipe file
319
+ tt --init
320
+ ```
321
+
322
+ ### State Management
323
+
324
+ ```bash
325
+ # Remove state file (reset task cache)
326
+ tt --clean
327
+ tt --clean-state
328
+ tt --reset
329
+ ```
330
+
331
+ ### Common Workflows
332
+
333
+ ```bash
334
+ # Fresh build of everything
335
+ tt --force build
336
+
337
+ # Run a task without rebuilding dependencies
338
+ tt --only test
339
+
340
+ # Test with a different shell/environment
341
+ tt --env python test
342
+
343
+ # Force rebuild and deploy
344
+ tt --force deploy production
345
+ ```
346
+
211
347
  ## Example: Full Build Pipeline
212
348
 
213
349
  ```yaml
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tasktree"
3
- version = "0.0.2"
3
+ version = "0.0.3"
4
4
  description = "A task automation tool with incremental execution"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"