Use Azure Artifacts feed only in CI, standard repos locally#35218
Closed
PureWeen wants to merge 3 commits into
Closed
Use Azure Artifacts feed only in CI, standard repos locally#35218PureWeen wants to merge 3 commits into
PureWeen wants to merge 3 commits into
Conversation
…nce (#35089) <!-- 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! ## Problem The official build pipeline (`dotnet-maui`, def 1095) fails because [CFSClean network isolation](#34540) 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](https://aka.ms/1es/netiso/CFS), 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](https://pkgs.dev.azure.com/artifacts-public/PublicTools/_packaging/AzureArtifacts/maven/v1) 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](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](https://dev.azure.com/dnceng/internal/_build/results?buildId=2961149) passed — Pack macOS + Pack Windows both green - ✅ Same pattern used by dotnet/aspnetcore ([PR #64962](dotnet/aspnetcore#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) --------- 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>
- init.gradle: mention Gradle Plugin Portal in comment - settings.gradle: clarify credential provider comes from separate feed - ingest-maven-deps.sh: add python3 to prerequisites Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The credential provider plugin and Azure Artifacts feed add significant overhead locally (~10+ min builds). Use google()/ mavenCentral() for local builds and only switch to the Azure Artifacts feed when TF_BUILD=True (Azure Pipelines). This also removes the credential provider plugin dependency for local builds since it's not needed when using standard Maven repos. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35218Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35218" |
Contributor
🔍 Skill Validation Results✅ Static Checks PassedSkills checked: 15 | Agents checked: 3 Full validator output⏭️ LLM Evaluation: SkippedNo changed skills with eval tests found. |
Member
Author
|
Superseded by new PR from latest main |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR restores fast local Gradle builds by using google()/mavenCentral() outside of Azure Pipelines, while keeping CFSClean CI compliant by routing Maven/Gradle resolution through the dotnet-public-maven Azure Artifacts feed (plus adds supporting CI/docs/tooling updates).
Changes:
- Switch
src/Core/AndroidNativeGradle repository configuration to prefer standard public repos locally and Azure Artifacts in CI. - Add/install a Gradle
init.gradlein CI and introduce a script to pre-ingest Maven dependencies into the Azure Artifacts feed. - Update repo guidance/docs to aid diagnosing and fixing Gradle/CFSClean 401 failures.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
src/Core/AndroidNative/settings.gradle |
Conditional repo selection for plugin/dependency resolution based on CI environment. |
src/Core/AndroidNative/build.gradle |
Conditional buildscript repo selection for CI vs local builds. |
src/Core/AndroidNative/gradle/wrapper/gradle-wrapper.properties |
Adds guardrail comment about staying on Gradle 8.x for current Android SDK compatibility. |
eng/pipelines/common/cache-gradle.yml |
Installs eng/init.gradle after cache restore so CI uses the intended init script. |
eng/init.gradle |
New init script to redirect known public Maven/Plugin Portal repos to Azure Artifacts in CI. |
eng/ingest-maven-deps.sh |
New helper script to pre-ingest dependencies into dotnet-public-maven for CFSClean CI. |
.github/skills/azdo-build-investigator/SKILL.md |
Documents Gradle/CFSClean 401/XAGRDL0000 failure pattern and remediation. |
.github/instructions/android.instructions.md |
Extends Android guidance scope to AndroidNative/Gradle tooling and adds CFSClean dependency ingestion notes. |
.github/copilot-instructions.md |
Adds CFSClean Gradle/Maven dependency failure guidance and the ingestion script pointer. |
| @@ -1,8 +1,16 @@ | |||
| // Top-level build file where you can add configuration options common to all sub-projects/modules. | |||
| buildscript { | |||
| def isCI = System.getenv('TF_BUILD') == 'True' || System.getenv('CI') != null | |||
Comment on lines
+88
to
+100
| cd "$ANDROID_DIR" | ||
| if ! ./gradlew build --no-daemon --refresh-dependencies \ | ||
| -Dazure.artifacts.credprovider.nonInteractive=true \ | ||
| -Dazure.artifacts.credprovider.isRetry=true 2>&1 | tail -20; then | ||
| echo "WARNING: Initial Gradle build failed (expected if packages need ingestion). Continuing..." | ||
| fi | ||
|
|
||
| # Step 4: Loop — build, find missing packages, curl-ingest them | ||
| echo "" | ||
| echo "Step 3/3: Ingesting any remaining packages via REST API..." | ||
| for i in $(seq 1 30); do | ||
| result=$(./gradlew build --no-daemon \ | ||
| -Dazure.artifacts.credprovider.nonInteractive=true 2>&1 || true) |
| condition: ne(variables['Agent.OS'], 'Windows_NT') | ||
|
|
||
| - pwsh: | | ||
| Copy-Item "${{ parameters.checkoutDirectory }}/eng/init.gradle" (Join-Path "$(GRADLE_USER_HOME)" "init.gradle") |
Comment on lines
+11
to
+13
| if (System.getenv('TF_BUILD') == 'True') { | ||
| maven { | ||
| url = 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-maven/maven/v1' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
PR #35169 switched all Gradle repos to the Azure Artifacts feed unconditionally. This causes 10+ minute local builds because the credential provider plugin adds significant auth overhead (MSAL token acquisition, feed latency vs direct Maven Central).
Fix
Use
google()/mavenCentral()locally and only switch to the Azure Artifacts feed whenTF_BUILD=True(Azure Pipelines with CFSClean). This keeps local builds fast while CI remains compliant.The
init.gradlestill handles the Android SDK bindings Gradle targets redirection in CI via the pipeline template.Verified
TF_BUILD=Truewhich activates the Azure Artifacts feed