Skip to content

Centralize Gradle Maven repositories via shared eng/gradle/repositories.gradle#11711

Merged
simonrozsival merged 7 commits into
mainfrom
jonathanpeppers-bookish-fortnight
Jun 24, 2026
Merged

Centralize Gradle Maven repositories via shared eng/gradle/repositories.gradle#11711
simonrozsival merged 7 commits into
mainfrom
jonathanpeppers-bookish-fortnight

Conversation

@jonathanpeppers

Copy link
Copy Markdown
Member

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).

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).

  • Useful description of why the change is necessary.

  • Links to issues fixed

  • Unit tests (N/A -- build-system plumbing only; verified by building all three Gradle projects through both code paths)

jonathanpeppers and others added 4 commits June 22, 2026 14:34
All Gradle projects in this repo (manifestmerger, r8, proguard-android) now resolve Maven dependencies through a single dnceng Azure Artifacts feed (dotnet-public-maven), which proxies Maven Central, Google Maven, and the Gradle Plugin Portal.

Repository configuration is centralized in eng/gradle/repositories.gradle (a gradle.ext.dotnetPublicMaven closure) and applied from each build.gradle.

Each settings.gradle inlines pluginManagement + the com.microsoft.azure.artifacts.credprovider plugin (Gradle disallows pluginManagement/plugins blocks in applied scripts, so the contents must be duplicated).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Refactor eng/gradle/repositories.gradle to conditionally point at the dnceng dotnet-public-maven feed only when RunningOnCI=true (Azure DevOps CI). Locally and from GitHub Actions / Dependabot, standard public repos (google, mavenCentral, gradlePluginPortal) are used so contributors and Dependabot need no feed credentials.

CI reads the feed anonymously; new packages are pre-ingested on a maintainer's machine by setting RunningOnCI=true locally and letting the artifacts-credprovider Gradle plugin authenticate. Detailed workflow and testing instructions are inline in eng/gradle/repositories.gradle.

