Skip to content

Commit cf39cfd

Browse files
committed
Merge remote-tracking branch 'origin/main' into jmoseley/canvas-runtime-support
# Conflicts: # nodejs/src/types.ts
2 parents ffa7c34 + f4d22d7 commit cf39cfd

952 files changed

Lines changed: 79218 additions & 6723 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.githooks/pre-commit

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/bin/sh
2+
#
3+
# Pre-commit hook that runs Spotless check on the Java SDK when Java source
4+
# files are staged. Only triggers if changes exist under java/src/.
5+
#
6+
# To install this hook, run from the repository root:
7+
# git config core.hooksPath .githooks
8+
#
9+
10+
# Only run Spotless if staged changes include Java source files under java/src/
11+
if ! git diff --cached --name-only | grep -q '^java/src/'; then
12+
exit 0
13+
fi
14+
15+
echo "Running Spotless check on java/ ..."
16+
17+
# Run spotless check from the java directory
18+
(cd java && mvn spotless:check -q)
19+
20+
if [ $? -ne 0 ]; then
21+
echo ""
22+
echo "❌ Spotless check failed!"
23+
echo " Run 'cd java && mvn spotless:apply' to fix formatting issues."
24+
echo ""
25+
exit 1
26+
fi
27+
28+
echo "✓ Spotless check passed"
29+
exit 0
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
name: "Java Test Report"
2+
description: "Generate and publish test reports with summary for Java SDK tests."
3+
inputs:
4+
report-path:
5+
description: "Path to the test report XML files (glob pattern)"
6+
required: false
7+
default: "java/target/surefire-reports*/TEST-*.xml"
8+
jacoco-path:
9+
description: "Path to the JaCoCo XML report"
10+
required: false
11+
default: "java/target/site/jacoco-coverage/jacoco.xml"
12+
jacoco-csv-path:
13+
description: "Path to the JaCoCo CSV report"
14+
required: false
15+
default: "java/target/site/jacoco-coverage/jacoco.csv"
16+
check-name:
17+
description: "Name for the check run"
18+
required: false
19+
default: "Java SDK Test Results"
20+
runs:
21+
using: "composite"
22+
steps:
23+
- name: Generate Test Summary
24+
shell: bash
25+
run: |
26+
echo "## 🧪 Copilot Java SDK :: Test Results" >> $GITHUB_STEP_SUMMARY
27+
echo "" >> $GITHUB_STEP_SUMMARY
28+
29+
if ls ${{ inputs.report-path }} 1>/dev/null 2>&1; then
30+
TESTS_RUN=$(grep -h "tests=" ${{ inputs.report-path }} 2>/dev/null | sed 's/.*tests="\([0-9]*\)".*/\1/' | awk '{s+=$1} END {print s}')
31+
FAILURES=$(grep -h "failures=" ${{ inputs.report-path }} 2>/dev/null | sed 's/.*failures="\([0-9]*\)".*/\1/' | awk '{s+=$1} END {print s}')
32+
ERRORS=$(grep -h "errors=" ${{ inputs.report-path }} 2>/dev/null | sed 's/.*errors="\([0-9]*\)".*/\1/' | awk '{s+=$1} END {print s}')
33+
SKIPPED=$(grep -h "skipped=" ${{ inputs.report-path }} 2>/dev/null | sed 's/.*skipped="\([0-9]*\)".*/\1/' | awk '{s+=$1} END {print s}')
34+
35+
TESTS_RUN=${TESTS_RUN:-0}
36+
FAILURES=${FAILURES:-0}
37+
ERRORS=${ERRORS:-0}
38+
SKIPPED=${SKIPPED:-0}
39+
PASSED=$((TESTS_RUN - FAILURES - ERRORS - SKIPPED))
40+
41+
if [ "$FAILURES" -eq 0 ] && [ "$ERRORS" -eq 0 ]; then
42+
echo "### ✅ All tests passed!" >> $GITHUB_STEP_SUMMARY
43+
else
44+
echo "### ❌ Some tests failed" >> $GITHUB_STEP_SUMMARY
45+
fi
46+
47+
echo "" >> $GITHUB_STEP_SUMMARY
48+
echo "| Metric | Count |" >> $GITHUB_STEP_SUMMARY
49+
echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY
50+
echo "| ✅ Passed | $PASSED |" >> $GITHUB_STEP_SUMMARY
51+
echo "| ❌ Failed | $FAILURES |" >> $GITHUB_STEP_SUMMARY
52+
echo "| 💥 Errors | $ERRORS |" >> $GITHUB_STEP_SUMMARY
53+
echo "| ⏭️ Skipped | $SKIPPED |" >> $GITHUB_STEP_SUMMARY
54+
echo "| 📊 Total | $TESTS_RUN |" >> $GITHUB_STEP_SUMMARY
55+
56+
echo "" >> $GITHUB_STEP_SUMMARY
57+
echo "### Test Classes" >> $GITHUB_STEP_SUMMARY
58+
echo "" >> $GITHUB_STEP_SUMMARY
59+
echo "| Class | Tests | Passed | Failed | Errors | Time |" >> $GITHUB_STEP_SUMMARY
60+
echo "|-------|-------|--------|--------|--------|------|" >> $GITHUB_STEP_SUMMARY
61+
62+
for file in ${{ inputs.report-path }}; do
63+
if [ -f "$file" ]; then
64+
CLASS=$(basename "$file" .xml | sed 's/TEST-//')
65+
T=$(grep -o 'tests="[0-9]*"' "$file" | head -1 | sed 's/[^0-9]//g')
66+
F=$(grep -o 'failures="[0-9]*"' "$file" | head -1 | sed 's/[^0-9]//g')
67+
E=$(grep -o 'errors="[0-9]*"' "$file" | head -1 | sed 's/[^0-9]//g')
68+
TIME=$(grep -o 'time="[0-9.]*"' "$file" | head -1 | sed 's/[^0-9.]//g')
69+
P=$((T - F - E))
70+
71+
STATUS="✅"
72+
if [ "${F:-0}" -gt 0 ] || [ "${E:-0}" -gt 0 ]; then
73+
STATUS="❌"
74+
fi
75+
76+
echo "| $STATUS $CLASS | ${T:-0} | ${P:-0} | ${F:-0} | ${E:-0} | ${TIME:-0}s |" >> $GITHUB_STEP_SUMMARY
77+
fi
78+
done
79+
else
80+
echo "⚠️ No test reports found at ${{ inputs.report-path }}" >> $GITHUB_STEP_SUMMARY
81+
fi
82+
83+
- name: Generate Coverage Summary
84+
shell: bash
85+
run: |
86+
JACOCO_XML="${{ inputs.jacoco-path }}"
87+
JACOCO_CSV="${{ inputs.jacoco-csv-path }}"
88+
89+
if [ -f "$JACOCO_XML" ]; then
90+
echo "" >> $GITHUB_STEP_SUMMARY
91+
echo "## 📊 Code Coverage" >> $GITHUB_STEP_SUMMARY
92+
echo "" >> $GITHUB_STEP_SUMMARY
93+
94+
# JaCoCo XML may be on a single line - split it for parsing
95+
# Extract report-level counters (last occurrence of each type before </report>)
96+
extract_counter() {
97+
local type=$1
98+
local field=$2
99+
# Split XML on > to get one tag per line, find counter, extract value
100+
sed 's/>/>\n/g' "$JACOCO_XML" | grep "<counter type=\"$type\"" | tail -1 | sed "s/.*$field=\"\([0-9]*\)\".*/\1/"
101+
}
102+
103+
INSTR_MISSED=$(extract_counter "INSTRUCTION" "missed")
104+
INSTR_COVERED=$(extract_counter "INSTRUCTION" "covered")
105+
106+
BRANCH_MISSED=$(extract_counter "BRANCH" "missed")
107+
BRANCH_COVERED=$(extract_counter "BRANCH" "covered")
108+
109+
LINE_MISSED=$(extract_counter "LINE" "missed")
110+
LINE_COVERED=$(extract_counter "LINE" "covered")
111+
112+
METHOD_MISSED=$(extract_counter "METHOD" "missed")
113+
METHOD_COVERED=$(extract_counter "METHOD" "covered")
114+
115+
CLASS_MISSED=$(extract_counter "CLASS" "missed")
116+
CLASS_COVERED=$(extract_counter "CLASS" "covered")
117+
118+
# Calculate percentages
119+
calc_pct() {
120+
local covered=$1
121+
local missed=$2
122+
if [ -n "$covered" ] && [ -n "$missed" ]; then
123+
local total=$((covered + missed))
124+
if [ "$total" -gt 0 ]; then
125+
echo "scale=1; $covered * 100 / $total" | bc
126+
else
127+
echo "0"
128+
fi
129+
else
130+
echo "N/A"
131+
fi
132+
}
133+
134+
INSTR_PCT=$(calc_pct "${INSTR_COVERED:-0}" "${INSTR_MISSED:-0}")
135+
BRANCH_PCT=$(calc_pct "${BRANCH_COVERED:-0}" "${BRANCH_MISSED:-0}")
136+
LINE_PCT=$(calc_pct "${LINE_COVERED:-0}" "${LINE_MISSED:-0}")
137+
METHOD_PCT=$(calc_pct "${METHOD_COVERED:-0}" "${METHOD_MISSED:-0}")
138+
CLASS_PCT=$(calc_pct "${CLASS_COVERED:-0}" "${CLASS_MISSED:-0}")
139+
140+
echo "| Metric | Covered | Missed | Coverage |" >> $GITHUB_STEP_SUMMARY
141+
echo "|--------|---------|--------|----------|" >> $GITHUB_STEP_SUMMARY
142+
echo "| 📝 Instructions | ${INSTR_COVERED:-0} | ${INSTR_MISSED:-0} | ${INSTR_PCT}% |" >> $GITHUB_STEP_SUMMARY
143+
echo "| 🌿 Branches | ${BRANCH_COVERED:-0} | ${BRANCH_MISSED:-0} | ${BRANCH_PCT}% |" >> $GITHUB_STEP_SUMMARY
144+
echo "| 📏 Lines | ${LINE_COVERED:-0} | ${LINE_MISSED:-0} | ${LINE_PCT}% |" >> $GITHUB_STEP_SUMMARY
145+
echo "| 🔧 Methods | ${METHOD_COVERED:-0} | ${METHOD_MISSED:-0} | ${METHOD_PCT}% |" >> $GITHUB_STEP_SUMMARY
146+
echo "| 📦 Classes | ${CLASS_COVERED:-0} | ${CLASS_MISSED:-0} | ${CLASS_PCT}% |" >> $GITHUB_STEP_SUMMARY
147+
148+
if [ -f "$JACOCO_CSV" ]; then
149+
extract_instruction_scope() {
150+
local scope=$1
151+
awk -F',' -v scope="$scope" -v generated_prefix="com.github.copilot.sdk.generated" '
152+
NR > 1 {
153+
is_generated = index($2, generated_prefix) == 1
154+
if ((scope == "generated" && is_generated) ||
155+
(scope == "handwritten" && !is_generated)) {
156+
missed += $4
157+
covered += $5
158+
}
159+
}
160+
END { print covered + 0 "," missed + 0 }
161+
' "$JACOCO_CSV"
162+
}
163+
164+
IFS=, read -r HANDWRITTEN_COVERED HANDWRITTEN_MISSED <<< "$(extract_instruction_scope handwritten)"
165+
IFS=, read -r GENERATED_COVERED GENERATED_MISSED <<< "$(extract_instruction_scope generated)"
166+
HANDWRITTEN_PCT=$(calc_pct "${HANDWRITTEN_COVERED:-0}" "${HANDWRITTEN_MISSED:-0}")
167+
GENERATED_PCT=$(calc_pct "${GENERATED_COVERED:-0}" "${GENERATED_MISSED:-0}")
168+
169+
echo "" >> $GITHUB_STEP_SUMMARY
170+
echo "### Coverage by Code Origin (Instructions)" >> $GITHUB_STEP_SUMMARY
171+
echo "" >> $GITHUB_STEP_SUMMARY
172+
echo "| Origin | Covered | Missed | Coverage |" >> $GITHUB_STEP_SUMMARY
173+
echo "|--------|---------|--------|----------|" >> $GITHUB_STEP_SUMMARY
174+
echo "| ✍️ Handwritten | ${HANDWRITTEN_COVERED:-0} | ${HANDWRITTEN_MISSED:-0} | ${HANDWRITTEN_PCT}% |" >> $GITHUB_STEP_SUMMARY
175+
echo "| 🤖 Generated | ${GENERATED_COVERED:-0} | ${GENERATED_MISSED:-0} | ${GENERATED_PCT}% |" >> $GITHUB_STEP_SUMMARY
176+
fi
177+
else
178+
echo "" >> $GITHUB_STEP_SUMMARY
179+
echo "## 📊 Code Coverage" >> $GITHUB_STEP_SUMMARY
180+
echo "" >> $GITHUB_STEP_SUMMARY
181+
echo "⚠️ No JaCoCo report found at $JACOCO_XML" >> $GITHUB_STEP_SUMMARY
182+
fi

