Skip to content

feat: global configuration for ADO feeds - #1831

Open
jamesadevine with Copilot wants to merge 5 commits into
mainfrom
copilot/add-global-supply-chain-filter
Open

feat: global configuration for ADO feeds#1831
jamesadevine with Copilot wants to merge 5 commits into
mainfrom
copilot/add-global-supply-chain-filter

Conversation

Copilot AI commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Pull request created by AI Agent

Copilot AI and others added 4 commits August 6, 2026 10:21
Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
1 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@jamesadevine
jamesadevine marked this pull request as ready for review August 6, 2026 11:21
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
1 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@jamesadevine

Copy link
Copy Markdown
Collaborator

/review

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Compiler Contract Reviewer completed the compiler contract review.

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

PR Security Reviewer completed the security review.

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed the test quality analysis.

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Compiler Contract Reviewer completed the compiler contract review.

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Rust Code Quality Reviewer completed the Rust code quality review.

@github-actions github-actions Bot 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.

Compiler contract review — clean

Checked this PR against the ado-aw compiler contracts (front-matter grammar, validated newtypes, IR/docs sync, codegen/lock drift, bash lint):

  • Front matter: packages is Option<PackageFeedConfig> with #[serde(default)] on SupplyChainConfig — existing workflows without it still parse. No rename/removal, so no codemod is needed.
  • Newtypes: feed, organization, and project all go through validated src/secure.rs newtypes (FeedRef, AdoUrlSegment) rather than raw String, matching the safe-output identifier rule, and is_valid_ado_url_segment correctly bans the leading-./space// cases that would otherwise produce a malformed URL.
  • Docs: docs/front-matter.md, docs/supply-chain.md, and docs/runtimes.md are all updated in the same PR and stay consistent with each other and with the derived-URL/precedence logic in types.rs and the three runtime extensions.
  • Network: the new pkgs.dev.azure.com endpoint is already in src/allowed_hosts.rs, so no network: allowlist change is required or missing.
  • Bash: the only touched bash:-generating helper (ensure_nuget_config_bash_step / ensure_npmrc_bash_step) is a signature refactor, not new script content — no new shellcheck surface.
  • No codegen/lock/smoke drift: this PR does not touch filter_ir.rs/Fact, .github/workflows/*.md, or tests/safe-outputs/, so none of the drift classes I check for apply here.

Good test coverage for precedence (feed-url > config > supply-chain.packages > public default), per-ecosystem opt-out, and the fail-closed no-org-resolvable case. No merge-blocking findings from the compiler-contract angle.

🏗️ Compiler contract review by Compiler Contract Reviewer · auto · 47.6 AIC · ⌖ 2.33 AIC · ⊞ 11.8K
Comment /review to run again

@github-actions github-actions Bot 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.

Security review of this diff: no regressions found.

The new supply-chain.packages feature composes derived feed URLs from organization/project/feed segments, but each of those is typed with a new validated newtype (AdoUrlSegment, reusing FeedRef) restricted to [A-Za-z0-9._-] (no /, no leading ., rejects at deserialization time via deny_unknown_fields). The fully-assembled URL is then passed through the existing validate_feed_url() (quote/injection rejection, scheme check) before being interpolated into the generated bash: steps in dotnet/node/python extensions — the same pattern already used for per-runtime feed-url:.

No write-capable token is touched, no new domain is added to the AWF allowlist (pkgs.dev.azure.com was already present in src/allowed_hosts.rs), and no existing validation was loosened — is_valid_ado_url_segment reuses the same strict allowlist as is_safe_path_segment. Test coverage for the unsafe-segment rejection paths looks thorough.

🔒 Security review by PR Security Reviewer · auto · 54.5 AIC · ⌖ 2.23 AIC · ⊞ 11.2K
Comment /review to run again

@github-actions github-actions Bot mentioned this pull request Aug 6, 2026

@github-actions github-actions Bot 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.

Security review

No security regressions found in this diff. The new supply-chain.packages feature reuses established patterns safely:

  • The organization/project segments used to build the derived feed URL are validated via the new AdoUrlSegment newtype ([A-Za-z0-9._-]), and the feed name via the existing FeedRef newtype (max one /, no .., no injection chars). The git-remote-inferred organization (not covered by front-matter deserialization) gets an explicit is_valid_ado_url_segment check in url_for before being embedded — good defense-in-depth.
  • The fully-derived URL is re-validated with validate_feed_url in CompileContext::package_feed_url before use, matching the existing feed-url: validation path.
  • No write-capable token or secret is introduced or newly projected into the Agent (Stage 1) step; these changes only affect which package-index URL/auth task (PipAuthenticate/npmAuthenticate/NuGetAuthenticate) is emitted, mirroring the pre-existing per-runtime feed-url: mechanism.
  • src/compile/ado_bundle.rs (the token-projection chokepoint) is untouched by this PR.

Nothing merge-blocking. Nice test coverage for precedence, opt-out, and the fail-closed no-org case.

🔒 Security review by PR Security Reviewer · auto · 39.8 AIC · ⌖ 13.6 AIC · ⊞ 11.3K
Comment /review to run again

@jamesadevine jamesadevine changed the title Considering global configuration for supply chain filter feat: global configuration for ADO feeds Aug 6, 2026

@github-actions github-actions Bot 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.

Reviewed the new supply-chain.packages shared feed feature (types.rs, extensions/mod.rs, and the three runtime extensions). One recurring correctness issue across all three runtime extensions: the config-skip warning branch calls ctx.package_feed_url()?, which performs org resolution and URL validation via ? even though the result is discarded except for .is_some() -- this can turn an unrelated, unused supply-chain.packages misconfiguration into a hard compile failure for runtimes that already opted out via config:. Flagged identically on all three files.

The rest of the new code (PackageFeedConfig deserialization, URL derivation, validation, AdoUrlSegment) looks sound and is well covered by tests.

🦀 Rust code quality review by Rust Code Quality Reviewer · auto · 80.4 AIC · ⌖ 2.1 AIC · ⊞ 11K
Comment /review to run again

Comment thread src/runtimes/dotnet/extension.rs Outdated
let effective_feed_url: Option<String> = match self.config.feed_url() {
Some(url) => Some(url.to_string()),
None if self.config.config().is_some() => {
if ctx.package_feed_url(PackageEcosystem::Dotnet)?.is_some() {

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.

? here can hard-fail compilation for a config that should just be silently skipped

This branch only exists to decide whether to emit a warning when runtimes.dotnet.config is set. But package_feed_url() also resolves the org and validates the derived URL, so if supply-chain.packages is configured without a resolvable org (or with an invalid derived URL), compilation now fails with an unrelated error -- even though the .NET runtime was never going to use that feed at all (it explicitly defers to config).

Suggested fix

Use a non-failing check here, e.g. inspect whether front_matter.supply_chain()...packages is present and applies_to(ecosystem) without invoking url_for/validate_feed_url, or swallow/log the error instead of propagating with ? in this diagnostic-only branch.

Comment thread src/runtimes/node/extension.rs Outdated
let effective_feed_url: Option<String> = match self.config.feed_url() {
Some(url) => Some(url.to_string()),
None if self.config.config().is_some() => {
if ctx.package_feed_url(PackageEcosystem::Node)?.is_some() {

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.

Same eager-? issue as the .NET/Python extensions

Calling package_feed_url() here (only to decide whether to warn) resolves the org and validates the URL even though this branch never uses the result -- Node defers to config. An unresolvable org or invalid derived segment turns an unrelated config:-based setup into a hard compile failure.

Suggested fix

Check applies_to/presence without invoking url_for in this diagnostic-only path, consistent across all three runtime extensions.

Comment thread src/runtimes/python/extension.rs Outdated
let effective_feed_url: Option<String> = match self.config.feed_url() {
Some(url) => Some(url.to_string()),
None if self.config.config().is_some() => {
if ctx.package_feed_url(PackageEcosystem::Python)?.is_some() {

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.

Same eager-? issue as the other runtime extensions

package_feed_url() performs org resolution + URL validation even in this diagnostic-only branch (deciding whether to emit the config: warning), so a bad/unresolvable supply-chain.packages config can fail Python compilation even though the feed is never applied here.

Suggested fix

Use a cheap presence/applies_to check instead of the full url_for resolution when only deciding whether to warn.

@github-actions github-actions Bot 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.

Verdict: no merge-blocking issues found.

Reviewed the new supply-chain.packages shared feed feature (PackageFeedConfig in types.rs, package_feed_url in extensions/mod.rs, and the dotnet/node/python extension wiring). Validation ordering is sound — SupplyChainConfig::validate() (which validates packages, including the leading-dot rejection) runs before any extension calls ctx.package_feed_url() in every compile target (build_pipeline_context in agentic_pipeline.rs), so an unsafe feed/org/project value cannot reach a generated URL unvalidated. is_valid_ado_url_segment correctly reuses the strict path-segment allowlist to avoid unescaped URL injection. Test coverage for the new type is thorough (precedence, opt-out, mutual exclusivity, org inference failure).

One maintainability note left inline: the feed-resolution precedence (feed-urlconfig: skip-with-warning → supply-chain.packages → default) is duplicated near-verbatim across the three runtime extensions and would benefit from a shared helper.

🦀 Rust code quality review by Rust Code Quality Reviewer · auto · 72.4 AIC · ⌖ 2.23 AIC · ⊞ 11K
Comment /review to run again

@github-actions github-actions Bot 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.

Solid test coverage overall for the new supply-chain.packages feature — precedence, opt-out, project-scoping, and the fail-closed no-org path are all exercised at both the unit (types.rs) and integration (compiler_tests.rs, per-runtime extension) levels. Two minor gaps flagged inline: (1) the config:-set + unresolvable-org interaction in each runtime extension isn't tested, and (2) the no-org integration test doesn't distinguish "no git remote" from "remote present but not ADO". Neither is merge-blocking; the core logic is well covered by direct unit tests on PackageFeedConfig.

🧪 Test quality analysis by Test Quality Sentinel · auto · 71.7 AIC · ⌖ 2.11 AIC · ⊞ 10.8K
Comment /review to run again

@github-actions github-actions Bot 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.

Reviewed for ado-aw compiler contract drift (front-matter grammar, safe-output/security newtypes, docs sync, codegen/lock drift). No issues found:

  • SupplyChainConfig.packages: Option<PackageFeedConfig> is additive and defaults via #[serde(default)], so no codemod is required for existing workflows.
  • PackageFeedConfig/AdoUrlSegment route through validated newtypes (FeedRef, AdoUrlSegment) and src/validate.rs primitives rather than raw String — consistent with the src/secure.rs contract.
  • New behavior is documented in docs/front-matter.md, docs/runtimes.md, and docs/supply-chain.md, and the cross-doc anchor (supply-chain.md#shared-package-feed-for-the-runtimes-packages) resolves correctly.
  • No .github/workflows/*.md / IR / gate-schema changes in this PR, so no lock-file or codegen drift to flag.
  • pkgs.dev.azure.com allowlist claim in the new doc section checks out against src/allowed_hosts.rs.

No merge-blocking findings.

🏗️ Compiler contract review by Compiler Contract Reviewer · auto · 68.4 AIC · ⌖ 12.3 AIC · ⊞ 11.8K
Comment /review to run again

@jamesadevine

Copy link
Copy Markdown
Collaborator

@copilot address reviewer suggestions

@github-actions github-actions Bot 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.

Test Quality review

Good breadth of coverage for the new supply-chain.packages feature — precedence, opt-out, project-scoping, and the org-resolution failure are all exercised at the PackageFeedConfig/types.rs unit level, and each of the three runtime extensions has matching precedence/opt-out/config-skip tests.

Two findings posted inline:

  1. Untested integration error path — none of the three runtime-extension test suites (python, node, dotnet) exercise declarations() when supply-chain.packages is set but no ADO org can be resolved. Every test there uses CompileContext::for_test_with_org, so the ?-propagation of ctx.package_feed_url()'s error through the actual call site used in production is never verified — only the lower-level PackageFeedConfig::url_for unit test in types.rs checks that. A regression that dropped or mis-formatted the error during extension integration would ship silently.
  2. Test claritytest_packages_rejects_unsafe_url_segments loops over four cases that fail for two unrelated reasons (charset validation vs. deny_unknown_fields); splitting the unknown-field case out would make a future failure immediately diagnosable instead of a generic "expected rejection" message.

Neither is merge-blocking; the second is a nice-to-have, but the first (item 1) is worth adding given it's the actual failure mode a user would hit.

🧪 Test quality analysis by Test Quality Sentinel · auto · 79.4 AIC · ⌖ 2.18 AIC · ⊞ 10.8K
Comment /review to run again

Comments that could not be inline-anchored

src/runtimes/python/extension.rs:95

No test exercises the error path here: when supply-chain.packages is configured but the org cannot be inferred, ctx.package_feed_url() returns Err, and this ? propagates it out of declarations(). Every existing packages-related test in this file uses CompileContext::for_test_with_org, so a regression that silently swallowed or mishandled this error during runtime-extension integration (as opposed to the unit-level PackageFeedConfig::url_for test in types.rs) would ship undetec…

src/compile/types.rs:568

This table-driven loop conflates two different failure mechanisms (rejected at Deserialize vs. only reachable via validate()), so when one case in the loop stops failing, the assertion just reports "expected rejection for: (yaml)" without saying which rule broke or why.

<details><summary>💡 Why it matters</summary>

The fourth case, unknown: true, tests #[serde(deny_unknown_fields)] — an orthogonal concern (schema strictness) from the URL-segment charset checks in the other three. If s…

…paths

Co-authored-by: jamesadevine <4742697+jamesadevine@users.noreply.github.com>

Copilot AI commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address reviewer suggestions

Addressed in 76b7d8b.

All three reviewer comments were the same issue: the diagnostic-only branch that decides whether to warn "config: takes precedence" called ctx.package_feed_url(...)?, which eagerly resolves the ADO org and validates the derived URL — so an unresolvable org could hard-fail compilation for a runtime that was never going to use the shared feed.

Added a non-failing ExtensionContext::has_package_feed(ecosystem) that only checks block presence + applies_to, and swapped it into the warn-only branches of the .NET, Node and Python extensions. The real resolution path still uses package_feed_url()? so a genuinely applied feed keeps failing closed.

Also added test_supply_chain_packages_skipped_for_config_owned_runtime, which compiles a config-owned runtime against an unresolvable supply-chain.packages org — it fails on the old code and passes now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants