Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
d3180a5
feat: scaffold hm-dsl-engine crate with DslEngine trait
markovejnovic May 24, 2026
c70e212
feat(dsl-engine): detect DSL language from .harmont/ contents
markovejnovic May 24, 2026
837c8d9
feat(dsl-engine): WASM runtime download + SHA-256 cache
markovejnovic May 24, 2026
893ef6e
feat(dsl-engine): wasmtime engine factory with compilation cache
markovejnovic May 24, 2026
405795b
feat(dsl-engine): embed harmont-py + croniter sources in binary
markovejnovic May 24, 2026
555706c
feat(dsl-engine): build-time TS→JS bundle with SHA-256 polyfill
markovejnovic May 24, 2026
5b147e9
feat(dsl-engine): TS→JS preprocessing via oxc + import rewriting
markovejnovic May 24, 2026
597e829
feat(dsl-engine): system-interpreter fallback (python3 subprocess)
markovejnovic May 24, 2026
6abe658
feat(dsl-engine): Python WASI engine via wasmtime + cpython.wasm
markovejnovic May 24, 2026
8059d4c
feat(dsl-engine): QuickJS WASI engine for TypeScript pipeline evaluation
markovejnovic May 24, 2026
afc3d34
feat: integrate DslEngine dispatch into hm run
markovejnovic May 24, 2026
de914a6
test(dsl-engine): integration tests for Python + TS engine roundtrips
markovejnovic May 24, 2026
f8c88f8
chore: fix workspace feature gating and document embedded DSL engine …
markovejnovic May 24, 2026
7dfc68f
build(dsl-engine): add build-time deps for asset fetching
markovejnovic May 24, 2026
3f8cd42
build(dsl-engine): add fetch + verify helper for build-time assets
markovejnovic May 24, 2026
4d7ca98
build(dsl-engine): fetch quickjs.wasm at build time instead of embedd…
markovejnovic May 24, 2026
0d493b8
build(dsl-engine): fetch Python vendor packages from PyPI at build time
markovejnovic May 24, 2026
84a4b7b
chore(dsl-engine): remove checked-in quickjs.wasm and vendor/ — now f…
markovejnovic May 24, 2026
e18d400
build(dsl-engine): add rerun-if-changed guards and document build-tim…
markovejnovic May 24, 2026
c5abdc6
ci: remove Python/Node install steps — DSL engines now embedded
markovejnovic May 24, 2026
3ee9ffe
fix(dsl-engine): allow clippy panics in build script
markovejnovic May 24, 2026
1007306
ci: trigger workflow run
markovejnovic May 24, 2026
1854f8c
chore: update Cargo.lock with build-time dependencies
markovejnovic May 24, 2026
14752d9
ci: retrigger workflow
markovejnovic May 24, 2026
f7c9b43
fix(dsl-engine): prefer TypeScript when both .py and .ts present in .…
markovejnovic May 24, 2026
076cfbc
ci: retrigger
markovejnovic May 25, 2026
4cfb01d
ci: add workflow_dispatch trigger for manual CI runs
markovejnovic May 25, 2026
6295a05
refactor(dsl-engine): delete dead fallback.rs
markovejnovic May 25, 2026
74640eb
refactor(dsl-engine): replace WASM engines with system-runtime archit…
markovejnovic May 25, 2026
bbeb4ca
feat(dsl-engine): add SubprocessPythonEngine for pipeline evaluation
markovejnovic May 25, 2026
32cd7dc
feat(dsl-engine): add SubprocessTsEngine for TypeScript pipeline eval…
markovejnovic May 25, 2026
58c1111
refactor: wire SubprocessPythonEngine + SubprocessTsEngine in engine_…
markovejnovic May 25, 2026
ee01a51
chore: remove unused dirs dependency from hm-dsl-engine
markovejnovic May 25, 2026
cf0ffcd
test(dsl-engine): add integration tests for Python and TypeScript sub…
markovejnovic May 25, 2026
497a4b3
chore: remove wasm32-wasip1 from CI and update CLAUDE.md for subproce…
markovejnovic May 25, 2026
9097daf
fix: suppress clippy unwrap/expect lints in dsl-engine test modules
markovejnovic May 25, 2026
412b348
chore: address code review findings
markovejnovic May 25, 2026
25b5e87
Merge remote-tracking branch 'origin/main' into feat/embedded-ts-python
markovejnovic May 25, 2026
fab1311
fix(ci): add Node 22 to dogfood and examples jobs
markovejnovic May 25, 2026
f51c9ec
fix(ci): use Node 23 and show full DSL error chain
markovejnovic May 25, 2026
e918bb7
fix(dsl-engine): symlink harmont package into .harmont/node_modules
markovejnovic May 25, 2026
4bdf1ef
style: cargo fmt
markovejnovic May 25, 2026
9be7770
fix(examples): set laravel: false in php-laravel TS pipeline
markovejnovic May 25, 2026
0ac4b59
chore(ci): remove pip install of DSL runtime deps from integration job
markovejnovic May 25, 2026
4ff489b
chore: remove php-laravel example
markovejnovic May 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 18 additions & 19 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: CI

