tasktree 0.0.1__py3-none-any.whl

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.
@@ -0,0 +1,387 @@
1
+ Metadata-Version: 2.4
2
+ Name: tasktree
3
+ Version: 0.0.1
4
+ Summary: A task automation tool with intelligent incremental execution
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: click>=8.1.0
7
+ Requires-Dist: colorama>=0.4.6
8
+ Requires-Dist: pyyaml>=6.0
9
+ Requires-Dist: rich>=13.0.0
10
+ Requires-Dist: typer>=0.9.0
11
+ Provides-Extra: dev
12
+ Requires-Dist: pytest>=9.0.2; extra == 'dev'
13
+ Description-Content-Type: text/markdown
14
+
15
+ # Task Tree (tt)
16
+
17
+ [![Tests](https://github.com/kevinchannon/tasktree/actions/workflows/test.yml/badge.svg)](https://github.com/kevinchannon/tasktree/actions/workflows/test.yml)
18
+
19
+ A task automation tool that combines simple command execution with intelligent dependency tracking and incremental execution.
20
+
21
+ ## Installation
22
+
23
+ ### From PyPI (Recommended)
24
+
25
+ ```bash
26
+ pipx install tasktree
27
+ ```
28
+
29
+ ### From Source
30
+
31
+ For the latest unreleased version from GitHub:
32
+
33
+ ```bash
34
+ pipx install git+https://github.com/kevinchannon/tasktree.git
35
+ ```
36
+
37
+ Or to install from a local clone:
38
+
39
+ ```bash
40
+ git clone https://github.com/kevinchannon/tasktree.git
41
+ cd tasktree
42
+ pipx install .
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ Create a `tasktree.yaml` (or `tt.yaml`) in your project:
48
+
49
+ ```yaml
50
+ build:
51
+ desc: Compile the application
52
+ outputs: [target/release/bin]
53
+ cmd: cargo build --release
54
+
55
+ test:
56
+ desc: Run tests
57
+ deps: [build]
58
+ cmd: cargo test
59
+ ```
60
+
61
+ Run tasks:
62
+
63
+ ```bash
64
+ tt build # Build the application
65
+ tt test # Run tests (builds first if needed)
66
+ tt --list # Show all available tasks
67
+ ```
68
+
69
+ ## Core Concepts
70
+
71
+ ### Intelligent Incremental Execution
72
+
73
+ Task Tree only runs tasks when necessary. A task executes if:
74
+
75
+ - Its definition (command, outputs, working directory) has changed
76
+ - Any input files have changed since the last run
77
+ - Any dependencies have re-run
78
+ - It has never been executed before
79
+ - It has no inputs or outputs (always runs)
80
+
81
+ ### Automatic Input Inheritance
82
+
83
+ Tasks automatically inherit inputs from dependencies, eliminating redundant declarations:
84
+
85
+ ```yaml
86
+ build:
87
+ outputs: [dist/app]
88
+ cmd: go build -o dist/app
89
+
90
+ package:
91
+ deps: [build]
92
+ outputs: [dist/app.tar.gz]
93
+ cmd: tar czf dist/app.tar.gz dist/app
94
+ # Automatically tracks dist/app as an input
95
+ ```
96
+
97
+ ### Single State File
98
+
99
+ All state lives in `.tasktree-state` at your project root. Stale entries are automatically pruned—no manual cleanup needed.
100
+
101
+ ## Task Definition
102
+
103
+ ### Basic Structure
104
+
105
+ ```yaml
106
+ task-name:
107
+ 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
114
+ ```
115
+
116
+ ### Commands
117
+
118
+ Multi-line commands using YAML literal blocks:
119
+
120
+ ```yaml
121
+ deploy:
122
+ cmd: |
123
+ mkdir -p dist
124
+ cp build/* dist/
125
+ rsync -av dist/ server:/opt/app/
126
+ ```
127
+
128
+ Or folded blocks for long single-line commands:
129
+
130
+ ```yaml
131
+ compile:
132
+ cmd: >
133
+ gcc -o bin/app
134
+ src/*.c
135
+ -I include
136
+ -L lib -lm
137
+ ```
138
+
139
+ ### Parameterised Tasks
140
+
141
+ Tasks can accept arguments with optional defaults:
142
+
143
+ ```yaml
144
+ deploy:
145
+ args: [environment, region=eu-west-1]
146
+ deps: [build]
147
+ cmd: |
148
+ aws s3 cp dist/app.zip s3://{{environment}}-{{region}}/
149
+ aws lambda update-function-code --function-name app-{{environment}}
150
+ ```
151
+
152
+ Invoke with: `tt deploy production` or `tt deploy staging us-east-1` or `tt deploy staging region=us-east-1`.
153
+
154
+ Arguments may be typed, or not and have a default, or not. Valid argument types are:
155
+
156
+ * int - an integer value (e.g. 0, 10, 123, -9)
157
+ * float - a floating point value (e.g. 1.234, -3.1415, 2e-4)
158
+ * bool - Boolean-ish value (e.g. true, false, yes, no, 1, 0, etc)
159
+ * str - a string
160
+ * path - a pathlike string
161
+ * datetime - a datetime in the format 2025-12-17T16:56:12
162
+ * ip - an ip address (v4 or v6)
163
+ * ipv4 - an IPv4 value
164
+ * ipv6 - an IPv6 value
165
+ * email - String validated, but not positively confirmed to be a reachable address.
166
+ * hostname - looks like a hostname, resolution of the name is not attempted as part of the validation
167
+
168
+ Different argument values are tracked separately—tasks re-run when invoked with new arguments.
169
+
170
+ ## File Imports
171
+
172
+ Split task definitions across multiple files for better organisation:
173
+
174
+ ```yaml
175
+ # tasktree.yaml
176
+ import:
177
+ - file: build/tasks.yml
178
+ as: build
179
+ - file: deploy/tasks.yml
180
+ as: deploy
181
+
182
+ test:
183
+ deps: [build.compile, build.test-compile]
184
+ cmd: ./run-tests.sh
185
+
186
+ ci:
187
+ deps: [build.all, test, deploy.staging]
188
+ ```
189
+
190
+ Imported tasks are namespaced and can be referenced as dependencies. Each imported file is self-contained—it cannot depend on tasks in the importing file.
191
+
192
+ ## Glob Patterns
193
+
194
+ Input and output patterns support standard glob syntax:
195
+
196
+ - `src/*.rs` — All Rust files in `src/`
197
+ - `src/**/*.rs` — All Rust files recursively
198
+ - `{file1,file2}` — Specific files
199
+ - `**/*.{js,ts}` — Multiple extensions recursively
200
+
201
+ ## State Management
202
+
203
+ ### How State Works
204
+
205
+ Each task is identified by a hash of its definition (command, outputs, working directory). State tracks:
206
+
207
+ - When the task last ran
208
+ - Timestamps of input files at that time
209
+
210
+ Tasks are re-run when their definition changes or inputs are newer than the last run.
211
+
212
+ ### What's Not In The Hash
213
+
214
+ Changes to these don't invalidate cached state:
215
+
216
+ - Task name (tasks can be renamed freely)
217
+ - Description
218
+ - Dependencies (only affects execution order)
219
+ - Explicit inputs (tracked by timestamp, not definition)
220
+
221
+ ### Automatic Cleanup
222
+
223
+ 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
+
225
+ ## Example: Full Build Pipeline
226
+
227
+ ```yaml
228
+ imports:
229
+ - file: common/docker.yml
230
+ as: docker
231
+
232
+ compile:
233
+ desc: Build application binaries
234
+ outputs: [target/release/app]
235
+ cmd: cargo build --release
236
+
237
+ test-unit:
238
+ desc: Run unit tests
239
+ deps: [compile]
240
+ cmd: cargo test
241
+
242
+ package:
243
+ desc: Create distribution archive
244
+ deps: [compile]
245
+ outputs: [dist/app-{{version}}.tar.gz]
246
+ args: [version]
247
+ cmd: |
248
+ mkdir -p dist
249
+ tar czf dist/app-{{version}}.tar.gz \
250
+ target/release/app \
251
+ config/ \
252
+ migrations/
253
+
254
+ deploy:
255
+ desc: Deploy to environment
256
+ deps: [package, docker.build-runtime]
257
+ args: [environment, version]
258
+ cmd: |
259
+ scp dist/app-{{version}}.tar.gz {{environment}}:/opt/
260
+ ssh {{environment}} /opt/deploy.sh {{version}}
261
+
262
+ integration-test:
263
+ desc: Run integration tests against deployed environment
264
+ deps: [deploy]
265
+ args: [environment, version]
266
+ cmd: pytest tests/integration/ --env={{environment}}
267
+ ```
268
+
269
+ Run the full pipeline:
270
+
271
+ ```bash
272
+ tt integration-test staging version=1.2.3
273
+ ```
274
+
275
+ This will:
276
+ 1. Compile if sources have changed
277
+ 2. Run unit tests if compilation ran
278
+ 3. Package if compilation ran or version argument is new
279
+ 4. Build Docker runtime (from imported file) if needed
280
+ 5. Deploy if package or Docker image changed
281
+ 6. Run integration tests (always runs)
282
+
283
+ ## Implementation Notes
284
+
285
+ Built with Python 3.11+ using:
286
+
287
+ - **PyYAML** for recipe parsing
288
+ - **Typer**, **Click**, **Rich** for CLI
289
+ - **graphlib.TopologicalSorter** for dependency resolution
290
+ - **pathlib** for file operations and glob expansion
291
+
292
+ State file uses JSON format for simplicity and standard library compatibility.
293
+
294
+ ## Development
295
+
296
+ ### Setup Development Environment
297
+
298
+ ```bash
299
+ # Clone repository
300
+ git clone https://github.com/kevinchannon/tasktree.git
301
+ cd tasktree
302
+
303
+ # Install uv (if not already installed)
304
+ curl -LsSf https://astral.sh/uv/install.sh | sh
305
+
306
+ # Install dependencies
307
+ uv sync
308
+
309
+ # Install in editable mode
310
+ pipx install -e .
311
+ ```
312
+
313
+ ### Running Tests
314
+
315
+ ```bash
316
+ # Run all tests
317
+ uv run pytest
318
+
319
+ # Run with verbose output
320
+ uv run pytest -v
321
+
322
+ # Run specific test file
323
+ uv run pytest tests/unit/test_executor.py
324
+ ```
325
+
326
+ ### Using Task Tree for Development
327
+
328
+ The repository includes a `tasktree.yaml` with development tasks:
329
+
330
+ ```bash
331
+ tt test # Run tests
332
+ tt build # Build wheel package
333
+ tt install-dev # Install package in development mode
334
+ tt clean # Remove build artifacts
335
+ ```
336
+
337
+ ## Releasing
338
+
339
+ New releases are created by pushing version tags to GitHub. The release workflow automatically:
340
+ - Builds wheel and source distributions
341
+ - Creates a GitHub Release with artifacts
342
+ - Publishes to PyPI via trusted publishing
343
+
344
+ ### Release Process
345
+
346
+ 1. Ensure main branch is ready:
347
+ ```bash
348
+ git checkout main
349
+ git pull
350
+ ```
351
+
352
+ 2. Create and push a version tag:
353
+ ```bash
354
+ git tag v1.0.0
355
+ git push origin v1.0.0
356
+ ```
357
+
358
+ 3. GitHub Actions will automatically:
359
+ - Extract version from tag (e.g., `v1.0.0` → `1.0.0`)
360
+ - Update `pyproject.toml` with the version
361
+ - Build wheel and sdist
362
+ - Create GitHub Release
363
+ - Publish to PyPI
364
+
365
+ 4. Verify the release:
366
+ - GitHub: https://github.com/kevinchannon/tasktree/releases
367
+ - PyPI: https://pypi.org/project/tasktree/
368
+ - Test: `pipx install --force tasktree`
369
+
370
+ ### Version Numbering
371
+
372
+ Follow semantic versioning:
373
+ - `v1.0.0` - Major release (breaking changes)
374
+ - `v1.1.0` - Minor release (new features, backward compatible)
375
+ - `v1.1.1` - Patch release (bug fixes)
376
+
377
+ ### PyPI Trusted Publishing Setup
378
+
379
+ Before the first release, configure trusted publishing on PyPI:
380
+
381
+ 1. Go to https://pypi.org/manage/account/publishing/
382
+ 2. Add a new publisher:
383
+ - **PyPI Project Name**: `tasktree`
384
+ - **Owner**: `kevinchannon`
385
+ - **Repository name**: `tasktree`
386
+ - **Workflow name**: `release.yml`
387
+ - **Environment name**: (leave blank)
@@ -0,0 +1,13 @@
1
+ tasktree/__init__.py,sha256=MVmdvKb3JdqLlo0x2_TPGMfgFC0HsDnP79HAzGnFnjI,1081
2
+ tasktree/cli.py,sha256=hI9jqHE2YIb_6lYUjxVobLJOE88kOlunfAg52TsD1sQ,15681
3
+ tasktree/executor.py,sha256=TH59xTR6MNBEek9Q8yjYhgC-h0H4mjNsP-yjAcVgS-E,11838
4
+ tasktree/graph.py,sha256=9ngfg93y7EkOIN_lUQa0u-JhnwiMN1UdQQvIFw8RYCE,4181
5
+ tasktree/hasher.py,sha256=jvXBvIfFH9g6AOBHHd012v8nG5JOgVnHH35mIEtVkwc,2133
6
+ tasktree/parser.py,sha256=F2LbB84NinvBQT8zLONxn036R9Rued2y4XB3WGZ8PLk,9150
7
+ tasktree/state.py,sha256=rxKtS3SbsPtAuraHbN807RGWfoYYkQ3pe8CxUstwo2k,3535
8
+ tasktree/tasks.py,sha256=2QdQZtJAX2rSGbyXKG1z9VF_siz1DUzdvzCgPkykxtU,173
9
+ tasktree/types.py,sha256=wrBzO-Z2ebCTRjWyOWNvuCjqAq-74Zyb9E4FQ4beF38,3751
10
+ tasktree-0.0.1.dist-info/METADATA,sha256=aE9ihAgGTRvrNh7TarEA2vEFftKg3FV1DVlMAN0M9LU,9522
11
+ tasktree-0.0.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
12
+ tasktree-0.0.1.dist-info/entry_points.txt,sha256=lQINlvRYnimvteBbnhH84A9clTg8NnpEjCWqWkqg8KE,40
13
+ tasktree-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ tt = tasktree.cli:cli