Skip to content

Commit 48b280a

Browse files
authored
Java: add Apple Silicon macOS in-process runtime and native classifier publishing
Implements the `darwin-arm64` portion of #2399. Fixes #2400. ## Summary Adds Apple Silicon macOS (`darwin-arm64`) as a supported target for the Java SDK's experimental in-process runtime, alongside the existing GNU/Linux `linux-x64` and Windows `win32-x64` targets delivered by #2301 and #2393. - Packages a macOS native classifier containing `runtime.node`, `copilot`, and `platform.properties`. - Activates and validates the `darwin-arm64` classifier automatically on Apple Silicon macOS, including when Maven runs with `-Pinprocess`. - Extends native fetch, host-validation, artifact-validation, and local-publication tests to cover Darwin artifacts and reject unsupported Intel macOS hosts. - Runs the Java in-process test suite on `macos-26` in addition to the existing Ubuntu and Windows matrix. - Builds the Darwin classifier on an Apple Silicon macOS runner and adds it to the blocking publication-assembly test. - Extends both snapshot and Maven Central release workflows so Linux, Windows, and Darwin classifiers are built on their matching native hosts and published together in one Maven deployment. - Documents Apple Silicon setup, classifier contents, supported-host behavior, and the updated ADR-007 platform status. ## User experience In-process mode remains opt-in, experimental, and unchanged for existing Linux and Windows consumers. The SDK's default connection behavior is also unchanged. An Apple Silicon macOS application enables in-process mode by: 1. Depending on `com.github:copilot-sdk-java-runtime` with classifier `darwin-arm64`, plus JNA. 2. Configuring `CopilotClientOptions` with `RuntimeConnection.forInProcess()`. The classifier JAR contains: ```text native/darwin-arm64/runtime.node native/darwin-arm64/platform.properties native/darwin-arm64/copilot ``` For SDK development on Apple Silicon, `mvn -Pinprocess clean verify` detects `darwin-arm64`, validates that the host is macOS ARM64, fetches the pinned `@github/copilot-darwin-arm64` package, packages its version-matched runtime and transitional CLI, and exercises the in-process integration suite. Intel macOS and other unsupported OS/architecture combinations fail explicit in-process host validation rather than packaging the wrong binary. During the active Rust migration, the classifier intentionally includes the version-matched `copilot` embedded-host executable in addition to `runtime.node`. It can be removed once the native runtime no longer delegates unported method bodies to the CLI. ## Packaging and publication model This extends the coordinated publication model introduced by #2393 from two native classifiers to three: | Classifier | Build host | Native contents | |---|---|---| | `linux-x64` | Ubuntu x64 glibc | `runtime.node`, `copilot`, metadata | | `win32-x64` | Windows x64 | `runtime.node`, `copilot.exe`, metadata | | `darwin-arm64` | Apple Silicon macOS | `runtime.node`, `copilot`, metadata | The macOS job builds only the `darwin-arm64` classifier and a SHA-256 manifest. The sole Ubuntu publisher then: 1. Verifies that the macOS and Windows handoffs came from the same immutable source and Maven version as the Linux build. 2. Verifies each checksum, expected filename, pinned native-runtime version, required contents, and absence of cross-classifier contamination. 3. Attaches the external Windows and Darwin classifier JARs to the Maven reactor. 4. Builds `linux-x64` locally and performs one deployment containing the neutral SDK artifacts and all three native classifiers. Using one deployment preserves a shared Maven snapshot timestamp/build number and ensures release signing covers every classifier. Snapshot and release summaries now report the build host, filename, and SHA-256 hash for all three classifiers. ## CI and safety checks - The in-process Actions matrix covers `linux-x64`, `win32-x64`, and `darwin-arm64`. - A dedicated `macos-26` job builds and validates the Darwin publication input before upload. - Blocking publication assembly downloads both external native artifacts and validates the complete signed local repository before publication workflows can drift unnoticed. - Host validation accepts only `darwin` + `arm64` for `darwin-arm64`; Intel macOS and non-macOS hosts are rejected. - Artifact validation requires a nonempty Darwin `runtime.node`, `copilot`, and matching `platform.properties`. - Local-publication validation requires all three classifiers and rejects native resources from the wrong platform. - Fetch tests cover complete, missing, and stale Darwin staging states. ## Validation coverage - Darwin native-host acceptance and rejection tests. - Darwin classifier artifact-validation tests. - Three-classifier local-publication validation and contamination tests. - Native fetch tests across Linux, Windows, and Darwin classifiers. - Apple Silicon `mvn -Pinprocess clean verify` in the Java CI matrix. - Native publication-input build on `macos-26`. - Complete Linux/Windows/Darwin local publication assembly on Ubuntu.
1 parent 93351c9 commit 48b280a

