Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions .github/workflows/java-sdk-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ jobs:
classifier: win32-x64
- os: windows-11-arm
classifier: win32-arm64
- os: macos-15-intel
classifier: darwin-x64
- os: macos-26
classifier: darwin-arm64
runs-on: ${{ matrix.os }}
Expand Down Expand Up @@ -309,6 +311,64 @@ jobs:
if-no-files-found: error
retention-days: 1

java-native-publication-darwin-x64:
name: "Java Native Publication Input (darwin-x64)"
if: github.event.repository.fork == false
runs-on: macos-15-intel
permissions:
contents: read
outputs:
source_sha: ${{ steps.build.outputs.source_sha }}
version: ${{ steps.build.outputs.version }}
defaults:
run:
shell: bash
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 darwin-x64 classifier
id: build
run: |
set -euo pipefail
node copilot-native/scripts/validate-native-host.mjs darwin-x64
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-darwin-x64.jar"
PRIMARY_JAR="copilot-native/target/copilot-sdk-java-runtime-$VERSION.jar"
test -f "$JAR"
node copilot-native/scripts/validate-native-artifact.mjs \
classifier darwin-x64 "$JAR" "$(basename "$JAR")" ..
node copilot-native/scripts/validate-native-artifact.mjs placeholder "$PRIMARY_JAR"
MANIFEST="copilot-native/target/darwin-x64-$VERSION.sha256"
HASH=$(shasum -a 256 "$JAR" | cut -d ' ' -f 1)
printf '%s %s' "$HASH" "$(basename "$JAR")" > "$MANIFEST"
node copilot-native/scripts/validate-native-artifact.mjs \
checksum "$JAR" "$MANIFEST" "$(basename "$JAR")"
echo "source_sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: java-native-publication-darwin-x64-${{ github.run_id }}-${{ github.run_attempt }}
path: |
java/copilot-native/target/copilot-sdk-java-runtime-${{ steps.build.outputs.version }}-darwin-x64.jar
java/copilot-native/target/darwin-x64-${{ steps.build.outputs.version }}.sha256
if-no-files-found: error
retention-days: 1

java-native-publication-assembly:
name: "Java Native Publication Assembly"
if: github.event.repository.fork == false
Expand All @@ -318,6 +378,7 @@ jobs:
java-native-publication-windows,
java-native-publication-windows-arm64,
java-native-publication-darwin,
java-native-publication-darwin-x64,
]
runs-on: ubuntu-latest
defaults:
Expand Down Expand Up @@ -360,21 +421,29 @@ jobs:
name: java-native-publication-darwin-arm64-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ github.workspace }}/java/native-publication-input/darwin

- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
name: java-native-publication-darwin-x64-${{ github.run_id }}-${{ github.run_attempt }}
path: ${{ github.workspace }}/java/native-publication-input/darwin-x64

- name: Verify native inputs and deploy the complete local release
run: |
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 }}"
test "$(git rev-parse HEAD)" = "${{ needs.java-native-publication-darwin-x64.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 }}"
test "$VERSION" = "${{ needs.java-native-publication-darwin-x64.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"
DARWIN_X64_DIRECTORY="$GITHUB_WORKSPACE/java/native-publication-input/darwin-x64"
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"
Expand All @@ -383,6 +452,8 @@ jobs:
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"
DARWIN_X64_JAR="$DARWIN_X64_DIRECTORY/copilot-sdk-java-runtime-$VERSION-darwin-x64.jar"
DARWIN_X64_MANIFEST="$DARWIN_X64_DIRECTORY/darwin-x64-$VERSION.sha256"
node copilot-native/scripts/validate-native-artifact.mjs \
checksum "$LINUX_ARM64_JAR" "$LINUX_ARM64_MANIFEST" "$(basename "$LINUX_ARM64_JAR")"
node copilot-native/scripts/validate-native-artifact.mjs \
Expand All @@ -399,6 +470,10 @@ jobs:
checksum "$DARWIN_JAR" "$DARWIN_MANIFEST" "$(basename "$DARWIN_JAR")"
node copilot-native/scripts/validate-native-artifact.mjs \
classifier darwin-arm64 "$DARWIN_JAR" "$(basename "$DARWIN_JAR")" ..
node copilot-native/scripts/validate-native-artifact.mjs \
checksum "$DARWIN_X64_JAR" "$DARWIN_X64_MANIFEST" "$(basename "$DARWIN_X64_JAR")"
node copilot-native/scripts/validate-native-artifact.mjs \
classifier darwin-x64 "$DARWIN_X64_JAR" "$(basename "$DARWIN_X64_JAR")" ..
export GNUPGHOME="$GITHUB_WORKSPACE/java/copilot-native/target/local-publication-gpg"
rm -rf "$GNUPGHOME"
mkdir -p "$GNUPGHOME"
Expand All @@ -414,6 +489,7 @@ jobs:
"-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" \
"-Dcopilot.native.external.darwin.x64.classifier.path=$DARWIN_X64_JAR" \
"-Dmaven.repo.local=$LOCAL_REPOSITORY"
node copilot-native/scripts/validate-local-publication.mjs \
"$LOCAL_REPOSITORY" copilot-sdk-java-runtime "$VERSION" .. --signatures
Expand Down
14 changes: 7 additions & 7 deletions java/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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**, **win32-arm64**, 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**, **darwin-x64**, and **darwin-arm64**.