Add .github/instructions/gradle.instructions.md (scoped to **/*.gradle) so the conventions are surfaced to Copilot when editing Gradle files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 22, 2026 20:01

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 centralizes Gradle repository configuration for the repo’s src/* Gradle builds by introducing a shared eng/gradle/repositories.gradle, enabling Azure DevOps CFSClean-friendly Maven resolution via the dotnet-public-maven feed while keeping local/Dependabot builds working against public repos.

Changes:

  • Added eng/gradle/repositories.gradle and switched repositories based on RunningOnCI.
  • Updated each src/*/settings.gradle to apply the shared repositories to both pluginManagement and dependencyResolutionManagement, and added the Azure Artifacts credprovider plugin.
  • Removed per-project repositories {} blocks from build.gradle files; added Gradle-editing guidance via .github/instructions/gradle.instructions.md.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/r8/settings.gradle Adds shared repo wiring for plugin + dependency resolution and credprovider plugin declaration.
src/r8/build.gradle Removes ad-hoc repositories to rely on centralized settings-based resolution.
src/proguard-android/settings.gradle Replaces inline plugin repos with shared repository script and adds dependencyResolutionManagement.
src/proguard-android/build.gradle Removes ad-hoc repositories to rely on centralized settings-based resolution.
src/manifestmerger/settings.gradle Adds shared repo wiring for plugin + dependency resolution and credprovider plugin declaration.
src/manifestmerger/build.gradle Removes hard-coded/mixed repositories (incl. legacy ones) in favor of centralized config.
eng/gradle/repositories.gradle Introduces the shared repository list and CI-vs-local switching logic.
.github/instructions/gradle.instructions.md Documents the centralized repository pattern for future Gradle edits.

Comment thread eng/gradle/repositories.gradle Outdated
Comment thread .github/instructions/gradle.instructions.md Outdated
jonathanpeppers and others added 2 commits June 22, 2026 15:07
AzDO uppercases pipeline variables when exporting them as environment variables on Linux/macOS agents, so System.getenv('RunningOnCI') returns null there. Check both spellings.

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

Copy link
Copy Markdown
Member Author

/review

@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown

Android PR Reviewer completed successfully!

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 Code Review — ⚠️ Minor suggestions (non-blocking)

Solid, well-documented build-plumbing change. Centralizing the Maven repo list into eng/gradle/repositories.gradle and applying it to both pluginManagement and dependencyResolutionManagement is the established dotnet/maui pattern and works on this repo's Gradle 8.12. I formed an independent read of the diff first, then verified the PR's claims:

Verified ✅

  • RunningOnCI really is exported by build-tools/automation/yaml-templates/variables.yaml, and the System.getenv('RunningOnCI') ?: System.getenv('RUNNINGONCI') + == 'true' check correctly mirrors the hard-won lesson already encoded in CodeBehindTests.cs — AzDO uppercases the env var to RUNNINGONCI on Linux/macOS agents while the value stays lowercase true. Good defensive handling of both spellings.
  • Dependabot still covers all three projects (/src/r8, /src/manifestmerger, /src/proguard-android) in .github/dependabot.yml.
  • Nice cleanup: the old manifestmerger block resolved from the long-dead jcenter() and kotlin.bintray.com/kotlinx — both correctly dropped here.
  • The apply from "${rootDir}/../../eng/gradle/repositories.gradle" relative path is correct from each src/<project>/ location, and the credprovider plugin version is pinned (1.1.1), so Dependabot can bump it.

CI

  • The Azure DevOps run (buildId 1477428) is green across all legs (MSBuild, Emulator, Package, Linux, Windows Smoke, MAUI). A fresh re-run kicked off alongside this /review. mergeable_state: blocked reflects the pending required review (simonrozsival), not a CI failure.

Findings (see inline)

  • ⚠️ 1 warning — the instruction glob **/*.gradle over-claims relative to the src/*-only migration: a CI-built test fixture (tests/CodeGen-Binding/.../JavaLib/build.gradle) still hard-codes public repos.
  • 💡 1 suggestion — the AzureArtifacts feed is also injected into dependencyResolutionManagement, where it only adds a 404 round-trip per project dependency.

Neither is merge-blocking. Nice work — this is a clean, future-proofing refactor.

Generated by Android PR Reviewer for issue #11711 · 929 AIC · ⌖ 48.2 AIC · ⊞ 37.8K
Comment /review to run again

Comment thread .github/instructions/gradle.instructions.md
// Required even on the local path so the plugin is resolvable; harmless
// in dependencyResolutionManagement (it hosts no project dependencies).
maven {
url = 'https://pkgs.dev.azure.com/artifacts-public/PublicTools/_packaging/AzureArtifacts/maven/v1'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 💡 Performance — This AzureArtifacts feed is declared first and unconditionally, so the shared script injects it into dependencyResolutionManagement too. It only hosts the artifacts-credprovider plugin, yet now every project-dependency lookup (manifest-merger, r8, and their transitives) queries it first and 404s before falling through to google()/mavenCentral() (or dotnet-public-maven in CI) — an extra round-trip per dependency on every build, including local and Dependabot. Since the credprovider is a plugin, consider scoping this feed to pluginManagement only. Functionally harmless (as the comment notes); this is purely an optimization.

Rule: Don't inject a repository into scopes that never resolve from it

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Confirmed and fixed. Split the shared file: eng/gradle/plugin-repositories.gradle still includes the AzureArtifacts feed (the credprovider plugin lives there), and the new eng/gradle/dependency-repositories.gradle omits it so project-dependency lookups skip that 404 round-trip. Each settings.gradle now applies the right file to each scope.

The AzureArtifacts public feed only hosts the artifacts-credprovider Gradle plugin, so listing it in dependencyResolutionManagement.repositories added a 404 round-trip to every project dependency lookup. Split the shared file in two: plugin-repositories.gradle (includes AzureArtifacts) and dependency-repositories.gradle (does not).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@simonrozsival simonrozsival merged commit ce63639 into main Jun 24, 2026
40 checks passed
@simonrozsival simonrozsival deleted the jonathanpeppers-bookish-fortnight branch June 24, 2026 07:04
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.

3 participants