From 30e1c3422aa71328222bb99eadcf7ec09ba042a0 Mon Sep 17 00:00:00 2001 From: Ed Burns Date: Thu, 21 May 2026 17:58:27 -0700 Subject: [PATCH 1/3] 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 --- .../scripts/release/test-update-changelog.sh | 270 ++++++++++++++++++ .github/scripts/release/update-changelog.sh | 125 ++++++++ .github/workflows/java-publish-maven.yml | 46 +-- .github/workflows/java-publish-snapshot.yml | 6 +- .github/workflows/java-smoke-test.yml | 161 +++++++++++ .github/workflows/java.notes.template | 26 ++ java/pom.xml | 2 +- .../java/com/github/copilot/sdk/TestUtil.java | 16 +- 8 files changed, 610 insertions(+), 42 deletions(-) create mode 100755 .github/scripts/release/test-update-changelog.sh create mode 100755 .github/scripts/release/update-changelog.sh create mode 100644 .github/workflows/java-smoke-test.yml create mode 100644 .github/workflows/java.notes.template diff --git a/.github/scripts/release/test-update-changelog.sh b/.github/scripts/release/test-update-changelog.sh new file mode 100755 index 000000000..c5fb23792 --- /dev/null +++ b/.github/scripts/release/test-update-changelog.sh @@ -0,0 +1,270 @@ +#!/bin/bash +# Test script for update-changelog.sh + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +UPDATE_SCRIPT="${SCRIPT_DIR}/update-changelog.sh" +TEST_DIR="/tmp/changelog-test-$$" + +# Colors for output +GREEN='\033[0;32m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +passed=0 +failed=0 + +# Setup test directory +mkdir -p "$TEST_DIR" + +# Cleanup on exit +cleanup() { + rm -rf "$TEST_DIR" +} +trap cleanup EXIT + +# Helper function to run a test +run_test() { + local test_name="$1" + local test_func="$2" + + echo -n "Testing: $test_name ... " + + if $test_func; then + echo -e "${GREEN}PASSED${NC}" + passed=$((passed + 1)) + else + echo -e "${RED}FAILED${NC}" + failed=$((failed + 1)) + fi +} + +# Test 1: Basic functionality - Replace Unreleased with version +test_basic_replace() { + local test_file="${TEST_DIR}/test1.md" + cat > "$test_file" << 'EOF' +# Changelog + +## [Unreleased] + +### Added +- New feature + +## [1.0.0] - 2026-01-01 + +### Added +- Initial release + +[1.0.0]: https://github.com/test/repo/releases/tag/1.0.0 +EOF + + # Run the script + CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.1 > /dev/null 2>&1 + + # Verify the changes + if grep -q "## \[Unreleased\]" "$test_file" && \ + grep -q "## \[1.0.1\] - $(date +%Y-%m-%d)" "$test_file" && \ + grep -q "\[Unreleased\]: https://github.com/test/repo/compare/java/v1.0.1...HEAD" "$test_file" && \ + grep -q "\[1.0.1\]: https://github.com/test/repo/compare/java/v1.0.0...java/v1.0.1" "$test_file"; then + return 0 + else + return 1 + fi +} + +# Test 2: Handle CHANGELOG without Unreleased link +test_no_unreleased_link() { + local test_file="${TEST_DIR}/test2.md" + cat > "$test_file" << 'EOF' +# Changelog + +## [Unreleased] + +### Added +- New feature + +## [1.0.0] - 2026-01-01 + +[1.0.0]: https://github.com/test/repo/releases/tag/1.0.0 +EOF + + CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.1 > /dev/null 2>&1 + + # Should add both Unreleased and version links + if grep -q "\[Unreleased\]: https://github.com/test/repo/compare/java/v1.0.1...HEAD" "$test_file" && \ + grep -q "\[1.0.1\]: https://github.com/test/repo/compare/java/v1.0.0...java/v1.0.1" "$test_file"; then + return 0 + else + return 1 + fi +} + +# Test 3: Preserve content structure +test_preserve_content() { + local test_file="${TEST_DIR}/test3.md" + cat > "$test_file" << 'EOF' +# Changelog + +## [Unreleased] + +### Added +- Feature A +- Feature B + +### Fixed +- Bug fix + +## [1.0.0] - 2026-01-01 + +[1.0.0]: https://github.com/test/repo/releases/tag/1.0.0 +EOF + + CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.1 > /dev/null 2>&1 + + # Verify content is preserved under the new version + if grep -A 6 "## \[1.0.1\]" "$test_file" | grep -q "Feature A" && \ + grep -A 6 "## \[1.0.1\]" "$test_file" | grep -q "Bug fix"; then + return 0 + else + return 1 + fi +} + +# Test 4: Error handling - no Unreleased section +test_no_unreleased_section() { + local test_file="${TEST_DIR}/test4.md" + cat > "$test_file" << 'EOF' +# Changelog + +## [1.0.0] - 2026-01-01 + +[1.0.0]: https://github.com/test/repo/releases/tag/1.0.0 +EOF + + # Should fail because there's no Unreleased section + if ! CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.1 > /dev/null 2>&1; then + return 0 + else + return 1 + fi +} + +# Test 5: Multiple version handling +test_multiple_versions() { + local test_file="${TEST_DIR}/test5.md" + cat > "$test_file" << 'EOF' +# Changelog + +## [Unreleased] + +### Added +- New feature + +## [1.0.1] - 2026-02-01 + +## [1.0.0] - 2026-01-01 + +[1.0.1]: https://github.com/test/repo/compare/v1.0.0...v1.0.1 +[1.0.0]: https://github.com/test/repo/releases/tag/1.0.0 +EOF + + CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.2 > /dev/null 2>&1 + + # Verify the new version is added and links are updated + if grep -q "## \[1.0.2\] - $(date +%Y-%m-%d)" "$test_file" && \ + grep -q "\[1.0.2\]: https://github.com/test/repo/compare/java/v1.0.1...java/v1.0.2" "$test_file"; then + return 0 + else + return 1 + fi +} + +# Test 6: Beta-java version format (e.g., 1.0.0-beta-java.N) +test_beta_java_version() { + local test_file="${TEST_DIR}/test6.md" + cat > "$test_file" << 'EOF' +# Changelog + +## [Unreleased] + +### Added +- New feature + +## [1.0.0-beta-java.1] - 2026-05-01 + +[Unreleased]: https://github.com/test/repo/compare/v1.0.0-beta-java.1...HEAD +[1.0.0-beta-java.1]: https://github.com/test/repo/compare/v0.3.0-java.2...v1.0.0-beta-java.1 +[0.3.0-java.2]: https://github.com/test/repo/releases/tag/0.3.0-java.2 +EOF + + CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.0-beta-java.2 > /dev/null 2>&1 + + # The [Unreleased] link should now point to java/v1.0.0-beta-java.2 + # [1.0.0-beta-java.2] should compare from java/v1.0.0-beta-java.1 + if grep -q "\[Unreleased\]: https://github.com/test/repo/compare/java/v1.0.0-beta-java.2...HEAD" "$test_file" && \ + grep -q "\[1.0.0-beta-java.2\]: https://github.com/test/repo/compare/java/v1.0.0-beta-java.1...java/v1.0.0-beta-java.2" "$test_file"; then + return 0 + else + return 1 + fi +} + +# Test 7: No duplicate [Unreleased] links when existing [Unreleased] link is present +test_no_duplicate_unreleased_links() { + local test_file="${TEST_DIR}/test7.md" + cat > "$test_file" << 'EOF' +# Changelog + +## [Unreleased] + +### Added +- New feature + +## [1.0.0-beta-java.2] - 2026-05-08 + +## [1.0.0-beta-java.1] - 2026-05-05 + +[Unreleased]: https://github.com/test/repo/compare/v1.0.0-beta-java.2...HEAD +[1.0.0-beta-java.2]: https://github.com/test/repo/compare/v1.0.0-beta-java.1...v1.0.0-beta-java.2 +[1.0.0-beta-java.1]: https://github.com/test/repo/compare/v0.3.0-java.2...v1.0.0-beta-java.1 +[0.3.0-java.2]: https://github.com/test/repo/releases/tag/0.3.0-java.2 +EOF + + CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.0-beta-java.3 > /dev/null 2>&1 + + # Count [Unreleased] link definitions - there should be exactly one + local unreleased_count + unreleased_count=$(grep -c "^\[Unreleased\]:" "$test_file") + if [ "$unreleased_count" -eq 1 ] && \ + grep -q "\[Unreleased\]: https://github.com/test/repo/compare/java/v1.0.0-beta-java.3...HEAD" "$test_file" && \ + grep -q "\[1.0.0-beta-java.3\]: https://github.com/test/repo/compare/java/v1.0.0-beta-java.2...java/v1.0.0-beta-java.3" "$test_file"; then + return 0 + else + return 1 + fi +} + +# Run all tests +echo "Running CHANGELOG update script tests..." +echo "" + +run_test "Basic functionality - Replace Unreleased with version" test_basic_replace +run_test "Handle CHANGELOG without Unreleased link" test_no_unreleased_link +run_test "Preserve content structure" test_preserve_content +run_test "Error handling - no Unreleased section" test_no_unreleased_section +run_test "Multiple version handling" test_multiple_versions +run_test "Beta-java version format (e.g., 1.0.0-beta-java.N)" test_beta_java_version +run_test "No duplicate [Unreleased] links when existing link is present" test_no_duplicate_unreleased_links + +echo "" +echo "==========================================" +echo -e "Tests passed: ${GREEN}${passed}${NC}" +echo -e "Tests failed: ${RED}${failed}${NC}" +echo "==========================================" + +if [ $failed -eq 0 ]; then + exit 0 +else + exit 1 +fi diff --git a/.github/scripts/release/update-changelog.sh b/.github/scripts/release/update-changelog.sh new file mode 100755 index 000000000..6624f81dc --- /dev/null +++ b/.github/scripts/release/update-changelog.sh @@ -0,0 +1,125 @@ +#!/bin/bash +set -e + +# Script to update CHANGELOG.md during release process +# Usage: ./update-changelog.sh [reference-impl-hash] +# Example: ./update-changelog.sh 1.0.8 +# Example: ./update-changelog.sh 1.0.8 05e3c46c8c23130c9c064dc43d00ec78f7a75eab + +if [ -z "$1" ]; then + echo "Error: Version argument required" + echo "Usage: $0 [reference-impl-hash]" + exit 1 +fi + +VERSION="$1" +REFERENCE_IMPL_HASH="${2:-}" +CHANGELOG_FILE="${CHANGELOG_FILE:-CHANGELOG.md}" +RELEASE_DATE=$(date +%Y-%m-%d) + +echo "Updating CHANGELOG.md for version ${VERSION} (${RELEASE_DATE})" +if [ -n "$REFERENCE_IMPL_HASH" ]; then + echo " Reference implementation SDK sync: ${REFERENCE_IMPL_HASH:0:7}" +fi + +# Check if CHANGELOG.md exists +if [ ! -f "$CHANGELOG_FILE" ]; then + echo "Error: CHANGELOG.md not found" + exit 1 +fi + +# Check if there's an [Unreleased] section +if ! grep -q "## \[Unreleased\]" "$CHANGELOG_FILE"; then + echo "Error: No [Unreleased] section found in CHANGELOG.md" + exit 1 +fi + +# Create a temporary file +TEMP_FILE=$(mktemp) + +# Process the CHANGELOG +awk -v version="$VERSION" -v date="$RELEASE_DATE" -v REFERENCE_IMPL_HASH="$REFERENCE_IMPL_HASH" ' +BEGIN { + unreleased_found = 0 + content_found = 0 + links_section = 0 + first_version_link = "" + repo_url = "" + unreleased_link_handled = 0 +} + +# Track if we are in the links section at the bottom +/^\[/ { + links_section = 1 +} + +# Capture the repository URL from the first version link +links_section && repo_url == "" && /^\[[0-9]+\.[0-9]+\.[0-9]+(-(beta-)?java(-preview)?\.[0-9]+)?\]:/ { + match($0, /(https:\/\/github\.com\/[^\/]+\/[^\/]+)\//, arr) + if (arr[1] != "") { + repo_url = arr[1] + } +} + +# Replace [Unreleased] with the version and date +/^## \[Unreleased\]/ { + if (!unreleased_found) { + print "## [Unreleased]" + print "" + if (REFERENCE_IMPL_HASH != "") { + short_hash = substr(REFERENCE_IMPL_HASH, 1, 7) + print "> **Reference implementation sync:** [`github/copilot-sdk@" short_hash "`](https://github.com/github/copilot-sdk/commit/" REFERENCE_IMPL_HASH ")" + print "" + } + print "## [" version "] - " date + if (REFERENCE_IMPL_HASH != "") { + print "" + print "> **Reference implementation sync:** [`github/copilot-sdk@" short_hash "`](https://github.com/github/copilot-sdk/commit/" REFERENCE_IMPL_HASH ")" + } + unreleased_found = 1 + skip_old_reference_impl = 1 + next + } +} + +# Skip the old Reference implementation sync line and surrounding blank lines from the previous [Unreleased] section +skip_old_reference_impl && /^[[:space:]]*$/ { next } +skip_old_reference_impl && /^> \*\*Reference implementation sync:\*\*/ { next } +skip_old_reference_impl && !/^[[:space:]]*$/ && !/^> \*\*Reference implementation sync:\*\*/ { skip_old_reference_impl = 0 } + +# Update existing [Unreleased] link if present (must be checked before the first-version-link block) +links_section && /^\[Unreleased\]:/ { + # Get the previous version and repo URL from the existing link (handles both v and java/v prefix) + match($0, /(https:\/\/github\.com\/[^\/]+\/[^\/]+)\/compare\/(java\/)?v([0-9]+\.[0-9]+\.[0-9]+(-(beta-)?java(-preview)?\.[0-9]+)?)\.\.\.HEAD/, arr) + if (arr[1] != "" && arr[3] != "") { + print "[Unreleased]: " arr[1] "/compare/java/v" version "...HEAD" + print "[" version "]: " arr[1] "/compare/java/v" arr[3] "...java/v" version + unreleased_link_handled = 1 + next + } +} + +# Capture the first version link to get the previous version +# Only fires if the [Unreleased] link was not already handled above +links_section && first_version_link == "" && !unreleased_link_handled && /^\[[0-9]+\.[0-9]+\.[0-9]+(-(beta-)?java(-preview)?\.[0-9]+)?\]:/ { + match($0, /\[([0-9]+\.[0-9]+\.[0-9]+(-(beta-)?java(-preview)?\.[0-9]+)?)\]:/, arr) + if (arr[1] != "" && repo_url != "") { + first_version_link = arr[1] + # Insert Unreleased and new version links before first version link + print "[Unreleased]: " repo_url "/compare/java/v" version "...HEAD" + print "[" version "]: " repo_url "/compare/java/v" arr[1] "...java/v" version + } +} + +# Print all other lines unchanged +{ print } +' "$CHANGELOG_FILE" > "$TEMP_FILE" + +# Replace the original file +mv "$TEMP_FILE" "$CHANGELOG_FILE" + +echo "✓ CHANGELOG.md updated successfully" +echo " - Added version ${VERSION} with date ${RELEASE_DATE}" +echo " - Created new [Unreleased] section" +echo " - Updated version comparison links" + diff --git a/.github/workflows/java-publish-maven.yml b/.github/workflows/java-publish-maven.yml index 1c92e0109..ece7463fb 100644 --- a/.github/workflows/java-publish-maven.yml +++ b/.github/workflows/java-publish-maven.yml @@ -1,4 +1,4 @@ -name: Publish to Maven Central +name: "Java Publish to Maven Central" env: # Disable Husky Git hooks in CI to prevent local development hooks @@ -35,6 +35,10 @@ jobs: publish-maven: name: Publish Java SDK to Maven Central runs-on: ubuntu-latest + defaults: + run: + shell: bash + working-directory: ./java outputs: version: ${{ steps.versions.outputs.release_version }} steps: @@ -121,7 +125,7 @@ jobs: echo "Reference implementation SDK sync: ${REFERENCE_IMPL_SHORT} (${REFERENCE_IMPL_URL})" # Update CHANGELOG.md with release version and Reference implementation sync hash - ../.github/scripts/release/update-changelog.sh "${VERSION}" "${REFERENCE_IMPL_HASH}" + $GITHUB_WORKSPACE/.github/scripts/release/update-changelog.sh "${VERSION}" "${REFERENCE_IMPL_HASH}" # Update version in README.md (supports any version qualifier like -java.N, -java-preview.N, -beta-java.N) sed -i "s|[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\(-[a-z][a-z0-9-]*\.[0-9][0-9]*\)*|${VERSION}|g" README.md @@ -150,7 +154,7 @@ jobs: mvn -B release:prepare \ -DreleaseVersion=${{ steps.versions.outputs.release_version }} \ -DdevelopmentVersion=${{ steps.versions.outputs.dev_version }} \ - -DtagNameFormat=v@{project.version} \ + -DtagNameFormat=java/v@{project.version} \ -DpushChanges=true \ -Darguments="-DskipTests" env: @@ -185,6 +189,10 @@ jobs: needs: publish-maven if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest + defaults: + run: + shell: bash + working-directory: ./java steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: @@ -194,7 +202,7 @@ jobs: VERSION="${{ needs.publish-maven.outputs.version }}" GROUP_ID="com.github" ARTIFACT_ID="copilot-sdk-java" - CURRENT_TAG="v${VERSION}" + CURRENT_TAG="java/v${VERSION}" if gh release view "${CURRENT_TAG}" >/dev/null 2>&1; then echo "Release ${CURRENT_TAG} already exists. Skipping creation." @@ -203,11 +211,10 @@ jobs: # Generate release notes from template export VERSION GROUP_ID ARTIFACT_ID - RELEASE_NOTES=$(envsubst < .github/workflows/notes.template) + RELEASE_NOTES=$(envsubst < $GITHUB_WORKSPACE/.github/workflows/java.notes.template) # Get the previous tag for generating notes - PREV_TAG=$(git tag --list 'v*' --sort=-version:refname \ - | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+(-java(-preview)?\.[0-9]+)?$' \ + PREV_TAG=$(git tag --list 'java/v*' --sort=-version:refname \ | grep -Fxv "${CURRENT_TAG}" \ | head -n 1) @@ -229,28 +236,3 @@ jobs: gh release create "${GH_ARGS[@]}" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Move 'latest' tag to new release - run: | - VERSION="${{ needs.publish-maven.outputs.version }}" - git tag -f latest "v${VERSION}" - git push origin latest --force - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - deploy-site: - name: Deploy Documentation - needs: [publish-maven, github-release] - runs-on: ubuntu-latest - permissions: - actions: write - contents: read - steps: - - name: Trigger site deployment - run: | - gh workflow run deploy-site.yml \ - --repo ${{ github.repository }} \ - -f version="${{ needs.publish-maven.outputs.version }}" \ - -f publish_as_latest=true - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/java-publish-snapshot.yml b/.github/workflows/java-publish-snapshot.yml index ddc04c40b..7bc231c73 100644 --- a/.github/workflows/java-publish-snapshot.yml +++ b/.github/workflows/java-publish-snapshot.yml @@ -1,4 +1,4 @@ -name: Publish Snapshot to Maven Central +name: Java Publish Snapshot to Maven Central env: HUSKY: 0 @@ -19,6 +19,10 @@ jobs: publish-snapshot: name: Publish SNAPSHOT to Maven Central runs-on: ubuntu-latest + defaults: + run: + shell: bash + working-directory: ./java steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: diff --git a/.github/workflows/java-smoke-test.yml b/.github/workflows/java-smoke-test.yml new file mode 100644 index 000000000..cffef0a35 --- /dev/null +++ b/.github/workflows/java-smoke-test.yml @@ -0,0 +1,161 @@ +name: "Java smoke test" + +on: + workflow_dispatch: + workflow_call: + secrets: + COPILOT_GITHUB_TOKEN: + required: true + +permissions: + contents: read + +jobs: + smoke-test-jdk17: + name: Build SDK and run smoke test (JDK 17) + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' + defaults: + run: + shell: bash + working-directory: ./java + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Set up JDK 17 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: "17" + distribution: "microsoft" + cache: "maven" + + - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v6 + with: + node-version: 22 + + - name: Read pinned @github/copilot version from pom.xml + id: cli-version + run: | + PROP="readonly-copilot-sdk-ref-impl-version-from-lastmerge-file-updated-by-reference-impl-sync" + VERSION=$(sed -n "s|.*<${PROP}>\(.*\).*|\1|p" pom.xml | head -n 1 | tr -d '[:space:]') + if [[ -z "$VERSION" || "$VERSION" == "PRIMER_TO_REPLACE" ]]; then + echo "::error::Could not read pinned @github/copilot version from pom.xml property <${PROP}>" >&2 + exit 1 + fi + echo "Pinned @github/copilot version: $VERSION" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Install Copilot CLI globally (pinned to pom.xml version) + run: npm install -g "@github/copilot@${{ steps.cli-version.outputs.version }}" + + - name: Verify CLI works + run: copilot --version + + - name: Build SDK and install to local repo + run: mvn -DskipTests -Pskip-test-harness clean install + + - name: Create and run smoke test via Copilot CLI + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + run: | + cat > /tmp/smoke-test-prompt.txt << 'PROMPT_EOF' + You are running inside the copilot-sdk monorepo, in the java/ subdirectory. + The SDK has already been built and installed into the local Maven repository. + JDK 17 and Maven are already installed and on PATH. + + Execute the prompt at `src/test/prompts/PROMPT-smoke-test.md` with the following critical overrides: + + **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`. + + **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. + + 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`). + + If any step fails, exit with a non-zero exit code. Do not silently fix errors. + PROMPT_EOF + + copilot --yolo --prompt "$(cat /tmp/smoke-test-prompt.txt)" + + - name: Run smoke test jar + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + run: | + cd smoke-test + java -jar ./target/copilot-sdk-smoketest-1.0-SNAPSHOT.jar + echo "Smoke test passed (exit code 0)" + + smoke-test-java25: + name: Build SDK and run smoke test (JDK 25) + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' + defaults: + run: + shell: bash + working-directory: ./java + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Set up JDK 25 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: "25" + distribution: "microsoft" + cache: "maven" + + - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v6 + with: + node-version: 22 + + - name: Read pinned @github/copilot version from pom.xml + id: cli-version + run: | + PROP="readonly-copilot-sdk-ref-impl-version-from-lastmerge-file-updated-by-reference-impl-sync" + VERSION=$(sed -n "s|.*<${PROP}>\(.*\).*|\1|p" pom.xml | head -n 1 | tr -d '[:space:]') + if [[ -z "$VERSION" || "$VERSION" == "PRIMER_TO_REPLACE" ]]; then + echo "::error::Could not read pinned @github/copilot version from pom.xml property <${PROP}>" >&2 + exit 1 + fi + echo "Pinned @github/copilot version: $VERSION" + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + + - name: Install Copilot CLI globally (pinned to pom.xml version) + run: npm install -g "@github/copilot@${{ steps.cli-version.outputs.version }}" + + - name: Verify CLI works + run: copilot --version + + - name: Build SDK and install to local repo + run: mvn -DskipTests -Pskip-test-harness clean install + + - name: Create and run smoke test via Copilot CLI + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + run: | + cat > /tmp/smoke-test-prompt.txt << 'PROMPT_EOF' + You are running inside the copilot-sdk monorepo, in the java/ subdirectory. + The SDK has already been built and installed into the local Maven repository. + JDK 25 and Maven are already installed and on PATH. + + Execute the prompt at `src/test/prompts/PROMPT-smoke-test.md` with the following critical overrides: + + **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`. + + **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. + + **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`). + Also set `maven.compiler.source` and `maven.compiler.target` to `25` in the `pom.xml`. + + 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`). + + If any step fails, exit with a non-zero exit code. Do not silently fix errors. + PROMPT_EOF + + copilot --yolo --prompt "$(cat /tmp/smoke-test-prompt.txt)" + + - name: Run smoke test jar + env: + COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} + run: | + cd smoke-test + java -jar ./target/copilot-sdk-smoketest-1.0-SNAPSHOT.jar + echo "Smoke test passed (exit code 0)" diff --git a/.github/workflows/java.notes.template b/.github/workflows/java.notes.template new file mode 100644 index 000000000..bec50a91b --- /dev/null +++ b/.github/workflows/java.notes.template @@ -0,0 +1,26 @@ +# Installation + +ℹ️ **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. + +⚠️ **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. + +📦 [View on Maven Central](https://central.sonatype.com/artifact/${GROUP_ID}/${ARTIFACT_ID}/${VERSION}) + +## Maven +```xml + + ${GROUP_ID} + ${ARTIFACT_ID} + ${VERSION} + +``` + +## Gradle (Kotlin DSL) +```kotlin +implementation("${GROUP_ID}:${ARTIFACT_ID}:${VERSION}") +``` + +## Gradle (Groovy DSL) +```groovy +implementation '${GROUP_ID}:${ARTIFACT_ID}:${VERSION}' +``` diff --git a/java/pom.xml b/java/pom.xml index db0f4c247..066822acc 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -641,7 +641,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.6.2 + 3.6.3 require-schema-version diff --git a/java/src/test/java/com/github/copilot/sdk/TestUtil.java b/java/src/test/java/com/github/copilot/sdk/TestUtil.java index d9462af87..af4474590 100644 --- a/java/src/test/java/com/github/copilot/sdk/TestUtil.java +++ b/java/src/test/java/com/github/copilot/sdk/TestUtil.java @@ -36,9 +36,9 @@ public static String tempPath(String filename) { *