13 files changed

Lines changed: 527 additions & 24 deletions

.github/workflows/java-publish-maven.yml

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,68 @@ jobs:
241241
if-no-files-found: error
242242
retention-days: 1
243243

244+
build-darwin-classifier:
245+
name: Build Darwin native classifier
246+
needs: prepare-release
247+
runs-on: macos-26
248+
permissions:
249+
contents: read
250+
defaults:
251+
run:
252+
shell: bash
253+
working-directory: ./java
254+
steps:
255+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
256+
with:
257+
ref: ${{ needs.prepare-release.outputs.release_tag }}
258+
fetch-depth: 1
259+
persist-credentials: false
260+
261+
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
262+
with:
263+
java-version: "25"
264+
distribution: "microsoft"
265+
cache: "maven"
266+
267+
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
268+
with:
269+
node-version: 22
270+
271+
- name: Build and validate darwin-arm64 classifier
272+
run: |
273+
set -euo pipefail
274+
SOURCE_COMMIT=$(git rev-parse HEAD)
275+
if [ "$SOURCE_COMMIT" != "${{ needs.prepare-release.outputs.tag_commit }}" ]; then
276+
echo "::error::Checked out $SOURCE_COMMIT instead of the prepared tag commit."
277+
exit 1
278+
fi
279+
node copilot-native/scripts/validate-native-host.mjs darwin-arm64
280+
mvn -B -pl copilot-native package -DskipTests
281+
VERSION="${{ needs.prepare-release.outputs.release_version }}"
282+
JAR="copilot-native/target/copilot-sdk-java-runtime-$VERSION-darwin-arm64.jar"
283+
PRIMARY_JAR="copilot-native/target/copilot-sdk-java-runtime-$VERSION.jar"
284+
test -f "$JAR"
285+
node copilot-native/scripts/validate-native-artifact.mjs \
286+
classifier darwin-arm64 "$JAR" "$(basename "$JAR")" ..
287+
node copilot-native/scripts/validate-native-artifact.mjs placeholder "$PRIMARY_JAR"
288+
MANIFEST="copilot-native/target/darwin-arm64-$VERSION.sha256"
289+
HASH=$(shasum -a 256 "$JAR" | cut -d ' ' -f 1)
290+
printf '%s %s' "$HASH" "$(basename "$JAR")" > "$MANIFEST"
291+
node copilot-native/scripts/validate-native-artifact.mjs \
292+
checksum "$JAR" "$MANIFEST" "$(basename "$JAR")"
293+
294+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
295+
with:
296+
name: java-native-darwin-arm64-release-${{ github.run_id }}-${{ github.run_attempt }}
297+
path: |
298+
java/copilot-native/target/copilot-sdk-java-runtime-${{ needs.prepare-release.outputs.release_version }}-darwin-arm64.jar
299+
java/copilot-native/target/darwin-arm64-${{ needs.prepare-release.outputs.release_version }}.sha256
300+
if-no-files-found: error
301+
retention-days: 1
302+
244303
deploy-maven:
245304
name: Deploy Java release to Maven Central
246-
needs: [prepare-release, build-windows-classifier]
305+
needs: [prepare-release, build-windows-classifier, build-darwin-classifier]
247306
runs-on: ubuntu-latest
248307
permissions:
249308
contents: read
@@ -283,6 +342,11 @@ jobs:
283342
name: java-native-win32-x64-release-${{ github.run_id }}-${{ github.run_attempt }}
284343
path: ${{ runner.temp }}/java-native-win32-x64
285344

