[release/10.0.1xx] Route Gradle dependencies through dotnet-public-maven - #12397
Open
jonathanpeppers wants to merge 6 commits into
Open
[release/10.0.1xx] Route Gradle dependencies through dotnet-public-maven#12397jonathanpeppers wants to merge 6 commits into
jonathanpeppers wants to merge 6 commits into
Conversation
…es.gradle (#11711) All Gradle projects in this repo (`src/manifestmerger`, `src/r8`, `src/proguard-android`) previously declared their own ad-hoc mix of `mavenCentral()`, `google()`, `jcenter()`, and `kotlin.bintray.com` repositories. That's a maintenance hazard and blocks any future CFSClean network-isolation work (see https://aka.ms/1es/netiso/CFS), which requires all Maven dependencies to flow through the dnceng `dotnet-public-maven` Azure Artifacts feed. ## Approach A single shared file `eng/gradle/repositories.gradle` is now the only place repository URLs are declared. Each `settings.gradle` applies it twice via `apply from: ..., to: <block>` to populate both `pluginManagement.repositories` and `dependencyResolutionManagement.repositories`. The `build.gradle` files no longer declare any `repositories {}` block. The shared file switches on `System.getenv('RunningOnCI')`: - **`RunningOnCI=true`** (set by `build-tools/automation/yaml-templates/variables.yaml` in our AzDO pipeline): the dnceng `dotnet-public-maven` feed, plus the anonymous AzureArtifacts feed for the credprovider Gradle plugin. - **unset** (local builds, Dependabot, GitHub Actions): `google()` + `mavenCentral()` + `gradlePluginPortal()` so contributors and Dependabot need no credentials. Adapted from dotnet/maui ([72cc860](dotnet/maui@72cc860)). ## Dependabot workflow This preserves Dependabot for the Gradle ecosystem (`/src/r8/`, `/src/manifestmerger/` in `.github/dependabot.yml`): 1. Dependabot opens a PR against public repos -> sees the latest upstream version. 2. CI runs with `RunningOnCI=true`. If the new version isn't cached in the dnceng feed yet, CI fails 401. 3. A maintainer runs `$env:RunningOnCI='true'; ./build-tools/gradle/gradlew.bat --project-dir src/<project> build` locally; the artifacts-credprovider plugin device-flow-logs-in once, the feed proxies + caches the package, and anonymous reads work from then on. 4. Re-run CI -> green. No PR edit required. CI itself reads the feed **anonymously** -- no PAT secret or pipeline auth setup is required. ## Notes for reviewers - All three projects (`manifestmerger`, `r8`, `proguard-android`) were verified to build through both code paths (`RunningOnCI` set and unset) on Windows. - `proguard-android/build.gradle` keeps the modern `plugins { id 'com.android.application' version '8.7.0' }` DSL; AGP is resolvable from both `gradlePluginPortal()` locally and `dotnet-public-maven` in CI. - `.github/instructions/gradle.instructions.md` (scoped via frontmatter to `**/*.gradle`) documents the pattern so Copilot picks it up when editing Gradle files. - The credprovider plugin is declared unconditionally in each `settings.gradle` because Gradle disallows wrapping `plugins {}` in `if (...)`. It is a no-op on the local path (no AzDO repos for it to authenticate).
…roid (#11717) Bumps com.android.application from 8.7.0 to 9.2.1. [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details>
PR #11711 centralized Gradle repository configuration, but applying the Azure Artifacts credential provider during ordinary builds caused authentication dialogs for local developers. CI does not need that provider because it reads packages already cached in `dotnet-public-maven` anonymously. This keeps repository selection and authentication as separate controls: - `RUNNINGONCI=true` selects `dotnet-public-maven` for Azure DevOps builds. - `ANDROID_MIRROR_MAVEN_DEPENDENCIES=true` loads the credential provider only while `mirror-dependencies.ps1` seeds uncached packages. - Local builds use Google, Maven Central, and the Gradle Plugin Portal without loading Azure authentication code. The credential provider is loaded through an applied script so it can be gated dynamically. Gradle cannot resolve a plugin by ID from that script's isolated `buildscript` classpath, so this context requires its implementation class. - [x] Useful description of *why the change is necessary*. - [x] Links to issues fixed: Follow-up to #11711 - [x] Unit tests: Configured all four Gradle projects in local, anonymous CI, and authenticated mirror-helper modes.
…12199) CFSClean reports test jobs that resolve Maven dependencies and Gradle plugins directly from public services. CI agents are network-isolated and can only reach the anonymous `dotnet-public-maven` Azure Artifacts feed, which mirrors both Maven Central and Google Maven. This routes every test Maven and Gradle resolution through that feed. Crucially, it does so **unconditionally** rather than only when `RUNNINGONCI` is set — a CI-only code path means a local run exercises different URLs than CI, so a test can pass locally and then fail in the pipeline. Making local and CI identical is the same principle applied to the mirror-seeding tool below. - `Xamarin.ProjectTools` exposes a single `TestEnvironment.DotNetPublicMaven` constant. Test download URLs and `<AndroidMavenLibrary Repository="...">` metadata are built from it directly, replacing the old `GetTestDownloadUrl`/`GetMavenRepository` helpers and their table of public-repository prefixes. A missing prefix in that table used to fail silently on CI only. - `AndroidGradleProject` writes a `settings.gradle.kts` that applies the shared `eng/gradle` repository scripts, and copies the repository Gradle wrapper instead of downloading an alternate distribution. - Java.Interop `java-source-utils` no longer declares `mavenCentral()` independently, and parallel Kotlin Gradle builds are isolated so they don't race. `eng/gradle/mirror-dependencies.ps1` now runs Gradle exactly the way CI does — anonymously, with the configuration cache enabled — instead of loading an Azure Artifacts credential-provider plugin behind an env var. That plugin forced the seeding run to differ from the real run, so lazily-resolved Kotlin and lint classpaths resolved differently and the feed was seeded with the wrong packages. Authentication moved out of Gradle entirely: 401 URLs are re-fetched over plain HTTP with an Azure DevOps OAuth token, which makes the feed's upstream connector cache them for anonymous reads. `eng/gradle/credential-provider.gradle` is removed. A `-MavenArtifact` mode seeds coordinates directly for tests that don't use Gradle. - `TestEnvironment.IsWindows`/`IsMacOS`/`IsLinux` are annotated `[SupportedOSPlatformGuard]` so CA1416 can see through them. The properties were always correct at runtime; the analyzer just couldn't recognize an arbitrary `bool` as a platform guard. Annotating the shared helper fixes every current and future caller instead of rewriting call sites. - `Xamarin.Google.Android.InstallReferrer` is bumped to 2.2.0.8 to match Facebook SDK 18.3.0, which requires `com.android.installreferrer:2.2`. - Built `Xamarin.ProjectTools`, `Xamarin.Android.Build.Tests`, and `MSBuildDeviceIntegration` — 0 errors. - All 17 `MavenDownloadTests` pass locally, including the three that download through the mirror. Because the mirror is now used locally too, this exercises the same URLs CI does. - Verified every artifact referenced by a test resolves on the feed (`HEAD` → 200), so nothing 401s on CI. - Routing all downloads through a repository URL would leave the `Repository="Central"`/`"Google"` shorthands unexercised, so that mapping is extracted to `MavenDownload.GetKnownRepository` and covered by new tests that need no network and therefore run under CI isolation. - Passed 106 Java.Interop Maven tests; `java-source-utils` resolves through the feed. - `GradleFBProj` passes on device after the InstallReferrer bump. - Full pipeline green apart from the pre-existing, unrelated `JnienvArrayMarshaling.GetObjectArray` JNI peer-registration flake. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The original Kotlin artifact is now mirrored through dotnet-public-maven, so keep the existing package while routing it through the approved feed. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Keep the release branch on its existing Gradle 8.12 wrapper and AGP 8.7 while retaining the public Maven repository routing from the backported mirror series. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Member
Author
|
/azp run |
|
Azure Pipelines: 1 pipeline(s) were filtered out due to trigger conditions. |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates release/10.0.1xx build/test infrastructure so Gradle plugin/dependency resolution and test Maven downloads flow through the anonymous dnceng dotnet-public-maven mirror (CI/network-isolation compatible), and adds a helper script to seed missing artifacts into the mirror when needed.
Changes:
- Centralize Gradle repository configuration via
eng/gradle/{plugin-repositories,dependency-repositories}.gradleand apply it from affectedsettings.gradle. - Route test Maven/Gradle downloads through
TestEnvironment.DotNetPublicMaven, and add mirror-friendly test behaviors (e.g., CI-only ignores for uncached artifacts). - Add
eng/gradle/mirror-dependencies.ps1to authenticate once and seed missing packages into the mirror, then re-run Gradle until it succeeds.
Reviewed changes
Copilot reviewed 28 out of 28 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs | Updates Gradle FB test dependencies and routes Maven libs through the mirror. |
| tests/CodeGen-Binding/Xamarin.Android.LibraryProjectZip-LibBinding/Xamarin.Android.LibraryProjectZip-LibBinding.csproj | Points binding input JAR to a stable extracted location. |
| tests/CodeGen-Binding/Xamarin.Android.LibraryProjectZip-LibBinding/java/JavaLib/settings.gradle | Applies shared Gradle repository scripts for JavaLib. |
| tests/CodeGen-Binding/Xamarin.Android.LibraryProjectZip-LibBinding/java/JavaLib/library/src/main/AndroidManifest.xml | Adjusts manifest for modern AGP namespace usage. |
| tests/CodeGen-Binding/Xamarin.Android.LibraryProjectZip-LibBinding/java/JavaLib/library/build.gradle | Modernizes module build and adds AAR classes.jar extraction task. |
| tests/CodeGen-Binding/Xamarin.Android.LibraryProjectZip-LibBinding/java/JavaLib/build.gradle | Switches to plugin DSL and newer AGP configuration. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs | Adds mirror base URL constant and OS guard attributes; adds CI detection helper. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/AndroidGradleProject.cs | Generates Gradle projects using repo wrapper + shared repository scripts; enables config cache/parallel/caching. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs | Routes test web downloads and Maven library metadata through the mirror. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/MavenDownloadTests.cs | Updates tests for mirror behavior and adds coverage for repository shorthand mapping. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs | Routes incremental test AAR download through the mirror. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildWithLibraryTests.cs | Routes library test downloads through the mirror. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs | Routes test AAR downloads through the mirror. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs | Routes various test Maven/Google artifacts through the mirror. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs | Routes binding test downloads and Maven repositories through the mirror. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidGradleProjectTests.cs | Pins FB SDK version and asserts wrapper presence for generated Gradle projects. |
| src/Xamarin.Android.Build.Tasks/Tasks/MavenDownload.cs | Factors out known-repository shorthand mapping into an internal helper. |
| src/r8/settings.gradle | Applies shared Gradle repository scripts for r8. |
| src/r8/build.gradle | Removes per-project repositories block (centralized in shared scripts). |
| src/proguard-android/settings.gradle | Applies shared Gradle repository scripts for proguard-android. |
| src/proguard-android/build.gradle | Removes per-project repositories block (centralized in shared scripts). |
| src/manifestmerger/settings.gradle | Applies shared Gradle repository scripts for manifestmerger. |
| src/manifestmerger/build.gradle | Removes ad-hoc repository list (centralized in shared scripts). |
| eng/gradle/plugin-repositories.gradle | New shared plugin repository selection (CI mirror vs local public repos). |
| eng/gradle/mirror-dependencies.ps1 | New helper to seed missing artifacts into dotnet-public-maven via authenticated fetches. |
| eng/gradle/dependency-repositories.gradle | New shared dependency repository selection (CI mirror vs local public repos). |
| .github/instructions/gradle.instructions.md | Documents the shared Gradle repository convention for future edits. |
| .github/dependabot.yml | Consolidates Gradle Dependabot updates across multiple directories. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Member
Author
|
/azp run |
|
Azure Pipelines: 1 pipeline(s) were filtered out due to trigger conditions. |
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Backports #11711, #11717, #12055, #12199, and #12368.
Validation
n- release-specific missing artifacts were seeded using ^[ng/gradle/mirror-dependencies.ps1nsrc/manifestmerger build retains its pre-existing Java 8 compatibility failure with manifest-merger:31.12.2; the same failure reproduces offline without mirror routing.