on:
workflow_dispatch:
pull_request:
push:
branches: [main]
Expand All @@ -19,11 +20,13 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
# build.rs cross-compiles hm-plugin-* wasm artifacts.
targets: wasm32-wasip1
components: clippy
- uses: Swatinem/rust-cache@v2

- name: Install esbuild (for harmont-ts bundle)
working-directory: dsls/harmont-ts
run: npm ci

- name: cargo build (all targets)
run: cargo build -p harmont-cli --all-targets

Expand Down Expand Up @@ -99,19 +102,22 @@ jobs:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-wasip1

- uses: Swatinem/rust-cache@v2

- uses: actions/setup-node@v4
with:
node-version: "23"
cache: npm
cache-dependency-path: dsls/harmont-ts/package-lock.json

- name: Install esbuild (for harmont-ts bundle)
working-directory: dsls/harmont-ts
run: npm ci

- name: Build hm
run: cargo build -p harmont-cli

- name: Install harmont-py into system Python
run: |
sudo /usr/bin/python3 -m pip install --break-system-packages dsls/harmont-py
/usr/bin/python3 -c "import harmont; print('harmont', harmont.__file__)"

- name: Restore harmont Docker cache
uses: actions/cache/restore@v4
with:
Expand Down Expand Up @@ -153,16 +159,11 @@ jobs:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable
with:
targets: wasm32-wasip1
- uses: Swatinem/rust-cache@v2

- uses: actions/setup-python@v5
with:
python-version: "3.12"

- name: Install harmont-py (editable)
run: pip install -e dsls/harmont-py
- name: Install esbuild (for harmont-ts bundle)
working-directory: dsls/harmont-ts
run: npm ci

- name: cargo build --tests (with docker-integration feature)
run: cargo build -p harmont-cli --tests --features docker-integration
Expand All @@ -171,8 +172,6 @@ jobs:
run: docker pull python:3.12-alpine

- name: cargo test --features docker-integration -- --ignored
env:
HARMONT_PYTHON: python3
run: |
cargo test -p harmont-cli \
--features docker-integration \
Expand Down
31 changes: 10 additions & 21 deletions .github/workflows/examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,30 +38,26 @@ jobs:
fi

# Build `hm` once and share the binary across every matrix leg.
# Each leg only needs Python + Docker + the binary; making them
# re-compile the whole workspace 17× was the long tent-pole.
# Each leg only needs Docker + the binary; making them re-compile
# the whole workspace 17× was the long tent-pole.
build-hm:
needs: validate-matrix
runs-on: ubuntu-latest
# Debug build only — examples just need a working `hm` binary;
# release-mode LTO/codegen on wasmtime+cranelift can't finish in
# GH's 6h cap on a 2-vCPU runner. Debug builds in ~10 minutes
# cold, ~1 minute warm.
# Debug build only — examples just need a working `hm` binary.
timeout-minutes: 30
steps:
- uses: actions/checkout@v4

- uses: dtolnay/rust-toolchain@stable
with:
# crates/hm/build.rs cross-compiles hm-plugin-docker as a wasm
# plugin embedded into the binary, so the target must be on
# the toolchain.
targets: wasm32-wasip1

- uses: Swatinem/rust-cache@v2
with:
shared-key: examples-hm

- name: Install esbuild (for harmont-ts bundle)
working-directory: dsls/harmont-ts
run: npm ci

- name: Build hm
run: cargo build -p harmont-cli

Expand Down Expand Up @@ -90,7 +86,6 @@ jobs:
- nextjs
- ocaml
- perl
- php-laravel
- python-uv
- react
- ruby
Expand All @@ -101,15 +96,9 @@ jobs:
steps:
- uses: actions/checkout@v4

# `hm run` shells out to `/usr/bin/python3` with PATH restricted
# to /usr/bin:/usr/local/bin:/bin (see render.rs), so harmont-py
# has to land in the *system* Python's site-packages — not the
# actions/setup-python hostedtoolcache. PEP 668's
# externally-managed marker requires --break-system-packages.
- name: Install harmont-py into system Python
run: |
sudo /usr/bin/python3 -m pip install --break-system-packages dsls/harmont-py
/usr/bin/python3 -c "import harmont; print('harmont', harmont.__file__)"
- uses: actions/setup-node@v4
with:
node-version: "23"