345+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
346+
with:
347+
name: java-native-darwin-arm64-release-${{ github.run_id }}-${{ github.run_attempt }}
348+
path: ${{ runner.temp }}/java-native-darwin-arm64
349+
286350
- name: Verify immutable source and Windows classifier
287351
id: windows-artifact
288352
run: |
@@ -304,12 +368,34 @@ jobs:
304368
echo "windows_jar=$JAR" >> "$GITHUB_OUTPUT"
305369
echo "windows_sha=$(cut -d ' ' -f 1 "$MANIFEST")" >> "$GITHUB_OUTPUT"
306370
371+
- name: Verify immutable source and Darwin classifier
372+
id: darwin-artifact
373+
run: |
374+
SOURCE_COMMIT=$(git rev-parse HEAD)
375+
if [ "$SOURCE_COMMIT" != "${{ needs.prepare-release.outputs.tag_commit }}" ]; then
376+
echo "::error::Checked out $SOURCE_COMMIT instead of the prepared tag commit."
377+
exit 1
378+
fi
379+
VERSION="${{ needs.prepare-release.outputs.release_version }}"
380+
ARTIFACT_DIRECTORY="${{ runner.temp }}/java-native-darwin-arm64"
381+
JAR="$ARTIFACT_DIRECTORY/copilot-sdk-java-runtime-$VERSION-darwin-arm64.jar"
382+
MANIFEST="$ARTIFACT_DIRECTORY/darwin-arm64-$VERSION.sha256"
383+
test -f "$JAR"
384+
test -f "$MANIFEST"
385+
node "$GITHUB_WORKSPACE/java/copilot-native/scripts/validate-native-artifact.mjs" \
386+
checksum "$JAR" "$MANIFEST" "$(basename "$JAR")"
387+
node "$GITHUB_WORKSPACE/java/copilot-native/scripts/validate-native-artifact.mjs" \
388+
classifier darwin-arm64 "$JAR" "$(basename "$JAR")" "$GITHUB_WORKSPACE"
389+
echo "darwin_jar=$JAR" >> "$GITHUB_OUTPUT"
390+
echo "darwin_sha=$(cut -d ' ' -f 1 "$MANIFEST")" >> "$GITHUB_OUTPUT"
391+
307392
- name: Build Linux classifier and deploy complete release
308393
id: publish-maven
309394
run: |
310395
VERSION="${{ needs.prepare-release.outputs.release_version }}"
311396
mvn -B deploy -DskipTests -Prelease -Dcopilot.native.libc=glibc \
312-
"-Dcopilot.native.external.win32.classifier.path=${{ steps.windows-artifact.outputs.windows_jar }}"
397+
"-Dcopilot.native.external.win32.classifier.path=${{ steps.windows-artifact.outputs.windows_jar }}" \
398+
"-Dcopilot.native.external.darwin.classifier.path=${{ steps.darwin-artifact.outputs.darwin_jar }}"
313399
LINUX_JAR="copilot-native/target/copilot-sdk-java-runtime-$VERSION-linux-x64.jar"
314400
test -f "$LINUX_JAR"
315401
node copilot-native/scripts/validate-native-artifact.mjs \
@@ -329,6 +415,7 @@ jobs:
329415
echo "| --- | --- | --- | --- | --- |"
330416
echo "| \`linux-x64\` | \`ubuntu-latest\` | \`$(basename "$LINUX_JAR")\` | \`$LINUX_SHA\` | Published |"
331417
echo "| \`win32-x64\` | \`windows-latest\` | \`$(basename "${{ steps.windows-artifact.outputs.windows_jar }}")\` | \`${{ steps.windows-artifact.outputs.windows_sha }}\` | Published |"
418+
echo "| \`darwin-arm64\` | \`macos-26\` | \`$(basename "${{ steps.darwin-artifact.outputs.darwin_jar }}")\` | \`${{ steps.darwin-artifact.outputs.darwin_sha }}\` | Published |"
332419
} >> "$GITHUB_STEP_SUMMARY"
333420
env:
334421
MAVEN_USERNAME: ${{ secrets.JAVA_MAVEN_CENTRAL_USERNAME }}
@@ -337,7 +424,7 @@ jobs:
337424

338425
rollback-release:
339426
name: Roll back failed Java release preparation
340-
needs: [prepare-release, build-windows-classifier, deploy-maven]
427+
needs: [prepare-release, build-windows-classifier, build-darwin-classifier, deploy-maven]
341428
if: ${{ failure() && needs.prepare-release.outputs.docs_commit != '' }}
342429
runs-on: ubuntu-latest
343430
permissions:

.github/workflows/java-publish-snapshot.yml

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ jobs:
4040
runs-on: windows-latest
4141
permissions:
4242
contents: read
43+
outputs:
44+
version: ${{ steps.build.outputs.version }}
4345
defaults:
4446
run:
4547
shell: pwsh
@@ -93,9 +95,72 @@ jobs:
9395
if-no-files-found: error
9496
retention-days: 1
9597

98+
build-darwin-classifier:
99+
name: Build Darwin snapshot classifier
100+
needs: resolve-source
101+
runs-on: macos-26
102+
permissions:
103+
contents: read
104+
outputs:
105+
version: ${{ steps.build.outputs.version }}
106+
defaults:
107+
run:
108+
shell: bash
109+
working-directory: ./java
110+
steps:
111+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
112+
with:
113+
ref: ${{ github.sha }}
114+
fetch-depth: 1
115+
persist-credentials: false
116+
117+
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
118+
with:
119+
java-version: "25"
120+
distribution: "microsoft"
121+
cache: "maven"
122+
123+
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
124+
with:
125+
node-version: 22
126+
127+
- name: Build and validate darwin-arm64 classifier
128+
id: build
129+
run: |
130+
set -euo pipefail
131+
SOURCE_COMMIT=$(git rev-parse HEAD)
132+
if [ "$SOURCE_COMMIT" != "${{ needs.resolve-source.outputs.source_sha }}" ]; then
133+
echo "::error::Checked out $SOURCE_COMMIT instead of the resolved snapshot source."
134+
exit 1
135+
fi
136+
node copilot-native/scripts/validate-native-host.mjs darwin-arm64
137+
mvn -B -pl copilot-native package -DskipTests
138+
VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
139+
JAR="copilot-native/target/copilot-sdk-java-runtime-$VERSION-darwin-arm64.jar"
140+
PRIMARY_JAR="copilot-native/target/copilot-sdk-java-runtime-$VERSION.jar"
141+
test -f "$JAR"
142+
node copilot-native/scripts/validate-native-artifact.mjs \
143+
classifier darwin-arm64 "$JAR" "$(basename "$JAR")" ..
144+
node copilot-native/scripts/validate-native-artifact.mjs placeholder "$PRIMARY_JAR"
145+
MANIFEST="copilot-native/target/darwin-arm64-$VERSION.sha256"
146+
HASH=$(shasum -a 256 "$JAR" | cut -d ' ' -f 1)
147+
printf '%s %s' "$HASH" "$(basename "$JAR")" > "$MANIFEST"
148+
node copilot-native/scripts/validate-native-artifact.mjs \
149+
checksum "$JAR" "$MANIFEST" "$(basename "$JAR")"
150+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
151+
152+
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
153+
with:
154+
name: java-native-darwin-arm64-snapshot-${{ github.run_id }}-${{ github.run_attempt }}
155+
path: |
156+
java/copilot-native/target/copilot-sdk-java-runtime-${{ steps.build.outputs.version }}-darwin-arm64.jar
157+
java/copilot-native/target/darwin-arm64-${{ steps.build.outputs.version }}.sha256
158+
if-no-files-found: error
159+
retention-days: 1
160+
96161
deploy-snapshot:
97162
name: Publish SNAPSHOT to Maven Central
98-
needs: [resolve-source, build-windows-classifier]
163+
needs: [resolve-source, build-windows-classifier, build-darwin-classifier]
99164
runs-on: ubuntu-latest
100165
defaults:
101166
run:
@@ -128,6 +193,11 @@ jobs:
128193
name: java-native-win32-x64-snapshot-${{ github.run_id }}-${{ github.run_attempt }}
129194
path: ${{ runner.temp }}/java-native-win32-x64
130195

