Skip to content
Closed
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
4 changes: 2 additions & 2 deletions .github/workflows/java-publish-maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ jobs:

- uses: ./.github/actions/setup-copilot

- name: Set up JDK 17
- name: Set up JDK 25
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
java-version: "17"
java-version: "25"
distribution: "microsoft"
cache: "maven"
server-id: central
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/java-publish-snapshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ jobs:

- uses: ./.github/actions/setup-copilot

- name: Set up JDK 17
- name: Set up JDK 25
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
java-version: "17"
java-version: "25"
distribution: "microsoft"
cache: "maven"
server-id: central
Expand Down
26 changes: 20 additions & 6 deletions .github/workflows/java-sdk-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,20 @@ permissions:

jobs:
java-sdk:
name: "Java SDK Tests"
name: "Java SDK Tests (JDK ${{ matrix.java-version }})"
if: github.event.repository.fork == false

runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# JDK 17 is the baseline --release target; JDK 25 also activates the
# java25-multi-release Maven profile, producing the MR-JAR overlay
# (META-INF/versions/25/) and exercising the virtual-thread default
# executor branch end-to-end via InternalExecutorProviderIT. The
# build-time verify-java25-overlay antrun guard fires only when the
# profile is active, so it is also exercised on the JDK 25 entry.
java-version: ["17", "25"]
defaults:
run:
shell: bash
Expand All @@ -52,7 +62,7 @@ jobs:

- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
java-version: "17"
java-version: ${{ matrix.java-version }}
distribution: "microsoft"
cache: "maven"

Expand Down Expand Up @@ -86,8 +96,12 @@ jobs:
COPILOT_CLI_PATH: ${{ steps.setup-copilot.outputs.cli-path }}
run: mvn verify

# Side-effects below (site artifact, JaCoCo badge, badge PR) are scoped
# to the JDK 17 matrix entry so the badge source-of-truth and the
# uploaded site artifact remain a single, stable baseline regardless
# of the second matrix entry's outcome.
- name: Upload test results for site generation
if: success() && github.ref == 'refs/heads/main'
if: success() && github.ref == 'refs/heads/main' && matrix.java-version == '17'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: test-results-for-site
Expand All @@ -98,12 +112,12 @@ jobs:
retention-days: 1

- name: Generate JaCoCo badge
if: success() && github.ref == 'refs/heads/main'
if: success() && github.ref == 'refs/heads/main' && matrix.java-version == '17'
working-directory: .
run: .github/scripts/generate-java-coverage-badge.sh java/target/site/jacoco-coverage/jacoco.csv .github/badges

- name: Create PR for JaCoCo badge update
if: success() && github.ref == 'refs/heads/main'
if: success() && github.ref == 'refs/heads/main' && matrix.java-version == '17'
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v7
with:
commit-message: "Update Java JaCoCo coverage badge"
Expand All @@ -121,7 +135,7 @@ jobs:
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: java-test-results
name: java-test-results-jdk${{ matrix.java-version }}
path: |
java/target/surefire-reports/
java/target/surefire-reports-isolated/
Expand Down
11 changes: 2 additions & 9 deletions java/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Java SDK for programmatic control of GitHub Copilot CLI, enabling you to build A

### Requirements

