Skip to content

Use Azure Artifacts Maven feed for CFSClean network isolation compliance#35089

Merged
PureWeen merged 16 commits into
release/10.0.1xx-sr6from
fix/gradle-azure-artifacts-feed
Apr 27, 2026
Merged

Use Azure Artifacts Maven feed for CFSClean network isolation compliance#35089
PureWeen merged 16 commits into
release/10.0.1xx-sr6from
fix/gradle-azure-artifacts-feed

Conversation

@PureWeen

@PureWeen PureWeen commented Apr 22, 2026

Copy link
Copy Markdown
Member

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Problem

The official build pipeline (dotnet-maui, def 1095) fails because CFSClean network isolation blocks direct access to repo.maven.apache.org. This breaks two separate Gradle invocations:

  1. src/Core/AndroidNative build — our own Gradle project
  2. Microsoft.Android.Sdk.Bindings.Gradle.targets — Android SDK binding generator in Core.csproj

Per 1ES CFS guidance, the fix is to route all Maven dependency resolution through an Azure Artifacts feed with upstream sources.

Fix

Gradle configuration changes

  • settings.gradle — Replace mavenCentral(), google(), gradlePluginPortal() with the dotnet-public-maven Azure Artifacts feed. Add the Azure Artifacts Gradle credential provider plugin (v1.1.1) for local authentication.
  • build.gradle — Point buildscript.repositories to the same feed for AGP classpath resolution.
  • eng/init.gradle — Global Gradle init script that redirects any remaining Maven Central/Google Maven references (e.g. from Microsoft.Android.Sdk.Bindings.Gradle.targets) to the feed. Installed into GRADLE_USER_HOME by the pipeline.

Pipeline changes

  • cache-gradle.yml — Copy init.gradle into GRADLE_USER_HOME after cache restore to prevent stale cached copies. Uses $(GRADLE_USER_HOME) variable for the destination path.

Why the ingestion script (eng/ingest-maven-deps.sh) is needed

The dotnet-public-maven feed proxies Maven Central, but new packages require an authenticated first-time pull to be saved. The Gradle credential provider plugin has two limitations that prevent dotnet build from self-ingesting:

  1. Skips entirely in CI — when TF_BUILD=True (Azure Pipelines), the plugin is a no-op
  2. Doesn't cover all Gradle scopes — the plugin injects auth into pluginManagement.repositories and project.repositories, but NOT buildscript.repositories or AGP's internal detachedConfiguration scopes. This means dotnet build locally cannot ingest new packages through the Android SDK binding targets even with correct credentials.

We verified this by adding an un-ingested package (io.coil-kt:coil:2.7.0) — dotnet build fails with 401 despite the credential provider authenticating successfully.

Upstream issue: microsoft/artifacts-credprovider#671

The script works around these gaps by:

  1. Acquiring an auth token via the .NET credential provider (MSAL)
  2. Pre-ingesting platform-specific artifacts (aapt2) for all OS variants (macOS/Linux/Windows)
  3. Running Gradle with --refresh-dependencies to bypass local cache
  4. Falling back to curl with Bearer token for unreachable scopes

Run ./eng/ingest-maven-deps.sh after adding or updating any Maven/Gradle dependency.