196+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
197+
with:
198+
name: java-native-darwin-arm64-snapshot-${{ github.run_id }}-${{ github.run_attempt }}
199+
path: ${{ runner.temp }}/java-native-darwin-arm64
200+
131201
- name: Verify version, source, and Windows classifier
132202
id: windows-artifact
133203
run: |
@@ -141,6 +211,10 @@ jobs:
141211
echo "::error::This workflow only publishes SNAPSHOT versions. Current version: $VERSION"
142212
exit 1
143213
fi
214+
if [ "$VERSION" != "${{ needs.build-windows-classifier.outputs.version }}" ]; then
215+
echo "::error::Windows classifier version does not match deploy version."
216+
exit 1
217+
fi
144218
ARTIFACT_DIRECTORY="${{ runner.temp }}/java-native-win32-x64"
145219
JAR="$ARTIFACT_DIRECTORY/copilot-sdk-java-runtime-$VERSION-win32-x64.jar"
146220
MANIFEST="$ARTIFACT_DIRECTORY/win32-x64-$VERSION.sha256"
@@ -154,11 +228,37 @@ jobs:
154228
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
155229
echo "windows_sha=$(cut -d ' ' -f 1 "$MANIFEST")" >> "$GITHUB_OUTPUT"
156230
231+
- name: Verify version, source, and Darwin classifier
232+
id: darwin-artifact
233+
run: |
234+
SOURCE_COMMIT=$(git rev-parse HEAD)
235+
if [ "$SOURCE_COMMIT" != "${{ needs.resolve-source.outputs.source_sha }}" ]; then
236+
echo "::error::Checked out $SOURCE_COMMIT instead of the resolved snapshot source."
237+
exit 1
238+
fi
239+
VERSION="${{ steps.windows-artifact.outputs.version }}"
240+
if [ "$VERSION" != "${{ needs.build-darwin-classifier.outputs.version }}" ]; then
241+
echo "::error::Darwin classifier version does not match deploy version."
242+
exit 1
243+
fi
244+
ARTIFACT_DIRECTORY="${{ runner.temp }}/java-native-darwin-arm64"
245+
JAR="$ARTIFACT_DIRECTORY/copilot-sdk-java-runtime-$VERSION-darwin-arm64.jar"
246+
MANIFEST="$ARTIFACT_DIRECTORY/darwin-arm64-$VERSION.sha256"
247+
test -f "$JAR"
248+
test -f "$MANIFEST"
249+
node "$GITHUB_WORKSPACE/java/copilot-native/scripts/validate-native-artifact.mjs" \
250+
checksum "$JAR" "$MANIFEST" "$(basename "$JAR")"
251+
node "$GITHUB_WORKSPACE/java/copilot-native/scripts/validate-native-artifact.mjs" \
252+
classifier darwin-arm64 "$JAR" "$(basename "$JAR")" "$GITHUB_WORKSPACE"
253+
echo "darwin_jar=$JAR" >> "$GITHUB_OUTPUT"
254+
echo "darwin_sha=$(cut -d ' ' -f 1 "$MANIFEST")" >> "$GITHUB_OUTPUT"
255+
157256
- name: Build Linux classifier and deploy complete snapshot
158257
run: |
159258
VERSION="${{ steps.windows-artifact.outputs.version }}"
160259
mvn -B deploy -DskipTests -Dcopilot.native.libc=glibc \
161-
"-Dcopilot.native.external.win32.classifier.path=${{ steps.windows-artifact.outputs.windows_jar }}"
260+
"-Dcopilot.native.external.win32.classifier.path=${{ steps.windows-artifact.outputs.windows_jar }}" \
261+
"-Dcopilot.native.external.darwin.classifier.path=${{ steps.darwin-artifact.outputs.darwin_jar }}"
162262
LINUX_JAR="copilot-native/target/copilot-sdk-java-runtime-$VERSION-linux-x64.jar"
163263
test -f "$LINUX_JAR"
164264
node copilot-native/scripts/validate-native-artifact.mjs \
@@ -176,6 +276,7 @@ jobs:
176276
echo "| --- | --- | --- | --- | --- |"
177277
echo "| \`linux-x64\` | \`ubuntu-latest\` | \`$(basename "$LINUX_JAR")\` | \`$LINUX_SHA\` | Published |"
178278
echo "| \`win32-x64\` | \`windows-latest\` | \`$(basename "${{ steps.windows-artifact.outputs.windows_jar }}")\` | \`${{ steps.windows-artifact.outputs.windows_sha }}\` | Published |"
279+
echo "| \`darwin-arm64\` | \`macos-26\` | \`$(basename "${{ steps.darwin-artifact.outputs.darwin_jar }}")\` | \`${{ steps.darwin-artifact.outputs.darwin_sha }}\` | Published |"
179280
} >> "$GITHUB_STEP_SUMMARY"
180281
env:
181282
MAVEN_USERNAME: ${{ secrets.JAVA_MAVEN_CENTRAL_USERNAME }}

0 commit comments

Comments
 (0)