Skip to content

Commit 0d81e7a

Browse files
docs(site): update filter-ir page to reflect Node/TypeScript gate evaluator (#634)
1 parent a36e96d commit 0d81e7a

1 file changed

Lines changed: 38 additions & 39 deletions

File tree

site/src/content/docs/reference/filter-ir.mdx

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,9 @@ require heuristic analysis and could produce false positives.
235235
### `compile_gate_step(ctx: GateContext, checks: &[FilterCheck]) -> String`
236236

237237
Produces 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
272271
quoting issues. Decoded, it contains:
273272
274273
```json
@@ -300,21 +299,22 @@ quoting issues. Decoded, it contains:
300299
```
301300

302301
The 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
304303
acquisition 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

311311
1. **Bypass logic** -- reads `ADO_BUILD_REASON` and exits early for non-matching
312312
trigger types
313313
2. **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()`
318318
3. **Failure policies** -- `fail_closed`, `fail_open`, `skip_dependents`
319319
4. **Predicate evaluation** -- recursive evaluator supporting all predicate types
320320
5. **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

367369
The 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

379376
Gate 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

384380
User 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

414412
A `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()`)
424422
2. Add a `Predicate` variant if a new test shape is needed
425423
3. 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__/`
428427
5. Extend the lowering function (`lower_pr_filters` or
429428
`lower_pipeline_filters`)
430429
6. Add validation rules if the new filter can conflict with existing ones

0 commit comments

Comments
 (0)