* Resolution order: *

    - *
  1. Search the system PATH using {@code where.exe} (Windows) or {@code which} - * (Linux/macOS).
  2. - *
  3. Fall back to the {@code COPILOT_CLI_PATH} environment variable.
  4. + *
  5. Use the {@code COPILOT_CLI_PATH} environment variable when set.
  6. + *
  7. Otherwise search the system PATH using {@code where.exe} (Windows) or + * {@code which} (Linux/macOS).
  8. *
  9. Walk parent directories looking for * {@code nodejs/node_modules/@github/copilot/index.js}.
  10. *
@@ -55,16 +55,16 @@ public static String tempPath(String filename) { * {@code null} if none was found */ static String findCliPath() { - String copilotInPath = findCopilotInPath(); - if (copilotInPath != null) { - return copilotInPath; - } - String envPath = System.getenv("COPILOT_CLI_PATH"); if (envPath != null && !envPath.isEmpty()) { return envPath; } + String copilotInPath = findCopilotInPath(); + if (copilotInPath != null) { + return copilotInPath; + } + Path current = Paths.get(System.getProperty("user.dir")); while (current != null) { Path cliPath = current.resolve("nodejs/node_modules/@github/copilot/index.js"); From 8202b04367dbd08f8c5fd5c20721ecbba398aef7 Mon Sep 17 00:00:00 2001 From: Ed Burns Date: Fri, 22 May 2026 11:10:20 -0700 Subject: [PATCH 2/3] Remove Java-specific CHANGELOG; use monorepo's release-changelog agent for java/v* and rust/v* scoped tags. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address [comments](https://github.com/github/copilot-sdk/pull/1369#discussion_r3289816220) 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. --- .../scripts/release/test-update-changelog.sh | 270 --------- .github/scripts/release/update-changelog.sh | 125 ---- .github/workflows/java-publish-maven.yml | 15 +- .github/workflows/release-changelog.lock.yml | 32 +- .github/workflows/release-changelog.md | 18 +- java/CHANGELOG.md | 535 ------------------ 6 files changed, 32 insertions(+), 963 deletions(-) delete mode 100755 .github/scripts/release/test-update-changelog.sh delete mode 100755 .github/scripts/release/update-changelog.sh delete mode 100644 java/CHANGELOG.md diff --git a/.github/scripts/release/test-update-changelog.sh b/.github/scripts/release/test-update-changelog.sh deleted file mode 100755 index c5fb23792..000000000 --- a/.github/scripts/release/test-update-changelog.sh +++ /dev/null @@ -1,270 +0,0 @@ -#!/bin/bash -# Test script for update-changelog.sh - -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -UPDATE_SCRIPT="${SCRIPT_DIR}/update-changelog.sh" -TEST_DIR="/tmp/changelog-test-$$" - -# Colors for output -GREEN='\033[0;32m' -RED='\033[0;31m' -NC='\033[0m' # No Color - -passed=0 -failed=0 - -# Setup test directory -mkdir -p "$TEST_DIR" - -# Cleanup on exit -cleanup() { - rm -rf "$TEST_DIR" -} -trap cleanup EXIT - -# Helper function to run a test -run_test() { - local test_name="$1" - local test_func="$2" - - echo -n "Testing: $test_name ... " - - if $test_func; then - echo -e "${GREEN}PASSED${NC}" - passed=$((passed + 1)) - else - echo -e "${RED}FAILED${NC}" - failed=$((failed + 1)) - fi -} - -# Test 1: Basic functionality - Replace Unreleased with version -test_basic_replace() { - local test_file="${TEST_DIR}/test1.md" - cat > "$test_file" << 'EOF' -# Changelog - -## [Unreleased] - -### Added -- New feature - -## [1.0.0] - 2026-01-01 - -### Added -- Initial release - -[1.0.0]: https://github.com/test/repo/releases/tag/1.0.0 -EOF - - # Run the script - CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.1 > /dev/null 2>&1 - - # Verify the changes - if grep -q "## \[Unreleased\]" "$test_file" && \ - grep -q "## \[1.0.1\] - $(date +%Y-%m-%d)" "$test_file" && \ - grep -q "\[Unreleased\]: https://github.com/test/repo/compare/java/v1.0.1...HEAD" "$test_file" && \ - grep -q "\[1.0.1\]: https://github.com/test/repo/compare/java/v1.0.0...java/v1.0.1" "$test_file"; then - return 0 - else - return 1 - fi -} - -# Test 2: Handle CHANGELOG without Unreleased link -test_no_unreleased_link() { - local test_file="${TEST_DIR}/test2.md" - cat > "$test_file" << 'EOF' -# Changelog - -## [Unreleased] - -### Added -- New feature - -## [1.0.0] - 2026-01-01 - -[1.0.0]: https://github.com/test/repo/releases/tag/1.0.0 -EOF - - CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.1 > /dev/null 2>&1 - - # Should add both Unreleased and version links - if grep -q "\[Unreleased\]: https://github.com/test/repo/compare/java/v1.0.1...HEAD" "$test_file" && \ - grep -q "\[1.0.1\]: https://github.com/test/repo/compare/java/v1.0.0...java/v1.0.1" "$test_file"; then - return 0 - else - return 1 - fi -} - -# Test 3: Preserve content structure -test_preserve_content() { - local test_file="${TEST_DIR}/test3.md" - cat > "$test_file" << 'EOF' -# Changelog - -## [Unreleased] - -### Added -- Feature A -- Feature B - -### Fixed -- Bug fix - -## [1.0.0] - 2026-01-01 - -[1.0.0]: https://github.com/test/repo/releases/tag/1.0.0 -EOF - - CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.1 > /dev/null 2>&1 - - # Verify content is preserved under the new version - if grep -A 6 "## \[1.0.1\]" "$test_file" | grep -q "Feature A" && \ - grep -A 6 "## \[1.0.1\]" "$test_file" | grep -q "Bug fix"; then - return 0 - else - return 1 - fi -} - -# Test 4: Error handling - no Unreleased section -test_no_unreleased_section() { - local test_file="${TEST_DIR}/test4.md" - cat > "$test_file" << 'EOF' -# Changelog - -## [1.0.0] - 2026-01-01 - -[1.0.0]: https://github.com/test/repo/releases/tag/1.0.0 -EOF - - # Should fail because there's no Unreleased section - if ! CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.1 > /dev/null 2>&1; then - return 0 - else - return 1 - fi -} - -# Test 5: Multiple version handling -test_multiple_versions() { - local test_file="${TEST_DIR}/test5.md" - cat > "$test_file" << 'EOF' -# Changelog - -## [Unreleased] - -### Added -- New feature - -## [1.0.1] - 2026-02-01 - -## [1.0.0] - 2026-01-01 - -[1.0.1]: https://github.com/test/repo/compare/v1.0.0...v1.0.1 -[1.0.0]: https://github.com/test/repo/releases/tag/1.0.0 -EOF - - CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.2 > /dev/null 2>&1 - - # Verify the new version is added and links are updated - if grep -q "## \[1.0.2\] - $(date +%Y-%m-%d)" "$test_file" && \ - grep -q "\[1.0.2\]: https://github.com/test/repo/compare/java/v1.0.1...java/v1.0.2" "$test_file"; then - return 0 - else - return 1 - fi -} - -# Test 6: Beta-java version format (e.g., 1.0.0-beta-java.N) -test_beta_java_version() { - local test_file="${TEST_DIR}/test6.md" - cat > "$test_file" << 'EOF' -# Changelog - -## [Unreleased] - -### Added -- New feature - -## [1.0.0-beta-java.1] - 2026-05-01 - -[Unreleased]: https://github.com/test/repo/compare/v1.0.0-beta-java.1...HEAD -[1.0.0-beta-java.1]: https://github.com/test/repo/compare/v0.3.0-java.2...v1.0.0-beta-java.1 -[0.3.0-java.2]: https://github.com/test/repo/releases/tag/0.3.0-java.2 -EOF - - CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.0-beta-java.2 > /dev/null 2>&1 - - # The [Unreleased] link should now point to java/v1.0.0-beta-java.2 - # [1.0.0-beta-java.2] should compare from java/v1.0.0-beta-java.1 - if grep -q "\[Unreleased\]: https://github.com/test/repo/compare/java/v1.0.0-beta-java.2...HEAD" "$test_file" && \ - grep -q "\[1.0.0-beta-java.2\]: https://github.com/test/repo/compare/java/v1.0.0-beta-java.1...java/v1.0.0-beta-java.2" "$test_file"; then - return 0 - else - return 1 - fi -} - -# Test 7: No duplicate [Unreleased] links when existing [Unreleased] link is present -test_no_duplicate_unreleased_links() { - local test_file="${TEST_DIR}/test7.md" - cat > "$test_file" << 'EOF' -# Changelog - -## [Unreleased] - -### Added -- New feature - -## [1.0.0-beta-java.2] - 2026-05-08 - -## [1.0.0-beta-java.1] - 2026-05-05 - -[Unreleased]: https://github.com/test/repo/compare/v1.0.0-beta-java.2...HEAD -[1.0.0-beta-java.2]: https://github.com/test/repo/compare/v1.0.0-beta-java.1...v1.0.0-beta-java.2 -[1.0.0-beta-java.1]: https://github.com/test/repo/compare/v0.3.0-java.2...v1.0.0-beta-java.1 -[0.3.0-java.2]: https://github.com/test/repo/releases/tag/0.3.0-java.2 -EOF - - CHANGELOG_FILE="$test_file" bash "$UPDATE_SCRIPT" 1.0.0-beta-java.3 > /dev/null 2>&1 - - # Count [Unreleased] link definitions - there should be exactly one - local unreleased_count - unreleased_count=$(grep -c "^\[Unreleased\]:" "$test_file") - if [ "$unreleased_count" -eq 1 ] && \ - grep -q "\[Unreleased\]: https://github.com/test/repo/compare/java/v1.0.0-beta-java.3...HEAD" "$test_file" && \ - grep -q "\[1.0.0-beta-java.3\]: https://github.com/test/repo/compare/java/v1.0.0-beta-java.2...java/v1.0.0-beta-java.3" "$test_file"; then - return 0 - else - return 1 - fi -} - -# Run all tests -echo "Running CHANGELOG update script tests..." -echo "" - -run_test "Basic functionality - Replace Unreleased with version" test_basic_replace -run_test "Handle CHANGELOG without Unreleased link" test_no_unreleased_link -run_test "Preserve content structure" test_preserve_content -run_test "Error handling - no Unreleased section" test_no_unreleased_section -run_test "Multiple version handling" test_multiple_versions -run_test "Beta-java version format (e.g., 1.0.0-beta-java.N)" test_beta_java_version -run_test "No duplicate [Unreleased] links when existing link is present" test_no_duplicate_unreleased_links - -echo "" -echo "==========================================" -echo -e "Tests passed: ${GREEN}${passed}${NC}" -echo -e "Tests failed: ${RED}${failed}${NC}" -echo "==========================================" - -if [ $failed -eq 0 ]; then - exit 0 -else - exit 1 -fi diff --git a/.github/scripts/release/update-changelog.sh b/.github/scripts/release/update-changelog.sh deleted file mode 100755 index 6624f81dc..000000000 --- a/.github/scripts/release/update-changelog.sh +++ /dev/null @@ -1,125 +0,0 @@ -#!/bin/bash -set -e - -# Script to update CHANGELOG.md during release process -# Usage: ./update-changelog.sh [reference-impl-hash] -# Example: ./update-changelog.sh 1.0.8 -# Example: ./update-changelog.sh 1.0.8 05e3c46c8c23130c9c064dc43d00ec78f7a75eab - -if [ -z "$1" ]; then - echo "Error: Version argument required" - echo "Usage: $0 [reference-impl-hash]" - exit 1 -fi - -VERSION="$1" -REFERENCE_IMPL_HASH="${2:-}" -CHANGELOG_FILE="${CHANGELOG_FILE:-CHANGELOG.md}" -RELEASE_DATE=$(date +%Y-%m-%d) - -echo "Updating CHANGELOG.md for version ${VERSION} (${RELEASE_DATE})" -if [ -n "$REFERENCE_IMPL_HASH" ]; then - echo " Reference implementation SDK sync: ${REFERENCE_IMPL_HASH:0:7}" -fi - -# Check if CHANGELOG.md exists -if [ ! -f "$CHANGELOG_FILE" ]; then - echo "Error: CHANGELOG.md not found" - exit 1 -fi - -# Check if there's an [Unreleased] section -if ! grep -q "## \[Unreleased\]" "$CHANGELOG_FILE"; then - echo "Error: No [Unreleased] section found in CHANGELOG.md" - exit 1 -fi - -# Create a temporary file -TEMP_FILE=$(mktemp) - -# Process the CHANGELOG -awk -v version="$VERSION" -v date="$RELEASE_DATE" -v REFERENCE_IMPL_HASH="$REFERENCE_IMPL_HASH" ' -BEGIN { - unreleased_found = 0 - content_found = 0 - links_section = 0 - first_version_link = "" - repo_url = "" - unreleased_link_handled = 0 -} - -# Track if we are in the links section at the bottom -/^\[/ { - links_section = 1 -} - -# Capture the repository URL from the first version link -links_section && repo_url == "" && /^\[[0-9]+\.[0-9]+\.[0-9]+(-(beta-)?java(-preview)?\.[0-9]+)?\]:/ { - match($0, /(https:\/\/github\.com\/[^\/]+\/[^\/]+)\//, arr) - if (arr[1] != "") { - repo_url = arr[1] - } -} - -# Replace [Unreleased] with the version and date -/^## \[Unreleased\]/ { - if (!unreleased_found) { - print "## [Unreleased]" - print "" - if (REFERENCE_IMPL_HASH != "") { - short_hash = substr(REFERENCE_IMPL_HASH, 1, 7) - print "> **Reference implementation sync:** [`github/copilot-sdk@" short_hash "`](https://github.com/github/copilot-sdk/commit/" REFERENCE_IMPL_HASH ")" - print "" - } - print "## [" version "] - " date - if (REFERENCE_IMPL_HASH != "") { - print "" - print "> **Reference implementation sync:** [`github/copilot-sdk@" short_hash "`](https://github.com/github/copilot-sdk/commit/" REFERENCE_IMPL_HASH ")" - } - unreleased_found = 1 - skip_old_reference_impl = 1 - next - } -} - -# Skip the old Reference implementation sync line and surrounding blank lines from the previous [Unreleased] section -skip_old_reference_impl && /^[[:space:]]*$/ { next } -skip_old_reference_impl && /^> \*\*Reference implementation sync:\*\*/ { next } -skip_old_reference_impl && !/^[[:space:]]*$/ && !/^> \*\*Reference implementation sync:\*\*/ { skip_old_reference_impl = 0 } - -# Update existing [Unreleased] link if present (must be checked before the first-version-link block) -links_section && /^\[Unreleased\]:/ { - # Get the previous version and repo URL from the existing link (handles both v and java/v prefix) - match($0, /(https:\/\/github\.com\/[^\/]+\/[^\/]+)\/compare\/(java\/)?v([0-9]+\.[0-9]+\.[0-9]+(-(beta-)?java(-preview)?\.[0-9]+)?)\.\.\.HEAD/, arr) - if (arr[1] != "" && arr[3] != "") { - print "[Unreleased]: " arr[1] "/compare/java/v" version "...HEAD" - print "[" version "]: " arr[1] "/compare/java/v" arr[3] "...java/v" version - unreleased_link_handled = 1 - next - } -} - -# Capture the first version link to get the previous version -# Only fires if the [Unreleased] link was not already handled above -links_section && first_version_link == "" && !unreleased_link_handled && /^\[[0-9]+\.[0-9]+\.[0-9]+(-(beta-)?java(-preview)?\.[0-9]+)?\]:/ { - match($0, /\[([0-9]+\.[0-9]+\.[0-9]+(-(beta-)?java(-preview)?\.[0-9]+)?)\]:/, arr) - if (arr[1] != "" && repo_url != "") { - first_version_link = arr[1] - # Insert Unreleased and new version links before first version link - print "[Unreleased]: " repo_url "/compare/java/v" version "...HEAD" - print "[" version "]: " repo_url "/compare/java/v" arr[1] "...java/v" version - } -} - -# Print all other lines unchanged -{ print } -' "$CHANGELOG_FILE" > "$TEMP_FILE" - -# Replace the original file -mv "$TEMP_FILE" "$CHANGELOG_FILE" - -echo "✓ CHANGELOG.md updated successfully" -echo " - Added version ${VERSION} with date ${RELEASE_DATE}" -echo " - Created new [Unreleased] section" -echo " - Updated version comparison links" - diff --git a/.github/workflows/java-publish-maven.yml b/.github/workflows/java-publish-maven.yml index ece7463fb..2f150f1b1 100644 --- a/.github/workflows/java-publish-maven.yml +++ b/.github/workflows/java-publish-maven.yml @@ -118,15 +118,6 @@ jobs: run: | VERSION="${{ steps.versions.outputs.release_version }}" - # Read the reference implementation SDK commit hash that this release is synced to - REFERENCE_IMPL_HASH=$(cat .lastmerge) - REFERENCE_IMPL_SHORT="${REFERENCE_IMPL_HASH:0:7}" - REFERENCE_IMPL_URL="https://github.com/github/copilot-sdk/commit/${REFERENCE_IMPL_HASH}" - echo "Reference implementation SDK sync: ${REFERENCE_IMPL_SHORT} (${REFERENCE_IMPL_URL})" - - # Update CHANGELOG.md with release version and Reference implementation sync hash - $GITHUB_WORKSPACE/.github/scripts/release/update-changelog.sh "${VERSION}" "${REFERENCE_IMPL_HASH}" - # Update version in README.md (supports any version qualifier like -java.N, -java-preview.N, -beta-java.N) sed -i "s|[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\(-[a-z][a-z0-9-]*\.[0-9][0-9]*\)*|${VERSION}|g" README.md 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 @@ -140,7 +131,7 @@ jobs: sed -i 's|copilot-sdk-java:${project\.version}|copilot-sdk-java:'"${VERSION}"'|g' jbang-example.java # Commit the documentation changes before release:prepare (requires clean working directory) - git add CHANGELOG.md README.md jbang-example.java + git add README.md jbang-example.java git commit -m "docs: update version references to ${VERSION}" # Save the commit SHA for potential rollback @@ -236,3 +227,7 @@ jobs: gh release create "${GH_ARGS[@]}" env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Trigger changelog generation + run: gh workflow run release-changelog.lock.yml -f tag="java/v${{ needs.publish-maven.outputs.version }}" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/release-changelog.lock.yml b/.github/workflows/release-changelog.lock.yml index 2a82f1660..473a5b609 100644 --- a/.github/workflows/release-changelog.lock.yml +++ b/.github/workflows/release-changelog.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"c06cce5802b74e1280963eef2e92515d84870d76d9cfdefa84b56c038e2b8da1","compiler_version":"v0.74.4","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"dbed522073916e78c89a833a04d5c3327a72accc607e97243b91b7da11c88192","compiler_version":"v0.74.4","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"d3abfe96a194bce3a523ed2093ddedd5704cdf62","version":"v0.74.4"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.46"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.46"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.46"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.9","digest":"sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.9@sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388"},{"image":"ghcr.io/github/github-mcp-server:v1.0.4"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -58,7 +58,7 @@ on: required: false type: string tag: - description: Release tag to generate changelog for (e.g., v0.1.30) + description: Release tag to generate changelog for (e.g., v0.1.30, java/v1.0.0, rust/v0.1.30) required: true type: string @@ -189,23 +189,23 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_41d0179c6df1e6c3_EOF' + cat << 'GH_AW_PROMPT_212da97049a185e7_EOF' - GH_AW_PROMPT_41d0179c6df1e6c3_EOF + GH_AW_PROMPT_212da97049a185e7_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_41d0179c6df1e6c3_EOF' + cat << 'GH_AW_PROMPT_212da97049a185e7_EOF' Tools: create_pull_request, update_release, missing_tool, missing_data, noop - GH_AW_PROMPT_41d0179c6df1e6c3_EOF + GH_AW_PROMPT_212da97049a185e7_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" - cat << 'GH_AW_PROMPT_41d0179c6df1e6c3_EOF' + cat << 'GH_AW_PROMPT_212da97049a185e7_EOF' - GH_AW_PROMPT_41d0179c6df1e6c3_EOF + GH_AW_PROMPT_212da97049a185e7_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_41d0179c6df1e6c3_EOF' + cat << 'GH_AW_PROMPT_212da97049a185e7_EOF' The following GitHub context information is available for this workflow: {{#if github.actor}} @@ -234,12 +234,12 @@ jobs: {{/if}} - GH_AW_PROMPT_41d0179c6df1e6c3_EOF + GH_AW_PROMPT_212da97049a185e7_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_41d0179c6df1e6c3_EOF' + cat << 'GH_AW_PROMPT_212da97049a185e7_EOF' {{#runtime-import .github/workflows/release-changelog.md}} - GH_AW_PROMPT_41d0179c6df1e6c3_EOF + GH_AW_PROMPT_212da97049a185e7_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -446,9 +446,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_185484bc160cdce2_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_e7fde5df9748c1e1_EOF' {"create_pull_request":{"draft":false,"labels":["automation","changelog"],"max":1,"max_patch_files":100,"max_patch_size":1024,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md","CLAUDE.md","GEMINI.md"],"title_prefix":"[changelog] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"update_release":{"max":1}} - GH_AW_SAFE_OUTPUTS_CONFIG_185484bc160cdce2_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_e7fde5df9748c1e1_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -687,7 +687,7 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_d0d73da3b3e2991f_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_a487310af394adf5_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -728,7 +728,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_d0d73da3b3e2991f_EOF + GH_AW_MCP_CONFIG_a487310af394adf5_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true diff --git a/.github/workflows/release-changelog.md b/.github/workflows/release-changelog.md index aba79d6f5..d82365ac5 100644 --- a/.github/workflows/release-changelog.md +++ b/.github/workflows/release-changelog.md @@ -4,7 +4,7 @@ on: workflow_dispatch: inputs: tag: - description: "Release tag to generate changelog for (e.g., v0.1.30)" + description: "Release tag to generate changelog for (e.g., v0.1.30, /v1.0.0)" required: true type: string permissions: @@ -54,8 +54,9 @@ Use the GitHub API to fetch the release corresponding to `${{ github.event.input 2. The **new version** is the release tag: `${{ github.event.inputs.tag }}` 3. Fetch the release metadata to determine if this is a **stable** or **prerelease** release. 4. Determine the **previous version** to diff against: - - **For stable releases**: find the previous **stable** release (skip prereleases). Check `CHANGELOG.md` for the most recent version heading (`## [vX.Y.Z](...)`), or fall back to listing releases via the API. This means stable changelogs include ALL changes since the last stable release, even if some were already mentioned in prerelease notes. - - **For prerelease releases**: find the most recent release of **any kind** (stable or prerelease) that precedes this one. This way prerelease notes only cover what's new since the last release. + - **Scoped tags**: If the tag has a language prefix (e.g., `java/v1.0.0` or `rust/v0.2.0`), the previous tag must use the **same prefix**. List tags matching that prefix (e.g., `java/v*` or `rust/v*`) sorted by version and pick the one immediately before the current tag. Only compare within the same scope. + - **For stable releases**: find the previous **stable** release (skip prereleases). Check `CHANGELOG.md` for the most recent version heading matching this scope (`## [vX.Y.Z](...)` for unscoped, `## [java/vX.Y.Z](...)` for Java, `## [rust/vX.Y.Z](...)` for Rust), or fall back to listing releases via the API. This means stable changelogs include ALL changes since the last stable release, even if some were already mentioned in prerelease notes. + - **For prerelease releases**: find the most recent release of **any kind** (stable or prerelease) that precedes this one within the same tag scope. This way prerelease notes only cover what's new since the last release. 5. If no previous release exists at all, use the first commit in the repo as the starting point. 6. After identifying the range, verify it by listing the commits in `PREVIOUS_TAG..NEW_TAG`. If the local result still looks suspiciously small or inconsistent, do **not** proceed based on local git alone — use the GitHub tools as the source of truth for the commits and PRs in the release. @@ -65,8 +66,9 @@ Use the GitHub API to fetch the release corresponding to `${{ github.event.input 2. Also list merged pull requests in that range. For each PR, note: - PR number and title - The PR author - - Which SDK(s) were affected (look for prefixes like `[C#]`, `[Python]`, `[Go]`, `[Node]` in the title, or infer from changed files) -3. Ignore: + - Which SDK(s) were affected (look for prefixes like `[C#]`, `[Python]`, `[Go]`, `[Node]`, `[Java]`, `[Rust]` in the title, or infer from changed files) +3. **For scoped tags** (e.g., `java/v*`, `rust/v*`): only include changes that touch the corresponding language directory (`java/`, `rust/`). Ignore changes to other languages unless they directly affect the scoped SDK. +4. Ignore: - Dependabot/bot PRs that only bump internal dependencies (like `Update @github/copilot to ...`) unless they bring user-facing changes - Merge commits with no meaningful content - Preview/prerelease-only changes that were already documented @@ -87,9 +89,9 @@ Additionally, identify **new contributors** — anyone whose first merged PR to **Skip this step entirely for prerelease releases.** 1. Read the current `CHANGELOG.md` file. -2. Add the new version entry **at the top** of the file, right after the title/header. +2. Add the new version entry **at the top** of the file, right after the title/header. Use the **full tag** as the version in the heading — e.g., `## [v0.2.3](...)` for unscoped tags, `## [java/v1.0.0](...)` for Java-scoped tags, `## [rust/v0.2.3](...)` for Rust-scoped tags. -**Format for each highlighted feature** — use an `### Feature:` or `### Fix:` heading, a 1-2 sentence description explaining what it does and why it matters, and at least one short code snippet (max 3 lines). Focus on **TypeScript** and **C#** as the primary languages. Only show Go/Python when giving a list of one-liner equivalents across all languages, or when their usage pattern is meaningfully different. +**Format for each highlighted feature** — use an `### Feature:` or `### Fix:` heading, a 1-2 sentence description explaining what it does and why it matters, and at least one short code snippet (max 3 lines). For unscoped releases, focus on **TypeScript** and **C#** as the primary languages; only show Go/Python when giving a list of one-liner equivalents across all languages, or when their usage pattern is meaningfully different. For **scoped releases** (e.g., `java/v*`), show code snippets in the scoped language only (e.g., Java for `java/v*`, Rust for `rust/v*`). **Format for other changes** — a single `### Other changes` section with a flat bulleted list. Each bullet has a lowercase prefix (`feature:`, `bugfix:`, `improvement:`) and a one-line description linking to the PR. **However, if there are no highlighted features above it, omit the `### Other changes` heading entirely** — just list the bullets directly under the version heading. @@ -107,6 +109,7 @@ Additionally, identify **new contributors** — anyone whose first merged PR to **Skip this step entirely for prerelease releases.** Use the `create-pull-request` output to submit your changes. The PR should: + - Have a clear title like "Add changelog for vX.Y.Z" - Include a brief body summarizing the number of changes @@ -160,6 +163,7 @@ While `session.rpc.models.setModel()` already worked, there is now a convenience ```` **Key rules visible in the example:** + - Highlighted features get their own `### Feature:` heading, a short description, and code snippets - Code snippets are TypeScript and C# primarily; Go/Python only when listing one-liner equivalents or when meaningfully different - The `### Other changes` section is a flat bulleted list with lowercase `bugfix:` / `feature:` / `improvement:` prefixes diff --git a/java/CHANGELOG.md b/java/CHANGELOG.md deleted file mode 100644 index 8e174dd21..000000000 --- a/java/CHANGELOG.md +++ /dev/null @@ -1,535 +0,0 @@ -# Changelog - -All notable changes to the GitHub Copilot SDK for Java will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). - -> Note: This file is automatically modified by scripts and coding agents. Do not change it manually. - -## [Unreleased] - -> **Reference implementation sync:** [`github/copilot-sdk@e20f5be`](https://github.com/github/copilot-sdk/commit/e20f5bef125860accb30c60d1b35109371a77f16) - -## [1.0.0-beta-java.4] - 2026-05-16 - -> **Reference implementation sync:** [`github/copilot-sdk@e20f5be`](https://github.com/github/copilot-sdk/commit/e20f5bef125860accb30c60d1b35109371a77f16) -## [1.0.0-beta-java.3] - 2026-05-11 - -> **Reference implementation sync:** [`github/copilot-sdk@4a0437b`](https://github.com/github/copilot-sdk/commit/4a0437bb03a0b60a1867f14ae8e3faf053afa5aa) -## [1.0.0-beta-java.2] - 2026-05-08 - -> **Reference implementation sync:** [`github/copilot-sdk@066a69c`](https://github.com/github/copilot-sdk/commit/066a69c1e849adf1bd98564ab1b52316ec471182) -## [1.0.0-beta-java.1] - 2026-05-05 - -> **Reference implementation sync:** [`github/copilot-sdk@c063458`](https://github.com/github/copilot-sdk/commit/c063458ecc3d606766f04cf203b11b08de672cc8) -## [0.3.0-java.2] - 2026-04-26 - -> **Reference implementation sync:** [`github/copilot-sdk@dd2dcbc`](https://github.com/github/copilot-sdk/commit/dd2dcbc439256acfb9feb2cff07c0b9c820091b8) -## [0.3.0-java-preview.1] - 2026-04-21 - -> **Reference implementation sync:** [`github/copilot-sdk@922959f`](https://github.com/github/copilot-sdk/commit/922959f4a7b83509c3620d4881733c6c5677f00c) -## [0.3.0-java-preview.0] - 2026-04-21 - -> **Reference implementation sync:** [`github/copilot-sdk@c3fa6cb`](https://github.com/github/copilot-sdk/commit/c3fa6cbfb83d4a20b7912b1a17013d48f5a277a1) -## [0.2.2-java.1] - 2026-04-07 - -> **Reference implementation sync:** [`github/copilot-sdk@c3fa6cb`](https://github.com/github/copilot-sdk/commit/c3fa6cbfb83d4a20b7912b1a17013d48f5a277a1) -### Added - -- Slash commands — register `/command` handlers invoked from the CLI TUI via `SessionConfig.setCommands()` (reference implementation: [`f7fd757`](https://github.com/github/copilot-sdk/commit/f7fd757)) -- `CommandDefinition`, `CommandContext`, `CommandHandler`, `CommandWireDefinition` — types for defining and handling slash commands -- `CommandExecuteEvent` — event dispatched when a registered slash command is executed -- Elicitation (UI dialogs) — incoming handler via `SessionConfig.setOnElicitationRequest()` and outgoing convenience methods via `session.getUi()` (reference implementation: [`f7fd757`](https://github.com/github/copilot-sdk/commit/f7fd757)) -- `ElicitationContext`, `ElicitationHandler`, `ElicitationParams`, `ElicitationResult`, `ElicitationResultAction`, `ElicitationSchema`, `InputOptions` — types for elicitation -- `ElicitationRequestedEvent` — event dispatched when an elicitation request is received -- `SessionUiApi` — convenience API on `session.getUi()` for `confirm()`, `select()`, `input()`, and `elicitation()` calls -- `SessionCapabilities` and `SessionUiCapabilities` — session capability reporting populated from create/resume response -- `CapabilitiesChangedEvent` — event dispatched when session capabilities are updated -- `CopilotClient.getSessionMetadata(String)` — O(1) session lookup by ID -- `GetSessionMetadataResponse` — response type for `getSessionMetadata` - -### Fixed - -- Permission events already resolved by a pre-hook now short-circuit before invoking the client-side handler -- `SessionUiApi` Javadoc now uses valid Java null-check syntax instead of `?.` -- README updated to say "GitHub Copilot CLI 1.0.17" instead of "GitHub Copilot 1.0.17" - -## [0.2.1-java.1] - 2026-04-02 - -> **Reference implementation sync:** [`github/copilot-sdk@4088739`](https://github.com/github/copilot-sdk/commit/40887393a9e687dacc141a645799441b0313ff15) -## [0.2.1-java.0] - 2026-03-26 - -> **Reference implementation sync:** [`github/copilot-sdk@4088739`](https://github.com/github/copilot-sdk/commit/40887393a9e687dacc141a645799441b0313ff15) -### Added - -- `UnknownSessionEvent` — forward-compatible placeholder for event types not yet known to the SDK; unknown events are now dispatched to handlers instead of being silently dropped (reference implementation: [`d82fd62`](https://github.com/github/copilot-sdk/commit/d82fd62)) -- `PermissionRequestResultKind.NO_RESULT` — new constant that signals the handler intentionally abstains from answering a permission request, leaving it unanswered for another client (reference implementation: [`df59a0e`](https://github.com/github/copilot-sdk/commit/df59a0e)) -- `ToolDefinition.skipPermission` field and `ToolDefinition.createSkipPermission()` factory — marks a tool to skip the permission prompt (reference implementation: [`10c4d02`](https://github.com/github/copilot-sdk/commit/10c4d02)) -- `SystemMessageMode.CUSTOMIZE` — new enum value for fine-grained system prompt customization (reference implementation: [`005b780`](https://github.com/github/copilot-sdk/commit/005b780)) -- `SectionOverrideAction` enum — specifies the operation on a system prompt section (replace, remove, append, prepend, transform) (reference implementation: [`005b780`](https://github.com/github/copilot-sdk/commit/005b780)) -- `SectionOverride` class — describes how one section of the system prompt should be modified, with optional transform callback (reference implementation: [`005b780`](https://github.com/github/copilot-sdk/commit/005b780)) -- `SystemPromptSections` constants — well-known section identifier strings for use with CUSTOMIZE mode (reference implementation: [`005b780`](https://github.com/github/copilot-sdk/commit/005b780)) -- `SystemMessageConfig.setSections(Map)` — section-level overrides for CUSTOMIZE mode (reference implementation: [`005b780`](https://github.com/github/copilot-sdk/commit/005b780)) -- `systemMessage.transform` RPC handler — the SDK now registers a handler that invokes transform callbacks registered in the session config (reference implementation: [`005b780`](https://github.com/github/copilot-sdk/commit/005b780)) -- `CopilotSession.setModel(String, String)` — new overload that accepts an optional reasoning effort level (reference implementation: [`ea90f07`](https://github.com/github/copilot-sdk/commit/ea90f07)) -- `CopilotSession.log(String, String, Boolean, String)` — new overload with an optional `url` parameter (minor addition) -- `BlobAttachment` class — inline base64-encoded binary attachment for messages (e.g., images) (reference implementation: [`698b259`](https://github.com/github/copilot-sdk/commit/698b259)) -- `MessageAttachment` sealed interface — type-safe base for all attachment types (`Attachment`, `BlobAttachment`), with Jackson polymorphic serialization support -- `TelemetryConfig` class — OpenTelemetry configuration for the CLI server; set on `CopilotClientOptions.setTelemetry()` (reference implementation: [`f2d21a0`](https://github.com/github/copilot-sdk/commit/f2d21a0)) -- `CopilotClientOptions.setTelemetry(TelemetryConfig)` — enables OpenTelemetry instrumentation in the CLI server (reference implementation: [`f2d21a0`](https://github.com/github/copilot-sdk/commit/f2d21a0)) - -### Changed - -- `Attachment` record now implements `MessageAttachment` sealed interface -- `BlobAttachment` class now implements `MessageAttachment` sealed interface and is `final` -- `MessageOptions.setAttachments(List)` — parameter type changed from `List` to `List` to support both `Attachment` and `BlobAttachment` in the same list with full compile-time safety -- `SendMessageRequest.setAttachments(List)` — matching change for the internal request type - -### Deprecated - -- `CopilotClientOptions.setAutoRestart(boolean)` — this option has no effect and will be removed in a future release - -## [0.1.32-java.0] - 2026-03-17 - -> **Reference implementation sync:** [`github/copilot-sdk@062b61c`](https://github.com/github/copilot-sdk/commit/062b61c8aa63b9b5d45fa1d7b01723e6660ffa83) -## [1.0.11] - 2026-03-12 - -> **Reference implementation sync:** [`github/copilot-sdk@062b61c`](https://github.com/github/copilot-sdk/commit/062b61c8aa63b9b5d45fa1d7b01723e6660ffa83) -### Added - -- `CopilotClientOptions.setOnListModels(Supplier>>)` — custom handler for `listModels()` used in BYOK mode to return models from a custom provider instead of querying the CLI (reference implementation: [`e478657`](https://github.com/github/copilot-sdk/commit/e478657)) -- `SessionConfig.setAgent(String)` — pre-selects a custom agent by name when creating a session (reference implementation: [`7766b1a`](https://github.com/github/copilot-sdk/commit/7766b1a)) -- `ResumeSessionConfig.setAgent(String)` — pre-selects a custom agent by name when resuming a session (reference implementation: [`7766b1a`](https://github.com/github/copilot-sdk/commit/7766b1a)) -- `SessionConfig.setOnEvent(Consumer)` — registers an event handler before the `session.create` RPC is issued, ensuring no early events are missed (reference implementation: [`4125fe7`](https://github.com/github/copilot-sdk/commit/4125fe7)) -- `ResumeSessionConfig.setOnEvent(Consumer)` — registers an event handler before the `session.resume` RPC is issued (reference implementation: [`4125fe7`](https://github.com/github/copilot-sdk/commit/4125fe7)) -- New broadcast session event types (protocol v3): `ExternalToolRequestedEvent` (`external_tool.requested`), `ExternalToolCompletedEvent` (`external_tool.completed`), `PermissionRequestedEvent` (`permission.requested`), `PermissionCompletedEvent` (`permission.completed`), `CommandQueuedEvent` (`command.queued`), `CommandCompletedEvent` (`command.completed`), `ExitPlanModeRequestedEvent` (`exit_plan_mode.requested`), `ExitPlanModeCompletedEvent` (`exit_plan_mode.completed`), `SystemNotificationEvent` (`system.notification`) (reference implementation: [`1653812`](https://github.com/github/copilot-sdk/commit/1653812), [`396e8b3`](https://github.com/github/copilot-sdk/commit/396e8b3)) -- `CopilotSession.log(String)` and `CopilotSession.log(String, String, Boolean)` — log a message to the session timeline (reference implementation: [`4125fe7`](https://github.com/github/copilot-sdk/commit/4125fe7)) - -### Changed - -- **Protocol version bumped to v3.** The SDK now supports CLI servers running v2 or v3 (backward-compatible range). Sessions are now registered in the client's session map *before* the `session.create`/`session.resume` RPC is issued, ensuring broadcast events emitted immediately on session start are never dropped (reference implementation: [`4125fe7`](https://github.com/github/copilot-sdk/commit/4125fe7), [`1653812`](https://github.com/github/copilot-sdk/commit/1653812)) -- In protocol v3, tool calls and permission requests that have a registered handler are now handled automatically via `ExternalToolRequestedEvent` and `PermissionRequestedEvent` broadcast events; results are sent back via `session.tools.handlePendingToolCall` and `session.permissions.handlePendingPermissionRequest` RPC calls (reference implementation: [`1653812`](https://github.com/github/copilot-sdk/commit/1653812)) - -## [1.0.10] - 2026-03-03 - -> **Reference implementation sync:** [`github/copilot-sdk@dcd86c1`](https://github.com/github/copilot-sdk/commit/dcd86c189501ce1b46b787ca60d90f3f315f3079) -### Added - -- `CopilotSession.setModel(String)` — changes the model for an existing session mid-conversation; the new model takes effect for the next message, and conversation history is preserved (reference implementation: [`bd98e3a`](https://github.com/github/copilot-sdk/commit/bd98e3a)) -- `ToolDefinition.createOverride(String, String, Map, ToolHandler)` — creates a tool definition that overrides a built-in CLI tool with the same name (reference implementation: [`f843c80`](https://github.com/github/copilot-sdk/commit/f843c80)) -- `ToolDefinition` record now includes `overridesBuiltInTool` field; when `true`, signals to the CLI that the custom tool intentionally replaces a built-in (reference implementation: [`f843c80`](https://github.com/github/copilot-sdk/commit/f843c80)) -- `CopilotSession.listAgents()` — lists custom agents available for selection (reference implementation: [`9d998fb`](https://github.com/github/copilot-sdk/commit/9d998fb)) -- `CopilotSession.getCurrentAgent()` — gets the currently selected custom agent (reference implementation: [`9d998fb`](https://github.com/github/copilot-sdk/commit/9d998fb)) -- `CopilotSession.selectAgent(String)` — selects a custom agent for the session (reference implementation: [`9d998fb`](https://github.com/github/copilot-sdk/commit/9d998fb)) -- `CopilotSession.deselectAgent()` — deselects the current custom agent (reference implementation: [`9d998fb`](https://github.com/github/copilot-sdk/commit/9d998fb)) -- `CopilotSession.compact()` — triggers immediate session context compaction (reference implementation: [`9d998fb`](https://github.com/github/copilot-sdk/commit/9d998fb)) -- `AgentInfo` — new JSON type representing a custom agent with `name`, `displayName`, and `description` (reference implementation: [`9d998fb`](https://github.com/github/copilot-sdk/commit/9d998fb)) -- New event types: `SessionTaskCompleteEvent` (`session.task_complete`), `AssistantStreamingDeltaEvent` (`assistant.streaming_delta`), `SubagentDeselectedEvent` (`subagent.deselected`) (reference implementation: various commits) -- `AssistantTurnStartEvent` data now includes `interactionId` field -- `AssistantMessageEvent` data now includes `interactionId` field -- `ToolExecutionCompleteEvent` data now includes `model` and `interactionId` fields -- `SkillInvokedEvent` data now includes `pluginName` and `pluginVersion` fields -- `AssistantUsageEvent` data now includes `copilotUsage` field with `CopilotUsage` and `TokenDetails` nested types -- E2E tests for custom tool permission approval and denial flows (reference implementation: [`388f2f3`](https://github.com/github/copilot-sdk/commit/388f2f3)) - -### Changed - -- **Breaking:** `createSession(SessionConfig)` now requires a non-null `onPermissionRequest` handler; throws `IllegalArgumentException` if not provided (reference implementation: [`279f6c4`](https://github.com/github/copilot-sdk/commit/279f6c4)) -- **Breaking:** `resumeSession(String, ResumeSessionConfig)` now requires a non-null `onPermissionRequest` handler; throws `IllegalArgumentException` if not provided (reference implementation: [`279f6c4`](https://github.com/github/copilot-sdk/commit/279f6c4)) -- **Breaking:** The no-arg `createSession()` and `resumeSession(String)` overloads were removed (reference implementation: [`279f6c4`](https://github.com/github/copilot-sdk/commit/279f6c4)) -- `AssistantMessageDeltaEvent` data: `totalResponseSizeBytes` field moved to new `AssistantStreamingDeltaEvent` (reference implementation: various) - -### Fixed - -- Permission checks now also apply to SDK-registered custom tools, invoking the `onPermissionRequest` handler with `kind="custom-tool"` before executing tools (reference implementation: [`388f2f3`](https://github.com/github/copilot-sdk/commit/388f2f3)) - -## [1.0.9] - 2026-02-16 - -> **Reference implementation sync:** [`github/copilot-sdk@e40d57c`](https://github.com/github/copilot-sdk/commit/e40d57c86e18b495722adbf42045288c03924342) -### Added - -#### Cookbook with Practical Recipes - -Added a comprehensive cookbook with 5 practical recipes demonstrating common SDK usage patterns. All examples are JBang-compatible and can be run directly without a full Maven project setup. - -**Recipes:** -- **Error Handling** - Connection failures, timeouts, cleanup patterns, tool errors -- **Multiple Sessions** - Parallel conversations, custom session IDs, lifecycle management -- **Managing Local Files** - AI-powered file organization with grouping strategies -- **PR Visualization** - Interactive CLI tool for analyzing PR age distribution via GitHub MCP Server -- **Persisting Sessions** - Save and resume conversations across restarts - -**Location:** `src/site/markdown/cookbook/` - -**Usage:** -```bash -jbang BasicErrorHandling.java -jbang MultipleSessions.java -jbang PRVisualization.java github/copilot-sdk -``` - -Each recipe includes JBang prerequisites, usage instructions, and best practices. - -#### Session Context and Filtering - -Added session context tracking and filtering capabilities to help manage multiple Copilot sessions across different repositories and working directories. - -**New Classes:** -- `SessionContext` - Represents working directory context (cwd, gitRoot, repository, branch) with fluent setters -- `SessionListFilter` - Filter sessions by context fields (extends SessionContext) -- `SessionContextChangedEvent` - Event fired when working directory context changes between turns - -**Updated APIs:** -- `SessionMetadata.getContext()` - Returns optional context information for persisted sessions -- `CopilotClient.listSessions(SessionListFilter)` - New overload to filter sessions by context criteria - -**Example:** -```java -// List sessions for a specific repository -var filter = new SessionListFilter() - .setRepository("owner/repo") - .setBranch("main"); -var sessions = client.listSessions(filter).get(); - -// Access context information -for (var session : sessions) { - var ctx = session.getContext(); - if (ctx != null) { - System.out.println("CWD: " + ctx.getCwd()); - System.out.println("Repo: " + ctx.getRepository()); - } -} - -// Listen for context changes -session.on(SessionContextChangedEvent.class, event -> { - SessionContext newContext = event.getData(); - System.out.println("Working directory changed to: " + newContext.getCwd()); -}); -``` - -**Requirements:** -- GitHub Copilot CLI 0.0.409 or later - -## [1.0.8] - 2026-02-08 - -> **Reference implementation sync:** [`github/copilot-sdk@05e3c46`](https://github.com/github/copilot-sdk/commit/05e3c46c8c23130c9c064dc43d00ec78f7a75eab) - -### Added - -#### ResumeSessionConfig Parity with SessionConfig -Added missing options to `ResumeSessionConfig` for parity with `SessionConfig` when resuming sessions. You can now change the model, system message, tool filters, and other settings when resuming: - -- `model` - Change the AI model when resuming -- `systemMessage` - Override or extend the system prompt -- `availableTools` - Restrict which tools are available -- `excludedTools` - Disable specific tools -- `configDir` - Override configuration directory -- `infiniteSessions` - Configure infinite session behavior - -**Example:** -```java -var config = new ResumeSessionConfig() - .setModel("claude-sonnet-4") - .setReasoningEffort("high") - .setSystemMessage(new SystemMessageConfig() - .setMode(SystemMessageMode.APPEND) - .setContent("Focus on security.")); - -var session = client.resumeSession(sessionId, config).get(); -``` - -#### EventErrorHandler for Custom Error Handling -Added `EventErrorHandler` interface for custom handling of exceptions thrown by event handlers. Set via `session.setEventErrorHandler()` to receive the event and exception when a handler fails. - -```java -session.setEventErrorHandler((event, exception) -> { - logger.error("Handler failed for event: " + event.getType(), exception); -}); -``` - -#### EventErrorPolicy for Dispatch Control -Added `EventErrorPolicy` enum to control whether event dispatch continues or stops when a handler throws an exception. Errors are always logged at `WARNING` level. The default policy is `PROPAGATE_AND_LOG_ERRORS` which stops dispatch on the first error. Set `SUPPRESS_AND_LOG_ERRORS` to continue dispatching despite errors: - -```java -session.setEventErrorPolicy(EventErrorPolicy.SUPPRESS_AND_LOG_ERRORS); -``` - -The `EventErrorHandler` is always invoked regardless of the policy. - -#### Type-Safe Event Handlers -Promoted type-safe `on(Class, Consumer)` event handlers as the primary API. Handlers now receive strongly-typed events instead of raw `AbstractSessionEvent`. - -```java -session.on(AssistantMessageEvent.class, msg -> { - System.out.println(msg.getData().getContent()); -}); -``` - -#### SpotBugs Static Analysis -Integrated SpotBugs for static code analysis with exclusion filters for `events` and `json` packages. - -### Changed - -- **Copilot CLI**: Minimum version updated to **0.0.405** -- **CopilotClient**: Made `final` to prevent Finalizer attacks (security hardening) -- **JBang Example**: Refactored `jbang-example.java` with streamlined session creation and usage metrics display -- **Code Style**: Use `var` for local variable type inference throughout the codebase - -### Fixed - -- **SpotBugs OS_OPEN_STREAM**: Wrap `BufferedReader` in try-with-resources to prevent resource leaks -- **SpotBugs REC_CATCH_EXCEPTION**: Narrow exception catch in `JsonRpcClient.handleMessage()` -- **SpotBugs DM_DEFAULT_ENCODING**: Add explicit UTF-8 charset to `InputStreamReader` -- **SpotBugs EI_EXPOSE_REP**: Add defensive copies to collection getters in events and JSON packages - -## [1.0.7] - 2026-02-05 - -### Added - -#### Session Lifecycle Hooks -Extended the hooks system with three new hook types for session lifecycle control: -- **`onSessionStart`** - Called when a session starts (new or resumed) -- **`onSessionEnd`** - Called when a session ends -- **`onUserPromptSubmitted`** - Called when the user submits a prompt - -New types: -- `SessionStartHandler`, `SessionStartHookInput`, `SessionStartHookOutput` -- `SessionEndHandler`, `SessionEndHookInput`, `SessionEndHookOutput` -- `UserPromptSubmittedHandler`, `UserPromptSubmittedHookInput`, `UserPromptSubmittedHookOutput` - -#### Session Lifecycle Events (Client-Level) -Added client-level lifecycle event subscriptions: -- `client.onLifecycle(handler)` - Subscribe to all session lifecycle events -- `client.onLifecycle(eventType, handler)` - Subscribe to specific event types -- `SessionLifecycleEventTypes.CREATED`, `DELETED`, `UPDATED`, `FOREGROUND`, `BACKGROUND` - -New types: `SessionLifecycleEvent`, `SessionLifecycleEventMetadata`, `SessionLifecycleHandler` - -#### Foreground Session Control (TUI+Server Mode) -For servers running with `--ui-server`: -- `client.getForegroundSessionId()` - Get the session displayed in TUI -- `client.setForegroundSessionId(sessionId)` - Switch TUI display to a session - -New types: `GetForegroundSessionResponse`, `SetForegroundSessionResponse` - -#### New Event Types -- **`SessionShutdownEvent`** - Emitted when session is shutting down, includes reason and exit code -- **`SkillInvokedEvent`** - Emitted when a skill is invoked, includes skill name and context - -#### Extended Event Data -- `AssistantMessageEvent.Data` - Added `id`, `isLastReply`, `thinkingContent` fields -- `AssistantUsageEvent.Data` - Added `outputReasoningTokens` field -- `SessionCompactionCompleteEvent.Data` - Added `success`, `messagesRemoved`, `tokensRemoved` fields -- `SessionErrorEvent.Data` - Extended with additional error context - -#### Documentation -- New **[hooks.md](src/site/markdown/hooks.md)** - Comprehensive guide covering all 5 session hooks with examples for security gates, logging, result enrichment, and lifecycle management -- Expanded **[documentation.md](src/site/markdown/documentation.md)** with all 33 event types, `getMessages()`, `abort()`, and custom timeout examples -- Enhanced **[advanced.md](src/site/markdown/advanced.md)** with session hooks, lifecycle events, and foreground session control -- Added **[.github/copilot-instructions.md](.github/copilot-instructions.md)** for AI assistants - -#### Testing -- `SessionEventParserTest` - 850+ lines of unit tests for JSON event deserialization -- `SessionEventsE2ETest` - End-to-end tests for session event lifecycle -- `ErrorHandlingTest` - Tests for error handling scenarios -- Enhanced `E2ETestContext` with snapshot validation and expected prompt logging -- Added logging configuration (`logging.properties`) - -#### Build & CI -- JaCoCo 0.8.14 for test coverage reporting -- Coverage reports generated at `target/site/jacoco-coverage/` -- New test report action at `.github/actions/test-report/` -- JaCoCo coverage summary in workflow summary -- Coverage report artifact upload - -### Changed - -- **Copilot CLI**: Minimum version updated from 0.0.400 to **0.0.404** -- Refactored `ProcessInfo` and `Connection` to use records -- Extended `SessionHooks` to support 5 hook types (was 2) -- Renamed test methods to match snapshot naming conventions with Javadoc - -### Fixed - -- Improved timeout exception handling with detailed logging -- Test infrastructure improvements for proxy resilience - -## [1.0.6] - 2026-02-02 - -### Added - -- Auth options for BYOK configuration (`authType`, `apiKey`, `organizationId`, `endpoint`) -- Reasoning effort configuration (`reasoningEffort` in session config) -- User input handler for freeform user prompts (`UserInputHandler`, `UserInputRequest`, `UserInputResponse`) -- Pre-tool use and post-tool use hooks (`PreToolUseHandler`, `PostToolUseHandler`) -- VSCode launch and debug configurations -- Logging configuration for test debugging - -### Changed - -- Enhanced permission request handling with graceful error recovery -- Updated test harness integration to clone from reference implementation SDK -- Improved logging for session events and user input requests - -### Fixed - -- Non-null answer enforcement in user input responses for CLI compatibility -- Permission handler error handling improvements - -## [1.0.5] - 2026-01-29 - -### Added - -- Skills configuration: `skillDirectories` and `disabledSkills` in `SessionConfig` -- Skill events handling (`SkillInvokedEvent`) -- Javadoc verification step in build workflow -- Deploy-site job for automatic documentation deployment after releases - -### Changed - -- Merged reference implementation SDK changes (commit 87ff5510) -- Added agentic-merge-reference-impl Claude skill for tracking reference implementation changes - -### Fixed - -- Resume session handling to keep first client alive -- Build workflow updated to use `test-compile` instead of `compile` -- NPM dependency installation in CI workflow -- Enhanced error handling in permission request processing -- Checkstyle and Maven Resources Plugin version updates -- Test harness CLI installation to match reference implementation version - -## [1.0.4] - 2026-01-27 - -### Added - -- Advanced usage documentation with comprehensive examples -- Getting started guide with Maven and JBang instructions -- Package-info.java files for `com.github.copilot.sdk`, `events`, and `json` packages -- `@since` annotations on all public classes -- Versioned documentation with version selector on GitHub Pages -- Maven resources plugin for site markdown filtering - -### Changed - -- Refactored tool argument handling for improved type safety -- Optimized event listener registration in examples -- Enhanced site navigation with documentation links -- Merged reference implementation SDK changes from commit f902b76 - -### Fixed - -- BufferedReader replaced with BufferedInputStream for accurate JSON-RPC byte reading -- Timeout thread now uses daemon thread to prevent JVM exit blocking -- XML root element corrected from `` to `` in site.xml -- Badge titles in README for consistency - -## [1.0.3] - 2026-01-26 - -### Added - -- MCP Servers documentation and integration examples -- Infinite sessions documentation section -- Versioned documentation template with version selector -- Guidelines for porting reference implementation SDK changes to Java -- Configuration for automatically generated release notes - -### Changed - -- Renamed and retitled GitHub Actions workflows for clarity -- Improved gh-pages initialization and remote setup - -### Fixed - -- Documentation navigation to include MCP Servers section -- GitHub Pages deployment workflow to use correct branch -- Enhanced version handling in documentation build steps -- Rollback mechanism added for release failures - -## [1.0.2] - 2026-01-25 - -### Added - -- Infinite sessions support with `InfiniteSessionConfig` and workspace persistence -- GitHub Actions workflow for GitHub Pages deployment -- Daily schedule trigger for SDK E2E tests -- Checkstyle configuration and Maven integration - -### Changed - -- Updated GitHub Actions to latest action versions -- Enhanced Maven site deployment with documentation versioning -- Simplified GitHub release title naming convention - -### Fixed - -- Documentation links in site.xml and README for consistency -- Maven build step to include `clean` for fresh builds -- Image handling in README and site generation - -## [1.0.1] - 2026-01-22 - -### Added - -- Metadata APIs implementation -- Tool execution progress event (`ToolExecutionProgressEvent`) -- SDK protocol version 2 support -- Image in README for visual representation -- Detailed sections in README with usage examples -- Badges for build status, Maven Central, Java version, and license - -### Changed - -- Enhanced version handling in Maven release workflow -- Updated SCM connection URLs to use HTTPS - -### Fixed - -- GitHub release command version formatting and title -- Documentation commit messages to include version information -- JBang dependency declaration with correct group ID - -## [1.0.0] - 2026-01-21 - -### Added - -- Initial release of the GitHub Copilot SDK for Java -- Core classes: `CopilotClient`, `CopilotSession`, `JsonRpcClient` -- Session configuration with `SessionConfig` -- Custom tools with `ToolDefinition` and `ToolHandler` -- Event system with 30+ event types extending `AbstractSessionEvent` -- Permission handling with `PermissionHandler` -- BYOK (Bring Your Own Key) support with `ProviderConfig` -- MCP server integration via `McpServerConfig` -- System message customization with `SystemMessageConfig` -- File attachments support -- Streaming responses with delta events -- JBang example for quick testing -- GitHub Actions workflows for testing and Maven Central publishing -- Pre-commit hook for Spotless code formatting -- Comprehensive API documentation - -[Unreleased]: https://github.com/github/copilot-sdk-java/compare/v1.0.0-beta-java.4...HEAD -[1.0.0-beta-java.4]: https://github.com/github/copilot-sdk-java/compare/v1.0.0-beta-java.3...v1.0.0-beta-java.4 -[1.0.0-beta-java.3]: https://github.com/github/copilot-sdk-java/compare/v1.0.0-beta-java.2...v1.0.0-beta-java.3 -[1.0.0-beta-java.2]: https://github.com/github/copilot-sdk-java/compare/v1.0.0-beta-java.1...v1.0.0-beta-java.2 -[1.0.0-beta-java.1]: https://github.com/github/copilot-sdk-java/compare/v0.3.0-java.2...v1.0.0-beta-java.1 -[0.3.0-java.2]: https://github.com/github/copilot-sdk-java/compare/v0.2.2-java.1...v0.3.0-java.2 -[0.3.0-java-preview.1]: https://github.com/github/copilot-sdk-java/compare/v0.2.2-java.1...v0.3.0-java-preview.1 -[0.3.0-java-preview.0]: https://github.com/github/copilot-sdk-java/compare/v0.2.2-java.1...v0.3.0-java-preview.0 -[0.2.2-java.1]: https://github.com/github/copilot-sdk-java/compare/v0.2.1-java.1...v0.2.2-java.1 -[0.2.1-java.1]: https://github.com/github/copilot-sdk-java/compare/v0.2.1-java.0...v0.2.1-java.1 -[0.2.1-java.0]: https://github.com/github/copilot-sdk-java/compare/v0.1.32-java.0...v0.2.1-java.0 -[0.1.32-java.0]: https://github.com/github/copilot-sdk-java/compare/v1.0.11...v0.1.32-java.0 -[1.0.11]: https://github.com/github/copilot-sdk-java/compare/v1.0.10...v1.0.11 -[1.0.10]: https://github.com/github/copilot-sdk-java/compare/v1.0.9...v1.0.10 -[1.0.9]: https://github.com/github/copilot-sdk-java/compare/v1.0.8...v1.0.9 -[1.0.8]: https://github.com/github/copilot-sdk-java/compare/v1.0.7...v1.0.8 -[1.0.7]: https://github.com/github/copilot-sdk-java/compare/v1.0.6...v1.0.7 -[1.0.6]: https://github.com/github/copilot-sdk-java/compare/v1.0.5...v1.0.6 -[1.0.5]: https://github.com/github/copilot-sdk-java/compare/v1.0.4...v1.0.5 -[1.0.4]: https://github.com/github/copilot-sdk-java/compare/v1.0.3...v1.0.4 -[1.0.3]: https://github.com/github/copilot-sdk-java/compare/v1.0.2...v1.0.3 -[1.0.2]: https://github.com/github/copilot-sdk-java/compare/v1.0.1...v1.0.2 -[1.0.1]: https://github.com/github/copilot-sdk-java/compare/1.0.0...v1.0.1 -[1.0.0]: https://github.com/github/copilot-sdk-java/releases/tag/1.0.0 From 728a54a172b699a149c6095851d426fdf92dee47 Mon Sep 17 00:00:00 2001 From: Ed Burns Date: Fri, 22 May 2026 11:17:43 -0700 Subject: [PATCH 3/3] Recompile workflows --- .github/workflows/release-changelog.lock.yml | 32 ++++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/release-changelog.lock.yml b/.github/workflows/release-changelog.lock.yml index 473a5b609..98cf18dc3 100644 --- a/.github/workflows/release-changelog.lock.yml +++ b/.github/workflows/release-changelog.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"dbed522073916e78c89a833a04d5c3327a72accc607e97243b91b7da11c88192","compiler_version":"v0.74.4","strict":true,"agent_id":"copilot"} +# gh-aw-metadata: {"schema_version":"v3","frontmatter_hash":"f56148e477b1349cf894dd5ee148dae8af3a90ab64cf708a41697d2c13b2da4b","compiler_version":"v0.74.4","strict":true,"agent_id":"copilot"} # gh-aw-manifest: {"version":1,"secrets":["COPILOT_GITHUB_TOKEN","GH_AW_CI_TRIGGER_TOKEN","GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GITHUB_TOKEN"],"actions":[{"repo":"actions/checkout","sha":"de0fac2e4500dabe0009e67214ff5f5447ce83dd","version":"v6.0.2"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"},{"repo":"github/gh-aw-actions/setup","sha":"d3abfe96a194bce3a523ed2093ddedd5704cdf62","version":"v0.74.4"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.25.46"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.25.46"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.25.46"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.9","digest":"sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.9@sha256:64828b42a4482f58fab16509d7f8f495a6d97c972a98a68aff20543531ac0388"},{"image":"ghcr.io/github/github-mcp-server:v1.0.4"},{"image":"node:lts-alpine","digest":"sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f","pinned_image":"node:lts-alpine@sha256:d1b3b4da11eefd5941e7f0b9cf17783fc99d9c6fc34884a665f40a06dbdfc94f"}]} # ___ _ _ # / _ \ | | (_) @@ -58,7 +58,7 @@ on: required: false type: string tag: - description: Release tag to generate changelog for (e.g., v0.1.30, java/v1.0.0, rust/v0.1.30) + description: Release tag to generate changelog for (e.g., v0.1.30, /v1.0.0) required: true type: string @@ -189,23 +189,23 @@ jobs: run: | bash "${RUNNER_TEMP}/gh-aw/actions/create_prompt_first.sh" { - cat << 'GH_AW_PROMPT_212da97049a185e7_EOF' + cat << 'GH_AW_PROMPT_8ca4e2fb6c3e0923_EOF' - GH_AW_PROMPT_212da97049a185e7_EOF + GH_AW_PROMPT_8ca4e2fb6c3e0923_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/xpia.md" cat "${RUNNER_TEMP}/gh-aw/prompts/temp_folder_prompt.md" cat "${RUNNER_TEMP}/gh-aw/prompts/markdown.md" cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_prompt.md" - cat << 'GH_AW_PROMPT_212da97049a185e7_EOF' + cat << 'GH_AW_PROMPT_8ca4e2fb6c3e0923_EOF' Tools: create_pull_request, update_release, missing_tool, missing_data, noop - GH_AW_PROMPT_212da97049a185e7_EOF + GH_AW_PROMPT_8ca4e2fb6c3e0923_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/safe_outputs_create_pull_request.md" - cat << 'GH_AW_PROMPT_212da97049a185e7_EOF' + cat << 'GH_AW_PROMPT_8ca4e2fb6c3e0923_EOF' - GH_AW_PROMPT_212da97049a185e7_EOF + GH_AW_PROMPT_8ca4e2fb6c3e0923_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/mcp_cli_tools_prompt.md" - cat << 'GH_AW_PROMPT_212da97049a185e7_EOF' + cat << 'GH_AW_PROMPT_8ca4e2fb6c3e0923_EOF' The following GitHub context information is available for this workflow: {{#if github.actor}} @@ -234,12 +234,12 @@ jobs: {{/if}} - GH_AW_PROMPT_212da97049a185e7_EOF + GH_AW_PROMPT_8ca4e2fb6c3e0923_EOF cat "${RUNNER_TEMP}/gh-aw/prompts/github_mcp_tools_with_safeoutputs_prompt.md" - cat << 'GH_AW_PROMPT_212da97049a185e7_EOF' + cat << 'GH_AW_PROMPT_8ca4e2fb6c3e0923_EOF' {{#runtime-import .github/workflows/release-changelog.md}} - GH_AW_PROMPT_212da97049a185e7_EOF + GH_AW_PROMPT_8ca4e2fb6c3e0923_EOF } > "$GH_AW_PROMPT" - name: Interpolate variables and render templates uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 @@ -446,9 +446,9 @@ jobs: mkdir -p "${RUNNER_TEMP}/gh-aw/safeoutputs" mkdir -p /tmp/gh-aw/safeoutputs mkdir -p /tmp/gh-aw/mcp-logs/safeoutputs - cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_e7fde5df9748c1e1_EOF' + cat > "${RUNNER_TEMP}/gh-aw/safeoutputs/config.json" << 'GH_AW_SAFE_OUTPUTS_CONFIG_6e92a7a47fdc567f_EOF' {"create_pull_request":{"draft":false,"labels":["automation","changelog"],"max":1,"max_patch_files":100,"max_patch_size":1024,"protect_top_level_dot_folders":true,"protected_files":["package.json","bun.lockb","bunfig.toml","deno.json","deno.jsonc","deno.lock","global.json","NuGet.Config","Directory.Packages.props","mix.exs","mix.lock","go.mod","go.sum","stack.yaml","stack.yaml.lock","pom.xml","build.gradle","build.gradle.kts","settings.gradle","settings.gradle.kts","gradle.properties","package-lock.json","yarn.lock","pnpm-lock.yaml","npm-shrinkwrap.json","requirements.txt","Pipfile","Pipfile.lock","pyproject.toml","setup.py","setup.cfg","Gemfile","Gemfile.lock","uv.lock","CODEOWNERS","DESIGN.md","README.md","CONTRIBUTING.md","CHANGELOG.md","SECURITY.md","CODE_OF_CONDUCT.md","AGENTS.md","CLAUDE.md","GEMINI.md"],"title_prefix":"[changelog] "},"create_report_incomplete_issue":{},"missing_data":{},"missing_tool":{},"noop":{"max":1,"report-as-issue":"true"},"report_incomplete":{},"update_release":{"max":1}} - GH_AW_SAFE_OUTPUTS_CONFIG_e7fde5df9748c1e1_EOF + GH_AW_SAFE_OUTPUTS_CONFIG_6e92a7a47fdc567f_EOF - name: Generate Safe Outputs Tools env: GH_AW_TOOLS_META_JSON: | @@ -687,7 +687,7 @@ jobs: mkdir -p /home/runner/.copilot GH_AW_NODE=$(which node 2>/dev/null || command -v node 2>/dev/null || echo node) - cat << GH_AW_MCP_CONFIG_a487310af394adf5_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" + cat << GH_AW_MCP_CONFIG_432de5cac6e63f96_EOF | "$GH_AW_NODE" "${RUNNER_TEMP}/gh-aw/actions/start_mcp_gateway.cjs" { "mcpServers": { "github": { @@ -728,7 +728,7 @@ jobs: "payloadDir": "${MCP_GATEWAY_PAYLOAD_DIR}" } } - GH_AW_MCP_CONFIG_a487310af394adf5_EOF + GH_AW_MCP_CONFIG_432de5cac6e63f96_EOF - name: Mount MCP servers as CLIs id: mount-mcp-clis continue-on-error: true