Skip to content

gate.js emits addBuildTag(\"pr-gate:passed\"); ADO server rejects the colon #915

@jamesadevine

Description

@jamesadevine

Summary

In ado-aw v0.32.0 and v0.33.0 (and likely earlier), every code path in scripts/ado-script/src/gate/ emits a build tag of the form ${tag_prefix}:${suffix} (e.g. pr-gate:passed, pr-gate:skipped, pr-gate:draft-mismatch). Azure DevOps' tag REST endpoint puts the tag in the URL path (PUT …/builds/<id>/tags/pr-gate:passed), and ASP.NET's request-path validator rejects the : with:

##[error]A potentially dangerous Request.Path value was detected from the client (:).

That single line marks the Setup task as failed, which cascades to the whole pipeline failing. Every ado-aw workflow with a gate (i.e. every on.pr-using workflow once a PR build fires) hits this on every run today.

Repro

Triggered by opening a PR (or in our case a CI-triggered build via git push) in an Azure DevOps repository against a pipeline compiled from an ado-aw agent with on.pr configured. Full failing build: msazuresphere/4x4 build 611836 (private, but the log excerpt below is representative).

2026-06-08T20:26:11.8616304Z Not a PR build -- gate passes automatically
2026-06-08T20:26:11.8756523Z
2026-06-08T20:26:11.8774003Z ##[section]Async Command Start: Add Build Tag
2026-06-08T20:26:12.1057572Z ##[section]Async Command End: Add Build Tag
2026-06-08T20:26:12.1076019Z ##[error]A potentially dangerous Request.Path value was detected from the client (:).
2026-06-08T20:26:12.1080695Z ##[section]Finishing: Evaluate PR filters

The build tag in this run was pr-gate:passed, emitted from bypass.ts.

Root cause

Four call sites in the gate emit colon-separated build tags:

  • scripts/ado-script/src/gate/bypass.ts:17addBuildTag(\${spec.context.tag_prefix}:passed`)`
  • scripts/ado-script/src/gate/selfcancel.ts:6addBuildTag(\${e.context.tag_prefix}:skipped`)`
  • scripts/ado-script/src/gate/predicates.tsaddBuildTag(\${e.context.tag_prefix}:${o.tag_suffix}`)` (failed-check path)

tag_prefix is pr-gate (set in src/compile/filter_ir.rs::tag_prefix) and pipeline-gate, both of which trigger the same server-side rejection.

Proposed fix

Replace : with . as the separator in all four call sites:

- addBuildTag(`${spec.context.tag_prefix}:passed`);
+ addBuildTag(`${spec.context.tag_prefix}.passed`);

(Or URL-encode the tag before emission — :%3A — but the literal-dot form is friendlier to consumers grepping the tag list.) Bump patch version.

Acceptance criteria

  • Unit test for addBuildTag asserting the emitted ##vso[build.addbuildtag]… line contains no :.
  • All four sites updated.
  • A snapshot test for one compiled pipeline confirms tag_prefix itself still has no : (defensive).
  • Patch release cut.

Blast radius

Anyone consuming the existing colon-form build tags (e.g. ADO dashboards, custom build queries) will need to update their filters. The format is internal to the gate, so I'd expect this to be near-zero, but worth a CHANGELOG note.

Why this matters / blocks other work

Until this is fixed, every path through gate.js fails on the addBuildTag step, so no PR-gated workflow can actually run. This is also a hard prerequisite for the separate "synthetic PR context from CI" feature I'll file as a follow-up issue — that work assumes the successful gate path actually succeeds.

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions