@@ -235,8 +235,9 @@ require heuristic analysis and could produce false positives.
235235### ` compile_gate_step(ctx: GateContext, checks: &[FilterCheck]) -> String `
236236
237237Produces a complete ADO pipeline step (` - bash: | ` ) with a ** data-driven
238- architecture** : bash is a thin ADO-macro shim, all filter logic lives in a
239- generic Python evaluator that reads a JSON gate spec.
238+ architecture** : bash is a thin ADO-macro shim, all filter logic lives in
239+ the bundled Node.js gate evaluator (` scripts/ado-script/dist/gate/index.js ` ) that reads a JSON
240+ gate spec.
240241
241242#### Generated Step Structure
242243
@@ -256,10 +257,8 @@ generic Python evaluator that reads a JSON gate spec.
256257 # 3. Access token passthrough
257258 export ADO_SYSTEM_ACCESS_TOKEN="$SYSTEM_ACCESSTOKEN"
258259
259- # 4. Embedded Python evaluator (heredoc -- never modified)
260- python3 << 'GATE_EVAL_EOF'
261- ...evaluator source...
262- GATE_EVAL_EOF
260+ # 4. Run the bundled Node evaluator (downloaded by the Setup job)
261+ node '/tmp/ado-aw-scripts/ado-script/dist/gate/index.js'
263262 name : prGate
264263 displayName : " Evaluate PR filters"
265264 env :
@@ -268,7 +267,7 @@ generic Python evaluator that reads a JSON gate spec.
268267
269268#### Gate Spec Format (JSON)
270269
271- The spec is base64-encoded to prevent ADO macro expansion and heredoc
270+ The spec is base64-encoded to prevent ADO macro expansion and shell
272271quoting issues. Decoded, it contains:
273272
274273` ` ` json
@@ -300,21 +299,22 @@ quoting issues. Decoded, it contains:
300299```
301300
302301The spec is declarative -- it uses fact * kinds* (e.g., ` "pr_title" ` ,
303- ` "pr_metadata" ` ) not raw REST endpoints. The Python evaluator owns
302+ ` "pr_metadata" ` ) not raw REST endpoints. The Node evaluator owns
304303acquisition logic.
305304
306- #### Python Gate Evaluator (` scripts/gate-eval.py ` )
305+ #### Bundled Gate Evaluator (` scripts/ado-script/src/gate/ ` )
307306
308- The evaluator is a self-contained Python script embedded via
309- ` include_str!() ` . It handles:
307+ The evaluator is a TypeScript program ncc-bundled to a single
308+ self-contained ` scripts/ado-script/dist/gate/index.js ` (~ 1.1 MB) that ships as part of the
309+ ` ado-script.zip ` release asset. It handles:
310310
3113111 . ** Bypass logic** -- reads ` ADO_BUILD_REASON ` and exits early for non-matching
312312 trigger types
3133132 . ** Fact acquisition** -- maps fact kinds to acquisition methods:
314- - Pipeline variables -> ` os.environ.get( "ADO_*") `
315- - PR metadata -> ` urllib ` call to ADO REST API
314+ - Pipeline variables -> ` process.env[ "ADO_*"] `
315+ - PR metadata -> ` azure-devops-node-api ` REST call to ADO
316316 - Changed files -> iteration API calls
317- - UTC time -> ` datetime .now(timezone.utc )`
317+ - UTC time -> ` Date .now()`
3183183 . ** Failure policies** -- ` fail_closed ` , ` fail_open ` , ` skip_dependents `
3193194 . ** Predicate evaluation** -- recursive evaluator supporting all predicate types
3203205 . ** Result reporting** -- ` ##vso[...] ` logging commands, build tags, self-cancel
@@ -343,7 +343,7 @@ The bash shim exports only the ADO macros needed by the spec's facts:
343343| ` numeric_range ` | ` fact ` , ` min? ` , ` max? ` | Integer range check |
344344| ` time_window ` | ` start ` , ` end ` | UTC HH:MM window (overnight-aware) |
345345| ` label_set_match ` | ` fact ` , ` any_of? ` , ` all_of? ` , ` none_of? ` | Label set predicates |
346- | ` file_glob_match ` | ` fact ` , ` include? ` , ` exclude? ` | Python ` fnmatch ` globs |
346+ | ` file_glob_match ` | ` fact ` , ` include? ` , ` exclude? ` | Glob match against changed file paths |
347347| ` and ` | ` operands ` | All must pass |
348348| ` or ` | ` operands ` | At least one must pass |
349349| ` not ` | ` operand ` | Inner must fail |
@@ -352,34 +352,30 @@ The bash shim exports only the ADO macros needed by the spec's facts:
352352
353353### TriggerFiltersExtension
354354
355- When Tier 2/3 filters are configured , the ` TriggerFiltersExtension `
355+ When any ` filters: ` configuration is present , the ` TriggerFiltersExtension `
356356(` src/compile/extensions/trigger_filters.rs ` ) activates via
357357` collect_extensions() ` . It implements ` CompilerExtension ` and controls:
358358
359- 1 . ** Download step** -- downloads ` scripts.zip ` from the ado-aw release
359+ 1 . ** Node install step** -- emits a ` NodeTool@0 ` step pinned to Node 20.x
360+ LTS so the gate evaluator has a runtime
361+ 2 . ** Download step** -- fetches ` ado-script.zip ` from the ado-aw release
360362 artifacts, verifies its SHA256 checksum via ` checksums.txt ` , then
361- extracts ` gate-eval.py ` to ` /tmp/ado-aw-scripts/gate-eval.py `
362- 2 . ** Gate step** -- calls ` compile_gate_step_external() ` to generate a step
363- that references the downloaded script (no inline heredoc)
364- 3 . ** Validation** -- runs ` validate_pr_filters() ` / ` validate_pipeline_filters() `
363+ extracts ` gate.js ` to ` /tmp/ado-aw-scripts/ado-script/dist/gate/index.js `
364+ 3 . ** Gate step** -- calls ` compile_gate_step_external() ` to generate a step
365+ that runs ` node /tmp/ado-aw-scripts/ado- script/dist/gate/index.js ` (no inline heredoc)
366+ 4 . ** Validation** -- runs ` validate_pr_filters() ` / ` validate_pipeline_filters() `
365367 during compilation via the ` validate() ` trait method
366368
367369The extension uses the ` setup_steps() ` trait method (not ` prepare_steps() ` )
368- because the gate must run in the ** Setup job** (before the SafeOutputs job).
369-
370- ### Tier 1 Inline Path
371-
372- When only Tier 1 filters are configured (pipeline variables -- title, author,
373- branch, commit-message, build-reason), the extension is NOT activated.
374- ` generate_pr_gate_step() ` generates an inline bash gate step directly, with
375- no Python evaluator and no download step.
370+ because the gate must run in the ** Setup job** (before the Agent job). All
371+ filter types are evaluated by the Node evaluator — there is no inline bash
372+ codegen path.
376373
377374### Gate Step Injection
378375
379376Gate steps are injected into the Setup job by ` generate_setup_job() ` in
380- ` common.rs ` . When the ` TriggerFiltersExtension ` is active, its
381- ` setup_steps() ` are collected and injected first (download + gate). When
382- only Tier 1 filters are present, the inline gate step is injected directly.
377+ ` common.rs ` . The ` TriggerFiltersExtension ` 's ` setup_steps() ` are collected
378+ and injected first (Node install + download + gate steps).
383379
384380User setup steps are conditioned on the gate output:
385381` condition: eq(variables['{stepName}.SHOULD_RUN'], 'true') `
@@ -406,13 +402,15 @@ The `expression` escape hatch is also ANDed if present.
406402
407403# ## Scripts Distribution
408404
409- ` gate-eval.py` lives at `scripts/gate-eval.py` in the repository and is
410- shipped inside a `scripts.zip` archive alongside the ado-aw binary. The
411- download URL is deterministic based on the ado-aw version :
412- ` https://github.com/githubnext/ado-aw/releases/download/v{VERSION}/scripts.zip`
405+ The `gate.js` bundle is built from the TypeScript workspace at
406+ ` scripts/ado-script/` and emitted to `scripts/ado-script/dist/gate/index.js`
407+ by the release workflow's build step. It ships inside the `ado-script.zip`
408+ release asset alongside any future bundled helpers. The download URL is
409+ deterministic based on the ado-aw version :
410+ ` https://github.com/githubnext/ado-aw/releases/download/v{VERSION}/ado-script.zip`
413411
414412A `checksums.txt` file is also published at the same URL base and used to
415- verify the SHA256 integrity of `scripts .zip` before extraction.
413+ verify the SHA256 integrity of `ado-script .zip` before extraction.
416414
417415# # Adding New Filter Types
418416
@@ -423,8 +421,9 @@ step-by-step guide. In summary:
423421 ` ado_exports()` , `dependencies()`, `failure_policy()`)
4244222. Add a `Predicate` variant if a new test shape is needed
4254233. Add a `PredicateSpec` variant for serialization
426- 4. Add an evaluator handler in `scripts/gate-eval.py` for the new predicate
427- type
424+ 4. Add an evaluator handler in `scripts/ado-script/src/gate/predicates.ts`
425+ for the new predicate type, and add corresponding tests in
426+ ` scripts/ado-script/src/gate/__tests__/`
4284275. Extend the lowering function (`lower_pr_filters` or
429428 ` lower_pipeline_filters` )
4304296. Add validation rules if the new filter can conflict with existing ones
0 commit comments