Documentation updates

  • settings.gradle — explains the feed setup and when to run the script
  • gradle-wrapper.properties — warning not to upgrade Gradle past 8.x (dotnet/android#10738)
  • copilot-instructions.md — always-on guidance for Gradle 401 failures
  • azdo-build-investigator/SKILL.md — error signatures and DO NOTs for CI investigation
  • android.instructions.md — quick reference for Android developers

Verified

  • ✅ Internal official build 2961149 passed — Pack macOS + Pack Windows both green
  • ✅ Same pattern used by dotnet/aspnetcore (PR #64962)
  • ✅ Feed is public — no auth needed to read already-ingested packages, external contributors can build without credentials
  • ✅ Locally verified: dotnet build works for already-ingested packages, fails for new ones (confirming script is needed)

Replace mavenCentral(), google(), and gradlePluginPortal() with the
dnceng public Azure Artifacts Maven feed in settings.gradle, matching
the pattern used by dotnet/aspnetcore (PR dotnet/aspnetcore#64962).

Also install an init.gradle into GRADLE_USER_HOME that redirects any
remaining Maven Central/Google Maven repository references (e.g. from
Microsoft.Android.Sdk.Bindings.Gradle.targets) to the same Azure
Artifacts feed. This covers Gradle invocations outside of our control.

Feed: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-maven/maven/v1

This is the proper fix for CFSClean network isolation blocking
repo.maven.apache.org on Windows 1ES agents.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 22, 2026 13:18
@github-actions

github-actions Bot commented Apr 22, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35089

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35089"

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 updates the Android/Gradle dependency resolution used by MAUI’s build and CI pipeline to comply with CFSClean network isolation by routing Maven/Google/Plugin Portal access through the public dnceng Azure Artifacts Maven feed.

Changes:

  • Replace google(), mavenCentral(), and gradlePluginPortal() usage in AndroidNative Gradle settings with the Azure Artifacts Maven feed and enforce FAIL_ON_PROJECT_REPOS.
  • Add a global eng/init.gradle init script intended to redirect Maven/Google/Plugin Portal repositories to the Azure Artifacts feed for Gradle invocations MAUI doesn’t directly control.
  • Update the Gradle cache pipeline template to copy eng/init.gradle into GRADLE_USER_HOME.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
src/Core/AndroidNative/settings.gradle Routes plugin/dependency resolution through the Azure Artifacts Maven feed; enforces no project-level repos.
src/Core/AndroidNative/build.gradle Removes buildscript repository declarations (but still uses buildscript classpath).
eng/pipelines/common/cache-gradle.yml Copies eng/init.gradle into GRADLE_USER_HOME during cache setup on macOS/Windows.
eng/init.gradle Adds an init script to rewrite certain Maven repository URLs to the Azure Artifacts feed.

Comment thread eng/pipelines/common/cache-gradle.yml
Comment thread src/Core/AndroidNative/build.gradle
Comment thread eng/init.gradle Outdated
Comment thread src/Core/AndroidNative/settings.gradle
Comment thread eng/pipelines/common/cache-gradle.yml
FAIL_ON_PROJECT_REPOS blocks buildscript classpath resolution when
the Android SDK bindings Gradle targets invoke our project. Revert
to PREFER_PROJECT and keep buildscript.repositories pointing to the
Azure Artifacts feed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actions Bot and others added 2 commits April 23, 2026 10:06
The Cache@2 task can restore a stale init.gradle from a previous run.
Move the init.gradle copy step after cache restore so the current
version always wins.

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

MauiBot commented Apr 23, 2026

Copy link
Copy Markdown
Collaborator

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

1 similar comment
@MauiBot

MauiBot commented Apr 23, 2026

Copy link
Copy Markdown
Collaborator

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

@MauiBot

MauiBot commented Apr 24, 2026

Copy link
Copy Markdown
Collaborator

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

2 similar comments
@MauiBot

MauiBot commented Apr 24, 2026

Copy link
Copy Markdown
Collaborator

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

@MauiBot

MauiBot commented Apr 24, 2026

Copy link
Copy Markdown
Collaborator

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

Create the feed repo once via findByName/maven, then only remove
matching repos in the all{} callback. Previously each matching repo
created a new duplicate dotnet-public-maven entry.

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

@jonathanpeppers jonathanpeppers left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This looks find 👍 , but I wonder if it blocks any contributors from building.

Microsoft.Android.Sdk 36.1.2's net.android.init.gradle.kts has a
Kotlin type mismatch (String? vs Any) that fails with Gradle 9.x.
The fix is merged upstream (dotnet/android#10738) but hasn't shipped
in this SDK version. Revert to Gradle 8.13.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
github-actions Bot and others added 9 commits April 24, 2026 16:22
New packages added to build.gradle must be ingested into the
dotnet-public-maven Azure Artifacts feed before CI can use them.
This script automates that process using the credential provider
for auth and curl fallback for packages in scopes the Gradle
plugin doesn't cover.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Explain why ingestion is needed (CFSClean + credential provider
skips in CI), when to run it, how it works, and the common pitfall
of local Gradle cache masking missing feed packages.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The Android SDK's net.android.init.gradle.kts is incompatible with
Gradle 9.x due to stricter Kotlin type checking (String? vs Any).
Fix merged upstream (dotnet/android#10738) but not yet shipped in
the SDK version used by this branch.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- set -e killed the script when gradlew build failed (the normal
  case when packages need ingesting). Add || true to capture output.
- set -e + pipefail killed the script when grep found no matching
  URLs, preventing the 'not a feed issue' diagnostic. Add || true.
- Step 1 now logs a warning on failure instead of silently swallowing.
- Step 1 shows last 20 lines instead of 3 for better diagnostics.
- curl token moved from -H arg to --oauth2-bearer to avoid exposure
  in process listings (ps aux).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Hardcoded $HOME/.gradle could diverge from GRADLE_USER_HOME if it's
overridden. Use the pipeline variable to ensure init.gradle is always
copied to where Gradle actually reads it.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Gradle on macOS only resolves aapt2-osx.jar. CI builds on Windows
and Linux need their platform-specific variants pre-ingested too.
The script now explicitly curls all three OS classifiers (osx, linux,
windows) before running the Gradle build.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When agents or developers hit Gradle 401 errors from the Azure
Artifacts feed, they'll now see clear guidance: run the ingestion
script. Also added the Gradle 8.x version constraint.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This is always loaded regardless of which files are being worked on,
so agents investigating CI failures will see the guidance to run
eng/ingest-maven-deps.sh for Gradle 401 errors.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When agents investigate CI failures and see XAGRDL0000 or 401 errors
from the Maven feed, they'll now see the exact fix (run the ingestion
script) and explicit DO NOT guidance (don't remove CFSClean, don't
upgrade Gradle, don't add mavenCentral() back).

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

github-actions Bot commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

🔍 Skill Validation Results

❌ Static Checks Failed

Skills checked: 15 | Agents checked: 0

Full validator output
Found 1 skill(s)
[azdo-build-investigator] 📊 azdo-build-investigator: 1,292 BPE tokens [chars/4: 1,209] (detailed ✓), 8 sections, 3 code blocks
[azdo-build-investigator]    ⚠  No numbered workflow steps — agents follow sequenced procedures more reliably.
✅ All checks passed (1 skill(s))
No agents found in the specified paths: "/home/runner/work/maui/maui/.github/agents"

⏭️ LLM Evaluation: Skipped

No changed skills with eval tests found.

🔍 Full results and investigation steps

Each file now has a distinct role:
- copilot-instructions.md: always-on context (5 lines)
- azdo-build-investigator: error signatures + DO NOTs for investigation
- android.instructions.md: one-liner pointing to script

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

Copy link
Copy Markdown
Member Author

Upstream issue filed: microsoft/artifacts-credprovider#671 — the Gradle credential provider plugin doesn't cover buildscript.repositories or detachedConfiguration scopes, which is why we need the eng/ingest-maven-deps.sh script as a workaround.

@PureWeen PureWeen changed the title Use Azure Artifacts Maven feed for CFSClean compliance Use Azure Artifacts Maven feed for CFSClean network isolation compliance Apr 27, 2026
@PureWeen PureWeen merged commit bf61568 into release/10.0.1xx-sr6 Apr 27, 2026
39 of 46 checks passed
@PureWeen PureWeen deleted the fix/gradle-azure-artifacts-feed branch April 27, 2026 18:42
@github-actions github-actions Bot added this to the .NET 10 SR6 milestone Apr 27, 2026
PureWeen added a commit that referenced this pull request Apr 28, 2026
…compliance (#35169)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

Cherry-pick of #35089 from `release/10.0.1xx-sr6` to `main`.

See #35089 for full details — routes Gradle/Maven dependency resolution
through Azure Artifacts feed for CFSClean compliance.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Matt Mitchell (.NET) <mmitche@microsoft.com>
PureWeen added a commit that referenced this pull request Apr 28, 2026
…an network isolation compliance (#35170)

<!-- Please let the below note in for people that find this PR -->
> [!NOTE]
> Are you waiting for the changes in this PR to be merged?
> It would be very helpful if you could [test the resulting
artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from
this PR and let us know in a comment if this change resolves your issue.
Thank you!

Cherry-pick of #35089 from `release/10.0.1xx-sr6` to
`release/11.0.1xx-preview4`.

See #35089 for full details — routes Gradle/Maven dependency resolution
through Azure Artifacts feed for CFSClean compliance.

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Matt Mitchell (.NET) <mmitche@microsoft.com>
@github-actions github-actions Bot locked and limited conversation to collaborators May 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants