name: "Update @github/copilot Dependency" on: workflow_dispatch: inputs: version: description: 'Target version of @github/copilot (e.g. 1.0.24)' required: true type: string permissions: contents: write pull-requests: write actions: write jobs: update: name: "Update @github/copilot to ${{ inputs.version }}" runs-on: ubuntu-latest steps: - name: Validate version input env: VERSION: ${{ inputs.version }} run: | if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9._-]+)?$ ]]; then echo "::error::Invalid version format '$VERSION'. Expected semver (e.g. 1.0.24)." exit 1 fi - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6 with: node-version: 22 - name: Update @github/copilot in scripts/codegen env: VERSION: ${{ inputs.version }} working-directory: ./scripts/codegen # npm install updates package.json and package-lock.json to the new # version; npm ci (below) then does a clean, reproducible install from # the updated lock file. Both steps are required: npm install alone # leaves leftover packages, while npm ci alone cannot change the pinned # version in the lock file. run: npm install "@github/copilot@$VERSION" - name: Install codegen dependencies working-directory: ./scripts/codegen run: npm ci - name: Run codegen working-directory: ./scripts/codegen run: npm run generate - uses: ./.github/actions/setup-copilot - name: Verify generated code against schema env: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} run: | cat > /tmp/verify-codegen-prompt.txt << 'PROMPT_EOF' You are running inside the copilot-sdk-java repository. The code generator has just run and produced Java source files under src/generated/java/com/github/copilot/sdk/generated/rpc/. Your task is to spot-check the generated API classes against the source JSON schema to verify the generator produced correct output. **Critical constraint: Do NOT modify any files. This is a read-only verification. Use only read/inspect operations.** **Steps:** 1. Read the API schema at: scripts/codegen/node_modules/@github/copilot/schemas/api.schema.json 2. Pick these 3 generated API classes to verify: - src/generated/java/com/github/copilot/sdk/generated/rpc/SessionToolsApi.java - src/generated/java/com/github/copilot/sdk/generated/rpc/SessionUiApi.java - src/generated/java/com/github/copilot/sdk/generated/rpc/SessionPermissionsApi.java 3. For each class, verify: - Every RPC method in the schema's corresponding namespace has a matching Java method in the generated class - Parameter record fields match the JSON schema property names - Java types are consistent with JSON schema types (String for "string", Integer/int for "integer", Boolean/boolean for "boolean", List for "array", Map or a generated class for "object", etc.) - No extra methods exist in the Java class that are not in the schema 4. Print a summary table of what was checked and the result for each method. 5. If ANY mismatch is found, print the details and exit with a non-zero code. If all checks pass, print "Schema verification passed" and exit 0. PROMPT_EOF copilot --yolo --prompt "$(cat /tmp/verify-codegen-prompt.txt)" # --- Commit, create PR, then run mvn verify --- # The PR must exist before triggering the agentic fix workflow, which # uses push-to-pull-request-branch safe-output to push fixes. - name: Commit and push changes id: commit-changes env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} VERSION: ${{ inputs.version }} run: | BRANCH="update-copilot-$VERSION" git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" if git rev-parse --verify "origin/$BRANCH" >/dev/null 2>&1; then git checkout "$BRANCH" git reset --hard HEAD else git checkout -b "$BRANCH" fi git add -A if git diff --cached --quiet; then echo "No changes detected; skipping commit and PR creation." echo "has_changes=false" >> "$GITHUB_OUTPUT" exit 0 fi git commit -m "Update @github/copilot to $VERSION - Updated @github/copilot in scripts/codegen - Re-ran Java code generator" git push origin "$BRANCH" --force-with-lease echo "has_changes=true" >> "$GITHUB_OUTPUT" echo "branch=$BRANCH" >> "$GITHUB_OUTPUT" - name: Create pull request id: create-pr if: steps.commit-changes.outputs.has_changes == 'true' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} VERSION: ${{ inputs.version }} BRANCH: ${{ steps.commit-changes.outputs.branch }} run: | if gh pr view "$BRANCH" >/dev/null 2>&1; then echo "Pull request for branch '$BRANCH' already exists; updated branch only." PR_NUMBER=$(gh pr view "$BRANCH" --json number --jq .number) gh pr edit "$PR_NUMBER" --add-label dependencies else PR_NUMBER=$(gh pr create \ --title "Update @github/copilot to $VERSION" \ --body "Automated update of \`@github/copilot\` to version \`$VERSION\`. ### Changes - Updated \`@github/copilot\` in \`scripts/codegen/package.json\` - Re-ran Java code generator (\`scripts/codegen\`) > Created by the **Update @github/copilot Dependency** workflow." \ --label dependencies \ --base main \ --head "$BRANCH" \ | grep -oE '[0-9]+$' || gh pr view "$BRANCH" --json number --jq .number) fi echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT" # --- Build verification --- - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 if: steps.commit-changes.outputs.has_changes == 'true' with: java-version: "17" distribution: "microsoft" cache: "maven" - name: Run mvn verify id: mvn-verify if: steps.commit-changes.outputs.has_changes == 'true' continue-on-error: true env: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} run: | set -o pipefail mvn verify 2>&1 | tee /tmp/mvn-verify-output.txt echo "exit_code=$?" >> "$GITHUB_OUTPUT" - name: Capture error summary id: error-summary if: steps.mvn-verify.outcome == 'failure' run: | # Extract the last 80 lines as error summary (enough context for the agent) SUMMARY=$(tail -80 /tmp/mvn-verify-output.txt) # Write to file to avoid shell escaping issues with multiline strings echo "$SUMMARY" > /tmp/error-summary.txt echo "has_errors=true" >> "$GITHUB_OUTPUT" # --- Agentic fix on failure --- - name: Trigger agentic fix workflow id: trigger-fix if: steps.error-summary.outputs.has_errors == 'true' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} BRANCH: ${{ steps.commit-changes.outputs.branch }} PR_NUMBER: ${{ steps.create-pr.outputs.pr_number }} run: | ERROR_SUMMARY=$(cat /tmp/error-summary.txt) gh workflow run codegen-agentic-fix.lock.yml \ -f branch="$BRANCH" \ -f pr_number="$PR_NUMBER" \ -f error_summary="$ERROR_SUMMARY" echo "Triggered codegen-agentic-fix workflow on branch $BRANCH" - name: Wait for agentic fix to complete if: steps.trigger-fix.outcome == 'success' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} BRANCH: ${{ steps.commit-changes.outputs.branch }} run: | echo "Waiting for agentic fix workflow to start..." sleep 30 for i in $(seq 1 60); do RUN_ID=$(gh run list \ --workflow=codegen-agentic-fix.lock.yml \ --branch="$BRANCH" \ --limit=1 \ --json databaseId,status \ --jq '.[0].databaseId') STATUS=$(gh run list \ --workflow=codegen-agentic-fix.lock.yml \ --branch="$BRANCH" \ --limit=1 \ --json databaseId,status \ --jq '.[0].status') if [ "$STATUS" = "completed" ]; then echo "Agentic fix workflow run $RUN_ID completed." CONCLUSION=$(gh run view "$RUN_ID" --json conclusion --jq .conclusion) echo "Conclusion: $CONCLUSION" break fi echo "Run $RUN_ID status: $STATUS (attempt $i/60)" sleep 30 done if [ "$STATUS" != "completed" ]; then echo "::warning::Agentic fix workflow did not complete within 30 minutes." fi - name: Fetch latest changes after agentic fix if: steps.trigger-fix.outcome == 'success' env: BRANCH: ${{ steps.commit-changes.outputs.branch }} run: | git fetch origin "$BRANCH" git reset --hard "origin/$BRANCH" - name: Final mvn verify after agentic fix if: steps.trigger-fix.outcome == 'success' env: COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} run: mvn verify