- Java 17 or later. **JDK 25 recommended**. Selecting JDK 25 enables the use of virtual threads, as shown in the [Quick Start](#quick-start).
- Java 17 or later. **JDK 25 recommended**. On JDK 25 and later, the SDK automatically uses virtual threads for its default internal executor.
- GitHub Copilot CLI 1.0.17 or later installed and in `PATH` (or provide custom `cliPath`)

### Maven
Expand Down Expand Up @@ -66,23 +66,16 @@ implementation 'com.github:copilot-sdk-java:1.0.0-beta-java.4'
import com.github.copilot.CopilotClient;
import com.github.copilot.generated.AssistantMessageEvent;
import com.github.copilot.generated.SessionUsageInfoEvent;
import com.github.copilot.rpc.CopilotClientOptions;
import com.github.copilot.rpc.MessageOptions;
import com.github.copilot.rpc.PermissionHandler;
import com.github.copilot.rpc.SessionConfig;

import java.util.concurrent.Executors;

public class CopilotSDK {
public static void main(String[] args) throws Exception {
var lastMessage = new String[]{null};

// Create and start client
try (var client = new CopilotClient()) { // JDK 25+: comment out this line
// JDK 25+: uncomment the following 3 lines for virtual thread support
// var options = new CopilotClientOptions()
// .setExecutor(Executors.newVirtualThreadPerTaskExecutor());
// try (var client = new CopilotClient(options)) {
try (var client = new CopilotClient()) {
client.start().get();

// Create a session
Expand Down
113 changes: 113 additions & 0 deletions java/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,33 @@
</execution>
</executions>
</plugin>
<!--
Failsafe runs integration tests against the actually packaged
JAR (after the package phase). Used to validate multi-release
JAR behaviour end-to-end without reflecting on private fields
or hand-rolling a synthetic JAR. See
src/test/java/com/github/copilot/InternalExecutorProviderIT.java.
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.5.5</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
<configuration>
<systemPropertyVariables>
<project.build.directory>${project.build.directory}</project.build.directory>
<project.build.finalName>${project.build.finalName}</project.build.finalName>
<project.build.testOutputDirectory>${project.build.testOutputDirectory}</project.build.testOutputDirectory>
</systemPropertyVariables>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
Expand Down Expand Up @@ -447,6 +474,10 @@
<configuration>
<dataFile>${project.build.directory}/jacoco-test-results/sdk-tests.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco-coverage</outputDirectory>
<excludes>
<!-- Exclude multi-release classes to avoid duplicate class analysis. -->
<exclude>META-INF/versions/**/*.class</exclude>
</excludes>
</configuration>
</execution>
</executions>
Expand Down Expand Up @@ -507,6 +538,88 @@
<surefire.jvm.args>-XX:+EnableDynamicAgentLoading</surefire.jvm.args>
</properties>
</profile>
<profile>
<id>java25-multi-release</id>
<activation>
<jdk>[25,)</jdk>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<execution>
<id>compile-java25</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<release>25</release>
<useIncrementalCompilation>false</useIncrementalCompilation>
<compileSourceRoots>
<compileSourceRoot>${project.basedir}/src/main/java25</compileSourceRoot>
</compileSourceRoots>
<multiReleaseOutput>true</multiReleaseOutput>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Multi-Release>true</Multi-Release>
</manifestEntries>
</archive>
</configuration>
</plugin>
<!--
Structural guard: when this profile is active (JDK 25+
builds), assert that the packaged JAR contains the
JDK 25 multi-release overlay class. Catches accidental
profile-disable / classifier / shading regressions
before the failsafe IT runs.
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<id>verify-java25-overlay</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<condition property="java25.overlay.present">
<resourceexists>
<zipentry zipfile="${project.build.directory}/${project.build.finalName}.jar"
name="META-INF/versions/25/com/github/copilot/InternalExecutorProvider.class"/>
</resourceexists>
</condition>
<fail unless="java25.overlay.present">
JDK 25 multi-release overlay class is missing from the packaged JAR.
Expected entry: META-INF/versions/25/com/github/copilot/InternalExecutorProvider.class
JAR: ${project.build.directory}/${project.build.finalName}.jar

This usually means the 'java25-multi-release' Maven profile did not activate
(e.g. the build is running on a JDK older than 25) or maven-compiler-plugin
did not produce the multi-release output. Re-build on JDK 25+ and verify the
'compile-java25' execution ran during the 'compile' phase.
</fail>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<!-- Skip git-clone + npm install of the copilot-sdk test harness -->
<profile>
<id>skip-test-harness</id>
Expand Down
Loading
Loading