[ci] Fix Java.Interop test lanes on internal 1ES pipeline - #11957
Merged
Conversation
The internal DevDiv Xamarin.Android pipeline (azure-pipelines.yaml) extends MicroBuild.1ES.Official.yml, whose 1ES Pipeline Templates require Windows jobs to run on a 1ES-hosted pool. The Java.Interop test stage introduced with the Java.Interop merge was calling stage-java-interop-tests.yaml with no parameters, so both the `Windows - .NET` and `Mac - .NET` jobs fell back to the template defaults - `name: Azure Pipelines` with no `os:` set. 1ES PT's validateHostedPool.ps1 defaults to `-OS windows` when the pool has no `os:` field, and then rejects the hosted `Azure Pipelines`pool as `not a 1ESHostedPool`, failing both jobs in `1ES PT Pre-Job`. Fix: * Set `os: windows` / `os: macOS` on the template's default pools so callers that omit the parameter still land on a compliant setup. * Override the internal pipeline to run the Windows lane on `MAUI-1ESPT`+ `WindowsPoolImage1ESPT`, matching the other Windows jobs in the pipeline. The Mac lane can stay on hosted `Azure Pipelines` because 1ES has no macOS 1ES-hosted pool; `os: macOS` alone is enough. * Also set `os: windows` on the public pipeline's windowsPool for parity and safety. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
* Add a comment to stage-java-interop-tests.yaml explaining the windowsPool default is not 1ES-Official compliant and must be overridden by Official callers. * Declare `runNativeDotnetTests` in external/Java.Interop's core-tests.yaml. The parameter was referenced from the `Java.Interop-Tests`condition but never declared, so it evaluated to '' at expansion and the Windows Java.Interop-Tests step was silently skipped. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Member
Author
|
Internal pipeline run: |
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes the internal 1ES DevDiv pipeline’s Java.Interop Tests stage by ensuring pool definitions include an explicit os: and by wiring a previously-referenced-but-undeclared Java.Interop template parameter so the intended Windows test step actually runs.
Changes:
- Add explicit
os: windows/os: macOSto the default pools in the shared Java.Interop test stage template to satisfy 1ES PT hosted-pool validation behavior. - Override the Java.Interop Windows pool in the internal
azure-pipelines.yamlto use the 1ES-hostedMAUI-1ESPTpool + image. - Declare
runNativeDotnetTestsas a parameter in the Java.Interopcore-tests.yamltemplate so the Windows lane’srunNativeDotnetTests: truetakes effect (instead of being silently skipped).
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| external/Java.Interop/build-tools/automation/templates/core-tests.yaml | Declares runNativeDotnetTests parameter so the Java.Interop-Tests step condition can be driven by callers. |
| build-tools/automation/yaml-templates/stage-java-interop-tests.yaml | Adds os: to default pools (Windows/macOS) and documents 1ES Official mode requirements for Windows pools. |
| build-tools/automation/azure-pipelines.yaml | Internal pipeline now overrides windowsPool for the Java.Interop stage to a 1ES-hosted pool. |
| build-tools/automation/azure-pipelines-public.yaml | Adds os: windows on the Java.Interop stage’s Windows pool for parity/consistency. |
The Mac lane in build 14553565 crashed with:
FAILURE: Build failed with an exception.
* What went wrong:
BUG! exception in phase 'semantic analysis' in source unit '_BuildScript_'
Unsupported class file major version 69
Major version 69 is Java 25. The hosted macOS-15-arm64 image now ships
Java 25 as its default JDK, and Gradle 8.12 (used by java-source-utils
and tests/Xamarin.Android.Tools.Bytecode-Tests/kotlin-gradle) does not
support Java 25.
The rest of the dotnet/android pipeline avoids this by calling the
setup-jdk-variables.yaml template, which pins JAVA_HOME to a specific
agent JDK. The Java.Interop stage was skipping that step and inheriting
the agent default.
Add setup-jdk-variables.yaml to both the Windows and Mac Java.Interop
jobs, pinned to $(LatestJavaSdkMajorVersion) (21, defined in
build-tools/automation/yaml-templates/variables.yaml), matching the
rest of the pipeline. Windows did not fail this run but will hit the
same issue once its hosted image bumps default JDK.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The Java.Interop Mac test lane (dotnet/android build 14553956) failed with Gradle 8.12 rejecting "Unsupported class file major version 69" even after the pipeline pinned JAVA_HOME to Java 21 via setup-jdk-variables.yaml. Root cause: Prepare.targets is what actually decides which JDK the rest of the build uses. It runs the JdkInfo bootstrap task, which discovers a JDK and writes bin/BuildRelease/JdkInfo.props. Every downstream .targets file that shells out to Gradle passes EnvironmentVariables="JAVA_HOME=$(JavaSdkDirectory);..." to <Exec>, overriding whatever JAVA_HOME the process inherited. JdkInfo prefers an explicit JdksRoot when given one; otherwise it walks GetKnownSystemJdkInfos and takes the first hit. Prepare.targets only set JdksRoot from JAVA_HOME_17_X64 / JAVA_HOME_11_X64 - Azure Pipelines variables that exist only on x64 hosted agents. On macOS-15-arm64 (and any other arm64 or non-Azure-Pipelines environment) both were empty, JdksRoot stayed unset, and JdkInfo picked the newest system JDK - Java 25 on the current hosted image - blowing up Gradle. Add a third fallback: use $JAVA_HOME itself when it is set and points to an existing directory. This is what any pipeline or developer who has already selected a JDK expects, and it matches how the rest of dotnet/android's build steps propagate JAVA_HOME. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Member
Author
The previous attempt used setup-jdk-variables.yaml with useAgentJdkPath=true
to point JAVA_HOME at the agents preinstalled JDK. That works on the
internal DevDiv MAUI-1ESPT / hosted Azure Pipelines images (which set
JAVA_HOME_21_X64), but the dnceng-public NetCorePublicPool image does
not preinstall JDK 21, so the step failed with:
Get-Item : Cannot find path Env:\JAVA_HOME_21_X64 because it does not exist.
It was also fragile at another layer: the Java.Interop MSBuild targets
that shell out to Gradle pass EnvironmentVariables="JAVA_HOME=$(JavaSdkDirectory)"
on every <Exec>, so pipeline JAVA_HOME gets overridden anyway. What
actually matters is which JDK Prepare.targets JdkInfo bootstrap task
picks.
Simpler fix: set JI_MAX_JDK=21 as a stage-scope variable. Prepare.targets
already reads it via <_MaxJdk Condition=" $(_MaxJdk) == "> ${JI_MAX_JDK}
and forwards it to JdkInfo as MaximumJdkVersion. That caps the JDK to
one Gradle 8.12 supports on every agent, regardless of which JAVA_HOME_*
env vars the pool happens to preinstall.
Remove the pipeline JAVA_HOME juggling and drop the setup-jdk-variables
calls I added for the Java.Interop jobs. The Prepare.targets $JAVA_HOME
fallback added in the previous commit stays put - it is still a real
improvement for local devs who export JAVA_HOME.
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
simonrozsival
approved these changes
Jul 3, 2026
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Why
After merging
external/Java.Interopin-tree, the newJava.Interop Testsstage started failing on the internal DevDivXamarin.Androidpipeline (e.g. build 14551960) with:Both the
Windows - .NETandMac - .NETjobs failed in1ES PT Pre-Jobbefore doing any real work.Root cause
The internal pipeline extends
MicroBuild.1ES.Official.yml, which requires Windows jobs to run on a 1ES-hosted pool.stage-java-interop-tests.yamlwas called with no parameters, so both jobs fell back to the template defaults -name: Azure Pipelineswith noos:field. 1ES PT'svalidateHostedPool.ps1defaults to-OS windowswhen the pool has noos:, then rejects the hostedAzure Pipelinespool as non-1ES - so even the Mac job was validated as Windows and rejected.What changed
stage-java-interop-tests.yaml: setos: windows/os: macOSon the default pools so callers who omit the parameter still land on a valid setup, with a comment noting the Windows default is not Official-1ES compliant and must be overridden by Official callers.azure-pipelines.yaml(internal): overridewindowsPooltoMAUI-1ESPT+$(WindowsPoolImage1ESPT)+os: windows, matching the other internal Windows jobs. The Mac lane stays on hostedAzure Pipelines+os: macOSbecause 1ES has no macOS-hosted pool.azure-pipelines-public.yaml: addos: windowsonwindowsPoolfor parity.external/Java.Interop/build-tools/automation/templates/core-tests.yaml: declarerunNativeDotnetTestsas an actual parameter. It was referenced from theJava.Interop-Testsstep'scondition:but never declared, so it evaluated to''at template expansion and that test step was silently skipped on Windows. Declaring the parameter lets the Windows lane'srunNativeDotnetTests: truevalue take effect.Testing
No new automated tests; the pipeline itself is the test. Once merged, the next internal run should show
Java.Interop Testsreaching real build/test steps instead of failing in1ES PT Pre-Job, and the WindowsJava.Interop-Teststest step should actually execute.