@calmo/task-runner 3.4.1 → 3.6.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.
- package/.github/ISSUE_TEMPLATE/bug_report.yml +35 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +25 -0
- package/.github/workflows/ci.yml +1 -1
- package/.github/workflows/codeql.yml +101 -0
- package/.github/workflows/release.yml +2 -2
- package/AGENTS.md +15 -16
- package/CHANGELOG.md +27 -0
- package/README.md +89 -82
- package/coverage/coverage-final.json +4 -4
- package/coverage/index.html +9 -9
- package/coverage/lcov-report/index.html +9 -9
- package/coverage/lcov-report/src/EventBus.ts.html +4 -4
- package/coverage/lcov-report/src/TaskGraphValidationError.ts.html +1 -1
- package/coverage/lcov-report/src/TaskGraphValidator.ts.html +1 -1
- package/coverage/lcov-report/src/TaskRunner.ts.html +1 -1
- package/coverage/lcov-report/src/TaskRunnerBuilder.ts.html +1 -1
- package/coverage/lcov-report/src/TaskRunnerExecutionConfig.ts.html +1 -1
- package/coverage/lcov-report/src/TaskStateManager.ts.html +82 -52
- package/coverage/lcov-report/src/WorkflowExecutor.ts.html +197 -62
- package/coverage/lcov-report/src/contracts/RunnerEvents.ts.html +1 -1
- package/coverage/lcov-report/src/contracts/index.html +1 -1
- package/coverage/lcov-report/src/index.html +12 -12
- package/coverage/lcov-report/src/strategies/DryRunExecutionStrategy.ts.html +1 -1
- package/coverage/lcov-report/src/strategies/RetryingExecutionStrategy.ts.html +1 -1
- package/coverage/lcov-report/src/strategies/StandardExecutionStrategy.ts.html +3 -3
- package/coverage/lcov-report/src/strategies/index.html +1 -1
- package/coverage/lcov.info +202 -163
- package/coverage/src/EventBus.ts.html +4 -4
- package/coverage/src/TaskGraphValidationError.ts.html +1 -1
- package/coverage/src/TaskGraphValidator.ts.html +1 -1
- package/coverage/src/TaskRunner.ts.html +1 -1
- package/coverage/src/TaskRunnerBuilder.ts.html +1 -1
- package/coverage/src/TaskRunnerExecutionConfig.ts.html +1 -1
- package/coverage/src/TaskStateManager.ts.html +82 -52
- package/coverage/src/WorkflowExecutor.ts.html +197 -62
- package/coverage/src/contracts/RunnerEvents.ts.html +1 -1
- package/coverage/src/contracts/index.html +1 -1
- package/coverage/src/index.html +12 -12
- package/coverage/src/strategies/DryRunExecutionStrategy.ts.html +1 -1
- package/coverage/src/strategies/RetryingExecutionStrategy.ts.html +1 -1
- package/coverage/src/strategies/StandardExecutionStrategy.ts.html +3 -3
- package/coverage/src/strategies/index.html +1 -1
- package/dist/TaskStateManager.d.ts +6 -0
- package/dist/TaskStateManager.js +11 -2
- package/dist/TaskStateManager.js.map +1 -1
- package/dist/TaskStep.d.ts +5 -0
- package/dist/WorkflowExecutor.js +49 -8
- package/dist/WorkflowExecutor.js.map +1 -1
- package/openspec/changes/archive/2026-01-18-feat-conditional-execution/proposal.md +35 -0
- package/openspec/changes/archive/2026-01-18-feat-conditional-execution/tasks.md +32 -0
- package/package.json +2 -1
- package/src/TaskStateManager.ts +12 -2
- package/src/TaskStep.ts +6 -0
- package/src/WorkflowExecutor.ts +57 -12
- package/test-report.xml +132 -108
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: Bug Report
|
|
2
|
+
description: File a bug report
|
|
3
|
+
title: "[Bug]: "
|
|
4
|
+
labels: ["bug"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for taking the time to fill out this bug report!
|
|
10
|
+
- type: textarea
|
|
11
|
+
attributes:
|
|
12
|
+
label: Description
|
|
13
|
+
description: What happened?
|
|
14
|
+
placeholder: Describe the bug...
|
|
15
|
+
validations:
|
|
16
|
+
required: true
|
|
17
|
+
- type: textarea
|
|
18
|
+
attributes:
|
|
19
|
+
label: Reproduction Steps
|
|
20
|
+
description: How do we reproduce it?
|
|
21
|
+
placeholder: |
|
|
22
|
+
1. Go to '...'
|
|
23
|
+
2. Click on '...'
|
|
24
|
+
3. Scroll down to '...'
|
|
25
|
+
4. See error
|
|
26
|
+
validations:
|
|
27
|
+
required: true
|
|
28
|
+
- type: textarea
|
|
29
|
+
attributes:
|
|
30
|
+
label: Expected Behavior
|
|
31
|
+
description: What did you expect to happen?
|
|
32
|
+
- type: textarea
|
|
33
|
+
attributes:
|
|
34
|
+
label: Environment
|
|
35
|
+
description: OS, Node version, etc.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: Feature Request
|
|
2
|
+
description: Suggest a new feature
|
|
3
|
+
title: "[Feature]: "
|
|
4
|
+
labels: ["enhancement"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for suggesting a new feature!
|
|
10
|
+
- type: textarea
|
|
11
|
+
attributes:
|
|
12
|
+
label: Description
|
|
13
|
+
description: What is the problem you are trying to solve?
|
|
14
|
+
validations:
|
|
15
|
+
required: true
|
|
16
|
+
- type: textarea
|
|
17
|
+
attributes:
|
|
18
|
+
label: Proposed Solution
|
|
19
|
+
description: Describe the solution you'd like
|
|
20
|
+
validations:
|
|
21
|
+
required: true
|
|
22
|
+
- type: textarea
|
|
23
|
+
attributes:
|
|
24
|
+
label: Alternatives Considered
|
|
25
|
+
description: Any other approaches?
|
package/.github/workflows/ci.yml
CHANGED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# For most projects, this workflow file will not need changing; you simply need
|
|
2
|
+
# to commit it to your repository.
|
|
3
|
+
#
|
|
4
|
+
# You may wish to alter this file to override the set of languages analyzed,
|
|
5
|
+
# or to provide custom queries or build logic.
|
|
6
|
+
#
|
|
7
|
+
# ******** NOTE ********
|
|
8
|
+
# We have attempted to detect the languages in your repository. Please check
|
|
9
|
+
# the `language` matrix defined below to confirm you have the correct set of
|
|
10
|
+
# supported CodeQL languages.
|
|
11
|
+
#
|
|
12
|
+
name: "CodeQL Advanced"
|
|
13
|
+
|
|
14
|
+
on:
|
|
15
|
+
push:
|
|
16
|
+
branches: [ "main" ]
|
|
17
|
+
pull_request:
|
|
18
|
+
branches: [ "main" ]
|
|
19
|
+
schedule:
|
|
20
|
+
- cron: '18 8 * * 3'
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
analyze:
|
|
24
|
+
name: Analyze (${{ matrix.language }})
|
|
25
|
+
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
|
26
|
+
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
|
27
|
+
# - https://gh.io/supported-runners-and-hardware-resources
|
|
28
|
+
# - https://gh.io/using-larger-runners (GitHub.com only)
|
|
29
|
+
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
|
30
|
+
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
|
31
|
+
permissions:
|
|
32
|
+
# required for all workflows
|
|
33
|
+
security-events: write
|
|
34
|
+
|
|
35
|
+
# required to fetch internal or private CodeQL packs
|
|
36
|
+
packages: read
|
|
37
|
+
|
|
38
|
+
# only required for workflows in private repositories
|
|
39
|
+
actions: read
|
|
40
|
+
contents: read
|
|
41
|
+
|
|
42
|
+
strategy:
|
|
43
|
+
fail-fast: false
|
|
44
|
+
matrix:
|
|
45
|
+
include:
|
|
46
|
+
- language: actions
|
|
47
|
+
build-mode: none
|
|
48
|
+
- language: javascript-typescript
|
|
49
|
+
build-mode: none
|
|
50
|
+
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
|
|
51
|
+
# Use `c-cpp` to analyze code written in C, C++ or both
|
|
52
|
+
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
|
53
|
+
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
|
54
|
+
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
|
55
|
+
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
|
56
|
+
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
|
57
|
+
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
|
58
|
+
steps:
|
|
59
|
+
- name: Checkout repository
|
|
60
|
+
uses: actions/checkout@v4
|
|
61
|
+
|
|
62
|
+
# Add any setup steps before running the `github/codeql-action/init` action.
|
|
63
|
+
# This includes steps like installing compilers or runtimes (`actions/setup-node`
|
|
64
|
+
# or others). This is typically only required for manual builds.
|
|
65
|
+
# - name: Setup runtime (example)
|
|
66
|
+
# uses: actions/setup-example@v1
|
|
67
|
+
|
|
68
|
+
# Initializes the CodeQL tools for scanning.
|
|
69
|
+
- name: Initialize CodeQL
|
|
70
|
+
uses: github/codeql-action/init@v4
|
|
71
|
+
with:
|
|
72
|
+
languages: ${{ matrix.language }}
|
|
73
|
+
build-mode: ${{ matrix.build-mode }}
|
|
74
|
+
# If you wish to specify custom queries, you can do so here or in a config file.
|
|
75
|
+
# By default, queries listed here will override any specified in a config file.
|
|
76
|
+
# Prefix the list here with "+" to use these queries and those in the config file.
|
|
77
|
+
|
|
78
|
+
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
|
79
|
+
# queries: security-extended,security-and-quality
|
|
80
|
+
|
|
81
|
+
# If the analyze step fails for one of the languages you are analyzing with
|
|
82
|
+
# "We were unable to automatically build your code", modify the matrix above
|
|
83
|
+
# to set the build mode to "manual" for that language. Then modify this step
|
|
84
|
+
# to build your code.
|
|
85
|
+
# ℹ️ Command-line programs to run using the OS shell.
|
|
86
|
+
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
|
87
|
+
- name: Run manual build steps
|
|
88
|
+
if: matrix.build-mode == 'manual'
|
|
89
|
+
shell: bash
|
|
90
|
+
run: |
|
|
91
|
+
echo 'If you are using a "manual" build mode for one or more of the' \
|
|
92
|
+
'languages you are analyzing, replace this with the commands to build' \
|
|
93
|
+
'your code, for example:'
|
|
94
|
+
echo ' make bootstrap'
|
|
95
|
+
echo ' make release'
|
|
96
|
+
exit 1
|
|
97
|
+
|
|
98
|
+
- name: Perform CodeQL Analysis
|
|
99
|
+
uses: github/codeql-action/analyze@v4
|
|
100
|
+
with:
|
|
101
|
+
category: "/language:${{matrix.language}}"
|
|
@@ -16,12 +16,12 @@ jobs:
|
|
|
16
16
|
id-token: write # to enable use of OIDC for npm provenance
|
|
17
17
|
steps:
|
|
18
18
|
- name: Checkout
|
|
19
|
-
uses: actions/checkout@
|
|
19
|
+
uses: actions/checkout@v6
|
|
20
20
|
with:
|
|
21
21
|
fetch-depth: 0
|
|
22
22
|
|
|
23
23
|
- name: Setup pnpm
|
|
24
|
-
uses: pnpm/action-setup@
|
|
24
|
+
uses: pnpm/action-setup@v4
|
|
25
25
|
with:
|
|
26
26
|
version: 10.28.0
|
|
27
27
|
|
package/AGENTS.md
CHANGED
|
@@ -27,6 +27,21 @@ Keep this managed block so 'openspec update' can refresh the instructions.
|
|
|
27
27
|
- Always prefer to add more tests instead of simply bypassing coverage validation with comments.
|
|
28
28
|
- Its forbidden to have coverage drop below 100%, thats non negotiable.
|
|
29
29
|
|
|
30
|
+
## Operational Protocols
|
|
31
|
+
|
|
32
|
+
- **Critic-First Generation**: Every code block you generate must undergo an internal "Reflection" pass. Explicitly flag potential race conditions, security flaws (OWASP Top 10), or architectural debt.
|
|
33
|
+
- **Verification Gatekeeping**: You are STRICTLY FORBIDDEN from claiming a task is "finished" until you provide terminal output of a passing test suite, a successful build log and a successful lint log.
|
|
34
|
+
- **Planning Sparring**: For any task >20 lines, you must first output a blueprint and validate it. You will not write implementation code until the user approves the blueprint.
|
|
35
|
+
- **Tool-Augmented Research**: Use `/search` and `/read` to understand the entire context of the project. Do not assume; verify existing utility functions to ensure DRY (Don't Repeat Yourself) compliance.
|
|
36
|
+
- **The Confession Rule**: If you hit a logic error or a hallucination, you must immediately halt and state: "I have identified an inconsist- - **Atomic Commits for Complex Features:** When working on complex multi-task features, you MUST commit after completing each distinct task. Before each commit, ensure that `pnpm build`, `pnpm lint`, and `pnpm test` pass. This creates safe rollback points and prevents restarting the entire feature if issues arise.
|
|
37
|
+
|
|
38
|
+
## Style & Tone
|
|
39
|
+
|
|
40
|
+
- **Tone**: Professional, technical, and high-density.
|
|
41
|
+
- **Zero Politeness Fluff**: No "I'd be happy to," "Great question," etc.
|
|
42
|
+
- **Architectural Comparisons**: Use markdown tables for comparing architectural trade-offs.
|
|
43
|
+
- **Hypothesis Labeling**: Label speculative thoughts clearly as `[ARCHITECTURAL_HYPOTHESIS]`.
|
|
44
|
+
|
|
30
45
|
# task-runner Development Guidelines
|
|
31
46
|
|
|
32
47
|
Auto-generated from all feature plans. Last updated: 2026-01-17
|
|
@@ -62,19 +77,3 @@ tests/
|
|
|
62
77
|
- 005-concurrency-control: Added TypeScript 5.9.3 + vitest 4.0.17
|
|
63
78
|
- 002-task-cancellation: Added TypeScript 5.9.3 + vitest 4.0.17, AbortSignal/AbortController (standard Web APIs)
|
|
64
79
|
- 004-pre-execution-validation: Added TypeScript 5.9.3 + vitest 4.0.17 (for testing)
|
|
65
|
-
|
|
66
|
-
<!-- MANUAL ADDITIONS START -->
|
|
67
|
-
|
|
68
|
-
- **Atomic Commits for Complex Features:** When working on complex multi-task features, you MUST commit after completing each distinct task. Before each commit, ensure that `pnpm build`, `pnpm lint`, and `pnpm test` pass. This creates safe rollback points and prevents restarting the entire feature if issues arise.
|
|
69
|
-
- Never edit CHANGELOG.md manually. This file is for semantic release and is filled automatically.
|
|
70
|
-
|
|
71
|
-
Before marking a task as concluded, YOU MUST:
|
|
72
|
-
|
|
73
|
-
1. run pnpm install
|
|
74
|
-
2. run pnpm build
|
|
75
|
-
3. run pnpm test
|
|
76
|
-
4. run pnpm lint
|
|
77
|
-
|
|
78
|
-
If any of those command fail, review your changes.
|
|
79
|
-
|
|
80
|
-
<!-- MANUAL ADDITIONS END -->
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
## 3.6.0 (2026-01-19)
|
|
2
|
+
|
|
3
|
+
* Add CodeQL analysis workflow configuration ([b2ee976](https://github.com/thalesraymond/task-runner/commit/b2ee976))
|
|
4
|
+
* Merge pull request #66 from thalesraymond/dependabot/github_actions/actions/checkout-6 ([cb6e75f](https://github.com/thalesraymond/task-runner/commit/cb6e75f)), closes [#66](https://github.com/thalesraymond/task-runner/issues/66)
|
|
5
|
+
* Merge pull request #67 from thalesraymond/dependabot/github_actions/pnpm/action-setup-4 ([4c9e9f3](https://github.com/thalesraymond/task-runner/commit/4c9e9f3)), closes [#67](https://github.com/thalesraymond/task-runner/issues/67)
|
|
6
|
+
* Merge pull request #68 from thalesraymond/dependabot/github_actions/SonarSource/sonarqube-scan-actio ([9980f4d](https://github.com/thalesraymond/task-runner/commit/9980f4d)), closes [#68](https://github.com/thalesraymond/task-runner/issues/68)
|
|
7
|
+
* Merge pull request #71 from thalesraymond/chore/codeQLworkflow ([db4f46a](https://github.com/thalesraymond/task-runner/commit/db4f46a)), closes [#71](https://github.com/thalesraymond/task-runner/issues/71)
|
|
8
|
+
* Merge pull request #72 from thalesraymond/setup-issue-templates-6661562951039014259 ([f3281bf](https://github.com/thalesraymond/task-runner/commit/f3281bf)), closes [#72](https://github.com/thalesraymond/task-runner/issues/72)
|
|
9
|
+
* feat: add issue templates ([6ff97f1](https://github.com/thalesraymond/task-runner/commit/6ff97f1))
|
|
10
|
+
* chore(deps): bump actions/checkout from 4 to 6 ([f0b2f0e](https://github.com/thalesraymond/task-runner/commit/f0b2f0e))
|
|
11
|
+
* chore(deps): bump pnpm/action-setup from 2 to 4 ([2a5c3e1](https://github.com/thalesraymond/task-runner/commit/2a5c3e1))
|
|
12
|
+
* chore(deps): bump SonarSource/sonarqube-scan-action from 6 to 7 ([df236cd](https://github.com/thalesraymond/task-runner/commit/df236cd))
|
|
13
|
+
|
|
14
|
+
## 3.5.0 (2026-01-18)
|
|
15
|
+
|
|
16
|
+
* Merge pull request #69 from thalesraymond/feat/conditional-execution ([dd1dd8d](https://github.com/thalesraymond/task-runner/commit/dd1dd8d)), closes [#69](https://github.com/thalesraymond/task-runner/issues/69)
|
|
17
|
+
* Update README.md ([8808f94](https://github.com/thalesraymond/task-runner/commit/8808f94))
|
|
18
|
+
* docs: ✏️ archive conditional specs since its implemented ([b3db067](https://github.com/thalesraymond/task-runner/commit/b3db067))
|
|
19
|
+
* docs: ✏️ conditional execution spec ([5a670c4](https://github.com/thalesraymond/task-runner/commit/5a670c4))
|
|
20
|
+
* docs: ✏️ fix typo ([d969ff5](https://github.com/thalesraymond/task-runner/commit/d969ff5))
|
|
21
|
+
* docs: ✏️ rewriting readme with latest changes ([c968fc3](https://github.com/thalesraymond/task-runner/commit/c968fc3))
|
|
22
|
+
* docs: ✏️ update readme with example of conditional execution ([da9a818](https://github.com/thalesraymond/task-runner/commit/da9a818))
|
|
23
|
+
* feat: 🎸 new conditional execution feature ([e936ad7](https://github.com/thalesraymond/task-runner/commit/e936ad7))
|
|
24
|
+
* chore: 🤖 add AI skills ([5feacc6](https://github.com/thalesraymond/task-runner/commit/5feacc6))
|
|
25
|
+
* chore: 🤖 removed skill md file, general skills moved to workspa ([5a8bd0e](https://github.com/thalesraymond/task-runner/commit/5a8bd0e))
|
|
26
|
+
* chore: 🤖 removed workspace skills ([e819e00](https://github.com/thalesraymond/task-runner/commit/e819e00))
|
|
27
|
+
|
|
1
28
|
## <small>3.4.1 (2026-01-18)</small>
|
|
2
29
|
|
|
3
30
|
* Merge pull request #65 from thalesraymond/perf/async-event-listeners-3002139613350975332 ([77edbc7](https://github.com/thalesraymond/task-runner/commit/77edbc7)), closes [#65](https://github.com/thalesraymond/task-runner/issues/65)
|
package/README.md
CHANGED
|
@@ -13,30 +13,24 @@ A lightweight, type-safe, and domain-agnostic task orchestration engine. It reso
|
|
|
13
13
|
- **Type-Safe Context**: Fully typed shared state using TypeScript Generics.
|
|
14
14
|
- **Parallel Execution**: Automatically identifies and runs independent steps concurrently.
|
|
15
15
|
- **Dependency Management**: Enforces execution order based on dependencies.
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
18
|
-
- **
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
The `TaskRunner` implements an Observer Pattern, allowing you to subscribe to various lifecycle events.
|
|
23
|
-
|
|
24
|
-
```typescript
|
|
25
|
-
runner.on("taskStart", ({ step }) => {
|
|
26
|
-
console.log(`Starting step: ${step.name}`);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
runner.on("taskEnd", ({ step, result }) => {
|
|
30
|
-
console.log(`Step ${step.name} finished with status: ${result.status}`);
|
|
31
|
-
});
|
|
32
|
-
```
|
|
16
|
+
- **Automatic Retries**: Configurable retry logic for flaky tasks.
|
|
17
|
+
- **Dry Run Mode**: Simulate workflow execution to verify dependency graphs.
|
|
18
|
+
- **Visualization**: Generate Mermaid.js diagrams of your task graph.
|
|
19
|
+
- **Event System**: Subscribe to lifecycle events for logging or monitoring.
|
|
20
|
+
- **Runtime Validation**: Automatically detects circular dependencies and missing dependencies.
|
|
21
|
+
- **Conditional Execution**: Skip tasks dynamically based on context state.
|
|
33
22
|
|
|
34
23
|
## Usage Example
|
|
35
24
|
|
|
36
|
-
|
|
25
|
+
The library now provides a fluent `TaskRunnerBuilder` for easy configuration.
|
|
37
26
|
|
|
38
27
|
```typescript
|
|
39
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
TaskRunnerBuilder,
|
|
30
|
+
TaskStep,
|
|
31
|
+
RetryingExecutionStrategy,
|
|
32
|
+
StandardExecutionStrategy
|
|
33
|
+
} from "@calmo/task-runner";
|
|
40
34
|
|
|
41
35
|
// 1. Define your domain-specific context
|
|
42
36
|
interface ValidationContext {
|
|
@@ -51,16 +45,21 @@ interface ValidationContext {
|
|
|
51
45
|
const UrlFormatStep: TaskStep<ValidationContext> = {
|
|
52
46
|
name: "UrlFormatStep",
|
|
53
47
|
run: async (ctx) => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
if (!ctx.issueBody.includes("github.com")) {
|
|
49
|
+
return { status: "failure", error: "Invalid URL" };
|
|
50
|
+
}
|
|
51
|
+
return { status: "success" };
|
|
58
52
|
},
|
|
59
53
|
};
|
|
60
54
|
|
|
61
55
|
const DataLoaderStep: TaskStep<ValidationContext> = {
|
|
62
56
|
name: "DataLoaderStep",
|
|
63
57
|
dependencies: ["UrlFormatStep"],
|
|
58
|
+
retry: {
|
|
59
|
+
attempts: 3,
|
|
60
|
+
delay: 1000,
|
|
61
|
+
backoff: "exponential"
|
|
62
|
+
},
|
|
64
63
|
run: async (ctx) => {
|
|
65
64
|
// Simulate API call
|
|
66
65
|
ctx.prData = { additions: 20, ciStatus: "success" };
|
|
@@ -68,29 +67,25 @@ const DataLoaderStep: TaskStep<ValidationContext> = {
|
|
|
68
67
|
},
|
|
69
68
|
};
|
|
70
69
|
|
|
71
|
-
|
|
72
|
-
name: "MaxChangesStep",
|
|
73
|
-
dependencies: ["DataLoaderStep"],
|
|
74
|
-
run: async (ctx) => {
|
|
75
|
-
// Safe access because dependencies ensured execution order
|
|
76
|
-
if (!ctx.prData) return { status: "failure", error: "Missing PR Data" };
|
|
77
|
-
|
|
78
|
-
return ctx.prData.additions < 50
|
|
79
|
-
? { status: "success" }
|
|
80
|
-
: { status: "failure", error: "Too many changes" };
|
|
81
|
-
},
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
// 3. Execute the runner
|
|
70
|
+
// 3. Configure and Build the Runner
|
|
85
71
|
async function main() {
|
|
86
72
|
const context: ValidationContext = {
|
|
87
73
|
issueBody: "https://github.com/org/repo/pull/1",
|
|
88
74
|
};
|
|
89
75
|
|
|
90
|
-
const runner = new
|
|
76
|
+
const runner = new TaskRunnerBuilder(context)
|
|
77
|
+
.useStrategy(new RetryingExecutionStrategy(new StandardExecutionStrategy()))
|
|
78
|
+
.on("taskStart", ({ step }) => console.log(`Starting: ${step.name}`))
|
|
79
|
+
.on("taskEnd", ({ step, result }) => console.log(`Finished: ${step.name} -> ${result.status}`))
|
|
80
|
+
.build();
|
|
91
81
|
|
|
92
|
-
const steps = [UrlFormatStep, DataLoaderStep
|
|
93
|
-
|
|
82
|
+
const steps = [UrlFormatStep, DataLoaderStep];
|
|
83
|
+
|
|
84
|
+
// 4. Execute with options
|
|
85
|
+
const results = await runner.execute(steps, {
|
|
86
|
+
concurrency: 5, // Run up to 5 tasks in parallel
|
|
87
|
+
timeout: 30000 // 30s timeout for the whole workflow
|
|
88
|
+
});
|
|
94
89
|
|
|
95
90
|
console.table(Object.fromEntries(results));
|
|
96
91
|
}
|
|
@@ -98,67 +93,79 @@ async function main() {
|
|
|
98
93
|
main();
|
|
99
94
|
```
|
|
100
95
|
|
|
101
|
-
##
|
|
96
|
+
## Advanced Configuration
|
|
102
97
|
|
|
103
|
-
|
|
98
|
+
### Execution Strategies
|
|
104
99
|
|
|
105
|
-
|
|
100
|
+
The `TaskRunner` is built on top of composable execution strategies.
|
|
106
101
|
|
|
107
|
-
|
|
102
|
+
- **StandardExecutionStrategy**: The default strategy that simply runs the task.
|
|
103
|
+
- **RetryingExecutionStrategy**: Wraps another strategy to add retry logic. Configured via the `retry` property on `TaskStep`.
|
|
104
|
+
- **DryRunExecutionStrategy**: Simulates execution without running the actual task logic. Useful for validating your graph or testing conditions.
|
|
108
105
|
|
|
109
|
-
|
|
106
|
+
You can set a strategy globally using the `TaskRunnerBuilder`:
|
|
110
107
|
|
|
111
|
-
|
|
108
|
+
```typescript
|
|
109
|
+
runnerBuilder.useStrategy(new DryRunExecutionStrategy());
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Execution Options
|
|
112
113
|
|
|
113
|
-
|
|
114
|
+
When calling `execute`, you can provide a configuration object:
|
|
114
115
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
- **concurrency**: Limits the number of tasks running in parallel. Defaults to unlimited.
|
|
117
|
+
- **timeout**: Sets a maximum execution time for the entire workflow.
|
|
118
|
+
- **signal**: Accepts an `AbortSignal` to cancel the workflow programmatically.
|
|
119
|
+
- **dryRun**: Overrides the current strategy with `DryRunExecutionStrategy` for this execution.
|
|
118
120
|
|
|
119
121
|
```typescript
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
await runner.execute(steps, {
|
|
123
|
+
concurrency: 2,
|
|
124
|
+
dryRun: true
|
|
125
|
+
});
|
|
126
|
+
```
|
|
123
127
|
|
|
124
|
-
|
|
125
|
-
apiData: {
|
|
126
|
-
user: string;
|
|
127
|
-
isPro: boolean;
|
|
128
|
-
};
|
|
129
|
-
}
|
|
128
|
+
## Visualization
|
|
130
129
|
|
|
131
|
-
|
|
132
|
-
class UserLoaderStep implements TaskStep<MyProjectContext> {
|
|
133
|
-
name = "UserLoaderStep";
|
|
134
|
-
async run(ctx: MyProjectContext & Partial<MyProjectFullContext>) {
|
|
135
|
-
// Fetch data and update context
|
|
136
|
-
ctx.apiData = { user: "john_doe", isPro: true };
|
|
137
|
-
return { status: "success" };
|
|
138
|
-
}
|
|
139
|
-
}
|
|
130
|
+
You can generate a [Mermaid.js](https://mermaid.js.org/) diagram to visualize your task dependencies.
|
|
140
131
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
name = "PremiumCheckStep";
|
|
144
|
-
dependencies = ["UserLoaderStep"]; // Ensures data is ready
|
|
132
|
+
```typescript
|
|
133
|
+
import { TaskRunner } from "@calmo/task-runner";
|
|
145
134
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
: { status: "failure", error: "User is not a Pro member" };
|
|
150
|
-
}
|
|
151
|
-
}
|
|
135
|
+
const graph = TaskRunner.getMermaidGraph(steps);
|
|
136
|
+
console.log(graph);
|
|
137
|
+
// Output: graph TD; A-->B; ...
|
|
152
138
|
```
|
|
153
139
|
|
|
154
|
-
|
|
140
|
+
## Skip Propagation
|
|
141
|
+
|
|
142
|
+
If a task fails or is skipped, the `TaskRunner` automatically marks all subsequent tasks that depend on it as `skipped`. This ensures that your pipeline doesn't attempt to run steps with missing prerequisites.
|
|
143
|
+
|
|
144
|
+
## Conditional Execution
|
|
145
|
+
|
|
146
|
+
You can define a `condition` function for a task. If it returns `false`, the task is marked as `skipped`, and its dependencies are also skipped.
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
const deployStep: TaskStep<MyContext> = {
|
|
150
|
+
name: "deploy",
|
|
151
|
+
condition: (ctx) => ctx.env === "production",
|
|
152
|
+
run: async () => {
|
|
153
|
+
// Deploy logic
|
|
154
|
+
return { status: "success" };
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
```
|
|
155
158
|
|
|
156
159
|
## Why I did this?
|
|
157
160
|
|
|
158
|
-
In my
|
|
161
|
+
In my current job I have a Github Issue validation engine that checks **a lot** of stuff and I wanted to make a package that encapsulates the "validation engine" logic for use outside that use case. I also wanted to try to make a package that is not tied to a specific scenario. I don't know if someone will find it useful but here it is.
|
|
162
|
+
|
|
163
|
+
## AI Usage
|
|
164
|
+
|
|
165
|
+
One of the reasons this project exists is to test 'vibe coding' tools, so yes, this is vibe coded (like, A LOT, I've added myself only specs and some conflict resolutions). This repository serves as a testbed for these tools. It's a way to create a real life scenario showcasing the capabilities of agentic AI development.
|
|
159
166
|
|
|
160
|
-
##
|
|
167
|
+
## Contributing and General Usage
|
|
161
168
|
|
|
162
|
-
|
|
169
|
+
Feel free to open issues and PRs. I'm open to feedback and suggestions. I can't promise to act on them but I'll try my best. If you want to play with it, feel free to fork it, change it and use it in your own projects.
|
|
163
170
|
|
|
164
171
|
---
|