diff --git a/.github/instructions/gradle.instructions.md b/.github/instructions/gradle.instructions.md index 28629fe2e73..b702b46d390 100644 --- a/.github/instructions/gradle.instructions.md +++ b/.github/instructions/gradle.instructions.md @@ -12,8 +12,8 @@ All `src/*` Gradle projects share two repo config files: **`eng/gradle/plugin-re pluginManagement { apply from: "${rootDir}/../../eng/gradle/plugin-repositories.gradle", to: pluginManagement } -plugins { - id 'com.microsoft.azure.artifacts.credprovider' version '1.1.1' +if (System.getenv('ANDROID_MIRROR_MAVEN_DEPENDENCIES') == 'true') { + apply from: "${rootDir}/../../eng/gradle/credential-provider.gradle" } dependencyResolutionManagement { apply from: "${rootDir}/../../eng/gradle/dependency-repositories.gradle", to: dependencyResolutionManagement @@ -25,12 +25,17 @@ rootProject.name = '' ## CI vs local -Both files switch on `System.getenv('RunningOnCI')` (or `RUNNINGONCI` — AzDO uppercases env vars on Linux/macOS agents): +Both files switch on `System.getenv('RUNNINGONCI')`. Azure DevOps exports the +`RunningOnCI` pipeline variable under this normalized environment-variable name. -- **`RunningOnCI=true`** (Azure DevOps, set in `build-tools/automation/yaml-templates/variables.yaml`) → dnceng `dotnet-public-maven` feed (CFSClean isolation, https://aka.ms/1es/netiso/CFS). Anonymous read of cached packages. +- **`RUNNINGONCI=true`** (Azure DevOps, sourced from `RunningOnCI` in `build-tools/automation/yaml-templates/variables.yaml`) → dnceng `dotnet-public-maven` feed (CFSClean isolation, https://aka.ms/1es/netiso/CFS). Anonymous read of cached packages. - **unset** (local, Dependabot, GitHub Actions) → `google()` + `mavenCentral()` + `gradlePluginPortal()` for plugins, `google()` + `mavenCentral()` for deps. No credentials needed. -Test the CI path locally: `$env:RunningOnCI='true'` (PowerShell) or `RunningOnCI=true ...` (bash). +CI reads cached packages from the mirror anonymously. The Azure Artifacts +credential provider is loaded only when `ANDROID_MIRROR_MAVEN_DEPENDENCIES=true`; +`mirror-dependencies.ps1` sets this while seeding uncached packages. + +Test the CI path locally: `$env:RUNNINGONCI='true'` (PowerShell) or `RUNNINGONCI=true ...` (bash). ## When CI fails 401 on a Dependabot bump @@ -54,5 +59,4 @@ After it succeeds, just re-run the failed CI job. No PR edits needed — the pac ## Don'ts - Don't hard-code Maven repo URLs in `build.gradle` / `settings.gradle`; use the shared file. -- Don't wrap `plugins {}` in `if (...)` — Gradle rejects it. - Don't use modern `plugins { id 'com.android.application' version '...' }` DSL without confirming the plugin is in `dotnet-public-maven`; prefer `buildscript { ... } / apply plugin: '...'` when in doubt. \ No newline at end of file diff --git a/eng/gradle/credential-provider.gradle b/eng/gradle/credential-provider.gradle new file mode 100644 index 00000000000..32f6fa95e8b --- /dev/null +++ b/eng/gradle/credential-provider.gradle @@ -0,0 +1,17 @@ +// The dependency-mirroring helper uses this plugin to authenticate with the +// Maven mirror. Regular local and CI builds do not apply this script. +buildscript { + repositories { + maven { + url = 'https://pkgs.dev.azure.com/artifacts-public/PublicTools/_packaging/AzureArtifacts/maven/v1' + name = 'AzureArtifacts' + } + } + dependencies { + classpath 'com.microsoft.azure:artifacts-gradle-credprovider:1.1.1' + } +} + +// Plugins loaded through an applied script's buildscript classpath cannot be +// resolved by ID; Gradle requires the implementation class in this context. +apply plugin: com.microsoft.azure.artifacts.credprovider.gradle.GradleCredentialProviderPlugin diff --git a/eng/gradle/dependency-repositories.gradle b/eng/gradle/dependency-repositories.gradle index ac491c649c2..a9daafecc52 100644 --- a/eng/gradle/dependency-repositories.gradle +++ b/eng/gradle/dependency-repositories.gradle @@ -2,16 +2,10 @@ // (dependencyResolutionManagement.repositories) across every settings.gradle // in this repo. See plugin-repositories.gradle for plugin resolution. // -// Switches on RunningOnCI for the same CFSClean reasons described there. -// AzureArtifacts is intentionally NOT included here — it only hosts the -// credprovider plugin, so listing it in this scope would add a 404 round-trip -// to every dependency lookup. +// Switches on RUNNINGONCI for the same CFSClean reasons described there. repositories { - // AzDO uppercases pipeline variables when exporting them as env vars on - // Linux/macOS agents, so check both spellings. - def runningOnCI = System.getenv('RunningOnCI') ?: System.getenv('RUNNINGONCI') - if (runningOnCI == 'true') { + if (System.getenv('RUNNINGONCI') == 'true') { maven { url = 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-maven/maven/v1' name = 'dotnet-public-maven' diff --git a/eng/gradle/mirror-dependencies.ps1 b/eng/gradle/mirror-dependencies.ps1 index 20a225c9d21..dedf0abbdfc 100644 --- a/eng/gradle/mirror-dependencies.ps1 +++ b/eng/gradle/mirror-dependencies.ps1 @@ -11,7 +11,7 @@ so a developer has to authenticate locally once to seed the feed. This script does that by running the requested gradle build in a loop: - 1. Run gradle with RunningOnCI=true so it points at the dnceng feed. + 1. Run gradle with RUNNINGONCI=true so it points at the dnceng feed. 2. Parse any 'Could not GET' URLs out of the build log. 3. Re-fetch each failing URL with an Azure DevOps OAuth bearer token (obtained via `az account get-access-token`). The feed's upstream @@ -113,7 +113,8 @@ if ($AndroidHome) { Write-Host "ANDROID_HOME: $AndroidHome" } Get-AzDevOpsToken | Out-Null if ($AndroidHome) { $env:ANDROID_HOME = $AndroidHome } -$env:RunningOnCI = 'true' +$env:RUNNINGONCI = 'true' +$env:ANDROID_MIRROR_MAVEN_DEPENDENCIES = 'true' Push-Location $projectDirAbs try { diff --git a/eng/gradle/plugin-repositories.gradle b/eng/gradle/plugin-repositories.gradle index 5763cacff65..898391470d1 100644 --- a/eng/gradle/plugin-repositories.gradle +++ b/eng/gradle/plugin-repositories.gradle @@ -2,14 +2,11 @@ // across every settings.gradle in this repo. See plugin-repositories.gradle's // sibling, dependency-repositories.gradle, for project dependency resolution. // -// In our Azure DevOps CI pipeline (RunningOnCI=true), plugins resolve through +// In our Azure DevOps CI pipeline (RUNNINGONCI=true), plugins resolve through // the dnceng Azure Artifacts feed (dotnet-public-maven) for CFSClean network // isolation compliance (https://aka.ms/1es/netiso/CFS). Locally and from // GitHub Actions (e.g. Dependabot), the standard Gradle Plugin Portal is used. // -// AzureArtifacts (anonymous public feed) is always included because every -// settings.gradle loads the artifacts-credprovider plugin from there. -// // The dnceng feed proxies public sources. Once any package has been pulled // through the feed (an authenticated request), it is cached and anonymous // reads work forever after. CI therefore does NOT need credentials — it just @@ -22,17 +19,7 @@ // After it succeeds, just re-run the failed CI job — no PR edit is needed. repositories { - // Anonymous public Azure Artifacts feed that hosts the - // artifacts-credprovider Gradle plugin (loaded by every settings.gradle). - maven { - url = 'https://pkgs.dev.azure.com/artifacts-public/PublicTools/_packaging/AzureArtifacts/maven/v1' - name = 'AzureArtifacts' - } - - // AzDO uppercases pipeline variables when exporting them as env vars on - // Linux/macOS agents, so check both spellings. - def runningOnCI = System.getenv('RunningOnCI') ?: System.getenv('RUNNINGONCI') - if (runningOnCI == 'true') { + if (System.getenv('RUNNINGONCI') == 'true') { maven { url = 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public-maven/maven/v1' name = 'dotnet-public-maven' diff --git a/src/manifestmerger/settings.gradle b/src/manifestmerger/settings.gradle index 483063983cd..47d043fb305 100644 --- a/src/manifestmerger/settings.gradle +++ b/src/manifestmerger/settings.gradle @@ -3,8 +3,8 @@ pluginManagement { apply from: "${rootDir}/../../eng/gradle/plugin-repositories.gradle", to: pluginManagement } -plugins { - id 'com.microsoft.azure.artifacts.credprovider' version '1.1.1' +if (System.getenv('ANDROID_MIRROR_MAVEN_DEPENDENCIES') == 'true') { + apply from: "${rootDir}/../../eng/gradle/credential-provider.gradle" } dependencyResolutionManagement { diff --git a/src/proguard-android/settings.gradle b/src/proguard-android/settings.gradle index f1d5c0e6326..8a8d63d070d 100644 --- a/src/proguard-android/settings.gradle +++ b/src/proguard-android/settings.gradle @@ -3,8 +3,8 @@ pluginManagement { apply from: "${rootDir}/../../eng/gradle/plugin-repositories.gradle", to: pluginManagement } -plugins { - id 'com.microsoft.azure.artifacts.credprovider' version '1.1.1' +if (System.getenv('ANDROID_MIRROR_MAVEN_DEPENDENCIES') == 'true') { + apply from: "${rootDir}/../../eng/gradle/credential-provider.gradle" } dependencyResolutionManagement { diff --git a/src/r8/settings.gradle b/src/r8/settings.gradle index 0d56e34025f..39e8674b5d8 100644 --- a/src/r8/settings.gradle +++ b/src/r8/settings.gradle @@ -3,8 +3,8 @@ pluginManagement { apply from: "${rootDir}/../../eng/gradle/plugin-repositories.gradle", to: pluginManagement } -plugins { - id 'com.microsoft.azure.artifacts.credprovider' version '1.1.1' +if (System.getenv('ANDROID_MIRROR_MAVEN_DEPENDENCIES') == 'true') { + apply from: "${rootDir}/../../eng/gradle/credential-provider.gradle" } dependencyResolutionManagement { diff --git a/tests/CodeGen-Binding/Xamarin.Android.LibraryProjectZip-LibBinding/java/JavaLib/settings.gradle b/tests/CodeGen-Binding/Xamarin.Android.LibraryProjectZip-LibBinding/java/JavaLib/settings.gradle index 571862a24e5..0f5b891e40c 100644 --- a/tests/CodeGen-Binding/Xamarin.Android.LibraryProjectZip-LibBinding/java/JavaLib/settings.gradle +++ b/tests/CodeGen-Binding/Xamarin.Android.LibraryProjectZip-LibBinding/java/JavaLib/settings.gradle @@ -3,8 +3,8 @@ pluginManagement { apply from: "${rootDir}/../../../../../eng/gradle/plugin-repositories.gradle", to: pluginManagement } -plugins { - id 'com.microsoft.azure.artifacts.credprovider' version '1.1.1' +if (System.getenv('ANDROID_MIRROR_MAVEN_DEPENDENCIES') == 'true') { + apply from: "${rootDir}/../../../../../eng/gradle/credential-provider.gradle" } dependencyResolutionManagement {