[release/10.0.1xx] Route Gradle dependencies through dotnet-public-maven - #12395
Closed
jonathanpeppers wants to merge 6 commits into
Closed
[release/10.0.1xx] Route Gradle dependencies through dotnet-public-maven#12395jonathanpeppers wants to merge 6 commits into
jonathanpeppers wants to merge 6 commits into
Conversation
…es.gradle (dotnet#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 (dotnet#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 dotnet#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 dotnet#11711 - [x] Unit tests: Configured all four Gradle projects in local, anonymous CI, and authenticated mirror-helper modes.
…otnet#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
Routes Gradle plugin/dependency resolution (and test Maven/Gradle downloads) through the anonymous dotnet-public-maven mirror to satisfy CI network isolation requirements, while keeping local builds on public repositories.
Changes:
- Centralize Gradle
pluginManagement/dependencyResolutionManagementrepositories viaeng/gradle/*.gradleand update Gradle subprojects to consume them. - Route test-time Maven downloads and
<AndroidMavenLibrary Repository=...>metadata throughTestEnvironment.DotNetPublicMaven. - Add
eng/gradle/mirror-dependencies.ps1helper for seeding missing artifacts into the mirror and adjust test Gradle project plumbing (wrapper usage / stable artifact paths).
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 | Bump Facebook SDK version and route related Maven libraries through the mirror in device integration tests. |
| tests/CodeGen-Binding/Xamarin.Android.LibraryProjectZip-LibBinding/Xamarin.Android.LibraryProjectZip-LibBinding.csproj | Update binding input JAR path to a stable location not tied to AGP intermediates. |
| tests/CodeGen-Binding/Xamarin.Android.LibraryProjectZip-LibBinding/java/JavaLib/settings.gradle | Apply shared repository scripts for plugin/dependency resolution. |
| tests/CodeGen-Binding/Xamarin.Android.LibraryProjectZip-LibBinding/java/JavaLib/library/src/main/AndroidManifest.xml | Remove manifest package in favor of Gradle namespace. |
| tests/CodeGen-Binding/Xamarin.Android.LibraryProjectZip-LibBinding/java/JavaLib/library/build.gradle | Modernize Android library module config and add task to extract classes.jar to a stable path. |
| tests/CodeGen-Binding/Xamarin.Android.LibraryProjectZip-LibBinding/java/JavaLib/build.gradle | Switch to plugins DSL and adjust clean task for newer Gradle/AGP behavior. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs | Add DotNetPublicMaven constant, platform guard attributes, and IsRunningOnCI helper. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/AndroidGradleProject.cs | Generate settings.gradle.kts applying shared repo scripts and copy the repo Gradle wrapper into generated projects. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs | Route test web downloads and Maven library metadata through DotNetPublicMaven. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/MavenDownloadTests.cs | Adjust tests for mirror behavior, add coverage for repository shorthand mapping, and harden null handling. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs | Route AAR downloads through DotNetPublicMaven. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildWithLibraryTests.cs | Route AAR downloads through DotNetPublicMaven. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs | Route AAR downloads through DotNetPublicMaven. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs | Route Maven Central/Google Maven downloads through DotNetPublicMaven. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs | Route binding test downloads and <AndroidMavenLibrary> repository metadata through DotNetPublicMaven. |
| src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidGradleProjectTests.cs | Pin Facebook SDK version to a specific release for test stability. |
| src/Xamarin.Android.Build.Tasks/Tasks/MavenDownload.cs | Factor repository-shorthand mapping into GetKnownRepository and reuse in repository resolution. |
| src/r8/settings.gradle | Apply shared repository scripts for plugin/dependency resolution. |
| src/r8/build.gradle | Remove per-project repositories block in favor of centralized settings.gradle configuration. |
| src/proguard-android/settings.gradle | Apply shared repository scripts for plugin/dependency resolution. |
| src/proguard-android/build.gradle | Remove per-project repositories block in favor of centralized settings.gradle configuration. |
| src/manifestmerger/settings.gradle | Apply shared repository scripts for plugin/dependency resolution. |
| src/manifestmerger/build.gradle | Remove per-project repositories block in favor of centralized settings.gradle configuration. |
| eng/gradle/plugin-repositories.gradle | New shared plugin repository list switching on RUNNINGONCI. |
| eng/gradle/dependency-repositories.gradle | New shared dependency repository list switching on RUNNINGONCI. |
| eng/gradle/mirror-dependencies.ps1 | New script to seed missing Gradle/Maven artifacts into the mirror via authenticated refetch. |
| .github/instructions/gradle.instructions.md | Document the centralized Gradle repo pattern and mirror-seeding workflow. |
| .github/dependabot.yml | Consolidate Gradle Dependabot coverage to include additional Gradle projects/directories. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Member
Author
|
Superseded by #12397, which uses a branch hosted directly in dotnet/android. |
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.