diff --git a/.github/workflows/java-publish-maven.yml b/.github/workflows/java-publish-maven.yml
index 51c50d979..fd07aae15 100644
--- a/.github/workflows/java-publish-maven.yml
+++ b/.github/workflows/java-publish-maven.yml
@@ -300,6 +300,63 @@ jobs:
if-no-files-found: error
retention-days: 1
+ build-windows-arm64-classifier:
+ name: Build Windows ARM64 native classifier
+ needs: prepare-release
+ runs-on: windows-11-arm
+ permissions:
+ contents: read
+ defaults:
+ run:
+ shell: pwsh
+ working-directory: ./java
+ steps:
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ with:
+ ref: ${{ needs.prepare-release.outputs.release_tag }}
+ fetch-depth: 1
+ persist-credentials: false
+
+ - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
+ with:
+ java-version: "25"
+ distribution: "microsoft"
+ cache: "maven"
+
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
+ with:
+ node-version: 22
+
+ - name: Build and validate win32-arm64 classifier
+ run: |
+ $sourceCommit = git rev-parse HEAD
+ if ($sourceCommit -ne '${{ needs.prepare-release.outputs.tag_commit }}') {
+ throw "Checked out $sourceCommit instead of the prepared tag commit."
+ }
+ node copilot-native/scripts/validate-native-host.mjs win32-arm64
+ mvn -B -pl copilot-native package -DskipTests
+ $version = '${{ needs.prepare-release.outputs.release_version }}'
+ $jar = "copilot-native/target/copilot-sdk-java-runtime-$version-win32-arm64.jar"
+ $primaryJar = "copilot-native/target/copilot-sdk-java-runtime-$version.jar"
+ if (-not (Test-Path -LiteralPath $jar -PathType Leaf)) {
+ throw "Expected Windows ARM64 classifier was not produced: $jar"
+ }
+ node copilot-native/scripts/validate-native-artifact.mjs classifier win32-arm64 $jar ([IO.Path]::GetFileName($jar)) ..
+ node copilot-native/scripts/validate-native-artifact.mjs placeholder $primaryJar
+ $manifest = "copilot-native/target/win32-arm64-$version.sha256"
+ $hash = (Get-FileHash -Algorithm SHA256 -LiteralPath $jar).Hash.ToLowerInvariant()
+ "$hash $([IO.Path]::GetFileName($jar))" | Set-Content -NoNewline -Encoding ascii $manifest
+ node copilot-native/scripts/validate-native-artifact.mjs checksum $jar $manifest ([IO.Path]::GetFileName($jar))
+
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
+ with:
+ name: java-native-win32-arm64-release-${{ github.run_id }}-${{ github.run_attempt }}
+ path: |
+ java/copilot-native/target/copilot-sdk-java-runtime-${{ needs.prepare-release.outputs.release_version }}-win32-arm64.jar
+ java/copilot-native/target/win32-arm64-${{ needs.prepare-release.outputs.release_version }}.sha256
+ if-no-files-found: error
+ retention-days: 1
+
build-darwin-classifier:
name: Build Darwin native classifier
needs: prepare-release
@@ -366,6 +423,7 @@ jobs:
prepare-release,
build-linux-arm64-classifier,
build-windows-classifier,
+ build-windows-arm64-classifier,
build-darwin-classifier,
]
runs-on: ubuntu-latest
@@ -412,6 +470,11 @@ jobs:
name: java-native-win32-x64-release-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/java-native-win32-x64
+ - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+ with:
+ name: java-native-win32-arm64-release-${{ github.run_id }}-${{ github.run_attempt }}
+ path: ${{ runner.temp }}/java-native-win32-arm64
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: java-native-darwin-arm64-release-${{ github.run_id }}-${{ github.run_attempt }}
@@ -480,6 +543,27 @@ jobs:
echo "darwin_jar=$JAR" >> "$GITHUB_OUTPUT"
echo "darwin_sha=$(cut -d ' ' -f 1 "$MANIFEST")" >> "$GITHUB_OUTPUT"
+ - name: Verify immutable source and Windows ARM64 classifier
+ id: windows-arm64-artifact
+ run: |
+ SOURCE_COMMIT=$(git rev-parse HEAD)
+ if [ "$SOURCE_COMMIT" != "${{ needs.prepare-release.outputs.tag_commit }}" ]; then
+ echo "::error::Checked out $SOURCE_COMMIT instead of the prepared tag commit."
+ exit 1
+ fi
+ VERSION="${{ needs.prepare-release.outputs.release_version }}"
+ ARTIFACT_DIRECTORY="${{ runner.temp }}/java-native-win32-arm64"
+ JAR="$ARTIFACT_DIRECTORY/copilot-sdk-java-runtime-$VERSION-win32-arm64.jar"
+ MANIFEST="$ARTIFACT_DIRECTORY/win32-arm64-$VERSION.sha256"
+ test -f "$JAR"
+ test -f "$MANIFEST"
+ node "$GITHUB_WORKSPACE/java/copilot-native/scripts/validate-native-artifact.mjs" \
+ checksum "$JAR" "$MANIFEST" "$(basename "$JAR")"
+ node "$GITHUB_WORKSPACE/java/copilot-native/scripts/validate-native-artifact.mjs" \
+ classifier win32-arm64 "$JAR" "$(basename "$JAR")" "$GITHUB_WORKSPACE"
+ echo "windows_arm64_jar=$JAR" >> "$GITHUB_OUTPUT"
+ echo "windows_arm64_sha=$(cut -d ' ' -f 1 "$MANIFEST")" >> "$GITHUB_OUTPUT"
+
- name: Build Linux classifier and deploy complete release
id: publish-maven
run: |
@@ -487,6 +571,7 @@ jobs:
mvn -B deploy -DskipTests -Prelease -Dcopilot.native.libc=glibc \
"-Dcopilot.native.external.linux.arm64.classifier.path=${{ steps.linux-arm64-artifact.outputs.linux_arm64_jar }}" \
"-Dcopilot.native.external.win32.classifier.path=${{ steps.windows-artifact.outputs.windows_jar }}" \
+ "-Dcopilot.native.external.win32.arm64.classifier.path=${{ steps.windows-arm64-artifact.outputs.windows_arm64_jar }}" \
"-Dcopilot.native.external.darwin.classifier.path=${{ steps.darwin-artifact.outputs.darwin_jar }}"
LINUX_JAR="copilot-native/target/copilot-sdk-java-runtime-$VERSION-linux-x64.jar"
test -f "$LINUX_JAR"
@@ -525,6 +610,7 @@ jobs:
echo "| \`linux-x64\` | \`ubuntu-latest\` | \`$(basename "$LINUX_JAR")\` | \`$LINUX_SHA\` | Published |"
echo "| \`linux-arm64\` | \`ubuntu-24.04-arm\` | \`$(basename "${{ steps.linux-arm64-artifact.outputs.linux_arm64_jar }}")\` | \`${{ steps.linux-arm64-artifact.outputs.linux_arm64_sha }}\` | Published |"
echo "| \`win32-x64\` | \`windows-latest\` | \`$(basename "${{ steps.windows-artifact.outputs.windows_jar }}")\` | \`${{ steps.windows-artifact.outputs.windows_sha }}\` | Published |"
+ echo "| \`win32-arm64\` | \`windows-11-arm\` | \`$(basename "${{ steps.windows-arm64-artifact.outputs.windows_arm64_jar }}")\` | \`${{ steps.windows-arm64-artifact.outputs.windows_arm64_sha }}\` | Published |"
echo "| \`darwin-arm64\` | \`macos-26\` | \`$(basename "${{ steps.darwin-artifact.outputs.darwin_jar }}")\` | \`${{ steps.darwin-artifact.outputs.darwin_sha }}\` | Published |"
} >> "$GITHUB_STEP_SUMMARY"
env:
@@ -539,6 +625,7 @@ jobs:
prepare-release,
build-linux-arm64-classifier,
build-windows-classifier,
+ build-windows-arm64-classifier,
build-darwin-classifier,
deploy-maven,
]
diff --git a/.github/workflows/java-publish-snapshot.yml b/.github/workflows/java-publish-snapshot.yml
index 3b15c3f0d..c0a894dca 100644
--- a/.github/workflows/java-publish-snapshot.yml
+++ b/.github/workflows/java-publish-snapshot.yml
@@ -158,6 +158,67 @@ jobs:
if-no-files-found: error
retention-days: 1
+ build-windows-arm64-classifier:
+ name: Build Windows ARM64 snapshot classifier
+ needs: resolve-source
+ runs-on: windows-11-arm
+ permissions:
+ contents: read
+ outputs:
+ version: ${{ steps.build.outputs.version }}
+ defaults:
+ run:
+ shell: pwsh
+ working-directory: ./java
+ steps:
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ with:
+ ref: ${{ github.sha }}
+ fetch-depth: 1
+ persist-credentials: false
+
+ - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
+ with:
+ java-version: "25"
+ distribution: "microsoft"
+ cache: "maven"
+
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
+ with:
+ node-version: 22
+
+ - name: Build and validate win32-arm64 classifier
+ id: build
+ run: |
+ $sourceCommit = git rev-parse HEAD
+ if ($sourceCommit -ne '${{ needs.resolve-source.outputs.source_sha }}') {
+ throw "Checked out $sourceCommit instead of the resolved snapshot source."
+ }
+ node copilot-native/scripts/validate-native-host.mjs win32-arm64
+ mvn -B -pl copilot-native package -DskipTests
+ $version = mvn help:evaluate "-Dexpression=project.version" -q "-DforceStdout"
+ $jar = "copilot-native/target/copilot-sdk-java-runtime-$version-win32-arm64.jar"
+ $primaryJar = "copilot-native/target/copilot-sdk-java-runtime-$version.jar"
+ if (-not (Test-Path -LiteralPath $jar -PathType Leaf)) {
+ throw "Expected Windows ARM64 classifier was not produced: $jar"
+ }
+ node copilot-native/scripts/validate-native-artifact.mjs classifier win32-arm64 $jar ([IO.Path]::GetFileName($jar)) ..
+ node copilot-native/scripts/validate-native-artifact.mjs placeholder $primaryJar
+ $manifest = "copilot-native/target/win32-arm64-$version.sha256"
+ $hash = (Get-FileHash -Algorithm SHA256 -LiteralPath $jar).Hash.ToLowerInvariant()
+ "$hash $([IO.Path]::GetFileName($jar))" | Set-Content -NoNewline -Encoding ascii $manifest
+ node copilot-native/scripts/validate-native-artifact.mjs checksum $jar $manifest ([IO.Path]::GetFileName($jar))
+ "version=$version" | Add-Content $env:GITHUB_OUTPUT
+
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
+ with:
+ name: java-native-win32-arm64-snapshot-${{ github.run_id }}-${{ github.run_attempt }}
+ path: |
+ java/copilot-native/target/copilot-sdk-java-runtime-${{ steps.build.outputs.version }}-win32-arm64.jar
+ java/copilot-native/target/win32-arm64-${{ steps.build.outputs.version }}.sha256
+ if-no-files-found: error
+ retention-days: 1
+
build-darwin-classifier:
name: Build Darwin snapshot classifier
needs: resolve-source
@@ -228,6 +289,7 @@ jobs:
resolve-source,
build-linux-arm64-classifier,
build-windows-classifier,
+ build-windows-arm64-classifier,
build-darwin-classifier,
]
runs-on: ubuntu-latest
@@ -267,6 +329,11 @@ jobs:
name: java-native-win32-x64-snapshot-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ runner.temp }}/java-native-win32-x64
+ - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+ with:
+ name: java-native-win32-arm64-snapshot-${{ github.run_id }}-${{ github.run_attempt }}
+ path: ${{ runner.temp }}/java-native-win32-arm64
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: java-native-darwin-arm64-snapshot-${{ github.run_id }}-${{ github.run_attempt }}
@@ -353,12 +420,38 @@ jobs:
echo "darwin_jar=$JAR" >> "$GITHUB_OUTPUT"
echo "darwin_sha=$(cut -d ' ' -f 1 "$MANIFEST")" >> "$GITHUB_OUTPUT"
+ - name: Verify version, source, and Windows ARM64 classifier
+ id: windows-arm64-artifact
+ run: |
+ SOURCE_COMMIT=$(git rev-parse HEAD)
+ if [ "$SOURCE_COMMIT" != "${{ needs.resolve-source.outputs.source_sha }}" ]; then
+ echo "::error::Checked out $SOURCE_COMMIT instead of the resolved snapshot source."
+ exit 1
+ fi
+ VERSION="${{ steps.windows-artifact.outputs.version }}"
+ if [ "$VERSION" != "${{ needs.build-windows-arm64-classifier.outputs.version }}" ]; then
+ echo "::error::Windows ARM64 classifier version does not match deploy version."
+ exit 1
+ fi
+ ARTIFACT_DIRECTORY="${{ runner.temp }}/java-native-win32-arm64"
+ JAR="$ARTIFACT_DIRECTORY/copilot-sdk-java-runtime-$VERSION-win32-arm64.jar"
+ MANIFEST="$ARTIFACT_DIRECTORY/win32-arm64-$VERSION.sha256"
+ test -f "$JAR"
+ test -f "$MANIFEST"
+ node "$GITHUB_WORKSPACE/java/copilot-native/scripts/validate-native-artifact.mjs" \
+ checksum "$JAR" "$MANIFEST" "$(basename "$JAR")"
+ node "$GITHUB_WORKSPACE/java/copilot-native/scripts/validate-native-artifact.mjs" \
+ classifier win32-arm64 "$JAR" "$(basename "$JAR")" "$GITHUB_WORKSPACE"
+ echo "windows_arm64_jar=$JAR" >> "$GITHUB_OUTPUT"
+ echo "windows_arm64_sha=$(cut -d ' ' -f 1 "$MANIFEST")" >> "$GITHUB_OUTPUT"
+
- name: Build Linux classifier and deploy complete snapshot
run: |
VERSION="${{ steps.windows-artifact.outputs.version }}"
mvn -B deploy -DskipTests -Dcopilot.native.libc=glibc \
"-Dcopilot.native.external.linux.arm64.classifier.path=${{ steps.linux-arm64-artifact.outputs.linux_arm64_jar }}" \
"-Dcopilot.native.external.win32.classifier.path=${{ steps.windows-artifact.outputs.windows_jar }}" \
+ "-Dcopilot.native.external.win32.arm64.classifier.path=${{ steps.windows-arm64-artifact.outputs.windows_arm64_jar }}" \
"-Dcopilot.native.external.darwin.classifier.path=${{ steps.darwin-artifact.outputs.darwin_jar }}"
LINUX_JAR="copilot-native/target/copilot-sdk-java-runtime-$VERSION-linux-x64.jar"
test -f "$LINUX_JAR"
@@ -395,6 +488,7 @@ jobs:
echo "| \`linux-x64\` | \`ubuntu-latest\` | \`$(basename "$LINUX_JAR")\` | \`$LINUX_SHA\` | Published |"
echo "| \`linux-arm64\` | \`ubuntu-24.04-arm\` | \`$(basename "${{ steps.linux-arm64-artifact.outputs.linux_arm64_jar }}")\` | \`${{ steps.linux-arm64-artifact.outputs.linux_arm64_sha }}\` | Published |"
echo "| \`win32-x64\` | \`windows-latest\` | \`$(basename "${{ steps.windows-artifact.outputs.windows_jar }}")\` | \`${{ steps.windows-artifact.outputs.windows_sha }}\` | Published |"
+ echo "| \`win32-arm64\` | \`windows-11-arm\` | \`$(basename "${{ steps.windows-arm64-artifact.outputs.windows_arm64_jar }}")\` | \`${{ steps.windows-arm64-artifact.outputs.windows_arm64_sha }}\` | Published |"
echo "| \`darwin-arm64\` | \`macos-26\` | \`$(basename "${{ steps.darwin-artifact.outputs.darwin_jar }}")\` | \`${{ steps.darwin-artifact.outputs.darwin_sha }}\` | Published |"
} >> "$GITHUB_STEP_SUMMARY"
env:
diff --git a/.github/workflows/java-sdk-tests.yml b/.github/workflows/java-sdk-tests.yml
index 48fb2174a..36310d26b 100644
--- a/.github/workflows/java-sdk-tests.yml
+++ b/.github/workflows/java-sdk-tests.yml
@@ -31,6 +31,8 @@ jobs:
maven-args: -Dcopilot.native.libc=glibc
- os: windows-latest
classifier: win32-x64
+ - os: windows-11-arm
+ classifier: win32-arm64
- os: macos-26
classifier: darwin-arm64
runs-on: ${{ matrix.os }}
@@ -192,6 +194,63 @@ jobs:
if-no-files-found: error
retention-days: 1
+ java-native-publication-windows-arm64:
+ name: "Java Native Publication Input (win32-arm64)"
+ if: github.event.repository.fork == false
+ runs-on: windows-11-arm
+ permissions:
+ contents: read
+ outputs:
+ source_sha: ${{ steps.build.outputs.source_sha }}
+ version: ${{ steps.build.outputs.version }}
+ defaults:
+ run:
+ shell: pwsh
+ working-directory: ./java
+ steps:
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ with:
+ persist-credentials: false
+
+ - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
+ with:
+ java-version: "25"
+ distribution: "microsoft"
+ cache: "maven"
+
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
+ with:
+ node-version: 22
+
+ - name: Build and validate win32-arm64 classifier
+ id: build
+ run: |
+ node copilot-native/scripts/validate-native-host.mjs win32-arm64
+ mvn -B -pl copilot-native package -DskipTests
+ $version = mvn help:evaluate "-Dexpression=project.version" -q "-DforceStdout"
+ $jar = "copilot-native/target/copilot-sdk-java-runtime-$version-win32-arm64.jar"
+ $primaryJar = "copilot-native/target/copilot-sdk-java-runtime-$version.jar"
+ if (-not (Test-Path -LiteralPath $jar -PathType Leaf)) {
+ throw "Expected Windows ARM64 classifier was not produced: $jar"
+ }
+ node copilot-native/scripts/validate-native-artifact.mjs classifier win32-arm64 $jar ([IO.Path]::GetFileName($jar)) ..
+ node copilot-native/scripts/validate-native-artifact.mjs placeholder $primaryJar
+ $manifest = "copilot-native/target/win32-arm64-$version.sha256"
+ $hash = (Get-FileHash -Algorithm SHA256 -LiteralPath $jar).Hash.ToLowerInvariant()
+ "$hash $([IO.Path]::GetFileName($jar))" | Set-Content -NoNewline -Encoding ascii $manifest
+ node copilot-native/scripts/validate-native-artifact.mjs checksum $jar $manifest ([IO.Path]::GetFileName($jar))
+ echo "source_sha=$(git rev-parse HEAD)" >> $env:GITHUB_OUTPUT
+ echo "version=$version" >> $env:GITHUB_OUTPUT
+
+ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
+ with:
+ name: java-native-publication-win32-arm64-${{ github.run_id }}-${{ github.run_attempt }}
+ path: |
+ java/copilot-native/target/copilot-sdk-java-runtime-${{ steps.build.outputs.version }}-win32-arm64.jar
+ java/copilot-native/target/win32-arm64-${{ steps.build.outputs.version }}.sha256
+ if-no-files-found: error
+ retention-days: 1
+
java-native-publication-darwin:
name: "Java Native Publication Input (darwin-arm64)"
if: github.event.repository.fork == false
@@ -257,6 +316,7 @@ jobs:
[
java-native-publication-linux-arm64,
java-native-publication-windows,
+ java-native-publication-windows-arm64,
java-native-publication-darwin,
]
runs-on: ubuntu-latest
@@ -290,6 +350,11 @@ jobs:
name: java-native-publication-win32-x64-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ github.workspace }}/java/native-publication-input/windows
+ - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
+ with:
+ name: java-native-publication-win32-arm64-${{ github.run_id }}-${{ github.run_attempt }}
+ path: ${{ github.workspace }}/java/native-publication-input/windows-arm64
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: java-native-publication-darwin-arm64-${{ github.run_id }}-${{ github.run_attempt }}
@@ -300,17 +365,22 @@ jobs:
set -euo pipefail
test "$(git rev-parse HEAD)" = "${{ needs.java-native-publication-linux-arm64.outputs.source_sha }}"
test "$(git rev-parse HEAD)" = "${{ needs.java-native-publication-windows.outputs.source_sha }}"
+ test "$(git rev-parse HEAD)" = "${{ needs.java-native-publication-windows-arm64.outputs.source_sha }}"
test "$(git rev-parse HEAD)" = "${{ needs.java-native-publication-darwin.outputs.source_sha }}"
VERSION="${{ needs.java-native-publication-windows.outputs.version }}"
test "$VERSION" = "${{ needs.java-native-publication-linux-arm64.outputs.version }}"
+ test "$VERSION" = "${{ needs.java-native-publication-windows-arm64.outputs.version }}"
test "$VERSION" = "${{ needs.java-native-publication-darwin.outputs.version }}"
LINUX_ARM64_DIRECTORY="$GITHUB_WORKSPACE/java/native-publication-input/linux-arm64"
WINDOWS_DIRECTORY="$GITHUB_WORKSPACE/java/native-publication-input/windows"
+ WINDOWS_ARM64_DIRECTORY="$GITHUB_WORKSPACE/java/native-publication-input/windows-arm64"
DARWIN_DIRECTORY="$GITHUB_WORKSPACE/java/native-publication-input/darwin"
LINUX_ARM64_JAR="$LINUX_ARM64_DIRECTORY/copilot-sdk-java-runtime-$VERSION-linux-arm64.jar"
LINUX_ARM64_MANIFEST="$LINUX_ARM64_DIRECTORY/linux-arm64-$VERSION.sha256"
WINDOWS_JAR="$WINDOWS_DIRECTORY/copilot-sdk-java-runtime-$VERSION-win32-x64.jar"
WINDOWS_MANIFEST="$WINDOWS_DIRECTORY/win32-x64-$VERSION.sha256"
+ WINDOWS_ARM64_JAR="$WINDOWS_ARM64_DIRECTORY/copilot-sdk-java-runtime-$VERSION-win32-arm64.jar"
+ WINDOWS_ARM64_MANIFEST="$WINDOWS_ARM64_DIRECTORY/win32-arm64-$VERSION.sha256"
DARWIN_JAR="$DARWIN_DIRECTORY/copilot-sdk-java-runtime-$VERSION-darwin-arm64.jar"
DARWIN_MANIFEST="$DARWIN_DIRECTORY/darwin-arm64-$VERSION.sha256"
node copilot-native/scripts/validate-native-artifact.mjs \
@@ -321,6 +391,10 @@ jobs:
checksum "$WINDOWS_JAR" "$WINDOWS_MANIFEST" "$(basename "$WINDOWS_JAR")"
node copilot-native/scripts/validate-native-artifact.mjs \
classifier win32-x64 "$WINDOWS_JAR" "$(basename "$WINDOWS_JAR")" ..
+ node copilot-native/scripts/validate-native-artifact.mjs \
+ checksum "$WINDOWS_ARM64_JAR" "$WINDOWS_ARM64_MANIFEST" "$(basename "$WINDOWS_ARM64_JAR")"
+ node copilot-native/scripts/validate-native-artifact.mjs \
+ classifier win32-arm64 "$WINDOWS_ARM64_JAR" "$(basename "$WINDOWS_ARM64_JAR")" ..
node copilot-native/scripts/validate-native-artifact.mjs \
checksum "$DARWIN_JAR" "$DARWIN_MANIFEST" "$(basename "$DARWIN_JAR")"
node copilot-native/scripts/validate-native-artifact.mjs \
@@ -338,6 +412,7 @@ jobs:
-Dcopilot.native.test.local.publication=true \
"-Dcopilot.native.external.linux.arm64.classifier.path=$LINUX_ARM64_JAR" \
"-Dcopilot.native.external.win32.classifier.path=$WINDOWS_JAR" \
+ "-Dcopilot.native.external.win32.arm64.classifier.path=$WINDOWS_ARM64_JAR" \
"-Dcopilot.native.external.darwin.classifier.path=$DARWIN_JAR" \
"-Dmaven.repo.local=$LOCAL_REPOSITORY"
node copilot-native/scripts/validate-local-publication.mjs \
diff --git a/java/README.md b/java/README.md
index e699c6736..10eb72ce5 100644
--- a/java/README.md
+++ b/java/README.md
@@ -72,7 +72,7 @@ implementation 'com.github:copilot-sdk-java:1.0.14-preview.1-SNAPSHOT'
## In-process mode (experimental)
-The SDK supports running the Copilot runtime **in-process** as a native library instead of spawning a separate CLI process. This eliminates process management overhead and simplifies deployment. In-process mode is currently experimental and supported on **linux-x64** (glibc), **linux-arm64** (glibc), **win32-x64**, and **darwin-arm64**.
+The SDK supports running the Copilot runtime **in-process** as a native library instead of spawning a separate CLI process. This eliminates process management overhead and simplifies deployment. In-process mode is currently experimental and supported on **linux-x64** (glibc), **linux-arm64** (glibc), **win32-x64**, **win32-arm64**, and **darwin-arm64**.
Because in-process mode is experimental, see the [Using experimental APIs](#using-experimental-apis) section for how to opt in.
@@ -95,7 +95,7 @@ Add both the SDK and the platform-specific native runtime to your project:
${copilot.version}
linux-x64
-
+
net.java.dev.jna
@@ -511,7 +511,7 @@ mvn jacoco:prepare-agent@wire-up-coverage-instrumentation antrun:run@print-test-
Run native-runtime Maven commands from the `java` directory. Native packaging requires Node.js and npm in addition to JDK 25 and Maven because `copilot-native/scripts/fetch-native.mjs` retrieves the pinned npm runtime package.
-On a native Linux glibc host, Maven activates `native-linux-x64` or `native-linux-arm64` for the matching architecture when `copilot.native.libc=glibc` is set. On Windows x64 and Apple Silicon macOS, Maven activates `native-win32-x64` or `native-darwin-arm64` automatically. The matching profile validates the host, runs the native script tests, fetches the pinned `@github/copilot-` package during `generate-resources`, packages the classifier JAR during `package`, and verifies its native contents. Ensure npm can authenticate to the package registry before running the build.
+On a native Linux glibc host, Maven activates `native-linux-x64` or `native-linux-arm64` for the matching architecture when `copilot.native.libc=glibc` is set. On Windows x64, Windows ARM64, and Apple Silicon macOS, Maven activates `native-win32-x64`, `native-win32-arm64`, or `native-darwin-arm64` automatically. The matching profile validates the host, runs the native script tests, fetches the pinned `@github/copilot-` package during `generate-resources`, packages the classifier JAR during `package`, and verifies its native contents. Ensure npm can authenticate to the package registry before running the build.
Before opting in, validate that Node.js reports glibc for the build host:
@@ -526,7 +526,7 @@ The `inprocess` test profile performs the same validation and native packaging a
mvn -Pinprocess clean verify
```
-On Windows PowerShell, initialize Java and run the same profile:
+On Windows x64 or ARM64 PowerShell, initialize Java and run the same profile:
```powershell
mvn -Pinprocess clean verify
@@ -564,7 +564,7 @@ mvn clean verify -Dcopilot.native.libc=glibc
mvn clean package -pl copilot-native -DskipTests -Dcopilot.native.libc=glibc -Dcopilot.native.skip.download=true
```
-On Linux, the classifier JAR contains `runtime.node`, `platform.properties`, and `copilot` under `native/linux-x64` or `native/linux-arm64`. On Windows x64, it contains those resources under `native/win32-x64`, with the CLI named `copilot.exe`. On Apple Silicon macOS, it contains them under `native/darwin-arm64`. The placeholder JAR remains OS-neutral and contains no native binaries. Unsupported hosts retain the placeholder-only behavior.
+On Linux, the classifier JAR contains `runtime.node`, `platform.properties`, and `copilot` under `native/linux-x64` or `native/linux-arm64`. On Windows, it contains those resources under `native/win32-x64` or `native/win32-arm64`, with the CLI named `copilot.exe`. On Apple Silicon macOS, it contains them under `native/darwin-arm64`. The placeholder JAR remains OS-neutral and contains no native binaries. Unsupported hosts retain the placeholder-only behavior.
## License
diff --git a/java/copilot-native/pom.xml b/java/copilot-native/pom.xml
index 48f11e440..f3694457d 100644
--- a/java/copilot-native/pom.xml
+++ b/java/copilot-native/pom.xml
@@ -235,8 +235,8 @@
@@ -465,6 +465,61 @@
+
+ native-win32-arm64
+
+
+ Windows
+ aarch64
+
+
+
+ win32-arm64
+ copilot.exe
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+
+
+ validate-native-host
+ validate
+
+
+ fetch-native
+ generate-resources
+
+
+ test-fetch-native
+ test
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ jar-native
+ package
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+ verify-native-jars
+ package
+
+
+
+
+
+
native-darwin-arm64
@@ -583,8 +638,8 @@
@@ -645,9 +700,71 @@
+
+
+ attach-external-win32-arm64-classifier
+
+
+ copilot.native.external.win32.arm64.classifier.path
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+
+
+ validate-external-win32-arm64-classifier
+ validate
+
+ exec
+
+
+ node
+
+ ${project.basedir}/scripts/validate-native-artifact.mjs
+ classifier
+ win32-arm64
+ ${copilot.native.external.win32.arm64.classifier.path}
+ ${project.build.finalName}-win32-arm64.jar
+ ${copilot.sdk.root}
+
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+ attach-external-win32-arm64-classifier
+ package
+
+ attach-artifact
+
+
+
+
+ ${copilot.native.external.win32.arm64.classifier.path}
+ jar
+ win32-arm64
+
+
+
+
+
+
+
+
+
attach-external-darwin-classifier
diff --git a/java/copilot-native/scripts/fetch-native.test.mjs b/java/copilot-native/scripts/fetch-native.test.mjs
index a2e7ad2a0..3ca1e2fde 100644
--- a/java/copilot-native/scripts/fetch-native.test.mjs
+++ b/java/copilot-native/scripts/fetch-native.test.mjs
@@ -17,7 +17,7 @@ const runtimeContent = 'runtime content';
const cliContent = 'cli content';
const scriptPath = fileURLToPath(new URL('./fetch-native.mjs', import.meta.url));
-for (const classifier of ['linux-x64', 'linux-arm64', 'win32-x64', 'darwin-arm64']) {
+for (const classifier of ['linux-x64', 'linux-arm64', 'win32-x64', 'win32-arm64', 'darwin-arm64']) {
test(`${classifier}: missing CLI does not use incremental fast path`, (t) => {
const fixture = createFixture(t, classifier);
fs.rmSync(fixture.cliPath);
diff --git a/java/copilot-native/scripts/validate-local-publication.mjs b/java/copilot-native/scripts/validate-local-publication.mjs
index a2586f6c1..c83f9682d 100644
--- a/java/copilot-native/scripts/validate-local-publication.mjs
+++ b/java/copilot-native/scripts/validate-local-publication.mjs
@@ -33,6 +33,7 @@ export function validateLocalPublication({
`${artifactId}-${version}-linux-x64.jar`,
`${artifactId}-${version}-linux-arm64.jar`,
`${artifactId}-${version}-win32-x64.jar`,
+ `${artifactId}-${version}-win32-arm64.jar`,
`${artifactId}-${version}-darwin-arm64.jar`,
];
const files = new Set(fs.readdirSync(artifactDirectory));
@@ -67,6 +68,7 @@ export function validateLocalPublication({
"linux-x64",
"linux-arm64",
"win32-x64",
+ "win32-arm64",
"darwin-arm64",
]) {
const filename = `${artifactId}-${version}-${classifier}.jar`;
diff --git a/java/copilot-native/scripts/validate-native-artifact.test.mjs b/java/copilot-native/scripts/validate-native-artifact.test.mjs
index f84b4add6..eb99d432d 100644
--- a/java/copilot-native/scripts/validate-native-artifact.test.mjs
+++ b/java/copilot-native/scripts/validate-native-artifact.test.mjs
@@ -43,6 +43,36 @@ test("accepts a matching, complete Windows classifier", (t) => {
);
});
+test("accepts a matching, complete Windows ARM64 classifier", (t) => {
+ const fixture = createFixture(t);
+ const windowsArm64Classifier = "win32-arm64";
+ const windowsArm64ArtifactName =
+ "copilot-sdk-java-runtime-1.2.3-win32-arm64.jar";
+ const windowsArm64JarPath = path.join(
+ fixture.root,
+ windowsArm64ArtifactName,
+ );
+ createNativeClassifierTestFixture({
+ classifier: windowsArm64Classifier,
+ outputPath: windowsArm64JarPath,
+ repoRoot: fixture.repoRoot,
+ });
+
+ assert.deepEqual(
+ validateNativeClassifierJar({
+ classifier: windowsArm64Classifier,
+ jarPath: windowsArm64JarPath,
+ expectedFilename: windowsArm64ArtifactName,
+ repoRoot: fixture.repoRoot,
+ }),
+ {
+ classifier: windowsArm64Classifier,
+ nativeVersion: "9.8.10",
+ sha256: undefined,
+ },
+ );
+});
+
test("accepts a matching, complete Darwin classifier", (t) => {
const fixture = createFixture(t);
const darwinClassifier = "darwin-arm64";
@@ -328,6 +358,7 @@ test("validates one complete signed local publication", (t) => {
const linuxJar = `${artifactId}-${version}-linux-x64.jar`;
const linuxArm64Jar = `${artifactId}-${version}-linux-arm64.jar`;
const windowsJar = `${artifactId}-${version}-win32-x64.jar`;
+ const windowsArm64Jar = `${artifactId}-${version}-win32-arm64.jar`;
const darwinJar = `${artifactId}-${version}-darwin-arm64.jar`;
writeStoredZip(path.join(publicationDirectory, primaryJar), [
["META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n"],
@@ -355,6 +386,11 @@ test("validates one complete signed local publication", (t) => {
outputPath: path.join(publicationDirectory, windowsJar),
repoRoot: fixture.repoRoot,
});
+ createNativeClassifierTestFixture({
+ classifier: "win32-arm64",
+ outputPath: path.join(publicationDirectory, windowsArm64Jar),
+ repoRoot: fixture.repoRoot,
+ });
createNativeClassifierTestFixture({
classifier: "darwin-arm64",
outputPath: path.join(publicationDirectory, darwinJar),
@@ -372,6 +408,7 @@ test("validates one complete signed local publication", (t) => {
linuxJar,
linuxArm64Jar,
windowsJar,
+ windowsArm64Jar,
darwinJar,
]) {
fs.writeFileSync(
@@ -446,6 +483,14 @@ test("local publication validation rejects cross-classifier contamination", (t)
),
repoRoot: fixture.repoRoot,
});
+ createNativeClassifierTestFixture({
+ classifier: "win32-arm64",
+ outputPath: path.join(
+ publicationDirectory,
+ `${artifactId}-${version}-win32-arm64.jar`,
+ ),
+ repoRoot: fixture.repoRoot,
+ });
createNativeClassifierTestFixture({
classifier: "darwin-arm64",
outputPath: path.join(
@@ -496,6 +541,7 @@ function createFixture(t) {
JSON.stringify({
packages: {
"node_modules/@github/copilot-win32-x64": { version: "9.8.7" },
+ "node_modules/@github/copilot-win32-arm64": { version: "9.8.10" },
"node_modules/@github/copilot-linux-x64": { version: "9.8.6" },
"node_modules/@github/copilot-linux-arm64": { version: "9.8.9" },
"node_modules/@github/copilot-darwin-arm64": { version: "9.8.8" },
diff --git a/java/copilot-native/scripts/validate-native-host.mjs b/java/copilot-native/scripts/validate-native-host.mjs
index a07dddee3..a0b7a7004 100644
--- a/java/copilot-native/scripts/validate-native-host.mjs
+++ b/java/copilot-native/scripts/validate-native-host.mjs
@@ -21,10 +21,12 @@ export function validateNativeHost(classifier, host) {
return `Validated native build host: ${classifier} (glibc ${host.glibcVersionRuntime})`;
}
- if (classifier === "win32-x64") {
- if (host.platform !== "win32" || host.arch !== "x64") {
+ if (classifier === "win32-x64" || classifier === "win32-arm64") {
+ const expectedArch = classifier === "win32-x64" ? "x64" : "arm64";
+ const displayArch = expectedArch === "x64" ? "x64" : "ARM64";
+ if (host.platform !== "win32" || host.arch !== expectedArch) {
throw new Error(
- `Native ${classifier} packaging requires Windows x64; detected ${host.platform}-${host.arch}`,
+ `Native ${classifier} packaging requires Windows ${displayArch}; detected ${host.platform}-${host.arch}`,
);
}
return `Validated native build host: ${classifier}`;
diff --git a/java/copilot-native/scripts/validate-native-host.test.mjs b/java/copilot-native/scripts/validate-native-host.test.mjs
index 1a71eff44..cb3429489 100644
--- a/java/copilot-native/scripts/validate-native-host.test.mjs
+++ b/java/copilot-native/scripts/validate-native-host.test.mjs
@@ -40,6 +40,17 @@ test("accepts Windows x64 without a libc requirement", () => {
);
});
+test("accepts Windows ARM64 without a libc requirement", () => {
+ assert.equal(
+ validateNativeHost("win32-arm64", {
+ platform: "win32",
+ arch: "arm64",
+ glibcVersionRuntime: undefined,
+ }),
+ "Validated native build host: win32-arm64",
+ );
+});
+
test("accepts macOS ARM64 without a libc requirement", () => {
assert.equal(
validateNativeHost("darwin-arm64", {
@@ -135,6 +146,18 @@ test("rejects Windows ARM64 for the Windows x64 classifier", () => {
);
});
+test("rejects Windows x64 for the Windows ARM64 classifier", () => {
+ assert.throws(
+ () =>
+ validateNativeHost("win32-arm64", {
+ platform: "win32",
+ arch: "x64",
+ glibcVersionRuntime: undefined,
+ }),
+ /requires Windows ARM64/,
+ );
+});
+
test("rejects a non-macOS host for the macOS classifier", () => {
assert.throws(
() =>
diff --git a/java/docs/adr/adr-007-native-bundling-strategy.md b/java/docs/adr/adr-007-native-bundling-strategy.md
index 78276f348..154082936 100644
--- a/java/docs/adr/adr-007-native-bundling-strategy.md
+++ b/java/docs/adr/adr-007-native-bundling-strategy.md
@@ -208,9 +208,9 @@ If none succeeds, startup fails. The PATH fallback does not claim to support eve
### Current platform scope
-The platform detector recognizes the 8 classifiers listed in this ADR. The Maven build binds native packaging only for a host matching an implemented classifier. Linux x64 and ARM64 glibc hosts can opt in with `copilot.native.libc=glibc`, while Windows x64 and Apple Silicon macOS hosts package `win32-x64` or `darwin-arm64` automatically. The `inprocess` test profile selects the matching implemented classifier automatically on all four hosts. Every path validates the host before downloading or packaging native files. Linux musl and other unsupported hosts build only the OS-neutral placeholder, sources, and Javadoc artifacts unless they explicitly request in-process tests, which fail during host validation. Additional classifier artifacts remain follow-up work.
+The platform detector recognizes the 8 classifiers listed in this ADR. The Maven build binds native packaging only for a host matching an implemented classifier. Linux x64 and ARM64 glibc hosts can opt in with `copilot.native.libc=glibc`, while Windows x64, Windows ARM64, and Apple Silicon macOS hosts package `win32-x64`, `win32-arm64`, or `darwin-arm64` automatically. The `inprocess` test profile selects the matching implemented classifier automatically on all five hosts. Every path validates the host before downloading or packaging native files. Linux musl and other unsupported hosts build only the OS-neutral placeholder, sources, and Javadoc artifacts unless they explicitly request in-process tests, which fail during host validation. Additional classifier artifacts remain follow-up work.
-Maven Central release and snapshot workflows build each classifier on its matching native host from the same immutable source. The Linux ARM64, Windows, and macOS jobs each upload only their verified classifier and checksum manifest. The Ubuntu x64 job verifies and attaches all three, builds `linux-x64` with the glibc opt-in, and performs the only Maven deployment. Release signing therefore covers the neutral artifacts and all four classifiers in one deployment.
+Maven Central release and snapshot workflows build each classifier on its matching native host from the same immutable source. The Linux ARM64, Windows x64, Windows ARM64, and macOS jobs each upload only their verified classifier and checksum manifest. The Ubuntu x64 job verifies and attaches all four, builds `linux-x64` with the glibc opt-in, and performs the only Maven deployment. Release signing therefore covers the neutral artifacts and all five classifiers in one deployment.
## Binding technology: JNA over Panama FFM
@@ -362,7 +362,7 @@ The pattern follows DJL's `LibUtils.loadLibrary()` approach: detect the platform
3. Extracts `runtime.node` and the transitional CLI entrypoint into `~/.copilot/runtime-cache/` if valid cached files are not already present.
4. Loads it via [JNA](#references) using the C ABI entry points, per the [binding technology decision](#binding-technology-jna-over-panama-ffm) above. The JNA-specific code is confined behind an internal binding interface to preserve a future FFM migration path.
* A validated supported-host profile fetches the pinned matching `@github/copilot-` npm package, verifies its SHA-512 integrity from `nodejs/package-lock.json`, and packages the version-matched runtime and CLI files.
-* The current release work publishes the `linux-x64`, `linux-arm64`, `win32-x64`, and `darwin-arm64` classifiers. The planned classifier set expands to the other detected platforms.
+* The current release work publishes the `linux-x64`, `linux-arm64`, `win32-x64`, `win32-arm64`, and `darwin-arm64` classifiers. The planned classifier set expands to the other detected platforms.
* Adding an implemented platform requires validated host activation, a profile that supplies the classifier and platform CLI filename, and lifecycle bindings for the shared host validation, fetch, script test, package, and verification executions.
* `cli-native.node` is not bundled. It provides terminal UI features that are irrelevant to the Java SDK's programmatic API surface.
diff --git a/java/sdk/pom.xml b/java/sdk/pom.xml
index 6bad3d2f6..4f9ece635 100644
--- a/java/sdk/pom.xml
+++ b/java/sdk/pom.xml
@@ -708,6 +708,18 @@ did not produce the multi-release output. Re-build on JDK 25+ and verify the
win32-x64
+
+ native-win32-arm64
+
+
+ Windows
+ aarch64
+
+
+
+ win32-arm64
+
+
native-darwin-arm64