.github/aw/actions-lock.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,20 @@
1515
"version": "v8",
1616
"sha": "ed597411d8f924073f98dfc5c65a23a2325f34cd"
1717
},
18+
"actions/github-script@v9.0.0": {
19+
"repo": "actions/github-script",
20+
"version": "v9.0.0",
21+
"sha": "3a2844b7e9c422d3c10d287c895573f7108da1b3"
22+
},
1823
"actions/upload-artifact@v7.0.0": {
1924
"repo": "actions/upload-artifact",
2025
"version": "v7.0.0",
2126
"sha": "bbbca2ddaa5d8feaa63e36b76fdaad77386f024f"
2227
},
23-
"github/gh-aw-actions/setup@v0.67.4": {
28+
"github/gh-aw-actions/setup@v0.74.4": {
2429
"repo": "github/gh-aw-actions/setup",
25-
"version": "v0.67.4",
26-
"sha": "9d6ae06250fc0ec536a0e5f35de313b35bad7246"
30+
"version": "v0.74.4",
31+
"sha": "d3abfe96a194bce3a523ed2093ddedd5704cdf62"
2732
},
2833
"github/gh-aw/actions/setup@v0.52.1": {
2934
"repo": "github/gh-aw/actions/setup",

.github/copilot-instructions.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44

55
## Big picture 🔧
66

7-
- The repo implements language SDKs (Node/TS, Python, Go, .NET, Rust) that speak to the **Copilot CLI** via **JSON‑RPC** (see `README.md` and `nodejs/src/client.ts`).
8-
- Typical flow: your App → SDK client → JSON-RPC → Copilot CLI (server mode). The CLI must be installed or you can connect to an external CLI server via the `CLI URL option (language-specific casing)` (Node: `cliUrl`, Go: `CLIUrl`, .NET: `CliUrl`, Python: `cli_url`).
7+
- The repo implements language SDKs (Node/TS, Python, Go, .NET, Rust, Java) that speak to the **Copilot CLI** via **JSON‑RPC** (see `README.md` and `nodejs/src/client.ts`).
8+
- Typical flow: your App → SDK client → JSON-RPC → Copilot CLI (server mode). The CLI must be installed or you can connect to an external CLI server via the `CLI URL option (language-specific casing)` (Node: `cliUrl`, Go: `CLIUrl`, .NET: `CliUrl`, Python: `cli_url`, Java: `cliUrl`).
99

1010
## Most important files to read first 📚
1111

1212
- Top-level: `README.md` (architecture + quick start)
1313
- Language entry points: `nodejs/src/client.ts`, `python/README.md`, `go/README.md`, `dotnet/README.md`
14+
- Java: `java/README.md`, `java/pom.xml`
1415
- Test harness & E2E: `test/harness/*`, Python harness wrapper `python/e2e/testharness/proxy.py`
1516
- Schemas & type generation: `nodejs/scripts/generate-session-types.ts`
1617
- Session snapshots used by E2E: `test/snapshots/` (used by the replay proxy)
@@ -26,12 +27,15 @@
2627
- Go: `cd go && go test ./...`
2728
- .NET: `cd dotnet && dotnet test test/GitHub.Copilot.SDK.Test.csproj`
2829
- **.NET testing note:** Never add `InternalsVisibleTo` to any project file when writing tests. Tests must only access public APIs.
30+
- Java: `cd java && mvn clean verify` (full build + tests), `mvn spotless:apply` (format code before commit)
31+
- **Java testing note:** Always use `mvn verify` without `-q` and without piping through `grep`. Never add `InternalsVisibleTo` equivalent — tests must only access public APIs.
2932

3033
## Testing & E2E tips ⚙️
3134

3235
- E2E runs against a local **replaying CAPI proxy** (see `test/harness/server.ts`). Most language E2E harnesses spawn that server automatically (see `python/e2e/testharness/proxy.py`).
3336
- Tests rely on YAML snapshot exchanges under `test/snapshots/` — to add test scenarios, add or edit the appropriate YAML files and update tests.
3437
- The harness prints `Listening: http://...` — tests parse this URL to configure CLI or proxy.
38+
- Java E2E tests use `E2ETestContext` which manages a `CapiProxy` (Node.js replaying proxy). The harness is cloned during Maven's `generate-test-resources` phase to `java/target/copilot-sdk/`.
3539

3640
## Project-specific conventions & patterns ✅
3741

@@ -42,13 +46,14 @@
4246

4347
## Integration & environment notes ⚠️
4448

45-
- The SDK requires a Copilot CLI installation or an external server reachable via the `CLI URL option (language-specific casing)` (Node: `cliUrl`, Go: `CLIUrl`, .NET: `CliUrl`, Python: `cli_url`) or `COPILOT_CLI_PATH`.
49+
- The SDK requires a Copilot CLI installation or an external server reachable via the `CLI URL option (language-specific casing)` (Node: `cliUrl`, Go: `CLIUrl`, .NET: `CliUrl`, Python: `cli_url`, Java: `cliUrl`) or `COPILOT_CLI_PATH`.
4650
- Some scripts (typegen, formatting) call external tools: `gofmt`, `dotnet format`, `tsx` (available via npm), `quicktype`/`quicktype-core` (used by the Node typegen script), and `prettier` (provided as an npm devDependency). Most of these are available through the repo's package scripts or devDependencies—run `just install` (and `cd nodejs && npm ci`) to install them. Ensure the required tools are available in CI / developer machines.
4751
- Tests may assume `node >= 18`, `python >= 3.9`, platform differences handled (Windows uses `shell=True` for npx in harness).
52+
- Java requires JDK 17+ and Maven 3.9+. Java E2E tests also require Node.js (for the replay proxy).
4853

4954
## Where to add new code or tests 🧭
5055

51-
- SDK code: `nodejs/src`, `python/copilot`, `go`, `dotnet/src`, `rust/src`
52-
- Unit tests: `nodejs/test`, `python/*`, `go/*`, `dotnet/test`, `rust/tests`
53-
- E2E tests: `*/e2e/` folders that use the shared replay proxy and `test/snapshots/`
54-
- Generated types: update schema in `@github/copilot` then run `cd nodejs && npm run generate:session-types` and commit generated files in `src/generated` or language generated location.
56+
- SDK code: `nodejs/src`, `python/copilot`, `go`, `dotnet/src`, `rust/src`, `java/src/main/java`
57+
- Unit tests: `nodejs/test`, `python/*`, `go/*`, `dotnet/test`, `rust/tests`, `java/src/test/java`
58+
- E2E tests: `*/e2e/` folders that use the shared replay proxy and `test/snapshots/`, `java/src/test/java/**/e2e/`
59+
- Generated types: update schema in `@github/copilot` then run `cd nodejs && npm run generate:session-types` and commit generated files in `src/generated` or language generated location. Java generated types: `java/src/generated/java`

.github/dependabot.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ updates:
88
directory: '/'
99
multi-ecosystem-group: 'all'
1010
patterns: ['*']
11+
ignore:
12+
# gh-aw generated files — action SHAs are managed by `gh aw compile`
13+
# via .github/aw/actions-lock.json, not by Dependabot.
14+
# Dependabot's find-and-replace breaks lockfile metadata headers.
15+
- dependency-name: "actions/github-script"
16+
- dependency-name: "github/gh-aw-actions"
1117
- package-ecosystem: 'devcontainers'
1218
directory: '/'
1319
multi-ecosystem-group: 'all'
@@ -36,3 +42,26 @@ updates:
3642
directory: '/dotnet'
3743
multi-ecosystem-group: 'all'
3844
patterns: ['*']
45+
# Java dependencies
46+
- package-ecosystem: 'maven'
47+
directory: '/java'
48+
schedule:
49+
interval: 'weekly'
50+
ignore:
51+
# Major version bumps often drop Java 17 support or have breaking
52+
# API changes. These must be evaluated and applied manually.
53+
- dependency-name: "*"
54+
update-types: ["version-update:semver-major"]
55+
groups:
56+
java-maven-deps:
57+
patterns:
58+
- "*"
59+
# Java codegen dependencies
60+
- package-ecosystem: 'npm'
61+
directory: '/java/scripts/codegen'
62+
schedule:
63+
interval: 'weekly'
64+
groups:
65+
java-codegen-deps:
66+
patterns:
67+
- "*"

0 commit comments

Comments
 (0)