Skip to content

Commit 217db5f

Browse files
authored
Implement phase 03 of merge to monorepo plan (#1369)
* Add Java publish workflows, smoke test, and release scripts for monorepo Implement Phase 03 of the Java-to-monorepo migration plan, adapting the Java SDK's publishing and testing automation for the monorepo structure. Changes: - java-publish-maven.yml: add working-directory, use java/v tag prefix, scope secrets to Java - java-publish-snapshot.yml: add working-directory for monorepo - java-smoke-test.yml: new workflow running smoke tests on JDK 17 and JDK 25 with globally installed Copilot CLI (version pinned from pom.xml) - java.notes.template: release notes template for GitHub Releases - update-changelog.sh: script to update CHANGELOG.md during release, generating compare links with java/v tag prefix - test-update-changelog.sh: tests for the changelog update script - TestUtil.java: align findCliPath() Javadoc with actual resolution order (COPILOT_CLI_PATH first, then PATH search) - pom.xml: update copilot-sdk-ref-impl version property * Remove Java-specific CHANGELOG; use monorepo's release-changelog agent for java/v* and rust/v* scoped tags. Address [comments](#1369 (comment)) from @stephentoub . .github/scripts/release/update-changelog.sh (deleted): Custom awk-based script that maintained java/CHANGELOG.md is no longer needed. .github/scripts/release/test-update-changelog.sh (deleted): Tests for the above script. .github/workflows/java-publish-maven.yml: Remove update-changelog.sh call and CHANGELOG.md from git-add; add "Trigger changelog generation" step that invokes release-changelog.lock.yml with the java/v* tag. .github/workflows/release-changelog.md: Surgical additions to handle language-prefixed tags (java/v*, rust/v*) — scoped previous-tag lookup, scoped file filtering, scoped code snippets, and scoped heading format in CHANGELOG.md. .github/workflows/release-changelog.lock.yml: Recompiled from release-changelog.md via `gh aw compile`. java/CHANGELOG.md (deleted): No longer maintaining a Java-specific changelog; releases flow through the root CHANGELOG.md via the release-changelog agent. * Recompile workflows
1 parent d99871c commit 217db5f

8 files changed

Lines changed: 243 additions & 606 deletions

File tree

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

Lines changed: 16 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Publish to Maven Central
1+
name: "Java Publish to Maven Central"
22

33
env:
44
# Disable Husky Git hooks in CI to prevent local development hooks
@@ -35,6 +35,10 @@ jobs:
3535
publish-maven:
3636
name: Publish Java SDK to Maven Central
3737
runs-on: ubuntu-latest
38+
defaults:
39+
run:
40+
shell: bash
41+
working-directory: ./java
3842
outputs:
3943
version: ${{ steps.versions.outputs.release_version }}
4044
steps:
@@ -114,15 +118,6 @@ jobs:
114118
run: |
115119
VERSION="${{ steps.versions.outputs.release_version }}"
116120
117-
# Read the reference implementation SDK commit hash that this release is synced to
118-
REFERENCE_IMPL_HASH=$(cat .lastmerge)
119-
REFERENCE_IMPL_SHORT="${REFERENCE_IMPL_HASH:0:7}"
120-
REFERENCE_IMPL_URL="https://github.com/github/copilot-sdk/commit/${REFERENCE_IMPL_HASH}"
121-
echo "Reference implementation SDK sync: ${REFERENCE_IMPL_SHORT} (${REFERENCE_IMPL_URL})"
122-
123-
# Update CHANGELOG.md with release version and Reference implementation sync hash
124-
../.github/scripts/release/update-changelog.sh "${VERSION}" "${REFERENCE_IMPL_HASH}"
125-
126121
# Update version in README.md (supports any version qualifier like -java.N, -java-preview.N, -beta-java.N)
127122
sed -i "s|<version>[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\(-[a-z][a-z0-9-]*\.[0-9][0-9]*\)*</version>|<version>${VERSION}</version>|g" README.md
128123
sed -i "s|copilot-sdk-java:[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\(-[a-z][a-z0-9-]*\.[0-9][0-9]*\)*|copilot-sdk-java:${VERSION}|g" README.md
@@ -136,7 +131,7 @@ jobs:
136131
sed -i 's|copilot-sdk-java:${project\.version}|copilot-sdk-java:'"${VERSION}"'|g' jbang-example.java
137132
138133
# Commit the documentation changes before release:prepare (requires clean working directory)
139-
git add CHANGELOG.md README.md jbang-example.java
134+
git add README.md jbang-example.java
140135
git commit -m "docs: update version references to ${VERSION}"
141136
142137
# Save the commit SHA for potential rollback
@@ -150,7 +145,7 @@ jobs:
150145
mvn -B release:prepare \
151146
-DreleaseVersion=${{ steps.versions.outputs.release_version }} \
152147
-DdevelopmentVersion=${{ steps.versions.outputs.dev_version }} \
153-
-DtagNameFormat=v@{project.version} \
148+
-DtagNameFormat=java/v@{project.version} \
154149
-DpushChanges=true \
155150
-Darguments="-DskipTests"
156151
env:
@@ -185,6 +180,10 @@ jobs:
185180
needs: publish-maven
186181
if: github.ref == 'refs/heads/main'
187182
runs-on: ubuntu-latest
183+
defaults:
184+
run:
185+
shell: bash
186+
working-directory: ./java
188187
steps:
189188
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
190189
with:
@@ -194,7 +193,7 @@ jobs:
194193
VERSION="${{ needs.publish-maven.outputs.version }}"
195194
GROUP_ID="com.github"
196195
ARTIFACT_ID="copilot-sdk-java"
197-
CURRENT_TAG="v${VERSION}"
196+
CURRENT_TAG="java/v${VERSION}"
198197
199198
if gh release view "${CURRENT_TAG}" >/dev/null 2>&1; then
200199
echo "Release ${CURRENT_TAG} already exists. Skipping creation."
@@ -203,11 +202,10 @@ jobs:
203202
204203
# Generate release notes from template
205204
export VERSION GROUP_ID ARTIFACT_ID
206-
RELEASE_NOTES=$(envsubst < .github/workflows/notes.template)
205+
RELEASE_NOTES=$(envsubst < $GITHUB_WORKSPACE/.github/workflows/java.notes.template)
207206
208207
# Get the previous tag for generating notes
209-
PREV_TAG=$(git tag --list 'v*' --sort=-version:refname \
210-
| grep -E '^v[0-9]+\.[0-9]+\.[0-9]+(-java(-preview)?\.[0-9]+)?$' \
208+
PREV_TAG=$(git tag --list 'java/v*' --sort=-version:refname \
211209
| grep -Fxv "${CURRENT_TAG}" \
212210
| head -n 1)
213211
@@ -229,28 +227,7 @@ jobs:
229227
gh release create "${GH_ARGS[@]}"
230228
env:
231229
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
232-
233-
- name: Move 'latest' tag to new release
234-
run: |
235-
VERSION="${{ needs.publish-maven.outputs.version }}"
236-
git tag -f latest "v${VERSION}"
237-
git push origin latest --force
238-
env:
239-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
240-
241-
deploy-site:
242-
name: Deploy Documentation
243-
needs: [publish-maven, github-release]
244-
runs-on: ubuntu-latest
245-
permissions:
246-
actions: write
247-
contents: read
248-
steps:
249-
- name: Trigger site deployment
250-
run: |
251-
gh workflow run deploy-site.yml \
252-
--repo ${{ github.repository }} \
253-
-f version="${{ needs.publish-maven.outputs.version }}" \
254-
-f publish_as_latest=true
230+
- name: Trigger changelog generation
231+
run: gh workflow run release-changelog.lock.yml -f tag="java/v${{ needs.publish-maven.outputs.version }}"
255232
env:
256233
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Publish Snapshot to Maven Central
1+
name: Java Publish Snapshot to Maven Central
22

33
env:
44
HUSKY: 0
@@ -19,6 +19,10 @@ jobs:
1919
publish-snapshot:
2020
name: Publish SNAPSHOT to Maven Central
2121
runs-on: ubuntu-latest
22+
defaults:
23+
run:
24+
shell: bash
25+
working-directory: ./java
2226
steps:
2327
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
2428
with:
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
name: "Java smoke test"
2+
3+
on:
4+
workflow_dispatch:
5+
workflow_call:
6+
secrets:
7+
COPILOT_GITHUB_TOKEN:
8+
required: true
9+
10+
permissions:
11+
contents: read
12+
13+
jobs:
14+
smoke-test-jdk17:
15+
name: Build SDK and run smoke test (JDK 17)
16+
runs-on: ubuntu-latest
17+
if: github.ref == 'refs/heads/main'
18+
defaults:
19+
run:
20+
shell: bash
21+
working-directory: ./java
22+
steps:
23+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
24+
25+
- name: Set up JDK 17
26+
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
27+
with:
28+
java-version: "17"
29+
distribution: "microsoft"
30+
cache: "maven"
31+
32+
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v6
33+
with:
34+
node-version: 22
35+
36+
- name: Read pinned @github/copilot version from pom.xml
37+
id: cli-version
38+
run: |
39+
PROP="readonly-copilot-sdk-ref-impl-version-from-lastmerge-file-updated-by-reference-impl-sync"
40+
VERSION=$(sed -n "s|.*<${PROP}>\(.*\)</${PROP}>.*|\1|p" pom.xml | head -n 1 | tr -d '[:space:]')
41+
if [[ -z "$VERSION" || "$VERSION" == "PRIMER_TO_REPLACE" ]]; then
42+
echo "::error::Could not read pinned @github/copilot version from pom.xml property <${PROP}>" >&2
43+
exit 1
44+
fi
45+
echo "Pinned @github/copilot version: $VERSION"
46+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
47+
48+
- name: Install Copilot CLI globally (pinned to pom.xml version)
49+
run: npm install -g "@github/copilot@${{ steps.cli-version.outputs.version }}"
50+
51+
- name: Verify CLI works
52+
run: copilot --version
53+
54+
- name: Build SDK and install to local repo
55+
run: mvn -DskipTests -Pskip-test-harness clean install
56+
57+
- name: Create and run smoke test via Copilot CLI
58+
env:
59+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
60+
run: |
61+
cat > /tmp/smoke-test-prompt.txt << 'PROMPT_EOF'
62+
You are running inside the copilot-sdk monorepo, in the java/ subdirectory.
63+
The SDK has already been built and installed into the local Maven repository.
64+
JDK 17 and Maven are already installed and on PATH.
65+
66+
Execute the prompt at `src/test/prompts/PROMPT-smoke-test.md` with the following critical overrides:
67+
68+
**Critical override — disable SNAPSHOT updates (but allow downloads):** The goal of this workflow is to validate the SDK SNAPSHOT that was just built and installed locally, not any newer SNAPSHOT that might exist in a remote repository. To ensure Maven does not download a newer timestamped SNAPSHOT of the SDK while still allowing it to download any missing plugins or dependencies, you must run the smoke-test Maven build without `-U` and with `--no-snapshot-updates`, so that it uses the locally installed SDK artifact. Use `mvn --no-snapshot-updates clean package` instead of `mvn -U clean package` or `mvn -o clean package`.
69+
70+
**Critical override — do NOT run the jar:** Stop after the `mvn --no-snapshot-updates clean package` build succeeds. Do NOT execute Step 4 (java -jar) or Step 5 (verify exit code) from the prompt. The workflow will run the jar in a separate deterministic step to guarantee the exit code propagates correctly.
71+
72+
Follow steps 1-3 only: create the `smoke-test/` directory, create `pom.xml` and the Java source file exactly as specified, and build with `mvn --no-snapshot-updates clean package` (no SNAPSHOT updates and without `-U`).
73+
74+
If any step fails, exit with a non-zero exit code. Do not silently fix errors.
75+
PROMPT_EOF
76+
77+
copilot --yolo --prompt "$(cat /tmp/smoke-test-prompt.txt)"
78+
79+
- name: Run smoke test jar
80+
env:
81+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
82+
run: |
83+
cd smoke-test
84+
java -jar ./target/copilot-sdk-smoketest-1.0-SNAPSHOT.jar
85+
echo "Smoke test passed (exit code 0)"
86+
87+
smoke-test-java25:
88+
name: Build SDK and run smoke test (JDK 25)
89+
runs-on: ubuntu-latest
90+
if: github.ref == 'refs/heads/main'
91+
defaults:
92+
run:
93+
shell: bash
94+
working-directory: ./java
95+
steps:
96+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
97+
98+
- name: Set up JDK 25
99+
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
100+
with:
101+
java-version: "25"
102+
distribution: "microsoft"
103+
cache: "maven"
104+
105+
- uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v6
106+
with:
107+
node-version: 22
108+
109+
- name: Read pinned @github/copilot version from pom.xml
110+
id: cli-version
111+
run: |
112+
PROP="readonly-copilot-sdk-ref-impl-version-from-lastmerge-file-updated-by-reference-impl-sync"
113+
VERSION=$(sed -n "s|.*<${PROP}>\(.*\)</${PROP}>.*|\1|p" pom.xml | head -n 1 | tr -d '[:space:]')
114+
if [[ -z "$VERSION" || "$VERSION" == "PRIMER_TO_REPLACE" ]]; then
115+
echo "::error::Could not read pinned @github/copilot version from pom.xml property <${PROP}>" >&2
116+
exit 1
117+
fi
118+
echo "Pinned @github/copilot version: $VERSION"
119+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
120+
121+
- name: Install Copilot CLI globally (pinned to pom.xml version)
122+
run: npm install -g "@github/copilot@${{ steps.cli-version.outputs.version }}"
123+
124+
- name: Verify CLI works
125+
run: copilot --version
126+
127+
- name: Build SDK and install to local repo
128+
run: mvn -DskipTests -Pskip-test-harness clean install
129+
130+
- name: Create and run smoke test via Copilot CLI
131+
env:
132+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
133+
run: |
134+
cat > /tmp/smoke-test-prompt.txt << 'PROMPT_EOF'
135+
You are running inside the copilot-sdk monorepo, in the java/ subdirectory.
136+
The SDK has already been built and installed into the local Maven repository.
137+
JDK 25 and Maven are already installed and on PATH.
138+
139+
Execute the prompt at `src/test/prompts/PROMPT-smoke-test.md` with the following critical overrides:
140+
141+
**Critical override — disable SNAPSHOT updates (but allow downloads):** The goal of this workflow is to validate the SDK SNAPSHOT that was just built and installed locally, not any newer SNAPSHOT that might exist in a remote repository. To ensure Maven does not download a newer timestamped SNAPSHOT of the SDK while still allowing it to download any missing plugins or dependencies, you must run the smoke-test Maven build without `-U` and with `--no-snapshot-updates`, so that it uses the locally installed SDK artifact. Use `mvn --no-snapshot-updates clean package` instead of `mvn -U clean package` or `mvn -o clean package`.
142+
143+
**Critical override — do NOT run the jar:** Stop after the `mvn --no-snapshot-updates clean package` build succeeds. Do NOT execute Step 4 (java -jar) or Step 5 (verify exit code) from the prompt. The workflow will run the jar in a separate deterministic step to guarantee the exit code propagates correctly.
144+
145+
**Critical override — enable Virtual Threads for JDK 25:** After creating the Java source file from the README "Quick Start" section but BEFORE building, you must modify the source file to enable virtual thread support. The Quick Start code contains inline comments that start with `// JDK 25+:` — these are instructions. Find every such comment and follow what it says (comment out lines it says to comment out, uncomment lines it says to uncomment). Add any imports required by the newly uncommented code (e.g. `java.util.concurrent.Executors`).
146+
Also set `maven.compiler.source` and `maven.compiler.target` to `25` in the `pom.xml`.
147+
148+
Follow steps 1-3 only: create the `smoke-test/` directory, create `pom.xml` and the Java source file exactly as specified, apply the JDK 25 virtual thread modifications described above, and build with `mvn --no-snapshot-updates clean package` (no SNAPSHOT updates and without `-U`).
149+
150+
If any step fails, exit with a non-zero exit code. Do not silently fix errors.
151+
PROMPT_EOF
152+
153+
copilot --yolo --prompt "$(cat /tmp/smoke-test-prompt.txt)"
154+
155+
- name: Run smoke test jar
156+
env:
157+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
158+
run: |
159+
cd smoke-test
160+
java -jar ./target/copilot-sdk-smoketest-1.0-SNAPSHOT.jar
161+
echo "Smoke test passed (exit code 0)"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Installation
2+
3+
ℹ️ **Public Preview:** This is the official Java SDK for GitHub Copilot. This repository treats the official .NET and Node.js SDKs for GitHub Copilot as reference implementations. These SDKs are all officially supported as GitHub open source projects. The Java implementation follows the backward compatibility guarantees offered by the reference implementations.
4+
5+
⚠️ **Artifact versioning plan:** Releases of this implementation track releases of the reference implementation. For each release of the reference implementation, there may follow a corresponding release of this implementation with the same number as the reference implementation. Release identifiers of the reference implementation are in the form `vMaj.Min.Micro`. For example v0.1.32. The corresponding maven version for the release will be `Maj.Min.Micro-java.N`, where `Maj`, `Min` and `Micro` are the corresponding numbers for the reference implementation release, and `N` is a monotonically increasing sequence number starting with 0 for each release. See the corresponding architectural decision record for more information in the `docs/adr` directory of the source code.
6+
7+
📦 [View on Maven Central](https://central.sonatype.com/artifact/${GROUP_ID}/${ARTIFACT_ID}/${VERSION})
8+
9+
## Maven
10+
```xml
11+
<dependency>
12+
<groupId>${GROUP_ID}</groupId>
13+
<artifactId>${ARTIFACT_ID}</artifactId>
14+
<version>${VERSION}</version>
15+
</dependency>
16+
```
17+
18+
## Gradle (Kotlin DSL)
19+
```kotlin
20+
implementation("${GROUP_ID}:${ARTIFACT_ID}:${VERSION}")
21+
```
22+
23+
## Gradle (Groovy DSL)
24+
```groovy
25+
implementation '${GROUP_ID}:${ARTIFACT_ID}:${VERSION}'
26+
```

0 commit comments

Comments
 (0)