Because in-process mode is experimental, see the [Using experimental APIs](#using-experimental-apis) section for how to opt in.

Expand All @@ -95,7 +95,7 @@ Add both the SDK and the platform-specific native runtime to your project:
<version>${copilot.version}</version>
<classifier>linux-x64</classifier>
</dependency>
<!-- Use linux-arm64, win32-x64, win32-arm64, or darwin-arm64 on those target platforms -->
<!-- Use linux-arm64, win32-x64, win32-arm64, darwin-x64, or darwin-arm64 on those target platforms -->
<!-- JNA (required for in-process mode) -->
<dependency>
<groupId>net.java.dev.jna</groupId>
Expand Down Expand Up @@ -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, 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-<classifier>` 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, Intel macOS, and Apple Silicon macOS, Maven activates `native-win32-x64`, `native-win32-arm64`, `native-darwin-x64`, or `native-darwin-arm64` automatically. The matching profile validates the host, runs the native script tests, fetches the pinned `@github/copilot-<classifier>` 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:

Expand All @@ -532,10 +532,10 @@ On Windows x64 or ARM64 PowerShell, initialize Java and run the same profile:
mvn -Pinprocess clean verify
```

The same command validates in-process mode on Apple Silicon macOS:
The same command validates in-process mode on macOS; use the classifier for the host architecture:

```bash
node copilot-native/scripts/validate-native-host.mjs darwin-arm64
node copilot-native/scripts/validate-native-host.mjs darwin-x64 # Use darwin-arm64 on Apple Silicon
mvn -Pinprocess clean verify
```

Expand All @@ -546,7 +546,7 @@ node copilot-native/scripts/validate-native-host.mjs linux-arm64
mvn -Pinprocess clean verify -Dcopilot.native.libc=glibc
```

On Intel macOS, Linux musl, and other unsupported hosts, do not set `copilot.native.libc=glibc`. A normal build produces only the OS-neutral primary, sources, and Javadoc JARs; it does not run native script tests, download or stage native files, or produce a platform classifier JAR.
On Linux musl and other unsupported hosts, do not set `copilot.native.libc=glibc`. A normal build produces only the OS-neutral primary, sources, and Javadoc JARs; it does not run native script tests, download or stage native files, or produce a platform classifier JAR.

To build only the OS-neutral artifacts on any host, or override the glibc opt-in, disable native download and packaging:

Expand All @@ -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, 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.
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 macOS, it contains them under `native/darwin-x64` or `native/darwin-arm64`. The placeholder JAR remains OS-neutral and contains no native binaries. Unsupported hosts retain the placeholder-only behavior.

## License

Expand Down
119 changes: 118 additions & 1 deletion java/copilot-native/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,61 @@
</plugins>
</build>
</profile>
<profile>
<id>native-darwin-x64</id>
<activation>
<os>
<family>mac</family>
<arch>x86_64</arch>
</os>
</activation>
<properties>
<copilot.native.classifier>darwin-x64</copilot.native.classifier>
<copilot.native.cli.filename>copilot</copilot.native.cli.filename>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>validate-native-host</id>
<phase>validate</phase>
</execution>
<execution>
<id>fetch-native</id>
<phase>generate-resources</phase>
</execution>
<execution>
<id>test-fetch-native</id>
<phase>test</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>jar-native</id>
<phase>package</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>verify-native-jars</id>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>native-darwin-arm64</id>
<activation>
Expand Down Expand Up @@ -763,7 +818,7 @@
</build>
</profile>
<!--
The Darwin classifier is assembled on an Apple Silicon macOS runner
The Darwin ARM64 classifier is assembled on an Apple Silicon macOS runner
and passed to the sole Ubuntu publisher with the Windows classifiers.
-->
<profile>
Expand Down Expand Up @@ -824,6 +879,68 @@
</plugins>
</build>
</profile>
<!--
The Darwin x64 classifier is assembled on an Intel macOS runner and
passed to the sole Ubuntu publisher with the other classifiers.
-->
<profile>
<id>attach-external-darwin-x64-classifier</id>
<activation>
<property>
<name>copilot.native.external.darwin.x64.classifier.path</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>validate-external-darwin-x64-classifier</id>
<phase>validate</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>node</executable>
<arguments>
<argument>${project.basedir}/scripts/validate-native-artifact.mjs</argument>
<argument>classifier</argument>
<argument>darwin-x64</argument>
<argument>${copilot.native.external.darwin.x64.classifier.path}</argument>
<argument>${project.build.finalName}-darwin-x64.jar</argument>
<argument>${copilot.sdk.root}</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>attach-external-darwin-x64-classifier</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>${copilot.native.external.darwin.x64.classifier.path}</file>
<type>jar</type>
<classifier>darwin-x64</classifier>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<!--
This test-only hook makes Windows-host local deployment validation
deterministic. Publication workflows never set this property: they
Expand Down
2 changes: 1 addition & 1 deletion java/copilot-native/scripts/fetch-native.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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', 'win32-arm64', 'darwin-arm64']) {
for (const classifier of ['linux-x64', 'linux-arm64', 'win32-x64', 'win32-arm64', 'darwin-x64', 'darwin-arm64']) {
test(`${classifier}: missing CLI does not use incremental fast path`, (t) => {
const fixture = createFixture(t, classifier);
fs.rmSync(fixture.cliPath);
Expand Down
Loading
Loading