From 24252012aaf6bdb99ae438a7863acc3a99cca94f Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 18 Aug 2026 11:13:13 -0500 Subject: [PATCH 1/5] [build] Fail incomplete Maven mirroring (#12412) ## Summary - return explicit success and failure counts from `Invoke-Mirror` - evaluate direct Maven mirroring per requested coordinate - fail `-MavenArtifact` when any coordinate mirrors no payloads Addresses the `eng/gradle/mirror-dependencies.ps1` feedback from dotnet/android#12397 without modifying the release backport. ## Validation - parsed `mirror-dependencies.ps1` with the PowerShell parser - verified a coordinate succeeds when at least one payload returns HTTP 200 - verified all-failed payloads exit with code 1 - verified multiple coordinates exit with code 1 when any coordinate has no successful payload - `git diff --check` Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> (cherry picked from commit 1c4d41c09eecfeb278f7012079f22f431198f913) --- eng/gradle/mirror-dependencies.ps1 | 38 +++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/eng/gradle/mirror-dependencies.ps1 b/eng/gradle/mirror-dependencies.ps1 index a1c43f1b547..c28bb0e20a0 100644 --- a/eng/gradle/mirror-dependencies.ps1 +++ b/eng/gradle/mirror-dependencies.ps1 @@ -35,7 +35,8 @@ Maven coordinates to mirror directly, for tests that do not use Gradle. Each value is group:artifact:version, which attempts the POM, JAR, AAR, and Gradle module metadata files. Append an exact filename as a fourth segment - when a test requests a nonstandard payload. + when a test requests a nonstandard payload. The command fails if no payload + can be mirrored for any requested coordinate. .PARAMETER GradleWrapper Optional path to the Gradle wrapper used by CI for this project, relative @@ -126,7 +127,12 @@ function Invoke-Mirror($logPath) { ForEach-Object { $_.Matches } | ForEach-Object { $_.Groups[1].Value } | Sort-Object -Unique - if ($urls.Count -eq 0) { return 0 } + if ($urls.Count -eq 0) { + return [pscustomobject]@{ + SuccessCount = 0 + FailureCount = 0 + } + } $token = Get-AzDevOpsToken $basicCredential = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$token")) $headers = @{ Authorization = "Basic $basicCredential" } @@ -141,7 +147,10 @@ function Invoke-Mirror($logPath) { } } Write-Host " -> mirrored OK=$ok, not-found=$fail (of $($urls.Count))" -ForegroundColor Cyan - return $urls.Count + return [pscustomobject]@{ + SuccessCount = $ok + FailureCount = $fail + } } function Get-MavenArtifactUrls($artifacts) { @@ -177,15 +186,26 @@ if ($PSCmdlet.ParameterSetName -eq 'MavenArtifact') { Write-Host "Mirroring Maven artifacts directly:" $MavenArtifact | ForEach-Object { Write-Host " $_" } $log = Join-Path ([IO.Path]::GetTempPath()) 'maven-artifact-mirror.log' + $failedArtifacts = @() try { - Get-MavenArtifactUrls $MavenArtifact | - ForEach-Object { "Could not GET '$_'" } | - Set-Content $log - Invoke-Mirror $log | Out-Null + foreach ($artifact in $MavenArtifact) { + Get-MavenArtifactUrls $artifact | + ForEach-Object { "Could not GET '$_'" } | + Set-Content $log + $result = Invoke-Mirror $log + if ($result.SuccessCount -eq 0) { + $failedArtifacts += $artifact + } + } } finally { Remove-Item $log -ErrorAction SilentlyContinue } + if ($failedArtifacts.Count -gt 0) { + Write-Host "`nNo payloads were mirrored for:" -ForegroundColor Red + $failedArtifacts | ForEach-Object { Write-Host " $_" -ForegroundColor Red } + exit 1 + } return } @@ -208,8 +228,8 @@ try { Write-Host "`nBUILD SUCCESSFUL after $i iteration(s). The feed now has the packages CI needs." -ForegroundColor Green return } - $count = Invoke-Mirror $log - if ($count -eq 0) { + $result = Invoke-Mirror $log + if (($result.SuccessCount + $result.FailureCount) -eq 0) { Write-Host "`nGradle failed but no 401s to mirror — see $log" -ForegroundColor Red Get-Content $log -Tail 30 exit 1 From 1e411712e7fafc460c607fa1d2365769b7febe7f Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 20 Aug 2026 15:59:18 -0500 Subject: [PATCH 2/5] [release/10.0.1xx] Update Java.Interop Maven hardening Pin dotnet/java-interop#1495's single release backport commit, which validates Maven coordinates and keeps resolved cache paths contained. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- external/Java.Interop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/Java.Interop b/external/Java.Interop index 33992194b93..e9e18f8b96b 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit 33992194b9373e9322244612c94ed9941b9bc2fd +Subproject commit e9e18f8b96b00f5dc6d090543c73f59d6252d127 From 43b345d81d34cb30a8b2f5766a58b9abb0cbe8cb Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Thu, 20 Aug 2026 16:09:58 -0500 Subject: [PATCH 3/5] [release/10.0.1xx] Use complete Java.Interop Maven backport Replace the superseded hardening-only pin with dotnet/java-interop#1498's single release commit, adding approved-feed routing for Java.Interop Maven tests and java-source-utils. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- external/Java.Interop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/Java.Interop b/external/Java.Interop index e9e18f8b96b..7c110bfad3e 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit e9e18f8b96b00f5dc6d090543c73f59d6252d127 +Subproject commit 7c110bfad3ee0a87f303609426167722ccb4ba77 From cee1c6e6e398cd6ffd12fdd4ab974ce2632d31bf Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 21 Aug 2026 10:16:40 -0500 Subject: [PATCH 4/5] [release/10.0.1xx] Handle inherited Maven coordinates Backport the Android-side parent POM coordinate fallback from 7da7db72a and cover POMs that inherit groupId and version. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 30d6319e-30d5-4311-831c-58c4a0571403 --- .../Tasks/JavaDependencyVerification.cs | 8 ++++++- .../Tasks/JavaDependencyVerificationTests.cs | 21 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/JavaDependencyVerification.cs b/src/Xamarin.Android.Build.Tasks/Tasks/JavaDependencyVerification.cs index 3e9740609e7..92380901e3d 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/JavaDependencyVerification.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/JavaDependencyVerification.cs @@ -272,7 +272,13 @@ public MSBuildLoggingPomResolver (TaskLoggingHelper logger) try { using (var file = File.OpenRead (filename)) { var project = Project.Load (file); - var registered_artifact = Artifact.Parse (project.VersionedArtifactString); + + // POMs may inherit GroupId/Version from a element, so fall back to + // the parent's values when the project itself doesn't declare them. (Without + // this, building an Artifact would fail validation with an empty coordinate.) + var groupId = project.GroupId.HasValue () ? project.GroupId : (project.Parent?.GroupId ?? ""); + var version = project.Version.HasValue () ? project.Version : (project.Parent?.Version ?? ""); + var registered_artifact = new Artifact (groupId, project.ArtifactId ?? "", version); // Return the registered artifact, preferring any overrides specified in the task item var final_artifact = new Artifact ( diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/JavaDependencyVerificationTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/JavaDependencyVerificationTests.cs index 4c59593ebf3..eb5774ed761 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/JavaDependencyVerificationTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/JavaDependencyVerificationTests.cs @@ -78,6 +78,27 @@ public void NoSpecifiedDependencies () Assert.AreEqual (0, engine.Errors.Count); } + [Test] + public void InheritedArtifactCoordinates () + { + using var parent_pom = new PomBuilder ("com.google.auto.value", "auto-value-parent", "1.10.4").BuildTemporary (); + using var pom = new PomBuilder ("", "auto-value-annotations", "") + .WithParent ("com.google.auto.value", "auto-value-parent", "1.10.4") + .BuildTemporary (); + + var engine = new MockBuildEngine (TestContext.Out, []); + var task = new JavaDependencyVerification { + BuildEngine = engine, + AndroidLibraries = [CreateAndroidLibraryTaskItem ("auto-value-annotations.jar", pom.FilePath)], + AdditionalManifests = [CreateAndroidAdditionManifestTaskItem (parent_pom.FilePath)], + }; + + var result = task.RunTask (); + + Assert.True (result); + Assert.AreEqual (0, engine.Errors.Count); + } + [Test] public void MissingSpecifiedDependency () { From 333b968d18ced2ff0287d4abcfbab2cd8df465d7 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Fri, 21 Aug 2026 12:08:26 -0500 Subject: [PATCH 5/5] [release/10.0.1xx] Track merged Java.Interop backport Update the gitlink to the current dotnet/java-interop release/10.0.1xx tip containing merged PR #1498. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 30d6319e-30d5-4311-831c-58c4a0571403 --- external/Java.Interop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/Java.Interop b/external/Java.Interop index 7c110bfad3e..8e8291c9ef4 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit 7c110bfad3ee0a87f303609426167722ccb4ba77 +Subproject commit 8e8291c9ef45b4bbc28b09456dc5888eb80af77b