- name: Download hm binary
uses: actions/download-artifact@v4
Expand Down
28 changes: 4 additions & 24 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,12 @@ jobs:
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
# crates/hm/build.rs cross-compiles hm-plugin-docker as a wasm
# plugin embedded into the binary, so the target must be on
# the toolchain for the `cargo check` in the next step.
targets: wasm32-wasip1
- uses: Swatinem/rust-cache@v2

- name: Install esbuild (for harmont-ts bundle)
working-directory: dsls/harmont-ts
run: npm ci

- name: Set version from tag
run: |
VERSION="${GITHUB_REF_NAME#v}"
Expand Down Expand Up @@ -61,25 +60,6 @@ jobs:
- name: Wait for crates.io index
run: sleep 30

- name: Build embedded WASM plugins
# The harmont-cli build.rs prefers crates/hm/embedded/*.wasm
# over the in-workspace cross-compile. Stage them here so the
# `cargo publish -p harmont-cli` verify-build (which runs in
# target/package/harmont-cli-<ver>/ without the sibling plugin
# crates) and any downstream `cargo install harmont-cli` both
# find the wasms already cooked. The include = [...] in
# crates/hm/Cargo.toml carries them into the tarball.
run: |
set -euo pipefail
for crate in hm-plugin-docker hm-plugin-output-human hm-plugin-output-json hm-plugin-cloud; do
cargo build --target wasm32-wasip1 -p "$crate" --release
done
mkdir -p crates/hm/embedded
for name in hm_plugin_docker hm_plugin_output_human hm_plugin_output_json hm_plugin_cloud; do
cp "target/wasm32-wasip1/release/$name.wasm" "crates/hm/embedded/$name.wasm"
done
ls -la crates/hm/embedded/

- name: Publish harmont-cli
run: |
if curl -sf -A "harmont-release-ci (github-actions)" "https://crates.io/api/v1/crates/harmont-cli/$VERSION" > /dev/null 2>&1; then
Expand Down
7 changes: 2 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@ The `cli/` directory is a Cargo workspace.
- `crates/hm-util/` — shared OS and filesystem utilities.
- `crates/hm-plugin-protocol/` — wire types (serde structs only).
- `crates/hm-plugin-sdk/` — authoring SDK for plugin writers.
- `crates/hm-fixtures/` — test-only WASM plugins; compiled to
`target/wasm32-wasip1/debug/` by the test harness.

Run `cargo build` from the workspace root. Plugin fixtures need the
`wasm32-wasip1` target; install with `rustup target add wasm32-wasip1`.
Run `cargo build` from the workspace root. Build requires esbuild
(`npm ci` in `dsls/harmont-ts/`).

For cross-cutting doctrine see [PRINCIPLES.md](../PRINCIPLES.md).

Expand Down
59 changes: 56 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ members = [
"crates/hm-pipeline-ir",
"crates/hm-util",
"crates/hm-plugin-cloud",
"crates/hm-dsl-engine",
]
default-members = [
"crates/hm",
"crates/hm-plugin-protocol",
"crates/hm-pipeline-ir",
"crates/hm-util",
"crates/hm-plugin-cloud",
"crates/hm-dsl-engine",
]

[workspace.package]
Expand All @@ -24,7 +26,10 @@ repository = "https://github.com/harmont-dev/harmont-cli"
hm-plugin-protocol = { path = "crates/hm-plugin-protocol", version = "0.0.0-dev" }
hm-pipeline-ir = { path = "crates/hm-pipeline-ir", version = "0.0.0-dev" }
hm-util = { path = "crates/hm-util", version = "0.0.0-dev" }
hm-dsl-engine = { path = "crates/hm-dsl-engine", version = "0.0.0-dev" }
anyhow = "1"
async-trait = "0.1"
dirs = "6"
daggy = { version = "0.9", features = ["serde-1"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
Expand Down
30 changes: 30 additions & 0 deletions crates/hm-dsl-engine/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[package]
name = "hm-dsl-engine"
version = "0.0.0-dev"
edition.workspace = true
license.workspace = true
repository.workspace = true
description = "DSL engine: evaluate Python/TypeScript pipeline definitions via system runtimes."
publish = false

[lib]
path = "src/lib.rs"

[dependencies]
anyhow = { workspace = true }
async-trait = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
include_dir = "0.7"
tempfile = "3"
tokio = { version = "1", features = ["process", "fs"] }
tracing = "0.1"
which = "7"

[dev-dependencies]
tempfile = "3"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
which = "7"

[lints]
workspace = true
Loading
Loading