Skip to content

Upstream-aware downstream CI (#4860) - #4874

Merged
Yuchao Yan (msyyc) merged 26 commits into
Azure:mainfrom
msyyc:design/upstream-aware-emitter-ci
Jul 22, 2026
Merged

Yuchao Yan (msyyc) merged 26 commits into
Azure:mainfrom
msyyc:design/upstream-aware-emitter-ci

Conversation

@msyyc

@msyyc Yuchao Yan (msyyc) commented Jul 13, 2026 •

Copy link
Copy Markdown
Member

Implements #4860.

What

Adds upstream-aware downstream CI: when a PR/merge-group changes an upstream dependency (compiler core/ submodule or in-repo libs like typespec-client-generator-core), the affected downstream emitter checks now run automatically. Closes the gap where an upstream-only change could merge with no emitter check.

How

  • Upstream package dependencies are derived from the real pnpm workspace graph (pnpm --filter "...<pkg>"), not a hand-maintained list — adding a new upstream lib needs zero config changes and cannot drift/under-trigger.
  • eng/scripts/detect-affected.ts (zero external deps, run directly via node; node --test unit/contract tests) — diffs the event's base..head (event-aware for pull_request vs merge_group), self-filters ignored files (**/test/**, **/tests/**, **/*.md), maps changes to workspace packages, expands to graph dependents, and emits one boolean output per target.
  • The small residual config the graph can't express is an inlined typed CONFIG in detect-affected.ts: per-target package name, CI-infra extra paths, and a coreSubmodule flag (for core/ submodule bumps).
  • .github/workflows/ci-downstream.yml — always-on entrypoint: detect-affected -> conditional per-target reusable-workflow jobs -> downstream-ci-gate.
  • ci-python/java/typescript.yml converted to on: workflow_call (invoked only by the entrypoint -> no double-runs).

Follow-up required before this gates merges (Strategy A migration)

A repo admin must add downstream / CI / Downstream CI Gate to required status checks (PR + merge queue) and remove any obsolete standalone emitter check names in the same window.

@azure-sdk-automation

Copy link
Copy Markdown
Contributor

No changes needing a change description found.

In workflow_call context github.workflow resolves to the caller
(downstream / CI), so ci-python and ci-java computed an identical
concurrency group and cancelled each other, leaving only TypeScript
to dispatch. Concurrency is already handled by the ci-downstream
entrypoint, so drop the redundant per-workflow blocks.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Jul 13, 2026 •

Copy link
Copy Markdown
Contributor

⚡ Benchmark Results

⚠️ 6 metric(s) regressed above the +5% threshold:

Metric Baseline Current Change
loader 🟡 304.5ms 🟡 320.1ms +5.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-header-explode 🔴 26.5ms 🔴 28.3ms +7.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-query-explode 🔴 27.6ms 🔴 29.5ms +6.8% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-agent-base-type-child-resources 🔴 20.3ms 🔴 22.4ms +10.2% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/lro-location-header 🟡 19.5ms 🔴 20.8ms +6.7% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-response-body 🔴 29.5ms 🔴 31.2ms +5.6% 🔴
Full details – comparing f12f73c vs baseline rolling-baseline-3b1e01f-e161baf (rolling baseline (20 main runs))
Metric Baseline Current Change
total 🔴 1.00s 🔴 1.05s +4.4%
loader 🟡 304.5ms 🟡 320.1ms +5.1% 🔴
resolver 🟢 40.1ms 🟢 41.8ms +4.2%
checker 🟡 361.4ms 🟡 376.6ms +4.2%
validation 🟢 84.2ms 🟢 86.8ms +3.1%
 ↳ validation/@azure-tools/typespec-azure-core 🟡 12.5ms 🟡 13.3ms +6.2%
 ↳ validation/@typespec/http 🟡 15.4ms 🟡 16.1ms +4.6%
 ↳ validation/@typespec/rest 🟢 1.6ms 🟢 1.6ms +1.5%
 ↳ validation/@typespec/versioning 🔴 50.8ms 🔴 51.8ms +2.0%
 ↳ validation/compiler 🟢 3.8ms 🟢 3.9ms +2.4%
linter 🟡 213.4ms 🟡 222.7ms +4.4%
 ↳ linter/@azure-tools/typespec-azure-core/auth-required 🟢 0.1ms 🟢 0.1ms +3.8%
 ↳ linter/@azure-tools/typespec-azure-core/bad-record-type 🟢 0.6ms 🟢 0.6ms +1.0%
 ↳ linter/@azure-tools/typespec-azure-core/byos 🟢 8.3ms 🟢 8.5ms +2.5%
 ↳ linter/@azure-tools/typespec-azure-core/casing-style 🟢 1.4ms 🟢 1.5ms +2.0%
 ↳ linter/@azure-tools/typespec-azure-core/composition-over-inheritance 🟢 0.2ms 🟢 0.2ms +2.3%
 ↳ linter/@azure-tools/typespec-azure-core/documentation-required 🟢 1.9ms 🟢 2.0ms +3.0%
 ↳ linter/@azure-tools/typespec-azure-core/friendly-name 🟢 1.4ms 🟢 1.4ms +2.3%
 ↳ linter/@azure-tools/typespec-azure-core/key-visibility-required 🟢 0.4ms 🟢 0.4ms +2.9%
 ↳ linter/@azure-tools/typespec-azure-core/known-encoding 🟢 0.5ms 🟢 0.5ms +4.6%
 ↳ linter/@azure-tools/typespec-azure-core/long-running-polling-operation-required 🟢 0.8ms 🟢 0.8ms +1.5%
 ↳ linter/@azure-tools/typespec-azure-core/no-case-mismatch 🟢 0.7ms 🟢 0.7ms +6.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-closed-literal-union 🟢 1.0ms 🟢 1.0ms +0.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-enum 🟢 0.2ms 🟢 0.2ms +1.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-error-status-codes 🟢 0.3ms 🟢 0.3ms +1.5%
 ↳ linter/@azure-tools/typespec-azure-core/no-explicit-routes-resource-ops 🟢 0.2ms 🟢 0.2ms +2.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-format 🟢 0.8ms 🟢 0.8ms +3.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-generic-numeric 🟢 0.8ms 🟢 0.8ms +1.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-header-explode 🔴 26.5ms 🔴 28.3ms +7.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-legacy-usage 🟢 2.1ms 🟢 2.1ms +2.8%
 ↳ linter/@azure-tools/typespec-azure-core/no-multiple-discriminator 🟢 0.2ms 🟢 0.3ms +7.8%
 ↳ linter/@azure-tools/typespec-azure-core/no-nullable 🟢 0.4ms 🟢 0.4ms +2.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-offsetdatetime 🟢 2.0ms 🟢 2.0ms +4.1%
 ↳ linter/@azure-tools/typespec-azure-core/no-openapi 🟢 2.3ms 🟢 2.3ms +0.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-private-usage 🟢 3.2ms 🟢 3.2ms +1.9%
 ↳ linter/@azure-tools/typespec-azure-core/no-query-explode 🔴 27.6ms 🔴 29.5ms +6.8% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-response-body 🔴 33.2ms 🔴 34.6ms +4.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-rest-library-interfaces 🟢 0.1ms 🟢 0.1ms +1.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-route-parameter-name-mismatch 🟢 7.6ms 🟢 8.0ms +5.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-rpc-path-params 🟢 0.4ms 🟢 0.4ms +5.5%
 ↳ linter/@azure-tools/typespec-azure-core/no-string-discriminator 🟢 0.1ms 🟢 0.2ms +7.5%
 ↳ linter/@azure-tools/typespec-azure-core/no-unknown 🟢 0.3ms 🟢 0.4ms +4.8%
 ↳ linter/@azure-tools/typespec-azure-core/no-unnamed-union 🟢 0.8ms 🟢 0.8ms +1.4%
 ↳ linter/@azure-tools/typespec-azure-core/operation-missing-api-version 🟢 0.4ms 🟢 0.4ms -1.7%
 ↳ linter/@azure-tools/typespec-azure-core/request-body-problem 🟢 0.5ms 🟢 0.5ms +2.5%
 ↳ linter/@azure-tools/typespec-azure-core/require-versioned 🟢 0.1ms 🟢 0.1ms +4.3%
 ↳ linter/@azure-tools/typespec-azure-core/response-schema-problem 🔴 32.3ms 🔴 33.5ms +3.7%
 ↳ linter/@azure-tools/typespec-azure-core/rpc-operation-request-body 🟢 0.7ms 🟢 0.7ms +2.3%
 ↳ linter/@azure-tools/typespec-azure-core/spread-discriminated-model 🟢 0.4ms 🟢 0.5ms +3.9%
 ↳ linter/@azure-tools/typespec-azure-core/use-standard-names 🟢 7.5ms 🟢 7.9ms +5.6%
 ↳ linter/@azure-tools/typespec-azure-core/use-standard-operations 🟢 0.3ms 🟢 0.3ms +2.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-agent-base-type-child-resources 🔴 20.3ms 🔴 22.4ms +10.2% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-agent-base-type-lifecycle-operations 🟢 0.2ms 🟢 0.3ms +5.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-common-types-version 🟡 12.0ms 🟡 12.6ms +5.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-no-key 🟢 0.2ms 🟢 0.2ms +6.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage 🟢 0.1ms 🟢 0.1ms +6.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-delete-operation-response-codes 🟢 5.2ms 🟢 4.6ms -12.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-feature-file-usage-discourage 🟢 0.1ms 🟢 0.1ms +3.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-path-casing-conflicts 🟡 16.9ms 🟡 17.3ms +2.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-record 🟢 0.6ms 🟢 0.6ms +1.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-post-operation-response-codes 🟢 1.4ms 🟢 1.4ms +1.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-put-operation-response-codes 🟢 0.2ms 🟢 0.2ms -4.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-action-no-segment 🟢 0.4ms 🟢 0.5ms +1.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-duplicate-property 🟢 0.4ms 🟢 0.4ms +1.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-interface-requires-decorator 🟢 0.1ms 🟢 0.1ms +5.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-action-verb 🟢 0.2ms 🟢 0.2ms +1.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-envelope-property 🟢 0.3ms 🟢 0.3ms +3.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-version-format 🟢 0.2ms 🟢 0.2ms +3.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-key-invalid-chars 🟢 0.5ms 🟢 0.5ms +3.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-name-pattern 🟢 0.1ms 🟢 0.1ms +7.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation 🟢 0.5ms 🟢 0.6ms +2.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation-response 🟢 8.9ms 🟢 9.1ms +2.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-patch 🟢 0.8ms 🟢 0.8ms -1.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-path-segment-invalid-chars 🟢 0.4ms 🟢 0.4ms +3.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-provisioning-state 🟢 0.4ms 🟢 0.4ms +1.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/beyond-nesting-levels 🟢 0.2ms 🟢 0.2ms +1.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/empty-updateable-properties 🟢 0.4ms 🟢 0.4ms +3.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/improper-subscription-list-operation 🟢 0.1ms 🟢 0.1ms +7.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/lro-location-header 🟡 19.5ms 🔴 20.8ms +6.7% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-operations-endpoint 🟢 0.1ms 🟢 0.1ms +3.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-x-ms-identifiers 🟢 1.0ms 🟢 1.0ms +0.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-empty-model 🟢 0.3ms 🟢 0.3ms +1.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-override-props 🟢 0.3ms 🟢 0.3ms +0.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-reserved-resource-property 🟢 0.2ms 🟢 0.2ms +0.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-resource-delete-operation 🟢 0.5ms 🟢 0.5ms +6.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-response-body 🔴 29.5ms 🔴 31.2ms +5.6% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/patch-envelope 🟢 0.4ms 🟢 0.4ms +2.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/resource-name 🟢 0.4ms 🟢 0.4ms +0.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/secret-prop 🟢 5.3ms 🟢 5.4ms +1.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/unsupported-type 🟢 0.7ms 🟢 0.7ms +3.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/version-progression 🟢 0.3ms 🟢 0.3ms -2.5%
 ↳ linter/@azure-tools/typespec-client-generator-core/property-name-conflict 🟢 2.3ms 🟢 2.4ms +3.0%
 ↳ linter/@azure-tools/typespec-client-generator-core/require-client-suffix 🟢 1.7ms 🟢 1.7ms +0.6%
emit 🔴 5.98s 🔴 6.24s +4.4%
 ↳ emit/Azure-Tools 🟢 0.0ms 🟢 0.0ms +0.0%
 ↳ emit/@azure-tools/typespec-autorest 🟢 124.1ms 🟢 127.8ms +3.0%
 ↳ emit/@azure-tools/typespec-python 🔴 2.23s 🔴 2.34s +4.9%
 ↳ emit/typespec 🟢 0.0ms 🟢 0.0ms +0.0%
 ↳ emit/@typespec/http-client-js 🔴 566.1ms 🔴 582.9ms +3.0%
 ↳ emit/@typespec/openapi3 🟢 106.7ms 🟢 111.8ms +4.8%
 ↳ emit/@typespec/openapi3/compute 🟢 92.7ms 🟢 97.1ms +4.8%
 ↳ emit/@typespec/openapi3/write 🟢 13.7ms 🟢 14.4ms +5.1%

Averaged across 3 specs (azure-arm-resource-manager, azure-core-dataplane, azure-full).
Threshold: changes > ±5% are highlighted.
🟢 Fast · 🟡 Moderate (stages >200ms, rules >10ms) · 🔴 Slow (stages >400ms, rules >20ms)

- Remove docs/superpowers process artifacts from the PR (kept in session)
- Drop // @ts-check from detect-affected(.test).js: they import untyped
  js-yaml/minimatch that are not resolvable by root tsc during check:eng
  (matches existing lint-resourcemanager.js convention)
- Rename config key core-submodule -> coreSubmodule for valid JSDoc and
  clean property access
- prettier-format the scripts

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@azure-sdk-automation

Copy link
Copy Markdown
Contributor

You can try these changes here

🛝 Playground 🌐 Website

Replace the hand-maintained upstream dependency map with the real pnpm
workspace graph: changed files are self-filtered (test/**, *.md) in code,
mapped to their workspace packages, then expanded to graph dependents via
pnpm. This removes the drift-prone map (which under-triggered by omitting
autorest/rulesets) and covers all upstream deps automatically.

- Rewrite detect-affected as zero-dependency TypeScript run directly on
  Node (native type-stripping), no tsx and no js-yaml/minimatch.
- Inline the small residual config (per-target package name, CI-infra
  extra paths, coreSubmodule) that the graph cannot express as a typed const.
- Self-filter ignored files in code instead of pnpm --changed-files-ignore-pattern,
  which unreliably matches non-trailing-** globs.
- Enable allowImportingTsExtensions for eng tsconfig so the colocated test
  can import the .ts module under Node's native runner.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

⚡ External Spec Benchmark Results

⚠️ 5 metric(s) regressed above the +5% threshold:

Metric Baseline Current Change
 ↳ validation/@azure-tools/typespec-client-generator-core 🔴 20.4ms 🔴 24.5ms +20.4% 🔴
 ↳ validation/@typespec/rest 🔴 23.4ms 🔴 26.3ms +12.3% 🔴
 ↳ validation/compiler 🔴 24.7ms 🔴 27.9ms +13.0% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-rest-library-interfaces 🟡 16.4ms 🟡 17.6ms +7.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-record 🟢 3.4ms 🟢 4.6ms +34.5% 🔴
Full details – comparing f12f73c vs baseline rolling-baseline-3497e82-e161baf (rolling baseline (2 main runs))
Metric Baseline Current Change
total 🔴 6.97s 🔴 6.60s -5.3% 🟢
loader 🔴 2.04s 🔴 1.85s -9.4% 🟢
resolver 🟢 152.3ms 🟢 157.4ms +3.4%
checker 🔴 1.55s 🔴 1.52s -1.6%
validation 🟡 382.7ms 🟡 390.3ms +2.0%
 ↳ validation/@azure-tools/typespec-azure-core 🟢 0.2ms 🟢 0.2ms +4.8%
 ↳ validation/@azure-tools/typespec-client-generator-core 🔴 20.4ms 🔴 24.5ms +20.4% 🔴
 ↳ validation/@typespec/http 🔴 158.3ms 🔴 153.3ms -3.2%
 ↳ validation/@typespec/rest 🔴 23.4ms 🔴 26.3ms +12.3% 🔴
 ↳ validation/@typespec/versioning 🔴 154.3ms 🔴 156.2ms +1.2%
 ↳ validation/compiler 🔴 24.7ms 🔴 27.9ms +13.0% 🔴
linter 🔴 2.83s 🔴 2.69s -5.0%
 ↳ linter/@azure-tools/typespec-azure-core/auth-required 🟢 0.1ms 🟢 0.1ms +4.7%
 ↳ linter/@azure-tools/typespec-azure-core/byos 🔴 131.4ms 🔴 127.3ms -3.1%
 ↳ linter/@azure-tools/typespec-azure-core/casing-style 🟢 9.6ms 🟢 9.8ms +2.1%
 ↳ linter/@azure-tools/typespec-azure-core/composition-over-inheritance 🟢 1.0ms 🟢 1.0ms +0.2%
 ↳ linter/@azure-tools/typespec-azure-core/documentation-required 🟡 14.1ms 🟡 14.4ms +2.5%
 ↳ linter/@azure-tools/typespec-azure-core/friendly-name 🟡 10.4ms 🟡 10.4ms -0.0%
 ↳ linter/@azure-tools/typespec-azure-core/key-visibility-required 🟢 3.2ms 🟢 3.3ms +3.0%
 ↳ linter/@azure-tools/typespec-azure-core/known-encoding 🟢 2.9ms 🟢 2.8ms -2.1%
 ↳ linter/@azure-tools/typespec-azure-core/long-running-polling-operation-required 🟢 5.5ms 🟢 5.4ms -2.7%
 ↳ linter/@azure-tools/typespec-azure-core/no-case-mismatch 🟢 3.3ms 🟢 3.3ms +2.0%
 ↳ linter/@azure-tools/typespec-azure-core/no-closed-literal-union 🟢 5.2ms 🟢 5.4ms +4.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-enum 🟢 0.4ms 🟢 0.4ms +2.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-error-status-codes 🟢 2.1ms 🟢 2.1ms +1.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-explicit-routes-resource-ops 🟢 1.5ms 🟢 1.5ms +0.5%
 ↳ linter/@azure-tools/typespec-azure-core/no-format 🟢 7.3ms 🟢 7.6ms +3.2%
 ↳ linter/@azure-tools/typespec-azure-core/no-generic-numeric 🟢 3.6ms 🟢 3.7ms +1.8%
 ↳ linter/@azure-tools/typespec-azure-core/no-header-explode 🔴 282.9ms 🔴 259.8ms -8.1% 🟢
 ↳ linter/@azure-tools/typespec-azure-core/no-legacy-usage 🔴 22.5ms 🔴 22.0ms -2.1%
 ↳ linter/@azure-tools/typespec-azure-core/no-multiple-discriminator 🟢 0.8ms 🟢 0.8ms -0.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-nullable 🟢 2.9ms 🟢 2.9ms +1.4%
 ↳ linter/@azure-tools/typespec-azure-core/no-offsetdatetime 🟡 15.2ms 🟡 15.0ms -1.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-openapi 🔴 36.5ms 🔴 36.3ms -0.4%
 ↳ linter/@azure-tools/typespec-azure-core/no-private-usage 🔴 35.1ms 🔴 36.2ms +3.2%
 ↳ linter/@azure-tools/typespec-azure-core/no-query-explode 🔴 290.7ms 🔴 270.8ms -6.8% 🟢
 ↳ linter/@azure-tools/typespec-azure-core/no-rest-library-interfaces 🟡 16.4ms 🟡 17.6ms +7.1% 🔴
 ↳ linter/@azure-tools/typespec-azure-core/no-route-parameter-name-mismatch 🔴 128.6ms 🔴 116.7ms -9.3% 🟢
 ↳ linter/@azure-tools/typespec-azure-core/no-rpc-path-params 🟢 1.9ms 🟢 2.0ms +4.6%
 ↳ linter/@azure-tools/typespec-azure-core/no-string-discriminator 🟢 0.6ms 🟢 0.6ms -2.3%
 ↳ linter/@azure-tools/typespec-azure-core/no-unknown 🟢 2.2ms 🟢 2.2ms +0.2%
 ↳ linter/@azure-tools/typespec-azure-core/no-unnamed-union 🟢 5.4ms 🟢 5.6ms +4.0%
 ↳ linter/@azure-tools/typespec-azure-core/operation-missing-api-version 🟢 3.3ms 🟢 3.4ms +2.8%
 ↳ linter/@azure-tools/typespec-azure-core/request-body-problem 🟢 5.1ms 🟢 5.5ms +6.8%
 ↳ linter/@azure-tools/typespec-azure-core/require-versioned 🟢 0.1ms 🟢 0.1ms -4.1%
 ↳ linter/@azure-tools/typespec-azure-core/response-schema-problem 🔴 324.9ms 🔴 307.7ms -5.3% 🟢
 ↳ linter/@azure-tools/typespec-azure-core/rpc-operation-request-body 🟢 0.7ms 🟢 0.7ms -2.0%
 ↳ linter/@azure-tools/typespec-azure-core/spread-discriminated-model 🟢 3.4ms 🟢 3.6ms +3.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-agent-base-type-child-resources 🔴 66.9ms 🔴 62.8ms -6.1% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-agent-base-type-lifecycle-operations 🟢 0.2ms 🟢 0.2ms -7.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-common-types-version 🔴 127.7ms 🔴 124.6ms -2.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-no-key 🟢 0.9ms 🟢 0.9ms -3.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-custom-resource-usage-discourage 🟢 0.6ms 🟢 0.6ms -1.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-delete-operation-response-codes 🟢 3.7ms 🟢 3.6ms -2.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-feature-file-usage-discourage 🟢 0.0ms 🟢 0.1ms +9.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-path-casing-conflicts 🔴 146.4ms 🔴 147.5ms +0.7%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-no-record 🟢 3.4ms 🟢 4.6ms +34.5% 🔴
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-post-operation-response-codes 🟢 9.9ms 🟢 9.0ms -9.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-put-operation-response-codes 🟢 0.3ms 🟢 0.3ms +4.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-action-no-segment 🟢 4.4ms 🟢 4.3ms -2.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-duplicate-property 🟢 1.0ms 🟢 1.0ms -4.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-interface-requires-decorator 🟢 0.5ms 🟢 0.5ms +5.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-action-verb 🟢 1.5ms 🟢 1.5ms +2.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-envelope-property 🟢 0.8ms 🟢 0.8ms -0.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-invalid-version-format 🟢 0.3ms 🟢 0.3ms -0.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-key-invalid-chars 🟢 1.9ms 🟢 1.8ms -3.8%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-name-pattern 🟢 0.2ms 🟢 0.2ms +2.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation 🟢 3.3ms 🟢 3.4ms +4.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-operation-response 🔴 66.4ms 🔴 65.3ms -1.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-patch 🟢 4.1ms 🟢 4.0ms -4.3%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-path-segment-invalid-chars 🟢 1.4ms 🟢 1.4ms +0.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/arm-resource-provisioning-state 🟢 0.9ms 🟢 1.0ms +3.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/beyond-nesting-levels 🟢 0.8ms 🟢 0.8ms -1.4%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/empty-updateable-properties 🟢 1.5ms 🟢 1.5ms +2.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/improper-subscription-list-operation 🟢 0.1ms 🟢 0.1ms +8.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/lro-location-header 🔴 287.6ms 🔴 264.5ms -8.0% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-operations-endpoint 🟢 0.2ms 🟢 0.2ms -3.5%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/missing-x-ms-identifiers 🟢 4.4ms 🟢 4.5ms +1.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-empty-model 🟢 0.7ms 🟢 0.8ms +4.0%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-override-props 🟢 0.7ms 🟢 0.8ms +9.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-reserved-resource-property 🟢 0.7ms 🟢 0.7ms -0.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-resource-delete-operation 🟢 2.2ms 🟢 2.3ms +5.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/no-response-body 🔴 473.8ms 🔴 443.4ms -6.4% 🟢
 ↳ linter/@azure-tools/typespec-azure-resource-manager/patch-envelope 🟢 1.5ms 🟢 1.5ms +1.2%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/resource-name 🟢 1.6ms 🟢 1.7ms +5.1%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/secret-prop 🔴 82.4ms 🔴 80.0ms -2.9%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/unsupported-type 🟢 4.1ms 🟢 4.1ms +0.6%
 ↳ linter/@azure-tools/typespec-azure-resource-manager/version-progression 🟢 0.3ms 🟢 0.3ms -1.6%
 ↳ linter/@azure-tools/typespec-client-generator-core/property-name-conflict 🔴 29.7ms 🔴 30.1ms +1.5%
 ↳ linter/@azure-tools/typespec-client-generator-core/require-client-suffix 🟢 6.6ms 🟢 6.8ms +2.2%
emit 🔴 11.50s 🔴 11.42s -0.7%
 ↳ emit/Azure-Tools 🟢 0.0ms 🟢 0.0ms +0.0%
 ↳ emit/@azure-tools/typespec-client-generator-core 🔴 5.75s 🔴 5.71s -0.7%

Averaged across 3 specs (compute, network, web).
Threshold: changes > ±5% are highlighted.
🟢 Fast · 🟡 Moderate (stages >200ms, rules >10ms) · 🔴 Slow (stages >400ms, rules >20ms)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an always-on “downstream / CI” entrypoint workflow that detects which downstream emitter CI jobs (Python/Java/TypeScript) are affected by upstream dependency changes, and then conditionally runs the corresponding reusable workflows to ensure emitter checks aren’t skipped when upstream-only changes land.

Changes:

  • Added downstream / CI workflow that runs an “affected targets” detector and gates results.
  • Added a new detect-affected script (and accompanying tests) to compute per-target boolean outputs.
  • Converted existing per-emitter CI workflows (python/java/typespec-ts) to workflow_call so they can be orchestrated by the entrypoint.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tsconfig.eng.json Enables TS extension imports for eng scripts/tests.
eng/scripts/package.json Adds a new dependency for eng scripts.
eng/scripts/detect-affected.ts Implements affected-target detection using git diff + pnpm workspace graph + extra path triggers.
eng/scripts/detect-affected.test.ts Adds node:test unit tests for the detection logic.
.github/workflows/ci-typescript.yml Converts TypeScript CI to a reusable workflow (workflow_call).
.github/workflows/ci-python.yml Converts Python CI to a reusable workflow (workflow_call).
.github/workflows/ci-java.yml Converts Java CI to a reusable workflow (workflow_call).
.github/workflows/ci-downstream.yml Adds the orchestrating “downstream / CI” workflow and a gate job.

Comment thread eng/scripts/detect-affected.ts Resolved
Comment thread eng/scripts/detect-affected.ts Resolved
Comment thread eng/scripts/detect-affected.ts Resolved
Comment thread .github/workflows/ci-downstream.yml Resolved
Comment thread eng/scripts/package.json Resolved
Comment thread eng/scripts/detect-affected.test.ts Resolved
Yuchao Yan (msyyc) and others added 2 commits July 14, 2026 15:19
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
…ector tests

- Correct the 'add a target' comment to reference CONFIG.targets (was TARGETS).
- Add **/tests/** to the ignore globs so plural tests directories (e.g.
  typespec-python/tests) are treated as non-meaningful like **/test/**.
- Remove the now-unused minimatch dependency (replaced by the built-in
  glob matcher during the pnpm-graph refactor).
- Run the detector unit tests in CI via 'node --test' in the detect-affected
  job, and add a 'test:eng' root script for local parity.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@msyyc

Copy link
Copy Markdown
Member Author

Timothee Guerin (@timotheeguerin) updated with your review comment and pls help review again.

Yuchao Yan (msyyc) and others added 5 commits July 17, 2026 09:47
Co-authored-by: Timothee Guerin <timothee.guerin@outlook.com>
Co-authored-by: Timothee Guerin <timothee.guerin@outlook.com>
Migrate eng/scripts/detect-affected.test.ts from node:test to the vitest
API and register eng/ as a vitest project so the detector unit test runs
as part of the normal `pnpm test` suite (ci.yml), mirroring the eng test
setup in typespec core.

- eng/vitest.config.ts: new project config merging defaultTypeSpecVitestConfig
- register eng/vitest.config.ts in vitest.config.fast.ts and vitest.config.ts
- test file now uses describe/it/expect and mocks console.log
- tsconfig.eng.json: exclude eng/vitest.config.ts (imports core, like core/eng)
- package.json test:eng: node --test -> vitest run
- ci-downstream.yml: drop redundant node --test step (covered by ci.yml)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 62793370-fd78-402e-b139-26588818aa1e
Make adding a new emitter (e.g. go) a config-only change: introduce
eng/scripts/detect-affected.config.json as the single source of truth for
the ignore globs, shared/extra CI-infra paths, submodule path, and the
target -> package map. The detector, its test, and the workflow gate are
now generic and no longer enumerate emitters by name.

- detect-affected.ts: load CONFIG from the JSON (readFileSync); use
  config.submodulePath; emit a single `affected=<json>` GITHUB_OUTPUT
- detect-affected.test.ts: add config-guard tests (submodulePath set,
  every target has a package)
- ci-downstream.yml:
  - detect-affected exposes one `affected` JSON output; emitter jobs gate
    on `fromJSON(needs.detect-affected.outputs.affected).<target>`
  - gate validates results generically via `toJSON(needs)` + jq, so a new
    emitter only needs a `needs:` entry, not a script edit

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 62793370-fd78-402e-b139-26588818aa1e
The JSDoc example omitted `--depth -1`, which the code actually passes.
Align the comment with the real command.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 62793370-fd78-402e-b139-26588818aa1e
@msyyc

Copy link
Copy Markdown
Member Author

python ci failure is caused by #4909

Yuchao Yan (msyyc) and others added 2 commits July 20, 2026 17:01
typespec-go has merged into main, so wire it into the config-driven
downstream-CI orchestrator like the other emitters:

- add `go` target (@azure-tools/typespec-go) to detect-affected.config.json
- convert ci-go.yml from `on: pull_request` to `on: workflow_call`
- add a `go` job + gate `needs:` entry in ci-downstream.yml

Also make the computeAffected tests derive their expected shapes from
CONFIG.targets so adding a future emitter is a config-only change, matching
the recipe documented in detect-affected.ts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 62793370-fd78-402e-b139-26588818aa1e
@msyyc

Yuchao Yan (msyyc) commented Jul 21, 2026 •

Copy link
Copy Markdown
Member Author

⚠️ Follow-up for repo admins: make the downstream CI actually gate merges

This PR adds the downstream emitter CI (Integration workflow) with a single aggregating Gate job (if: always()), but the check is not yet enforced. The main ruleset "CI" (id 598502) currently requires only:

Build (ubuntu-latest, Node 22.x), Build (ubuntu-latest, Node 24.x), Build (windows-latest, Node 24.x), Check Changes, E2E Tests, Format, Lint, Spell check, Website, license/cla

None of the downstream contexts (Gate, Python / …, Java / …, TypeScript / …, Go / …) are in that list, so a failing emitter CI will not block merge until the ruleset is updated.

Action (admin, one-time): add the single context Gate to ruleset 598502's required_status_checks.

  • Require only Gate — it aggregates every emitter's result and fails if any downstream job failed/was cancelled. This is future-proof: adding a new emitter needs no ruleset change.
  • Do not add the individual emitter jobs (Go / Mock API Tests, Python / …, etc.) as required. They run conditionally via if: fromJSON(...).<target>, so they're skipped on unaffected PRs; requiring them directly leads to fragile skipped/pending-check behavior. Gate runs with if: always() and handles skips correctly.

Rulesets are GitHub server-side settings (Settings → Rules → Rulesets), not a file in this repo, so this cannot be done via a PR.

======================
Up words are posted by AI but I am not sure whether it is right solution to make the new Integration / Gate a required item like other required CI items. Timothee Guerin (@timotheeguerin), do you know how to make our new github action a required check?

@msyyc
Yuchao Yan (msyyc) added this pull request to the merge queue Jul 22, 2026
Merged via the queue into Azure:main with commit 1081f06 Jul 22, 2026
44 checks passed
@msyyc
Yuchao Yan (msyyc) deleted the design/upstream-aware-emitter-ci branch July 22, 2026 02:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants