From f66b55619cd9280c2255ae4087bd5f2bcd7a594e Mon Sep 17 00:00:00 2001 From: Ed Burns Date: Tue, 12 May 2026 18:20:33 -0700 Subject: [PATCH 1/6] On branch edburns/80-java-monorepo-add-01 Commence work on https://github.com/github/cnew file: 80-java-monorepo-add-01-remove-before-merge/20260512-prompts.md - Commence practice of keeping running prompts for sharing and review. new file: 80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md - Document WIP plan for review. --- .../20260512-prompts.md | 366 ++++++++++ .../dd-2989727-move-java-to-monorepo-plan.md | 643 ++++++++++++++++++ 2 files changed, 1009 insertions(+) create mode 100644 80-java-monorepo-add-01-remove-before-merge/20260512-prompts.md create mode 100644 80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md diff --git a/80-java-monorepo-add-01-remove-before-merge/20260512-prompts.md b/80-java-monorepo-add-01-remove-before-merge/20260512-prompts.md new file mode 100644 index 000000000..36606fa96 --- /dev/null +++ b/80-java-monorepo-add-01-remove-before-merge/20260512-prompts.md @@ -0,0 +1,366 @@ + +### 17:17 Prompt + +Looking at `temporary-prompts/dd-2989727-move-java-to-monorepo-plan.md`, for each of the existing workflows in section "1B. `copilot-sdk-00` Workflows", with the exception of the already language specific `*-sdk-tests.yml`, what changes would one need to make to these workflows to ensure that none of the content in `java` would accidentally get picked up by those workflows? + +### 17:24 Response + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/temporary-prompts/dd-2989727-move-java-to-monorepo-plan.md#1-1), lines 1 to 200 + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/temporary-prompts/dd-2989727-move-java-to-monorepo-plan.md#200-200), lines 200 to 400 + +Let me look at the actual workflow files in the monorepo to assess each one. + +Searched for files matching `copilot-sdk-00` · `.github/workflows/*`, 20 matches + +Searched for files matching `copilot-sdk-00` · `.github/workflows/*`, 32 matches + +Created 13 todos + +Let me read all the non-language-specific workflow files in parallel: + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/codegen-check.yml) + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/publish.yml#1-1), lines 1 to 200 + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/scenario-builds.yml#1-1), lines 1 to 200 + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/docs-validation.yml) + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/update-copilot-dependency.yml) + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/copilot-setup-steps.yml) + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/verify-compiled.yml) + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/collect-corrections.yml) + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/corrections-tests.yml) + +Now let me read the remaining publish.yml and the agentic workflow `.md` files: + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/publish.yml#200-200), lines 200 to 315 + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/issue-classification.md#1-1), lines 1 to 100 + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/issue-triage.md) + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/handle-bug.md) + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/handle-documentation.md) + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/handle-enhancement.md) + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/handle-question.md) + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/cross-repo-issue-analysis.md#1-1), lines 1 to 100 + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/release-changelog.md#1-1), lines 1 to 100 + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/sdk-consistency-review.md) + +Starting: *Compile analysis* (2/2) + +Let me also check the codegen script to see if it could pick up Java content: + +Read [](file:///e%3A/workareas/copilot-sdk-00/scripts/codegen) + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/workflows/scenario-builds.yml#1-1), lines 1 to 30 + +Read [](file:///e%3A/workareas/copilot-sdk-00/scripts/codegen/package.json) + +Completed: *Compile analysis* (2/2) + +Here's the analysis of each non-`*-sdk-tests.yml` workflow in section 1B, grouped by risk level: + +--- + +## HIGH RISK — Workflows that would actively process or misrepresent Java content + +### 1. codegen-check.yml +- **Problem**: The `push` trigger on `main` has **no path filter** — every push to `main` (including Java-only changes) fires this workflow. While the existing codegen scripts (package.json `generate` script) only run `typescript.ts`, `csharp.ts`, `python.ts`, `go.ts`, `rust.ts`, if a `java.ts` is later merged into codegen, the `npm run generate` step would execute it too. +- **Changes needed**: + - Add `paths-ignore: ['java/**']` to the `push` trigger, or add explicit `paths:` matching the existing language dirs. + - Alternatively, after Java codegen is merged, do **not** add `java.ts` to the `generate` script in package.json — keep `generate:java` as a separate script only invoked by `java-sdk-tests.yml` / a separate `java-codegen-check` job. + +### 2. update-copilot-dependency.yml +- **Problem**: The `npm run generate` step ([line ~77](copilot-sdk-00/.github/workflows/update-copilot-dependency.yml)) runs **all** codegen scripts. If `java.ts` is added to the `generate` script, it would generate Java code. The subsequent "Format generated code" step only formats nodejs, dotnet, and rust — Java output would be committed **unformatted**. +- **Changes needed**: + - Ensure the `generate` npm script in package.json does NOT include Java. + - OR add an explicit `java/**` exclusion from the `git add -A` / commit step. + - The "Format generated code" step currently only references nodejs, dotnet, rust — if Java codegen is ever included, add `cd ../java && mvn spotless:apply` there, or better, keep Java out of this workflow entirely. + +### 3. publish.yml +- **Problem**: Manually triggered, but the `github-release` job creates a GitHub Release with auto-generated notes (`--generate-notes`). These notes include **all** PRs merged since the last tag, including Java PRs. Java changes would appear in release notes for a release that doesn't include Java. +- **Changes needed**: + - Add `--exclude-labels java` or similar filtering to the `gh release create` steps so Java-only PRs are excluded from the release notes. + - Alternatively, document that the release-changelog.md agentic workflow is the source of truth and configure `--notes ""` plus rely on the changelog agent to filter. + +### 4. release-changelog.md +- **Problem**: Gathers ALL merged PRs/commits between tags and categorizes by SDK. Java PRs would be included in the changelog. The prompt says "TypeScript and C# as the primary languages" for code snippets and only lists Node, Python, Go, .NET. Java changes would either be miscategorized or lumped into "Other changes." +- **Changes needed**: + - Add explicit instruction in the prompt: "Exclude PRs that only touch `java/**` — the Java SDK has its own independent release and changelog." + - Or add a filter step before the agent runs that identifies and excludes Java-only commits. + +--- + +## MEDIUM RISK — Workflows where Java content would cause incorrect agent behavior + +### 5. sdk-consistency-review.md +- **Problem**: Path triggers are `nodejs/**`, `python/**`, `go/**`, `dotnet/**` — does NOT include `java/**`. The "SDK Locations" in the prompt lists only 4 SDKs. If a PR touches both `dotnet/**` and `java/**`, the workflow fires (due to dotnet), but the agent would **not check Java for consistency** because it's not in its list. +- **Changes needed**: + - This is a deliberate non-inclusion per the plan (Java is to be added later). But to ensure the agent doesn't stumble upon java and give incorrect consistency advice, add a note to the prompt: "The java directory exists but is managed separately — do not include it in your consistency analysis." + +### 6. issue-triage.md +- **Problem**: The `add-labels.allowed` list includes `sdk/dotnet`, `sdk/go`, `sdk/nodejs`, `sdk/python` but NOT `sdk/java`. A Java-related issue would not receive proper SDK labeling. The agent's description says "implementations in .NET, Go, Node.js, and Python" — no Java. +- **Changes needed**: + - Until Java labeling is desired: add a note to the prompt telling the agent that java exists but should not receive an SDK label (or should receive a generic label like `needs-info` and be left for human triage). + +### 7. issue-classification.md +- **Problem**: Description says "multi-language SDK (Node.js/TypeScript, Python, Go, .NET)." A Java-related issue would still be classified (bug/enhancement/question/documentation are language-agnostic categories), but the agent lacks Java context and might misjudge whether behavior is a bug vs. working-as-designed. +- **Changes needed**: + - Add a note: "The java SDK also exists in this repository but has a separate triage process. If an issue specifically concerns the Java SDK, classify it normally but note in your comment that it relates to the Java SDK." + +### 8. handle-bug.md +- **Problem**: The investigation instructions tell the agent to search src, copilot, go, src — **not** java. A Java bug report would be investigated only in the other SDKs, leading to incorrect conclusions. +- **Changes needed**: + - Add a guard: "If the issue specifically references the Java SDK (java), note this in your comment and do not attempt to analyze Java source code — the Java SDK is maintained separately." + +### 9. cross-repo-issue-analysis.md +- **Problem**: Same as handle-bug — explicit directory list for searching SDK code doesn't include java. A Java SDK issue labeled `runtime triage` would be analyzed without looking at the Java code. +- **Changes needed**: + - Add `java/src/` to the list of SDK directories to search, or add the same "Java is maintained separately" guard. + +--- + +## LOW RISK — Workflows with minimal or no concern + +### 10. scenario-builds.yml +- **Problem**: The `find test/scenarios` commands look for language-specific markers (`*/typescript/package.json`, `*/python/main.py`, `*/go/go.mod`, `*.csproj`). None of these match Java files. The path triggers include `test/scenarios/**`, so Java scenario changes would trigger the workflow but **no Java job would run** (wasted CI only). +- **Changes needed**: + - Minor: add `!test/scenarios/**/java/**` to paths or rely on the fact that no job processes Java files. No functional risk. + +### 11. docs-validation.yml +- **Problem**: PR trigger includes `docs/**`. If Java code snippets (```java fenced blocks) are added to docs, the extraction scripts might pull them but there's no `validate:java` step. Depending on the extraction script behavior, these could be silently skipped or cause errors. +- **Changes needed**: + - Check docs-validation extraction scripts. If they extract by fenced code block language tag, ensure unknown languages are gracefully skipped. If they extract all blocks, add Java to the skip list. + +### 12. copilot-setup-steps.yml +- **No risk**. Only triggers on changes to itself. Installs dependencies for nodejs, python, go, dotnet. Java would need its own additions to this file eventually, but the existing workflow won't touch java. + +### 13. verify-compiled.yml +- **No risk (actually desired)**. Triggers on `.github/workflows/*.md` and `.lock.yml`. If Java agentic workflows (like `java-codegen-fix.md`) are added to workflows, this workflow correctly verifies their lock files. This is **correct behavior**, not accidental pickup. + +### 14. collect-corrections.yml +- **No risk**. Triggers on `repository_dispatch` and `workflow_dispatch`. Runs a specific JS script. Language-agnostic. + +### 15. corrections-tests.yml +- **No risk**. Only triggers on `scripts/corrections/**`. No language-specific content. + +### 16. handle-documentation.md, handle-enhancement.md, handle-question.md +- **No risk**. These just add labels. No language-specific logic or code search. + +--- + +## Summary of key protective measures + +| # | Action | Workflows protected | +|---|--------|-------------------| +| 1 | Keep `java.ts` out of the package.json `generate` script | codegen-check.yml, update-copilot-dependency.yml | +| 2 | Add `paths-ignore: ['java/**']` to codegen-check.yml push trigger | codegen-check.yml | +| 3 | Filter Java PRs from release notes generation | publish.yml, release-changelog.md | +| 4 | Add "Java is separately managed" guardrails to agentic prompts | issue-classification.md, issue-triage.md, handle-bug.md, cross-repo-issue-analysis.md, sdk-consistency-review.md | + +### 17:31 Prompt + +I'm not familiar with `just`. From what language ecosystem does this come? Do Java shops use it? + +### 17:33 Response + + + +`just` is a **command runner** inspired by `make`, written in **Rust** by Casey Rodarmor. It comes from the Rust ecosystem but is language-agnostic — it's essentially a modern, simpler alternative to `Makefile` for running project-specific commands. + +**Do Java shops use it?** Rarely. Java projects overwhelmingly rely on **Maven** or **Gradle** as their task runners (via lifecycle phases, plugins, and custom tasks). `just` is more popular in Rust, Go, and polyglot/scripting-heavy repos where there's no dominant build tool that already serves as a command runner. + +In this monorepo (`copilot-sdk-00`), `just` makes sense because it unifies commands across 5+ language ecosystems (`just test`, `just format`, `just lint`) — each of which has its own native build tool underneath. The justfile delegates to `npm`, go, dotnet, `uv`, `cargo`, etc. per language. + +### 17:33 Prompt + +But might it make sense to simply not make `just` touch the Java? + +### 17:34 Response + + + +Yes, absolutely. Maven already serves as Java's command runner, and every Java developer already knows `mvn verify`, `mvn spotless:apply`, etc. Adding `just` targets for Java would mean: + +- Maintaining a **redundant indirection layer** (`just test-java` → `cd java && mvn verify`) +- Requiring Java contributors to install a tool (`just`) that adds zero value over what Maven already provides +- Creating a discoverability problem — Java devs would need to know to look in the justfile instead of the pom.xml + +The other languages in the monorepo benefit from `just` because their native tools don't provide a unified CLI across the repo. But Maven is already a self-contained build/test/format/lint/publish lifecycle — it doesn't need wrapping. + +The practical approach: **don't add Java targets to the justfile**. Document in README.md that Java uses `mvn` commands directly, same as it does today. The top-level `just test` / `just format` / `just lint` recipes would continue to cover the other 5 SDKs, and Java would stay self-contained under java. + +### 17:39 Prompt + +The file `temporary-prompts/dd-2989727-move-java-to-monorepo-plan.md` was output from our work yesterday. One thing I am aware you are missing is what to do about the `src/test/prompts/PROMPT-smoke-test.md` smoke test. This test currently assumes a specific structure of the top level `README.md`. We will need to update this file and the `README.md` itself on the monorepo side so it can continue to function. Add an "Appendix C: Java smoketest" section describing how to handle this. Cover the workflows that invoke this. + +Make a reference to Appendix C at the first mention of the smoke test, which is here: + +``` +| `run-smoke-test.yml` | Builds SDK, installs locally, runs Copilot CLI smoke test on JDK 17 + JDK 25 | Java | M | +``` + +Update that **Brief Description** cell to include a reference to your new Appendix C. + +### 17:54 Response + +Searched for files matching `copilot-sdk-java-00` · `.github/workflows/run-smoke-test*`, 1 match + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/src/test/prompts/PROMPT-smoke-test.md#1-1), lines 1 to 100 + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/README.md#1-1), lines 1 to 100 + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/src/test/prompts/PROMPT-smoke-test.md#100-100), lines 100 to 136 + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/.github/workflows/run-smoke-test.yml) + +Now let me also check the monorepo's README to understand what exists there, and find the end of the plan document for the appendix: + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/temporary-prompts/dd-2989727-move-java-to-monorepo-plan.md#360-360), lines 360 to 500 + +Read [](file:///e%3A/workareas/copilot-sdk-00/README.md#1-1), lines 1 to 50 + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/temporary-prompts/dd-2989727-move-java-to-monorepo-plan.md#500-500), lines 500 to 539 + +Now I have all the context. Let me also check the monorepo's README.md to understand what exists there: + +Read [](file:///e%3A/workareas/copilot-sdk-00/java/README.md#1-1), lines 1 to 50 + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/README.md#100-100), lines 100 to 100 + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/README.md#60-60), lines 60 to 150 + +Now I have full context. Let me also check if there are any workflows that call run-smoke-test.yml: + +Searched for text `run-smoke-test` (`copilot-sdk-java-00` · `.github/workflows/**`), 1 result + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/.github/workflows/build-test.yml#20-20), lines 20 to 40 + +Searched for text `smoke-test` (`copilot-sdk-java-00` · `.github/workflows/**`), 18 results + +Now I have all the context. Let me also check the `publish-maven.yml` to see if it also calls the smoke test: + +Searched for text `smoke` (`copilot-sdk-java-00` · `.github/workflows/publish-maven.yml`), no results + +Good, only build-test.yml calls the smoke test. Now I have everything I need. Let me make the two edits to the plan document: + +Replacing 1 lines with 1 lines in [](file:///e%3A/workareas/copilot-sdk-java-00/temporary-prompts/dd-2989727-move-java-to-monorepo-plan.md) + + +``` + +``` +Now find the exact end of the document to add Appendix C: + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/temporary-prompts/dd-2989727-move-java-to-monorepo-plan.md#539-539), lines 539 to 539 + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/temporary-prompts/dd-2989727-move-java-to-monorepo-plan.md#535-535), lines 535 to 539 + +Replacing 1 lines with 103 lines in [](file:///e%3A/workareas/copilot-sdk-java-00/temporary-prompts/dd-2989727-move-java-to-monorepo-plan.md) + + +``` + +``` +Now add Appendix C to the table of contents: + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/temporary-prompts/dd-2989727-move-java-to-monorepo-plan.md#1-1), lines 1 to 12 + +Replacing 8 lines with 11 lines in [](file:///e%3A/workareas/copilot-sdk-java-00/temporary-prompts/dd-2989727-move-java-to-monorepo-plan.md) + + +``` + +``` +Done. Three edits made to dd-2989727-move-java-to-monorepo-plan.md: + +1. **Table of Contents** — added links for Appendices A, B, and C +2. **run-smoke-test.yml row** — appended "(see Appendix C)" to the description +3. **Appendix C: Java Smoketest** — new section at the end covering: + - How the smoke test works today (the prompt-driven design where PROMPT-smoke-test.md instructs Copilot CLI to read the README, extract Quick Start code, build, and run) + - What breaks (the prompt says "top level README" but post-migration that's the monorepo README, not README.md) + - The four required changes: update the prompt's README path, ensure README.md has the real content (not the monorepo placeholder), add `working-directory: ./java` to the workflow, and update the reusable workflow reference + - Risk table and verification checklist + +Made changes. + +### 17:55 Prompt + +I consider it essential that the work to implement the plan described in `dd-2989727-move-java-to-monorepo-plan.md` be done in a topic branch in the `upstream` remote for `copilot-sdk-00`. I am also aware that many of the CI/CD aspects require things to be on `main`. Without changing `dd-2989727-move-java-to-monorepo-plan.md` just yet, look at the "Risk Register" section and describe some of the risks of this `main` requirement. Or am I misunderstanding the risk and it's possible to iterate and make changes to CI/CD without requiring stuff reside on `main`? + +### 18:00 Response + +You're right to flag this — there is real tension, but it's more nuanced than "everything needs `main`." Let me break down exactly what can and can't be validated on a topic branch. + +## What WORKS on a topic branch (via PR) + +GitHub Actions uses the **PR branch's version** of workflow files for `pull_request`-triggered workflows. So these are fully testable: + +- **`java-sdk-tests.yml`** (the core CI) — `pull_request` with path triggers works from a branch +- **codegen-check.yml** changes — same, `pull_request` trigger +- **Reusable workflow calls** (`uses: ./.github/workflows/java-smoke-test.yml`) — resolved from the PR branch +- **Composite actions** (`uses: .github.`) — same +- **All source code** — `java/src/`, `java/pom.xml`, test infrastructure +- **`CODEOWNERS`**, **`dependabot.yaml`**, **justfile**, **copilot-instructions.md** — take effect on merge + +So the core development loop — "does Java build, test, and pass CI in the monorepo" — is fully achievable on a topic branch. + +## What CANNOT be tested on a topic branch + +### 1. Smoke test — hard-gated on `main` + +Both jobs in run-smoke-test.yml have: +```yaml +if: github.ref == 'refs/heads/main' +``` +On a PR, `github.ref` is `refs/pull/NNN/merge`, so both jobs are **unconditionally skipped**. You cannot validate the smoke test migration works until the workflow is on `main`. This is the most relevant risk from the register given your Appendix C work. + +### 2. `workflow_dispatch`-only workflows + +These can only be manually triggered from branches that **already exist in the repo** and are selectable in the Actions UI. New workflow files on a topic branch won't appear in the dispatch dropdown until they're on the default branch (or at least pushed). The affected workflows: +- `java-publish.yml` +- `java-publish-snapshot.yml` +- `java-deploy-site.yml` +- `java-smoke-test.yml` (when triggered manually) +- update-copilot-dependency.yml + +### 3. Scheduled workflows + +`schedule` triggers **only run from the default branch**. So `java-reference-impl-sync.md` (the daily check for new dotnet/nodejs changes) won't execute until it's on `main`. + +### 4. copilot-setup-steps.yml + +The Copilot coding agent reads this **exclusively from the default branch**. Adding JDK 17 + Maven setup won't take effect for agent sessions until merged to `main`. This means you can't use the coding agent to help with Java tasks in the monorepo until this lands. + +### 5. Required status checks — chicken-and-egg + +You can't add `java-sdk-tests` as a required check in branch protection until the workflow has **run at least once** and GitHub knows the check name exists. First run happens on the PR, but you can't enforce it as required until after merge. + +### 6. Secrets availability + +For `pull_request` events, secrets are available for PRs from branches **within the same repo** (not forks). Since this is an internal topic branch on the `upstream` remote, `COPILOT_GITHUB_TOKEN` and other secrets should be accessible. This is **not** a blocker — but it's worth verifying the repo's settings haven't restricted secrets to protected branches only. + +### 7. GitHub Pages deployment + +Pages deployment is typically configured for `main`. The `java-deploy-site.yml` workflow can't be validated until on `main`. + +## Practical implication + +The migration is naturally split into what the plan calls Phases 1-2 (source code + core CI) vs. Phases 3-4 (publish, smoke test, agentic workflows). Phases 1-2 are fully testable on a topic branch. Phases 3-4 inherently require `main`. + +The key question is whether you merge Phases 1-2 as one PR and then iterate Phases 3-4 as follow-up PRs on `main`, or whether you try to land everything in one big PR and accept that the `main`-gated pieces are unvalidated until merge. The former is safer — a broken smoke test workflow is recoverable, but a broken `java-sdk-tests.yml` that blocks the merge queue is not. + +The risk register items H1 (Maven Central Trusted Publisher), H4 (secret provisioning), and M3 (branch protection) are all in this "can't validate until `main`" category, which is why Phase 0 (pre-flight) exists — those should be resolved **before** any code lands. diff --git a/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md b/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md new file mode 100644 index 000000000..a370fc574 --- /dev/null +++ b/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md @@ -0,0 +1,643 @@ +# DD-2989727: Move Java SDK into copilot-sdk Monorepo — Plan + +## Table of Contents + +1. [Workflow Inventory Tables](#1-workflow-inventory-tables) +2. [Agents, Skills, Prompts, and Supporting Resources Inventory](#2-agents-skills-prompts-and-supporting-resources-inventory) +3. [Permissions and Secrets Challenges](#3-permissions-and-secrets-challenges) +4. [Naming Convention Proposal](#4-naming-convention-proposal) +5. [Current Language Separation Assessment](#5-current-language-separation-assessment) +6. [Migration Plan — Phases](#6-migration-plan--phases) +7. [Pitfalls and Risk Register](#7-pitfalls-and-risk-register) +8. [Post-Migration Verification Checklist](#8-post-migration-verification-checklist) +- [Appendix A: Files to Copy vs. Merge vs. Delete](#appendix-a-files-to-copy-vs-merge-vs-delete) +- [Appendix B: Unique Java Concerns vs Other Languages](#appendix-b-unique-java-concerns-vs-other-languages) +- [Appendix C: Java Smoketest](#appendix-c-java-smoketest) + +--- + +## 1. Workflow Inventory Tables + +### 1A. copilot-sdk-java-00 Workflows (Source) + +| YAML File Name | Brief Description | Primary Language | Complexity | +|---|---|---|---| +| `build-test.yml` | Main CI: Spotless, build, Javadoc, `mvn verify`, JaCoCo coverage badges | Java | L | +| `codegen-check.yml` | Re-runs Java codegen, commits regenerated files to PRs, triggers agentic fix on failure | Java | M | +| `codegen-agentic-fix.md` + `.lock.yml` | Agentic: auto-fixes compilation/test failures caused by codegen changes | Java | L | +| `reference-impl-sync.md` + `.lock.yml` | Agentic: checks for new commits in `github/copilot-sdk`, creates issue for Copilot agent to port | Java | L | +| `publish-maven.yml` | Publishes release to Maven Central via `maven-release-plugin`, GPG signing, GitHub Release creation | Java | XL | +| `publish-snapshot.yml` | Publishes SNAPSHOT builds to Maven Central Snapshots on a weekday schedule | Java | M | +| `deploy-site.yml` | Builds/deploys versioned Maven site docs to GitHub Pages | Java | M | +| `run-smoke-test.yml` | Builds SDK, installs locally, runs Copilot CLI smoke test on JDK 17 + JDK 25 (see [Appendix C](#appendix-c-java-smoketest)) | Java | M | +| `update-copilot-dependency.yml` | Updates `@github/copilot` npm dep in codegen, re-runs generator, creates PR | Java | M | +| `copilot-setup-steps.yml` | Environment setup for Copilot coding agent (JDK 17, Node 22, gh-aw, pre-commit hooks) | Java | S | +| `agentics-maintenance.yml` | Auto-generated gh-aw maintenance: closes expired discussions/issues/PRs | Cross-language (infra) | S | +| `notes.template` | Release notes template for Maven Central (not a workflow) | Java | S | + +### 1B. copilot-sdk-00 Workflows (Target Monorepo) + +| YAML File Name | Brief Description | Primary Language | Complexity | +|---|---|---|---| +| `nodejs-sdk-tests.yml` | Build + test Node.js SDK on 3 OS, prettier, ESLint, typecheck, E2E | Node.js | L | +| `dotnet-sdk-tests.yml` | Build + test .NET SDK on 3 OS, format check, E2E via replay proxy | .NET | L | +| `go-sdk-tests.yml` | Build + test Go SDK on 3 OS, gofmt, golangci-lint, E2E | Go | L | +| `python-sdk-tests.yml` | Build + test Python SDK on 3 OS, ruff, ty, E2E via pytest | Python | L | +| `rust-sdk-tests.yml` | Build + test Rust SDK on 3 OS, nightly fmt, clippy, cargo test | Rust | L | +| `codegen-check.yml` | Verifies generated files across Node, .NET, Python, Go, Rust | Cross-language | M | +| `publish.yml` | Publishes all SDKs (npm, NuGet, PyPI, Go tags, crates.io) from a single version | Cross-language | XL | +| `scenario-builds.yml` | Verifies example scenarios build for each language | Cross-language | M | +| `docs-validation.yml` | Extracts and validates code snippets from `docs/` | Cross-language | M | +| `update-copilot-dependency.yml` | Updates `@github/copilot` dep, re-runs codegen, opens PR | Cross-language | M | +| `copilot-setup-steps.yml` | Agent env setup: Node, Python, Go, .NET, Rust, just, gh-aw | Cross-language | M | +| `verify-compiled.yml` | Ensures `.lock.yml` files match `.md` sources | Cross-language (infra) | S | +| `collect-corrections.yml` | Collects triage agent feedback | Cross-language (infra) | S | +| `corrections-tests.yml` | Tests for triage correction scripts | Cross-language (infra) | S | +| `issue-classification.md` + `.lock.yml` | Agentic: classifies issues → routes to handle-* handlers | Cross-language | M | +| `issue-triage.md` + `.lock.yml` | Agentic: labels, acknowledges, requests clarification, closes dupes | Cross-language | L | +| `handle-bug.md` + `.lock.yml` | Agentic: investigates bug issues | Cross-language | M | +| `handle-documentation.md` + `.lock.yml` | Agentic: handles doc-related issues | Cross-language | S | +| `handle-enhancement.md` + `.lock.yml` | Agentic: labels enhancement issues | Cross-language | S | +| `handle-question.md` + `.lock.yml` | Agentic: labels question issues | Cross-language | S | +| `cross-repo-issue-analysis.md` + `.lock.yml` | Agentic: checks if issue root cause is in copilot-agent-runtime | Cross-language | M | +| `release-changelog.md` + `.lock.yml` | Agentic: generates release notes, updates CHANGELOG | Cross-language | M | +| `sdk-consistency-review.md` + `.lock.yml` | Agentic: reviews PRs for cross-SDK feature parity | Cross-language | L | + +--- + +## 2. Agents, Skills, Prompts, and Supporting Resources Inventory + +### 2A. copilot-sdk-java-00 + +| Resource | Location | Purpose | Must Migrate? | +|---|---|---|---| +| **Agent:** `agentic-workflows.agent.md` | `.github/agents/` | Dispatcher for gh-aw workflow creation/debug | Yes (merge with monorepo version) | +| **Skill:** `agentic-merge-reference-impl` | `.github/skills/` + `.github/prompts/` | Merges reference impl changes into Java | Yes — **must be reworked** (no longer cross-repo) | +| **Skill:** `commit-as-pull-request` | `.github/skills/` + `.github/prompts/` | Creates branch, pushes, opens PR | Yes (may already exist in monorepo) | +| **Skill:** `documentation-coverage` | `.github/skills/` + `.github/prompts/` | Assesses Java docs coverage | Yes | +| **Prompt:** `coding-agent-merge-reference-impl-instructions.md` | `.github/prompts/` | Instructions for coding agent merge | Yes | +| **Prompt:** `test-coverage-assessment.prompt.md` | `.github/prompts/` | Test coverage assessment | Yes | +| **Composite Action:** `setup-copilot` | `.github/actions/setup-copilot/` | Sets up Copilot CLI for Java tests | Yes — **adapt paths** | +| **Composite Action:** `test-report` | `.github/actions/test-report/` | Test report generation | Yes | +| **Scripts:** `release/`, `ci/`, `build/`, `reference-impl-sync/` | `.github/scripts/` | Release, CI, sync automation | Yes — **path rewrites** | +| **Dependabot:** `dependabot.yml` | `.github/` | Maven + GitHub Actions updates | Merge into monorepo's `dependabot.yaml` | +| **CODEOWNERS** | `.github/` | `@github/copilot-sdk-java` | Merge into monorepo's CODEOWNERS | +| **Issue Templates:** bug, documentation, feature, maintenance | `.github/ISSUE_TEMPLATE/` | Issue forms | Assess whether monorepo issue triage covers this | +| **PR Template** | `.github/pull_request_template.md` | PR form | Merge or keep per-language | +| **Release Config** | `.github/release.yml` | Auto-generated release notes config | Merge | +| **copilot-instructions.md** | `.github/` | Agent instructions for Java SDK | Merge (scoped to `java/`) | +| **Site templates** | `.github/templates/` | HTML/CSS for GitHub Pages | Migrate to `java/` | +| **Coverage badge script** | `.github/scripts/generate-coverage-badge.sh` | JaCoCo badge generation | Migrate | +| **`.lastmerge`** | repo root | Tracks last merged ref-impl commit | **This concept changes** — see §6 | +| **`.githooks/pre-commit`** | repo root | Runs `mvn spotless:check` | Migrate to `java/.githooks/` | +| **`instructions/copilot-sdk-java.instructions.md`** | `instructions/` | VS Code copilot instructions | Move to `java/` | + +### 2B. copilot-sdk-00 + +| Resource | Location | Purpose | +|---|---|---| +| **Agent:** `agentic-workflows.agent.md` | `.github/agents/` | Same dispatcher (newer version with more routing) | +| **Agent:** `docs-maintenance.agent.md` | `.github/agents/` | Docs auditor agent | +| **Skill:** `rust-coding-skill` | `.github/skills/` | Rust-specific coding skill | +| **Composite Action:** `setup-copilot` | `.github/actions/setup-copilot/` | Sets up Copilot CLI from nodejs package | +| **Command:** `triage_feedback.yml` | `.github/commands/` | Repository dispatch for triage feedback | +| **LSP Config:** `lsp.json` | `.github/` | C#, Go language server configs | +| **Dependabot:** `dependabot.yaml` | `.github/` | npm, pip, gomod, nuget, github-actions, devcontainers | +| **CODEOWNERS** | `.github/` | `@github/copilot-sdk` | +| **copilot-instructions.md** | `.github/` | Monorepo-wide agent instructions | + +--- + +## 3. Permissions and Secrets Challenges + +### 3A. Secrets That Must Be Provisioned in copilot-sdk + +The Java SDK publish workflow requires secrets that **do not currently exist** in the `copilot-sdk` repo: + +| Secret | Used By | Notes | +|---|---|---| +| `RELEASE_TOKEN` | `publish-maven.yml` | PAT with `contents:write` for pushing tags/commits during maven-release-plugin | +| `GPG_SECRET_KEY` | `publish-maven.yml` | GPG private key for signing Maven artifacts | +| `GPG_PASSPHRASE` | `publish-maven.yml` | Passphrase for the GPG key | +| `MAVEN_CENTRAL_USERNAME` | `publish-maven.yml`, `publish-snapshot.yml` | Sonatype/Maven Central credentials | +| `MAVEN_CENTRAL_PASSWORD` | `publish-maven.yml`, `publish-snapshot.yml` | Sonatype/Maven Central credentials | +| `COPILOT_GITHUB_TOKEN` | `build-test.yml`, `codegen-agentic-fix.lock.yml` | Token for Copilot CLI in CI | + +### 3B. Existing Secrets in copilot-sdk That May Conflict + +| Secret | Used By | Concern | +|---|---|---| +| `CARGO_REGISTRY_TOKEN` | `publish.yml` (Rust) | No conflict | +| `GH_AW_GITHUB_TOKEN` / `GH_AW_GITHUB_MCP_SERVER_TOKEN` | Agentic workflows | Likely already present; Java agentic workflows need the same | + +### 3C. Permissions / Access to Provision + +- [ ] **Repository secrets**: File a ticket to add the 6 Java-specific secrets to `github/copilot-sdk`. +- [ ] **CODEOWNERS team**: Ensure `@github/copilot-sdk-java` team has access to `github/copilot-sdk` and is added to CODEOWNERS for `java/**`. +- [ ] **Maven Central Trusted Publisher**: Currently configured for `github/copilot-sdk-java`. Must be updated to also allow publishing from `github/copilot-sdk` (or create a new namespace mapping). **This is the highest-risk permission issue** — Maven Central's Trusted Publisher setup ties the repository name to the publish flow. +- [ ] **GitHub Pages**: If `deploy-site.yml` moves, check if GitHub Pages is enabled on the monorepo and whether Java docs can coexist with any existing docs deployment. +- [ ] **Branch protection**: Ensure `main` branch protection rules in copilot-sdk permit the Java CI workflows (merge queues, required status checks, etc.). +- [ ] **Copilot coding agent**: Ensure the agent is enabled for `github/copilot-sdk` and the `copilot-setup-steps.yml` is updated to include Java tooling. + +--- + +## 4. Naming Convention Proposal + +### Current State + +The monorepo already uses a partially consistent pattern: + +- **Test workflows**: `{language}-sdk-tests.yml` (e.g., `dotnet-sdk-tests.yml`, `go-sdk-tests.yml`) +- **Cross-language workflows**: descriptive kebab-case names (e.g., `codegen-check.yml`, `publish.yml`) +- **Agentic workflows**: descriptive kebab-case (e.g., `issue-triage.md`, `handle-bug.md`) + +### Proposed Convention + +**Use kebab-case throughout. Language-specific workflows start with the language name.** + +#### Language-specific workflow naming: `{language}-{purpose}.yml` + +| Current (copilot-sdk) | Current (copilot-sdk-java) | Proposed New Name | +|---|---|---| +| `nodejs-sdk-tests.yml` | — | `nodejs-sdk-tests.yml` (keep) | +| `dotnet-sdk-tests.yml` | — | `dotnet-sdk-tests.yml` (keep) | +| `go-sdk-tests.yml` | — | `go-sdk-tests.yml` (keep) | +| `python-sdk-tests.yml` | — | `python-sdk-tests.yml` (keep) | +| `rust-sdk-tests.yml` | — | `rust-sdk-tests.yml` (keep) | +| — | `build-test.yml` | **`java-sdk-tests.yml`** | +| — | `publish-maven.yml` | **`java-publish.yml`** | +| — | `publish-snapshot.yml` | **`java-publish-snapshot.yml`** | +| — | `deploy-site.yml` | **`java-deploy-site.yml`** | +| — | `run-smoke-test.yml` | **`java-smoke-test.yml`** | +| — | `codegen-check.yml` | **Merge into existing `codegen-check.yml`** (add Java paths + job) | +| — | `codegen-agentic-fix.md` | **`java-codegen-fix.md`** + `.lock.yml` | +| — | `reference-impl-sync.md` | **`java-reference-impl-sync.md`** + `.lock.yml` (reworked for intra-repo) | +| — | `update-copilot-dependency.yml` | **Merge into existing `update-copilot-dependency.yml`** (add Java codegen step) | +| — | `copilot-setup-steps.yml` | **Merge into existing** (add JDK 17 + Maven setup) | +| — | `agentics-maintenance.yml` | Already exists via gh-aw in the monorepo; **do not duplicate** | + +#### Cross-language workflow naming: `{purpose}.yml` (no language prefix) + +Keep existing names: `publish.yml`, `codegen-check.yml`, `scenario-builds.yml`, `docs-validation.yml`, etc. + +#### Summary of naming rules + +1. **Language-specific** workflows: `{language}-{purpose}.yml` / `.md` +2. **Cross-language** workflows: `{purpose}.yml` / `.md` (no prefix) +3. **Kebab-case** throughout (already the convention) +4. **Agentic workflows**: same pattern but with `.md` extension +5. **Lock files**: auto-generated, always `{name}.lock.yml` + +--- + +## 5. Current Language Separation Assessment + +### Are the languages in copilot-sdk-00 already sufficiently separated? + +**Mostly yes, with a few cross-cutting concerns:** + +#### Well-separated + +- **Source code**: Each language lives in its own top-level directory (`nodejs/`, `python/`, `go/`, `dotnet/`, `rust/`). Java will go in `java/`. +- **Test workflows**: Each has its own `{language}-sdk-tests.yml` with path-scoped triggers (only fires on changes to that language's directory + `test/`). +- **Dependabot**: Already per-ecosystem, per-directory entries. + +#### Cross-cutting concerns (potential friction points) + +| Concern | Current State | Impact on Java | +|---|---|---| +| **Shared test harness** (`test/harness/`) | Node.js-based replay proxy used by all E2E tests | Java already uses this (clones it at build time from `copilot-sdk` repo). When in-repo, can reference it directly — **simpler**. | +| **Shared test snapshots** (`test/snapshots/`) | YAML snapshot files consumed by all languages | Java can share these — **positive change**. | +| **Unified codegen** (`scripts/codegen/`) | One `package.json` with generators for TS, C#, Python, Go, Rust | Java codegen (`java.ts`) must be **merged in**. The Java codegen currently has its own `package.json` with a direct `@github/copilot` dependency; the monorepo codegen gets it via `nodejs/node_modules`. This needs reconciliation. | +| **`justfile`** | Has per-language targets (`format-go`, `test-dotnet`, etc.) | Must add `format-java`, `lint-java`, `test-java`, `install-java` targets. | +| **Unified `publish.yml`** | Single workflow publishes all languages with one version number | **Java CANNOT join this** — Java has its own versioning scheme (`X.Y.Z-java.N`). Java must keep a separate `java-publish.yml`. | +| **`sdk-consistency-review`** agentic workflow | Reviews PRs for cross-SDK parity (currently watches nodejs, python, go, dotnet) | Must add `java/` to the path triggers and update the agent prompt to include Java. | +| **`copilot-setup-steps.yml`** | Sets up Node, Python, Go, .NET, Rust | Must add JDK 17 + Maven. | +| **`copilot-instructions.md`** | Monorepo-wide instructions | Must incorporate Java-specific guidance. | +| **`CODEOWNERS`** | Single `* @github/copilot-sdk` | Must add `java/ @github/copilot-sdk-java` line. | +| **`lsp.json`** | Configures C# and Go language servers for Copilot agent | May want to add Java LSP (jdtls or similar) — **optional**. | + +### The Big Question: `reference-impl-sync` + +Currently, the Java SDK has a scheduled workflow that polls `github/copilot-sdk` for new commits and creates issues for the Copilot agent to port. **This workflow is still needed** when Java lives in the same repo — the primary maintainers of `dotnet/` and `nodejs/` are not Java experts, and changes to those SDKs still need to be detected and ported into `java/`. + +What changes is the **mechanism**: instead of polling a remote repository, the workflow watches for commits that land on `main` touching `dotnet/src/` or `nodejs/src/` and compares against `java/.lastmerge` (which now stores a monorepo commit SHA rather than a cross-repo one). + +**Recommendation**: +1. **Keep `java/.lastmerge`** — it stores the last monorepo commit SHA whose `dotnet/`/`nodejs/` changes have been ported into Java. This is the anchor for diffing. +2. **Keep `reference-impl-sync` as `java-reference-impl-sync.md`** — reworked for intra-repo operation (see §6 Phase 4 for details). +3. **Keep `agentic-merge-reference-impl` skill** — reworked so that instead of cloning a remote repo, it reads diffs from the local `dotnet/` and `nodejs/` directories relative to the SHA in `java/.lastmerge`. +4. The `sdk-consistency-review` workflow provides an additional safety net on PRs, but is **not a replacement** for the scheduled sync — it only fires on PRs, not when changes land on `main` without Java updates. + +--- + +## 6. Migration Plan — Phases + +### Phase 0: Pre-Flight (Before Writing Any Code) + +- [ ] **Provision secrets** in `github/copilot-sdk` (see §3A) +- [ ] **Verify CODEOWNERS team** access +- [ ] **Check Maven Central Trusted Publisher** — can `github/copilot-sdk` publish to `com.github:copilot-sdk-java`? +- [ ] **Check GitHub Pages** — is it enabled? Can Java docs coexist? +- [ ] **Confirm branch protection** — will new required status checks be accepted? +- [ ] **Create tracking issue** in `github/copilot-sdk` for this migration +- [ ] **Freeze Java SDK changes** — declare a short freeze window in `copilot-sdk-java` to avoid merge conflicts during migration + +### Phase 1: Copy Source Code (No Workflows Yet) + +**Goal**: Get all Java source code building and testing in the monorepo without any CI/CD. + +1. Copy `copilot-sdk-java-00/` contents into `copilot-sdk-00/java/`: + - `src/` (main, test, generated, site) + - `pom.xml` + - `config/` (checkstyle, spotbugs) + - `scripts/codegen/` → merge `java.ts` into `copilot-sdk-00/scripts/codegen/` + - `CHANGELOG.md`, `README.md`, `jbang-example.java` + - `.lastmerge` → `java/.lastmerge` + - `.githooks/` → `java/.githooks/` + - `docs/adr/` → `java/docs/adr/` + - `instructions/` → `java/instructions/` (or merge into monorepo copilot-instructions) + +2. Update `pom.xml` paths if needed (should be self-contained under `java/`). + +3. Verify `mvn verify` works from `java/` directory locally. + +4. Add `justfile` targets for Java: + ```just + format-java: + @echo "=== Formatting Java code ===" + @cd java && mvn spotless:apply + + lint-java: + @echo "=== Linting Java code ===" + @cd java && mvn spotless:check + + test-java: + @echo "=== Testing Java code ===" + @cd java && mvn verify + + install-java: install-nodejs install-test-harness + @echo "=== Installing Java dependencies ===" + @cd java && mvn dependency:go-offline + ``` + +5. Update top-level `format`, `lint`, `test`, `install` recipes to include Java. + +### Phase 2: CI Workflows + +**Goal**: Java CI runs on PRs and main pushes within the monorepo. + +1. Create `java-sdk-tests.yml` (adapted from `build-test.yml`): + - Path triggers: `java/**`, `test/**`, `.github/workflows/java-sdk-tests.yml` + - Uses monorepo's `setup-copilot` action (or create `java/setup-copilot` action) + - Runs on 3 OS matrix (match other SDKs) + +2. Merge Java into `codegen-check.yml`: + - Add `java/src/generated/**` to path triggers + - Add a job that runs Java codegen and diffs + +3. Create `java-codegen-fix.md` (adapted from `codegen-agentic-fix.md`): + - Update paths, remove cross-repo references + - Compile with `gh aw compile` + +4. Merge Java into `copilot-setup-steps.yml`: + - Add JDK 17 setup step + - Add Maven cache + +5. Update `dependabot.yaml`: + - Add Maven ecosystem entry for `/java` + +6. Update `CODEOWNERS`: + - Add `java/ @github/copilot-sdk-java` + +### Phase 3: Publish Workflows + +**Goal**: Java can be independently published from the monorepo. + +1. Create `java-publish.yml` (adapted from `publish-maven.yml`): + - All paths updated to `java/` prefix + - Working directory set to `java/` + - Uses monorepo secrets + - **Independent trigger** — not part of the unified `publish.yml` + +2. Create `java-publish-snapshot.yml` (adapted from `publish-snapshot.yml`): + - Similar path/directory updates + +3. Create `java-deploy-site.yml` (adapted from `deploy-site.yml`): + - Adjust GitHub Pages setup for coexistence + - May need a subdirectory deployment strategy + +4. Create `java-smoke-test.yml` (adapted from `run-smoke-test.yml`). + +5. Migrate `notes.template` to `java/.github/notes.template` or similar. + +### Phase 4: Agentic Workflows and Skills + +**Goal**: Agentic automation works for Java within the monorepo. + +1. **`reference-impl-sync`** → **`java-reference-impl-sync.md`** — **REWORK** for intra-repo operation: + - **Trigger**: `schedule` (daily) + `workflow_dispatch` (same as today) + - **Behavior change**: Instead of cloning `github/copilot-sdk` and comparing commits, it: + 1. Reads `java/.lastmerge` (now a monorepo commit SHA) + 2. Runs `git log ..HEAD -- dotnet/src/ nodejs/src/` to find new reference-impl changes + 3. If changes exist → creates an issue assigned to Copilot agent (same as today) + 4. If no changes → closes stale sync issues (same as today) + - **Key simplification**: No cross-repo clone, no remote URL handling, no token for external repo access + - **Compile**: `gh aw compile java-reference-impl-sync.md` + +2. **`agentic-merge-reference-impl` skill** — **REWORK** for intra-repo operation: + - **Current behavior**: Clones `github/copilot-sdk`, checks out the target commit, computes a diff of `dotnet/src/` and `nodejs/src/` against the Java repo's `.lastmerge`, then applies equivalent Java changes. + - **New behavior**: + 1. Reads `java/.lastmerge` to get the base commit SHA + 2. Computes `git diff ..HEAD -- dotnet/src/ nodejs/src/` (all local, no clone needed) + 3. Analyzes the diff to identify what changed semantically (new methods, renamed types, new events, etc.) + 4. Applies equivalent idiomatic Java changes under `java/src/` + 5. Runs `mvn verify` from `java/` to validate + 6. Updates `java/.lastmerge` to the current HEAD SHA + 7. Commits and pushes (via `commit-as-pull-request` skill or direct push) + - **Scripts to update**: `.github/scripts/reference-impl-sync/` — all 5 scripts assume cross-repo operation: + - `merge-reference-impl-start.sh` — remove `git clone`, replace with local `git diff` + - `merge-reference-impl-diff.sh` — simplify to intra-repo diff + - `merge-reference-impl-finish.sh` — update `java/.lastmerge` with monorepo SHA + - `sync-cli-version-from-reference-impl.sh` — now reads from local `nodejs/package.json` directly + - `sync-codegen-version.sh` — now reads from local `scripts/codegen/package.json` + - **Prompt files to update**: + - `.github/prompts/agentic-merge-reference-impl.prompt.md` — remove cross-repo instructions, add intra-repo paths + - `.github/prompts/coding-agent-merge-reference-impl-instructions.md` — same + - **SKILL.md** — update with new paths and simplified flow + +3. **`sdk-consistency-review`** — Update: + - Add `java/**` to path triggers in the `.md` frontmatter + - Update agent prompt to include Java in the list of SDKs to review + +4. **`issue-triage`** — Update: + - Add `sdk/java` label to the list of per-SDK labels + +5. Merge `agentic-workflows.agent.md` — use the monorepo's (newer) version, no action needed. + +6. Migrate `documentation-coverage` skill to monorepo's skills directory (as `java-documentation-coverage`). + +7. Migrate `commit-as-pull-request` skill (check if monorepo already has equivalent). + +### Phase 5: Cross-Cutting Updates + +1. Update monorepo `copilot-instructions.md` to include Java section. +2. Update monorepo `README.md` to list Java as a supported language. +3. Update `scenario-builds.yml` to include Java scenarios (if applicable). +4. Update `docs-validation.yml` to include Java code snippets. +5. Update `lsp.json` to add Java LSP config (optional). +6. Add Java to `docs/` getting-started and feature pages. +7. Update `sdk-protocol-version.json` if Java needs it. + +### Phase 6: Cutover and Cleanup + +1. **Disable CI** in `copilot-sdk-java` (remove or disable workflows). +2. **Archive** `copilot-sdk-java` repo (make read-only). +3. **Update external references**: + - Maven Central POM `` URLs + - README badges pointing to the new repo + - Javadoc.io configuration + - Any links in copilot documentation +4. **Remove duplicate resources** that were merged rather than moved. +5. **Run full CI** in monorepo to validate everything. + +--- + +## 7. Pitfalls and Risk Register + +### HIGH RISK + +| # | Risk | Impact | Mitigation | +|---|---|---|---| +| H1 | **Maven Central Trusted Publisher** repo-name mismatch | Cannot publish Java releases from monorepo | Verify/update Trusted Publisher config in Maven Central **before** migration. If the GAV is bound to `github/copilot-sdk-java`, it must be updated. | +| H2 | **Unified `publish.yml` version collision** | All SDKs in monorepo share one version. Java has independent `X.Y.Z-java.N` versions. | Java must keep a **separate** publish workflow. Do NOT merge into `publish.yml`. | +| H3 | **`agentic-merge-reference-impl` breaks** | The core Java development loop relies on this skill to stay in sync with .NET/Node changes | Must be carefully reworked for intra-repo operation before cutover. Test thoroughly with a dry-run on a feature branch. The skill + its 5 shell scripts + 2 prompt files all assume cross-repo cloning. | +| H4 | **Secret provisioning delay** | Can't publish or run full CI until secrets are provisioned | Start secret provisioning **immediately** (Phase 0). | +| H5 | **Test harness path changes** | Java E2E tests currently clone `copilot-sdk` at build time to get `test/harness/` and `test/snapshots/`. In-repo, these paths change. | Update `pom.xml` and test infrastructure to reference local `test/` directory instead of cloning. **This simplifies things significantly.** | + +### MEDIUM RISK + +| # | Risk | Impact | Mitigation | +|---|---|---|---| +| M1 | **Codegen `package.json` merge** | Java codegen has its own `@github/copilot` dependency; monorepo codegen gets it from `nodejs/node_modules` | Align Java codegen to use the same dependency source. May need to add `generate:java` script to monorepo's `scripts/codegen/package.json`. | +| M2 | **GitHub Pages conflict** | Java deploys versioned docs to Pages. Monorepo may have its own Pages setup. | Use subdirectory deployment or a separate Pages branch for Java. | +| M3 | **Branch protection / required checks** | New `java-sdk-tests` check may not be in the required list | Add to branch protection after first successful run. | +| M4 | **CODEOWNERS team permissions** | `@github/copilot-sdk-java` team may not have write access to `github/copilot-sdk` | Verify team access and add to repo collaborators. | +| M5 | **`copilot-setup-steps.yml` bloat** | Adding JDK + Maven makes agent setup slower for non-Java tasks | Acceptable trade-off; other languages already add their tools. Could consider conditional setup but that's over-engineering. | +| M6 | **gh-aw version mismatch** | Java repo uses gh-aw `v0.68.3` setup action pinned at `v0.71.5`; monorepo uses `v0.64.2` reference in docs | Align gh-aw versions. Use the newer version. Recompile all `.lock.yml` files. | + +### LOW RISK + +| # | Risk | Impact | Mitigation | +|---|---|---|---| +| L1 | **Issue template conflicts** | Java has custom issue templates; monorepo uses agentic triage | Monorepo agentic triage covers this. Can add Java-specific labels. | +| L2 | **PR template differences** | Different PR templates | Use monorepo's template. Java-specific guidance in CONTRIBUTING.md. | +| L3 | **`.githooks` scope** | Java pre-commit hook runs `mvn spotless:check` globally | Scope hook to only run when Java files are changed. | +| L4 | **Duplicate `agentics-maintenance.yml`** | Java repo has its own; monorepo will generate one | The monorepo's gh-aw will handle this automatically. Don't migrate. | + +--- + +## 8. Post-Migration Verification Checklist + +### CI/CD +- [ ] `java-sdk-tests.yml` passes on all 3 OS platforms +- [ ] `codegen-check.yml` includes Java and passes +- [ ] `java-codegen-fix.md` compiles and agentic workflow functions +- [ ] `java-publish.yml` can do a dry-run publish +- [ ] `java-publish-snapshot.yml` publishes a SNAPSHOT +- [ ] `java-smoke-test.yml` passes on JDK 17 + JDK 25 +- [ ] `java-deploy-site.yml` successfully deploys docs + +### Integration +- [ ] `copilot-setup-steps.yml` includes JDK and Maven +- [ ] `dependabot.yaml` includes Maven ecosystem for `java/` +- [ ] `CODEOWNERS` includes `java/` path +- [ ] `justfile` has all Java targets and `just test` includes Java +- [ ] `sdk-consistency-review` includes `java/` in path triggers +- [ ] `issue-triage` knows about `sdk/java` label + +### Code +- [ ] `mvn verify` passes from `java/` directory +- [ ] E2E tests use local `test/harness/` and `test/snapshots/` (no cloning) +- [ ] Java codegen integrated into `scripts/codegen/` +- [ ] `.lastmerge` exists at `java/.lastmerge` + +### Documentation +- [ ] Monorepo `README.md` lists Java +- [ ] `copilot-instructions.md` includes Java guidance +- [ ] `java/README.md` links updated to monorepo +- [ ] Maven Central POM `` URLs updated + +### Agentic Sync +- [ ] `java-reference-impl-sync.md` compiles and detects new dotnet/nodejs changes via local `git log` +- [ ] `agentic-merge-reference-impl` skill works intra-repo (no cross-repo clone) +- [ ] `java/.lastmerge` correctly stores monorepo commit SHAs +- [ ] Sync scripts in `.github/scripts/java/reference-impl-sync/` use local paths + +### Cleanup +- [ ] `copilot-sdk-java` repo archived +- [ ] No broken links to old repo +- [ ] No duplicate `agentics-maintenance.yml` + +--- + +## Appendix A: Files to Copy vs. Merge vs. Delete + +| Source File (copilot-sdk-java-00) | Action | Target Location (copilot-sdk-00) | +|---|---|---| +| `src/` | Copy | `java/src/` | +| `config/` | Copy | `java/config/` | +| `pom.xml` | Copy + update paths | `java/pom.xml` | +| `CHANGELOG.md` | Copy | `java/CHANGELOG.md` | +| `README.md` | Copy + update links | `java/README.md` | +| `jbang-example.java` | Copy | `java/jbang-example.java` | +| `.lastmerge` | Copy | `java/.lastmerge` | +| `.githooks/pre-commit` | Copy + scope to Java changes | `java/.githooks/pre-commit` | +| `docs/adr/` | Copy | `java/docs/adr/` | +| `scripts/codegen/java.ts` | Copy | `scripts/codegen/java.ts` | +| `scripts/codegen/package.json` | **Merge** deps into monorepo's | `scripts/codegen/package.json` | +| `.github/workflows/build-test.yml` | **Adapt** → rename | `.github/workflows/java-sdk-tests.yml` | +| `.github/workflows/publish-maven.yml` | **Adapt** → rename | `.github/workflows/java-publish.yml` | +| `.github/workflows/publish-snapshot.yml` | **Adapt** → rename | `.github/workflows/java-publish-snapshot.yml` | +| `.github/workflows/deploy-site.yml` | **Adapt** → rename | `.github/workflows/java-deploy-site.yml` | +| `.github/workflows/run-smoke-test.yml` | **Adapt** → rename | `.github/workflows/java-smoke-test.yml` | +| `.github/workflows/codegen-check.yml` | **Merge** into existing | `.github/workflows/codegen-check.yml` | +| `.github/workflows/codegen-agentic-fix.md` | **Adapt** → rename | `.github/workflows/java-codegen-fix.md` | +| `.github/workflows/update-copilot-dependency.yml` | **Merge** into existing | `.github/workflows/update-copilot-dependency.yml` | +| `.github/workflows/copilot-setup-steps.yml` | **Merge** into existing | `.github/workflows/copilot-setup-steps.yml` | +| `.github/workflows/reference-impl-sync.md` + `.lock.yml` | **Adapt** → rename + rework for intra-repo | `.github/workflows/java-reference-impl-sync.md` + `.lock.yml` | +| `.github/workflows/agentics-maintenance.yml` | **DELETE** (monorepo has its own) | — | +| `.github/workflows/notes.template` | Copy | `.github/workflows/java-notes.template` | +| `.github/actions/setup-copilot/` | **Adapt** or merge | `.github/actions/java-setup-copilot/` or merge | +| `.github/actions/test-report/` | Copy | `.github/actions/java-test-report/` | +| `.github/scripts/*` | Copy + update paths | `.github/scripts/java/` (new subdirectory) | +| `.github/skills/agentic-merge-reference-impl/` | **Rework** for intra-repo (remove cross-repo clone, use local git diff) | `.github/skills/java-merge-reference-impl/` | +| `.github/skills/commit-as-pull-request/` | Check for duplicates | `.github/skills/commit-as-pull-request/` | +| `.github/skills/documentation-coverage/` | Copy | `.github/skills/java-documentation-coverage/` | +| `.github/prompts/*` | Copy + update | `.github/prompts/` (prefix with `java-` if needed) | +| `.github/dependabot.yml` | **Merge** into existing | `.github/dependabot.yaml` | +| `.github/CODEOWNERS` | **Merge** into existing | `.github/CODEOWNERS` | +| `.github/copilot-instructions.md` | **Merge** into existing | `.github/copilot-instructions.md` | +| `.github/release.yml` | **Merge** into existing | `.github/release.yml` (if it exists) | +| `.github/ISSUE_TEMPLATE/*` | Evaluate — likely skip | — | +| `.github/pull_request_template.md` | Evaluate — likely skip | — | +| `.github/templates/` | Copy | `java/.github/templates/` or `java/src/site/` | +| `instructions/` | Move | `java/instructions/` | +| `test` (file, not directory) | Copy if needed | `java/test` | + +## Appendix B: Unique Java Concerns vs Other Languages + +| Concern | Java | Other Languages | Notes | +|---|---|---|---| +| **Build system** | Maven (`pom.xml`) | npm, pip, go mod, dotnet, cargo | Fully self-contained under `java/` | +| **Versioning** | `X.Y.Z-java.N` (independent) | Shared `X.Y.Z` across all others | **Must keep separate publish workflow** | +| **Code formatting** | Spotless (Eclipse formatter) | prettier, ruff, gofmt, dotnet format, rustfmt | Runs only on Java files | +| **Test framework** | JUnit + Surefire | Vitest, pytest, go test, xunit, cargo test | Standard; no conflicts | +| **E2E test harness** | Clones `copilot-sdk` at build time | References local `test/harness/` | **Major simplification** when in-repo | +| **Codegen** | Own `java.ts` + own `@github/copilot` dep | Shared codegen scripts + shared dep | Needs reconciliation | +| **CI runner** | JDK 17 + JDK 25 (smoke test) | Node 22, Python 3.12, Go 1.24, .NET 10, Rust 1.94 | Just another tool in `copilot-setup-steps.yml` | +| **Publishing** | Maven Central (GPG + Sonatype) | npm, PyPI, NuGet, crates.io, Go tags | Completely different mechanism | +| **Docs hosting** | GitHub Pages (Maven site) | Not clear if monorepo has its own | Potential conflict | +| **Reference impl tracking** | `.lastmerge` + scheduled sync + agentic merge skill | N/A (they ARE the reference impl) | `.lastmerge` stores monorepo SHA; sync becomes intra-repo but is still needed because Java maintainers ≠ .NET/Node maintainers | + +--- + +## Appendix C: Java Smoketest + +### Overview + +The Java SDK has an AI-driven smoke test that validates the SDK's Quick Start code actually compiles and runs. The test is **prompt-driven**: the `run-smoke-test.yml` workflow invokes the Copilot CLI (`copilot --yolo`) with a prompt that instructs it to read the repository's `README.md`, extract the Quick Start code and Maven coordinates, generate a standalone Maven project, build it, and run it. Success = exit code 0. + +This design intentionally tests the README itself — if the documented code doesn't compile against the published artifact, the smoke test fails rather than silently fixing the code. This catches documentation drift. + +### How It Works Today + +1. **`src/test/prompts/PROMPT-smoke-test.md`** — The master prompt. It instructs the Copilot CLI to: + - Read the top-level `README.md` + - Extract the **"Snapshot Builds"** section (Maven GAV + snapshots repository config) + - Extract the **"Quick Start"** section (verbatim Java source code) + - Create a `smoke-test/` Maven project using those extracted values + - Build with `mvn -U clean package` + +2. **`run-smoke-test.yml`** — The workflow. It: + - Builds the SDK and installs it to the local Maven repo + - Feeds the prompt to `copilot --yolo` with overrides (use `--no-snapshot-updates`, stop after build) + - Runs the built jar in a separate deterministic step + - Has two jobs: `smoke-test-jdk17` and `smoke-test-java25` (the latter also applies virtual thread modifications via `// JDK 25+:` comments) + +3. **`build-test.yml`** — Calls `run-smoke-test.yml` as a reusable workflow. The main SDK test suite (`java-sdk` job) depends on the smoke test and only runs if it doesn't fail. + +### What Breaks When Moving to the Monorepo + +The smoke test prompt (`PROMPT-smoke-test.md`) contains these instructions: + +> Read the file `README.md` at the top level of this repository. You will need two sections from it: **"Snapshot Builds"** and **"Quick Start"** + +After migration, the **top-level `README.md`** is the monorepo's README (`copilot-sdk-00/README.md`), which does not contain a "Snapshot Builds" section or a "Quick Start" section with Java code. The Java-specific README moves to `java/README.md`. + +Additionally, the monorepo's top-level README contains Quick Start code for **other languages** (TypeScript, Python, Go, C#). If the prompt were naively updated to "read the README," the AI agent might extract the wrong language's code. + +### Required Changes + +#### 1. Update `PROMPT-smoke-test.md` — change the README path + +Replace: +``` +Read the file `README.md` at the top level of this repository. +``` + +With: +``` +Read the file `java/README.md` in this repository. +``` + +This is the only structural change needed in the prompt. The section names ("Snapshot Builds" and "Quick Start") remain the same in `java/README.md`. + +#### 2. Update `java/README.md` — ensure required sections survive the move + +The prompt depends on two specific sections by name: + +- **"Snapshot Builds"** — must contain the Maven GAV with `-SNAPSHOT` version and the `central-snapshots` repository XML +- **"Quick Start"** — must contain the verbatim Java source code with `// JDK 25+:` inline comments for virtual thread toggling + +When migrating `README.md` → `java/README.md`, these sections and their content must be preserved exactly. The current monorepo placeholder at `java/README.md` has a different Quick Start (different class name `QuickStart` vs `CopilotSDK`, different imports, no `// JDK 25+:` comments, no `System.exit` logic, no usage metrics handling). **The migrated `README.md` from `copilot-sdk-java` must replace the monorepo placeholder**, not the other way around. + +#### 3. Update `run-smoke-test.yml` → `java-smoke-test.yml` — working directory + +The workflow steps that run `mvn` and reference `src/test/prompts/PROMPT-smoke-test.md` assume the repo root is the Java project root. After migration: + +- Add `working-directory: ./java` to the "Build SDK and install to local repo" step +- Update the prompt text from `src/test/prompts/PROMPT-smoke-test.md` to `java/src/test/prompts/PROMPT-smoke-test.md` (or set working directory before invoking `copilot`) +- Update the `cd smoke-test` step to `cd java/smoke-test` +- Update the `uses: ./.github/actions/setup-copilot` reference to point to the monorepo's setup action (or a Java-specific one at `.github/actions/java-setup-copilot/`) + +#### 4. Update `build-test.yml` → `java-sdk-tests.yml` — smoke test call + +The current `build-test.yml` calls: +```yaml +uses: ./.github/workflows/run-smoke-test.yml +``` + +After rename, update to: +```yaml +uses: ./.github/workflows/java-smoke-test.yml +``` + +### Risk Assessment + +| Risk | Severity | Notes | +|---|---|---| +| Prompt reads wrong README | **HIGH** | If `PROMPT-smoke-test.md` still says "top level README," the AI agent reads the monorepo README and fails or extracts wrong-language code | +| `java/README.md` placeholder overwrites real content | **HIGH** | The monorepo already has a `java/README.md` with a different Quick Start. Must be replaced with the full Java SDK README during migration | +| `smoke-test/` directory created at wrong location | **MEDIUM** | Without `working-directory: ./java`, the smoke test project gets created at the monorepo root instead of under `java/` | +| `// JDK 25+:` comments missing from Quick Start | **MEDIUM** | The JDK 25 smoke test job relies on these comments to toggle virtual thread support. Missing comments → JDK 25 job builds without virtual threads and still passes (silent regression, not a failure) | + +### Verification Checklist + +- [ ] `PROMPT-smoke-test.md` references `java/README.md`, not `README.md` +- [ ] `java/README.md` contains "Snapshot Builds" and "Quick Start" sections with the full content from `copilot-sdk-java` +- [ ] Quick Start code includes `// JDK 25+:` inline comments and `System.exit` logic +- [ ] `java-smoke-test.yml` uses `working-directory: ./java` for Maven steps +- [ ] `java-smoke-test.yml` references the correct prompt path +- [ ] `java-sdk-tests.yml` calls `java-smoke-test.yml` (not `run-smoke-test.yml`) +- [ ] Smoke test passes locally from `java/` subdirectory before merging From 6b3e54d8f772e0bc8c51151f11a4fd5213bcb165 Mon Sep 17 00:00:00 2001 From: Ed Burns Date: Tue, 12 May 2026 18:32:51 -0700 Subject: [PATCH 2/6] refine to get ready for plan review --- .../20260512-prompts.md | 66 +++ .../dd-2989727-move-java-to-monorepo-plan.md | 403 +++++++++--------- 2 files changed, 274 insertions(+), 195 deletions(-) diff --git a/80-java-monorepo-add-01-remove-before-merge/20260512-prompts.md b/80-java-monorepo-add-01-remove-before-merge/20260512-prompts.md index 36606fa96..8073365b7 100644 --- a/80-java-monorepo-add-01-remove-before-merge/20260512-prompts.md +++ b/80-java-monorepo-add-01-remove-before-merge/20260512-prompts.md @@ -364,3 +364,69 @@ The migration is naturally split into what the plan calls Phases 1-2 (source cod The key question is whether you merge Phases 1-2 as one PR and then iterate Phases 3-4 as follow-up PRs on `main`, or whether you try to land everything in one big PR and accept that the `main`-gated pieces are unvalidated until merge. The former is safer — a broken smoke test workflow is recoverable, but a broken `java-sdk-tests.yml` that blocks the merge queue is not. The risk register items H1 (Maven Central Trusted Publisher), H4 (secret provisioning), and M3 (branch protection) are all in this "can't validate until `main`" category, which is why Phase 0 (pre-flight) exists — those should be resolved **before** any code lands. + +### 18:25 Prompt + +Consider this "MEDIUM RISK" item: + +``` +| M1 | **Codegen `package.json` merge** | Java codegen has its own `@github/copilot` dependency; monorepo codegen gets it from `nodejs/node_modules` | Align Java codegen to use the same dependency source. May need to add `generate:java` script to monorepo's `scripts/codegen/package.json`. | +``` + +I am inclined to **not** put the codegen into the monorepo's + +``` +| `.github/workflows/codegen-check.yml` | **Merge** into existing | `.github/workflows/codegen-check.yml` | +``` + +For fear of messing up existing non-Java aspects. What are the pros and cons of keeping this separate? + +### 18:28 Prompt + +Good instinct. This is the same logic as the `just` discussion — Java is self-contained and doesn't need to be force-fitted into the existing cross-language machinery. + +## Pros of keeping Java codegen separate (`java-codegen-check.yml`) + +- **Zero blast radius** — you cannot break Node/C#/Python/Go/Rust codegen. This is the strongest argument. +- **No JDK in codegen-check.yml** — the existing workflow installs Node, Go, and Rust. Adding JDK + Maven for one more language bloats it and slows it for everyone. +- **update-copilot-dependency.yml stays untouched** — that workflow runs `npm run generate` and formats for nodejs/dotnet/rust. Keeping Java out means no changes to a workflow that touches all other languages. +- **Independent `@github/copilot` version cadence** — Java already lags the reference impl by design (it's ported, not in lockstep). Forcing the same `@github/copilot` version across all codegen could break Java if a schema change hasn't been ported yet. +- **Consistent with Java's independent versioning** — Java already has its own publish workflow, its own version scheme. Separate codegen follows the same principle. + +## Cons of keeping it separate + +- **`@github/copilot` version drift** — when the monorepo updates to `@github/copilot@1.0.50`, Java might still be on `1.0.45`. This is intentional but could confuse contributors who expect uniformity. Need to document it. +- **Two codegen check workflows** — more YAML to maintain, two required status checks instead of one. +- **Java needs its own `update-copilot-dependency` mechanism** — the existing workflow won't cover Java, so you need a separate `java-update-copilot-dependency.yml` (or keep the one from `copilot-sdk-java` adapted for monorepo paths). +- **java.ts location is awkward** — if the file lives in codegen alongside the others but isn't in the shared `generate` script, it's confusing. If it lives in `java/scripts/codegen/`, it's clear but diverges from the monorepo layout. + +## Recommendation + +Keep it separate. The version-drift con is actually a **feature** — it's how the Java SDK already works, and the `reference-impl-sync` mechanism handles catching up deliberately. The `java.ts` location question resolves cleanly: put it in `java/scripts/codegen/` with its own package.json, making the boundary explicit. This also means Appendix A should change from: + +> java.ts → Copy → java.ts + +to: + +> java.ts → Copy → `java/scripts/codegen/java.ts` + +### 18:28 Prompt + +Yes, do change Appendix A. + +### 18:29 Response + +Replacing 2 lines with 2 lines in [](file:///e%3A/workareas/copilot-sdk-java-00/temporary-prompts/dd-2989727-move-java-to-monorepo-plan.md) + + +``` + +``` +Done. Both the `java.ts` and its package.json now stay self-contained under `java/scripts/codegen/` instead of merging into the monorepo's shared codegen. + +Made changes. + +### 18:30 Prompt + +Actually, I am now keeping `dd-2989727-move-java-to-monorepo-plan.md` under version control in `.\80-java-monorepo-add-01-remove-before-merge\dd-2989727-move-java-to-monorepo-plan.md` in `copilot-sdk-00`. Make the changes there. + diff --git a/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md b/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md index a370fc574..1f533aaee 100644 --- a/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md +++ b/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md @@ -10,6 +10,7 @@ 6. [Migration Plan — Phases](#6-migration-plan--phases) 7. [Pitfalls and Risk Register](#7-pitfalls-and-risk-register) 8. [Post-Migration Verification Checklist](#8-post-migration-verification-checklist) + - [Appendix A: Files to Copy vs. Merge vs. Delete](#appendix-a-files-to-copy-vs-merge-vs-delete) - [Appendix B: Unique Java Concerns vs Other Languages](#appendix-b-unique-java-concerns-vs-other-languages) - [Appendix C: Java Smoketest](#appendix-c-java-smoketest) @@ -20,48 +21,48 @@ ### 1A. copilot-sdk-java-00 Workflows (Source) -| YAML File Name | Brief Description | Primary Language | Complexity | -|---|---|---|---| -| `build-test.yml` | Main CI: Spotless, build, Javadoc, `mvn verify`, JaCoCo coverage badges | Java | L | -| `codegen-check.yml` | Re-runs Java codegen, commits regenerated files to PRs, triggers agentic fix on failure | Java | M | -| `codegen-agentic-fix.md` + `.lock.yml` | Agentic: auto-fixes compilation/test failures caused by codegen changes | Java | L | -| `reference-impl-sync.md` + `.lock.yml` | Agentic: checks for new commits in `github/copilot-sdk`, creates issue for Copilot agent to port | Java | L | -| `publish-maven.yml` | Publishes release to Maven Central via `maven-release-plugin`, GPG signing, GitHub Release creation | Java | XL | -| `publish-snapshot.yml` | Publishes SNAPSHOT builds to Maven Central Snapshots on a weekday schedule | Java | M | -| `deploy-site.yml` | Builds/deploys versioned Maven site docs to GitHub Pages | Java | M | -| `run-smoke-test.yml` | Builds SDK, installs locally, runs Copilot CLI smoke test on JDK 17 + JDK 25 (see [Appendix C](#appendix-c-java-smoketest)) | Java | M | -| `update-copilot-dependency.yml` | Updates `@github/copilot` npm dep in codegen, re-runs generator, creates PR | Java | M | -| `copilot-setup-steps.yml` | Environment setup for Copilot coding agent (JDK 17, Node 22, gh-aw, pre-commit hooks) | Java | S | -| `agentics-maintenance.yml` | Auto-generated gh-aw maintenance: closes expired discussions/issues/PRs | Cross-language (infra) | S | -| `notes.template` | Release notes template for Maven Central (not a workflow) | Java | S | +| YAML File Name | Brief Description | Primary Language | Complexity | +| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ---------- | +| `build-test.yml` | Main CI: Spotless, build, Javadoc, `mvn verify`, JaCoCo coverage badges | Java | L | +| `codegen-check.yml` | Re-runs Java codegen, commits regenerated files to PRs, triggers agentic fix on failure | Java | M | +| `codegen-agentic-fix.md` + `.lock.yml` | Agentic: auto-fixes compilation/test failures caused by codegen changes | Java | L | +| `reference-impl-sync.md` + `.lock.yml` | Agentic: checks for new commits in `github/copilot-sdk`, creates issue for Copilot agent to port | Java | L | +| `publish-maven.yml` | Publishes release to Maven Central via `maven-release-plugin`, GPG signing, GitHub Release creation | Java | XL | +| `publish-snapshot.yml` | Publishes SNAPSHOT builds to Maven Central Snapshots on a weekday schedule | Java | M | +| `deploy-site.yml` | Builds/deploys versioned Maven site docs to GitHub Pages | Java | M | +| `run-smoke-test.yml` | Builds SDK, installs locally, runs Copilot CLI smoke test on JDK 17 + JDK 25 (see [Appendix C](#appendix-c-java-smoketest)) | Java | M | +| `update-copilot-dependency.yml` | Updates `@github/copilot` npm dep in codegen, re-runs generator, creates PR | Java | M | +| `copilot-setup-steps.yml` | Environment setup for Copilot coding agent (JDK 17, Node 22, gh-aw, pre-commit hooks) | Java | S | +| `agentics-maintenance.yml` | Auto-generated gh-aw maintenance: closes expired discussions/issues/PRs | Cross-language (infra) | S | +| `notes.template` | Release notes template for Maven Central (not a workflow) | Java | S | ### 1B. copilot-sdk-00 Workflows (Target Monorepo) -| YAML File Name | Brief Description | Primary Language | Complexity | -|---|---|---|---| -| `nodejs-sdk-tests.yml` | Build + test Node.js SDK on 3 OS, prettier, ESLint, typecheck, E2E | Node.js | L | -| `dotnet-sdk-tests.yml` | Build + test .NET SDK on 3 OS, format check, E2E via replay proxy | .NET | L | -| `go-sdk-tests.yml` | Build + test Go SDK on 3 OS, gofmt, golangci-lint, E2E | Go | L | -| `python-sdk-tests.yml` | Build + test Python SDK on 3 OS, ruff, ty, E2E via pytest | Python | L | -| `rust-sdk-tests.yml` | Build + test Rust SDK on 3 OS, nightly fmt, clippy, cargo test | Rust | L | -| `codegen-check.yml` | Verifies generated files across Node, .NET, Python, Go, Rust | Cross-language | M | -| `publish.yml` | Publishes all SDKs (npm, NuGet, PyPI, Go tags, crates.io) from a single version | Cross-language | XL | -| `scenario-builds.yml` | Verifies example scenarios build for each language | Cross-language | M | -| `docs-validation.yml` | Extracts and validates code snippets from `docs/` | Cross-language | M | -| `update-copilot-dependency.yml` | Updates `@github/copilot` dep, re-runs codegen, opens PR | Cross-language | M | -| `copilot-setup-steps.yml` | Agent env setup: Node, Python, Go, .NET, Rust, just, gh-aw | Cross-language | M | -| `verify-compiled.yml` | Ensures `.lock.yml` files match `.md` sources | Cross-language (infra) | S | -| `collect-corrections.yml` | Collects triage agent feedback | Cross-language (infra) | S | -| `corrections-tests.yml` | Tests for triage correction scripts | Cross-language (infra) | S | -| `issue-classification.md` + `.lock.yml` | Agentic: classifies issues → routes to handle-* handlers | Cross-language | M | -| `issue-triage.md` + `.lock.yml` | Agentic: labels, acknowledges, requests clarification, closes dupes | Cross-language | L | -| `handle-bug.md` + `.lock.yml` | Agentic: investigates bug issues | Cross-language | M | -| `handle-documentation.md` + `.lock.yml` | Agentic: handles doc-related issues | Cross-language | S | -| `handle-enhancement.md` + `.lock.yml` | Agentic: labels enhancement issues | Cross-language | S | -| `handle-question.md` + `.lock.yml` | Agentic: labels question issues | Cross-language | S | -| `cross-repo-issue-analysis.md` + `.lock.yml` | Agentic: checks if issue root cause is in copilot-agent-runtime | Cross-language | M | -| `release-changelog.md` + `.lock.yml` | Agentic: generates release notes, updates CHANGELOG | Cross-language | M | -| `sdk-consistency-review.md` + `.lock.yml` | Agentic: reviews PRs for cross-SDK feature parity | Cross-language | L | +| YAML File Name | Brief Description | Primary Language | Complexity | +| -------------------------------------------- | ------------------------------------------------------------------------------- | ---------------------- | ---------- | +| `nodejs-sdk-tests.yml` | Build + test Node.js SDK on 3 OS, prettier, ESLint, typecheck, E2E | Node.js | L | +| `dotnet-sdk-tests.yml` | Build + test .NET SDK on 3 OS, format check, E2E via replay proxy | .NET | L | +| `go-sdk-tests.yml` | Build + test Go SDK on 3 OS, gofmt, golangci-lint, E2E | Go | L | +| `python-sdk-tests.yml` | Build + test Python SDK on 3 OS, ruff, ty, E2E via pytest | Python | L | +| `rust-sdk-tests.yml` | Build + test Rust SDK on 3 OS, nightly fmt, clippy, cargo test | Rust | L | +| `codegen-check.yml` | Verifies generated files across Node, .NET, Python, Go, Rust | Cross-language | M | +| `publish.yml` | Publishes all SDKs (npm, NuGet, PyPI, Go tags, crates.io) from a single version | Cross-language | XL | +| `scenario-builds.yml` | Verifies example scenarios build for each language | Cross-language | M | +| `docs-validation.yml` | Extracts and validates code snippets from `docs/` | Cross-language | M | +| `update-copilot-dependency.yml` | Updates `@github/copilot` dep, re-runs codegen, opens PR | Cross-language | M | +| `copilot-setup-steps.yml` | Agent env setup: Node, Python, Go, .NET, Rust, just, gh-aw | Cross-language | M | +| `verify-compiled.yml` | Ensures `.lock.yml` files match `.md` sources | Cross-language (infra) | S | +| `collect-corrections.yml` | Collects triage agent feedback | Cross-language (infra) | S | +| `corrections-tests.yml` | Tests for triage correction scripts | Cross-language (infra) | S | +| `issue-classification.md` + `.lock.yml` | Agentic: classifies issues → routes to handle-\* handlers | Cross-language | M | +| `issue-triage.md` + `.lock.yml` | Agentic: labels, acknowledges, requests clarification, closes dupes | Cross-language | L | +| `handle-bug.md` + `.lock.yml` | Agentic: investigates bug issues | Cross-language | M | +| `handle-documentation.md` + `.lock.yml` | Agentic: handles doc-related issues | Cross-language | S | +| `handle-enhancement.md` + `.lock.yml` | Agentic: labels enhancement issues | Cross-language | S | +| `handle-question.md` + `.lock.yml` | Agentic: labels question issues | Cross-language | S | +| `cross-repo-issue-analysis.md` + `.lock.yml` | Agentic: checks if issue root cause is in copilot-agent-runtime | Cross-language | M | +| `release-changelog.md` + `.lock.yml` | Agentic: generates release notes, updates CHANGELOG | Cross-language | M | +| `sdk-consistency-review.md` + `.lock.yml` | Agentic: reviews PRs for cross-SDK feature parity | Cross-language | L | --- @@ -69,42 +70,42 @@ ### 2A. copilot-sdk-java-00 -| Resource | Location | Purpose | Must Migrate? | -|---|---|---|---| -| **Agent:** `agentic-workflows.agent.md` | `.github/agents/` | Dispatcher for gh-aw workflow creation/debug | Yes (merge with monorepo version) | -| **Skill:** `agentic-merge-reference-impl` | `.github/skills/` + `.github/prompts/` | Merges reference impl changes into Java | Yes — **must be reworked** (no longer cross-repo) | -| **Skill:** `commit-as-pull-request` | `.github/skills/` + `.github/prompts/` | Creates branch, pushes, opens PR | Yes (may already exist in monorepo) | -| **Skill:** `documentation-coverage` | `.github/skills/` + `.github/prompts/` | Assesses Java docs coverage | Yes | -| **Prompt:** `coding-agent-merge-reference-impl-instructions.md` | `.github/prompts/` | Instructions for coding agent merge | Yes | -| **Prompt:** `test-coverage-assessment.prompt.md` | `.github/prompts/` | Test coverage assessment | Yes | -| **Composite Action:** `setup-copilot` | `.github/actions/setup-copilot/` | Sets up Copilot CLI for Java tests | Yes — **adapt paths** | -| **Composite Action:** `test-report` | `.github/actions/test-report/` | Test report generation | Yes | -| **Scripts:** `release/`, `ci/`, `build/`, `reference-impl-sync/` | `.github/scripts/` | Release, CI, sync automation | Yes — **path rewrites** | -| **Dependabot:** `dependabot.yml` | `.github/` | Maven + GitHub Actions updates | Merge into monorepo's `dependabot.yaml` | -| **CODEOWNERS** | `.github/` | `@github/copilot-sdk-java` | Merge into monorepo's CODEOWNERS | -| **Issue Templates:** bug, documentation, feature, maintenance | `.github/ISSUE_TEMPLATE/` | Issue forms | Assess whether monorepo issue triage covers this | -| **PR Template** | `.github/pull_request_template.md` | PR form | Merge or keep per-language | -| **Release Config** | `.github/release.yml` | Auto-generated release notes config | Merge | -| **copilot-instructions.md** | `.github/` | Agent instructions for Java SDK | Merge (scoped to `java/`) | -| **Site templates** | `.github/templates/` | HTML/CSS for GitHub Pages | Migrate to `java/` | -| **Coverage badge script** | `.github/scripts/generate-coverage-badge.sh` | JaCoCo badge generation | Migrate | -| **`.lastmerge`** | repo root | Tracks last merged ref-impl commit | **This concept changes** — see §6 | -| **`.githooks/pre-commit`** | repo root | Runs `mvn spotless:check` | Migrate to `java/.githooks/` | -| **`instructions/copilot-sdk-java.instructions.md`** | `instructions/` | VS Code copilot instructions | Move to `java/` | +| Resource | Location | Purpose | Must Migrate? | +| ---------------------------------------------------------------- | -------------------------------------------- | -------------------------------------------- | ------------------------------------------------- | +| **Agent:** `agentic-workflows.agent.md` | `.github/agents/` | Dispatcher for gh-aw workflow creation/debug | Yes (merge with monorepo version) | +| **Skill:** `agentic-merge-reference-impl` | `.github/skills/` + `.github/prompts/` | Merges reference impl changes into Java | Yes — **must be reworked** (no longer cross-repo) | +| **Skill:** `commit-as-pull-request` | `.github/skills/` + `.github/prompts/` | Creates branch, pushes, opens PR | Yes (may already exist in monorepo) | +| **Skill:** `documentation-coverage` | `.github/skills/` + `.github/prompts/` | Assesses Java docs coverage | Yes | +| **Prompt:** `coding-agent-merge-reference-impl-instructions.md` | `.github/prompts/` | Instructions for coding agent merge | Yes | +| **Prompt:** `test-coverage-assessment.prompt.md` | `.github/prompts/` | Test coverage assessment | Yes | +| **Composite Action:** `setup-copilot` | `.github/actions/setup-copilot/` | Sets up Copilot CLI for Java tests | Yes — **adapt paths** | +| **Composite Action:** `test-report` | `.github/actions/test-report/` | Test report generation | Yes | +| **Scripts:** `release/`, `ci/`, `build/`, `reference-impl-sync/` | `.github/scripts/` | Release, CI, sync automation | Yes — **path rewrites** | +| **Dependabot:** `dependabot.yml` | `.github/` | Maven + GitHub Actions updates | Merge into monorepo's `dependabot.yaml` | +| **CODEOWNERS** | `.github/` | `@github/copilot-sdk-java` | Merge into monorepo's CODEOWNERS | +| **Issue Templates:** bug, documentation, feature, maintenance | `.github/ISSUE_TEMPLATE/` | Issue forms | Assess whether monorepo issue triage covers this | +| **PR Template** | `.github/pull_request_template.md` | PR form | Merge or keep per-language | +| **Release Config** | `.github/release.yml` | Auto-generated release notes config | Merge | +| **copilot-instructions.md** | `.github/` | Agent instructions for Java SDK | Merge (scoped to `java/`) | +| **Site templates** | `.github/templates/` | HTML/CSS for GitHub Pages | Migrate to `java/` | +| **Coverage badge script** | `.github/scripts/generate-coverage-badge.sh` | JaCoCo badge generation | Migrate | +| **`.lastmerge`** | repo root | Tracks last merged ref-impl commit | **This concept changes** — see §6 | +| **`.githooks/pre-commit`** | repo root | Runs `mvn spotless:check` | Migrate to `java/.githooks/` | +| **`instructions/copilot-sdk-java.instructions.md`** | `instructions/` | VS Code copilot instructions | Move to `java/` | ### 2B. copilot-sdk-00 -| Resource | Location | Purpose | -|---|---|---| -| **Agent:** `agentic-workflows.agent.md` | `.github/agents/` | Same dispatcher (newer version with more routing) | -| **Agent:** `docs-maintenance.agent.md` | `.github/agents/` | Docs auditor agent | -| **Skill:** `rust-coding-skill` | `.github/skills/` | Rust-specific coding skill | -| **Composite Action:** `setup-copilot` | `.github/actions/setup-copilot/` | Sets up Copilot CLI from nodejs package | -| **Command:** `triage_feedback.yml` | `.github/commands/` | Repository dispatch for triage feedback | -| **LSP Config:** `lsp.json` | `.github/` | C#, Go language server configs | -| **Dependabot:** `dependabot.yaml` | `.github/` | npm, pip, gomod, nuget, github-actions, devcontainers | -| **CODEOWNERS** | `.github/` | `@github/copilot-sdk` | -| **copilot-instructions.md** | `.github/` | Monorepo-wide agent instructions | +| Resource | Location | Purpose | +| --------------------------------------- | -------------------------------- | ----------------------------------------------------- | +| **Agent:** `agentic-workflows.agent.md` | `.github/agents/` | Same dispatcher (newer version with more routing) | +| **Agent:** `docs-maintenance.agent.md` | `.github/agents/` | Docs auditor agent | +| **Skill:** `rust-coding-skill` | `.github/skills/` | Rust-specific coding skill | +| **Composite Action:** `setup-copilot` | `.github/actions/setup-copilot/` | Sets up Copilot CLI from nodejs package | +| **Command:** `triage_feedback.yml` | `.github/commands/` | Repository dispatch for triage feedback | +| **LSP Config:** `lsp.json` | `.github/` | C#, Go language server configs | +| **Dependabot:** `dependabot.yaml` | `.github/` | npm, pip, gomod, nuget, github-actions, devcontainers | +| **CODEOWNERS** | `.github/` | `@github/copilot-sdk` | +| **copilot-instructions.md** | `.github/` | Monorepo-wide agent instructions | --- @@ -114,21 +115,21 @@ The Java SDK publish workflow requires secrets that **do not currently exist** in the `copilot-sdk` repo: -| Secret | Used By | Notes | -|---|---|---| -| `RELEASE_TOKEN` | `publish-maven.yml` | PAT with `contents:write` for pushing tags/commits during maven-release-plugin | -| `GPG_SECRET_KEY` | `publish-maven.yml` | GPG private key for signing Maven artifacts | -| `GPG_PASSPHRASE` | `publish-maven.yml` | Passphrase for the GPG key | -| `MAVEN_CENTRAL_USERNAME` | `publish-maven.yml`, `publish-snapshot.yml` | Sonatype/Maven Central credentials | -| `MAVEN_CENTRAL_PASSWORD` | `publish-maven.yml`, `publish-snapshot.yml` | Sonatype/Maven Central credentials | -| `COPILOT_GITHUB_TOKEN` | `build-test.yml`, `codegen-agentic-fix.lock.yml` | Token for Copilot CLI in CI | +| Secret | Used By | Notes | +| ------------------------ | ------------------------------------------------ | ------------------------------------------------------------------------------ | +| `RELEASE_TOKEN` | `publish-maven.yml` | PAT with `contents:write` for pushing tags/commits during maven-release-plugin | +| `GPG_SECRET_KEY` | `publish-maven.yml` | GPG private key for signing Maven artifacts | +| `GPG_PASSPHRASE` | `publish-maven.yml` | Passphrase for the GPG key | +| `MAVEN_CENTRAL_USERNAME` | `publish-maven.yml`, `publish-snapshot.yml` | Sonatype/Maven Central credentials | +| `MAVEN_CENTRAL_PASSWORD` | `publish-maven.yml`, `publish-snapshot.yml` | Sonatype/Maven Central credentials | +| `COPILOT_GITHUB_TOKEN` | `build-test.yml`, `codegen-agentic-fix.lock.yml` | Token for Copilot CLI in CI | ### 3B. Existing Secrets in copilot-sdk That May Conflict -| Secret | Used By | Concern | -|---|---|---| -| `CARGO_REGISTRY_TOKEN` | `publish.yml` (Rust) | No conflict | -| `GH_AW_GITHUB_TOKEN` / `GH_AW_GITHUB_MCP_SERVER_TOKEN` | Agentic workflows | Likely already present; Java agentic workflows need the same | +| Secret | Used By | Concern | +| ------------------------------------------------------ | -------------------- | ------------------------------------------------------------ | +| `CARGO_REGISTRY_TOKEN` | `publish.yml` (Rust) | No conflict | +| `GH_AW_GITHUB_TOKEN` / `GH_AW_GITHUB_MCP_SERVER_TOKEN` | Agentic workflows | Likely already present; Java agentic workflows need the same | ### 3C. Permissions / Access to Provision @@ -157,24 +158,24 @@ The monorepo already uses a partially consistent pattern: #### Language-specific workflow naming: `{language}-{purpose}.yml` -| Current (copilot-sdk) | Current (copilot-sdk-java) | Proposed New Name | -|---|---|---| -| `nodejs-sdk-tests.yml` | — | `nodejs-sdk-tests.yml` (keep) | -| `dotnet-sdk-tests.yml` | — | `dotnet-sdk-tests.yml` (keep) | -| `go-sdk-tests.yml` | — | `go-sdk-tests.yml` (keep) | -| `python-sdk-tests.yml` | — | `python-sdk-tests.yml` (keep) | -| `rust-sdk-tests.yml` | — | `rust-sdk-tests.yml` (keep) | -| — | `build-test.yml` | **`java-sdk-tests.yml`** | -| — | `publish-maven.yml` | **`java-publish.yml`** | -| — | `publish-snapshot.yml` | **`java-publish-snapshot.yml`** | -| — | `deploy-site.yml` | **`java-deploy-site.yml`** | -| — | `run-smoke-test.yml` | **`java-smoke-test.yml`** | -| — | `codegen-check.yml` | **Merge into existing `codegen-check.yml`** (add Java paths + job) | -| — | `codegen-agentic-fix.md` | **`java-codegen-fix.md`** + `.lock.yml` | -| — | `reference-impl-sync.md` | **`java-reference-impl-sync.md`** + `.lock.yml` (reworked for intra-repo) | -| — | `update-copilot-dependency.yml` | **Merge into existing `update-copilot-dependency.yml`** (add Java codegen step) | -| — | `copilot-setup-steps.yml` | **Merge into existing** (add JDK 17 + Maven setup) | -| — | `agentics-maintenance.yml` | Already exists via gh-aw in the monorepo; **do not duplicate** | +| Current (copilot-sdk) | Current (copilot-sdk-java) | Proposed New Name | +| ---------------------- | ------------------------------- | ------------------------------------------------------------------------------- | +| `nodejs-sdk-tests.yml` | — | `nodejs-sdk-tests.yml` (keep) | +| `dotnet-sdk-tests.yml` | — | `dotnet-sdk-tests.yml` (keep) | +| `go-sdk-tests.yml` | — | `go-sdk-tests.yml` (keep) | +| `python-sdk-tests.yml` | — | `python-sdk-tests.yml` (keep) | +| `rust-sdk-tests.yml` | — | `rust-sdk-tests.yml` (keep) | +| — | `build-test.yml` | **`java-sdk-tests.yml`** | +| — | `publish-maven.yml` | **`java-publish.yml`** | +| — | `publish-snapshot.yml` | **`java-publish-snapshot.yml`** | +| — | `deploy-site.yml` | **`java-deploy-site.yml`** | +| — | `run-smoke-test.yml` | **`java-smoke-test.yml`** | +| — | `codegen-check.yml` | **Merge into existing `codegen-check.yml`** (add Java paths + job) | +| — | `codegen-agentic-fix.md` | **`java-codegen-fix.md`** + `.lock.yml` | +| — | `reference-impl-sync.md` | **`java-reference-impl-sync.md`** + `.lock.yml` (reworked for intra-repo) | +| — | `update-copilot-dependency.yml` | **Merge into existing `update-copilot-dependency.yml`** (add Java codegen step) | +| — | `copilot-setup-steps.yml` | **Merge into existing** (add JDK 17 + Maven setup) | +| — | `agentics-maintenance.yml` | Already exists via gh-aw in the monorepo; **do not duplicate** | #### Cross-language workflow naming: `{purpose}.yml` (no language prefix) @@ -204,18 +205,18 @@ Keep existing names: `publish.yml`, `codegen-check.yml`, `scenario-builds.yml`, #### Cross-cutting concerns (potential friction points) -| Concern | Current State | Impact on Java | -|---|---|---| -| **Shared test harness** (`test/harness/`) | Node.js-based replay proxy used by all E2E tests | Java already uses this (clones it at build time from `copilot-sdk` repo). When in-repo, can reference it directly — **simpler**. | -| **Shared test snapshots** (`test/snapshots/`) | YAML snapshot files consumed by all languages | Java can share these — **positive change**. | -| **Unified codegen** (`scripts/codegen/`) | One `package.json` with generators for TS, C#, Python, Go, Rust | Java codegen (`java.ts`) must be **merged in**. The Java codegen currently has its own `package.json` with a direct `@github/copilot` dependency; the monorepo codegen gets it via `nodejs/node_modules`. This needs reconciliation. | -| **`justfile`** | Has per-language targets (`format-go`, `test-dotnet`, etc.) | Must add `format-java`, `lint-java`, `test-java`, `install-java` targets. | -| **Unified `publish.yml`** | Single workflow publishes all languages with one version number | **Java CANNOT join this** — Java has its own versioning scheme (`X.Y.Z-java.N`). Java must keep a separate `java-publish.yml`. | -| **`sdk-consistency-review`** agentic workflow | Reviews PRs for cross-SDK parity (currently watches nodejs, python, go, dotnet) | Must add `java/` to the path triggers and update the agent prompt to include Java. | -| **`copilot-setup-steps.yml`** | Sets up Node, Python, Go, .NET, Rust | Must add JDK 17 + Maven. | -| **`copilot-instructions.md`** | Monorepo-wide instructions | Must incorporate Java-specific guidance. | -| **`CODEOWNERS`** | Single `* @github/copilot-sdk` | Must add `java/ @github/copilot-sdk-java` line. | -| **`lsp.json`** | Configures C# and Go language servers for Copilot agent | May want to add Java LSP (jdtls or similar) — **optional**. | +| Concern | Current State | Impact on Java | +| --------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **Shared test harness** (`test/harness/`) | Node.js-based replay proxy used by all E2E tests | Java already uses this (clones it at build time from `copilot-sdk` repo). When in-repo, can reference it directly — **simpler**. | +| **Shared test snapshots** (`test/snapshots/`) | YAML snapshot files consumed by all languages | Java can share these — **positive change**. | +| **Unified codegen** (`scripts/codegen/`) | One `package.json` with generators for TS, C#, Python, Go, Rust | Java codegen (`java.ts`) must be **merged in**. The Java codegen currently has its own `package.json` with a direct `@github/copilot` dependency; the monorepo codegen gets it via `nodejs/node_modules`. This needs reconciliation. | +| **`justfile`** | Has per-language targets (`format-go`, `test-dotnet`, etc.) | Must add `format-java`, `lint-java`, `test-java`, `install-java` targets. | +| **Unified `publish.yml`** | Single workflow publishes all languages with one version number | **Java CANNOT join this** — Java has its own versioning scheme (`X.Y.Z-java.N`). Java must keep a separate `java-publish.yml`. | +| **`sdk-consistency-review`** agentic workflow | Reviews PRs for cross-SDK parity (currently watches nodejs, python, go, dotnet) | Must add `java/` to the path triggers and update the agent prompt to include Java. | +| **`copilot-setup-steps.yml`** | Sets up Node, Python, Go, .NET, Rust | Must add JDK 17 + Maven. | +| **`copilot-instructions.md`** | Monorepo-wide instructions | Must incorporate Java-specific guidance. | +| **`CODEOWNERS`** | Single `* @github/copilot-sdk` | Must add `java/ @github/copilot-sdk-java` line. | +| **`lsp.json`** | Configures C# and Go language servers for Copilot agent | May want to add Java LSP (jdtls or similar) — **optional**. | ### The Big Question: `reference-impl-sync` @@ -224,6 +225,7 @@ Currently, the Java SDK has a scheduled workflow that polls `github/copilot-sdk` What changes is the **mechanism**: instead of polling a remote repository, the workflow watches for commits that land on `main` touching `dotnet/src/` or `nodejs/src/` and compares against `java/.lastmerge` (which now stores a monorepo commit SHA rather than a cross-repo one). **Recommendation**: + 1. **Keep `java/.lastmerge`** — it stores the last monorepo commit SHA whose `dotnet/`/`nodejs/` changes have been ported into Java. This is the anchor for diffing. 2. **Keep `reference-impl-sync` as `java-reference-impl-sync.md`** — reworked for intra-repo operation (see §6 Phase 4 for details). 3. **Keep `agentic-merge-reference-impl` skill** — reworked so that instead of cloning a remote repo, it reads diffs from the local `dotnet/` and `nodejs/` directories relative to the SHA in `java/.lastmerge`. @@ -263,6 +265,7 @@ What changes is the **mechanism**: instead of polling a remote repository, the w 3. Verify `mvn verify` works from `java/` directory locally. 4. Add `justfile` targets for Java: + ```just format-java: @echo "=== Formatting Java code ===" @@ -291,7 +294,7 @@ What changes is the **mechanism**: instead of polling a remote repository, the w - Path triggers: `java/**`, `test/**`, `.github/workflows/java-sdk-tests.yml` - Uses monorepo's `setup-copilot` action (or create `java/setup-copilot` action) - Runs on 3 OS matrix (match other SDKs) - + 2. Merge Java into `codegen-check.yml`: - Add `java/src/generated/**` to path triggers - Add a job that runs Java codegen and diffs @@ -407,39 +410,40 @@ What changes is the **mechanism**: instead of polling a remote repository, the w ### HIGH RISK -| # | Risk | Impact | Mitigation | -|---|---|---|---| -| H1 | **Maven Central Trusted Publisher** repo-name mismatch | Cannot publish Java releases from monorepo | Verify/update Trusted Publisher config in Maven Central **before** migration. If the GAV is bound to `github/copilot-sdk-java`, it must be updated. | -| H2 | **Unified `publish.yml` version collision** | All SDKs in monorepo share one version. Java has independent `X.Y.Z-java.N` versions. | Java must keep a **separate** publish workflow. Do NOT merge into `publish.yml`. | -| H3 | **`agentic-merge-reference-impl` breaks** | The core Java development loop relies on this skill to stay in sync with .NET/Node changes | Must be carefully reworked for intra-repo operation before cutover. Test thoroughly with a dry-run on a feature branch. The skill + its 5 shell scripts + 2 prompt files all assume cross-repo cloning. | -| H4 | **Secret provisioning delay** | Can't publish or run full CI until secrets are provisioned | Start secret provisioning **immediately** (Phase 0). | -| H5 | **Test harness path changes** | Java E2E tests currently clone `copilot-sdk` at build time to get `test/harness/` and `test/snapshots/`. In-repo, these paths change. | Update `pom.xml` and test infrastructure to reference local `test/` directory instead of cloning. **This simplifies things significantly.** | +| # | Risk | Impact | Mitigation | +| --- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| H1 | **Maven Central Trusted Publisher** repo-name mismatch | Cannot publish Java releases from monorepo | Verify/update Trusted Publisher config in Maven Central **before** migration. If the GAV is bound to `github/copilot-sdk-java`, it must be updated. | +| H2 | **Unified `publish.yml` version collision** | All SDKs in monorepo share one version. Java has independent `X.Y.Z-java.N` versions. | Java must keep a **separate** publish workflow. Do NOT merge into `publish.yml`. | +| H3 | **`agentic-merge-reference-impl` breaks** | The core Java development loop relies on this skill to stay in sync with .NET/Node changes | Must be carefully reworked for intra-repo operation before cutover. Test thoroughly with a dry-run on a feature branch. The skill + its 5 shell scripts + 2 prompt files all assume cross-repo cloning. | +| H4 | **Secret provisioning delay** | Can't publish or run full CI until secrets are provisioned | Start secret provisioning **immediately** (Phase 0). | +| H5 | **Test harness path changes** | Java E2E tests currently clone `copilot-sdk` at build time to get `test/harness/` and `test/snapshots/`. In-repo, these paths change. | Update `pom.xml` and test infrastructure to reference local `test/` directory instead of cloning. **This simplifies things significantly.** | ### MEDIUM RISK -| # | Risk | Impact | Mitigation | -|---|---|---|---| -| M1 | **Codegen `package.json` merge** | Java codegen has its own `@github/copilot` dependency; monorepo codegen gets it from `nodejs/node_modules` | Align Java codegen to use the same dependency source. May need to add `generate:java` script to monorepo's `scripts/codegen/package.json`. | -| M2 | **GitHub Pages conflict** | Java deploys versioned docs to Pages. Monorepo may have its own Pages setup. | Use subdirectory deployment or a separate Pages branch for Java. | -| M3 | **Branch protection / required checks** | New `java-sdk-tests` check may not be in the required list | Add to branch protection after first successful run. | -| M4 | **CODEOWNERS team permissions** | `@github/copilot-sdk-java` team may not have write access to `github/copilot-sdk` | Verify team access and add to repo collaborators. | -| M5 | **`copilot-setup-steps.yml` bloat** | Adding JDK + Maven makes agent setup slower for non-Java tasks | Acceptable trade-off; other languages already add their tools. Could consider conditional setup but that's over-engineering. | -| M6 | **gh-aw version mismatch** | Java repo uses gh-aw `v0.68.3` setup action pinned at `v0.71.5`; monorepo uses `v0.64.2` reference in docs | Align gh-aw versions. Use the newer version. Recompile all `.lock.yml` files. | +| # | Risk | Impact | Mitigation | +| --- | --------------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | +| M1 | **Codegen `package.json` merge** | Java codegen has its own `@github/copilot` dependency; monorepo codegen gets it from `nodejs/node_modules` | Align Java codegen to use the same dependency source. May need to add `generate:java` script to monorepo's `scripts/codegen/package.json`. | +| M2 | **GitHub Pages conflict** | Java deploys versioned docs to Pages. Monorepo may have its own Pages setup. | Use subdirectory deployment or a separate Pages branch for Java. | +| M3 | **Branch protection / required checks** | New `java-sdk-tests` check may not be in the required list | Add to branch protection after first successful run. | +| M4 | **CODEOWNERS team permissions** | `@github/copilot-sdk-java` team may not have write access to `github/copilot-sdk` | Verify team access and add to repo collaborators. | +| M5 | **`copilot-setup-steps.yml` bloat** | Adding JDK + Maven makes agent setup slower for non-Java tasks | Acceptable trade-off; other languages already add their tools. Could consider conditional setup but that's over-engineering. | +| M6 | **gh-aw version mismatch** | Java repo uses gh-aw `v0.68.3` setup action pinned at `v0.71.5`; monorepo uses `v0.64.2` reference in docs | Align gh-aw versions. Use the newer version. Recompile all `.lock.yml` files. | ### LOW RISK -| # | Risk | Impact | Mitigation | -|---|---|---|---| -| L1 | **Issue template conflicts** | Java has custom issue templates; monorepo uses agentic triage | Monorepo agentic triage covers this. Can add Java-specific labels. | -| L2 | **PR template differences** | Different PR templates | Use monorepo's template. Java-specific guidance in CONTRIBUTING.md. | -| L3 | **`.githooks` scope** | Java pre-commit hook runs `mvn spotless:check` globally | Scope hook to only run when Java files are changed. | -| L4 | **Duplicate `agentics-maintenance.yml`** | Java repo has its own; monorepo will generate one | The monorepo's gh-aw will handle this automatically. Don't migrate. | +| # | Risk | Impact | Mitigation | +| --- | ---------------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------- | +| L1 | **Issue template conflicts** | Java has custom issue templates; monorepo uses agentic triage | Monorepo agentic triage covers this. Can add Java-specific labels. | +| L2 | **PR template differences** | Different PR templates | Use monorepo's template. Java-specific guidance in CONTRIBUTING.md. | +| L3 | **`.githooks` scope** | Java pre-commit hook runs `mvn spotless:check` globally | Scope hook to only run when Java files are changed. | +| L4 | **Duplicate `agentics-maintenance.yml`** | Java repo has its own; monorepo will generate one | The monorepo's gh-aw will handle this automatically. Don't migrate. | --- ## 8. Post-Migration Verification Checklist ### CI/CD + - [ ] `java-sdk-tests.yml` passes on all 3 OS platforms - [ ] `codegen-check.yml` includes Java and passes - [ ] `java-codegen-fix.md` compiles and agentic workflow functions @@ -449,6 +453,7 @@ What changes is the **mechanism**: instead of polling a remote repository, the w - [ ] `java-deploy-site.yml` successfully deploys docs ### Integration + - [ ] `copilot-setup-steps.yml` includes JDK and Maven - [ ] `dependabot.yaml` includes Maven ecosystem for `java/` - [ ] `CODEOWNERS` includes `java/` path @@ -457,24 +462,28 @@ What changes is the **mechanism**: instead of polling a remote repository, the w - [ ] `issue-triage` knows about `sdk/java` label ### Code + - [ ] `mvn verify` passes from `java/` directory - [ ] E2E tests use local `test/harness/` and `test/snapshots/` (no cloning) - [ ] Java codegen integrated into `scripts/codegen/` - [ ] `.lastmerge` exists at `java/.lastmerge` ### Documentation + - [ ] Monorepo `README.md` lists Java - [ ] `copilot-instructions.md` includes Java guidance - [ ] `java/README.md` links updated to monorepo - [ ] Maven Central POM `` URLs updated ### Agentic Sync + - [ ] `java-reference-impl-sync.md` compiles and detects new dotnet/nodejs changes via local `git log` - [ ] `agentic-merge-reference-impl` skill works intra-repo (no cross-repo clone) - [ ] `java/.lastmerge` correctly stores monorepo commit SHAs - [ ] Sync scripts in `.github/scripts/java/reference-impl-sync/` use local paths ### Cleanup + - [ ] `copilot-sdk-java` repo archived - [ ] No broken links to old repo - [ ] No duplicate `agentics-maintenance.yml` @@ -483,62 +492,62 @@ What changes is the **mechanism**: instead of polling a remote repository, the w ## Appendix A: Files to Copy vs. Merge vs. Delete -| Source File (copilot-sdk-java-00) | Action | Target Location (copilot-sdk-00) | -|---|---|---| -| `src/` | Copy | `java/src/` | -| `config/` | Copy | `java/config/` | -| `pom.xml` | Copy + update paths | `java/pom.xml` | -| `CHANGELOG.md` | Copy | `java/CHANGELOG.md` | -| `README.md` | Copy + update links | `java/README.md` | -| `jbang-example.java` | Copy | `java/jbang-example.java` | -| `.lastmerge` | Copy | `java/.lastmerge` | -| `.githooks/pre-commit` | Copy + scope to Java changes | `java/.githooks/pre-commit` | -| `docs/adr/` | Copy | `java/docs/adr/` | -| `scripts/codegen/java.ts` | Copy | `scripts/codegen/java.ts` | -| `scripts/codegen/package.json` | **Merge** deps into monorepo's | `scripts/codegen/package.json` | -| `.github/workflows/build-test.yml` | **Adapt** → rename | `.github/workflows/java-sdk-tests.yml` | -| `.github/workflows/publish-maven.yml` | **Adapt** → rename | `.github/workflows/java-publish.yml` | -| `.github/workflows/publish-snapshot.yml` | **Adapt** → rename | `.github/workflows/java-publish-snapshot.yml` | -| `.github/workflows/deploy-site.yml` | **Adapt** → rename | `.github/workflows/java-deploy-site.yml` | -| `.github/workflows/run-smoke-test.yml` | **Adapt** → rename | `.github/workflows/java-smoke-test.yml` | -| `.github/workflows/codegen-check.yml` | **Merge** into existing | `.github/workflows/codegen-check.yml` | -| `.github/workflows/codegen-agentic-fix.md` | **Adapt** → rename | `.github/workflows/java-codegen-fix.md` | -| `.github/workflows/update-copilot-dependency.yml` | **Merge** into existing | `.github/workflows/update-copilot-dependency.yml` | -| `.github/workflows/copilot-setup-steps.yml` | **Merge** into existing | `.github/workflows/copilot-setup-steps.yml` | -| `.github/workflows/reference-impl-sync.md` + `.lock.yml` | **Adapt** → rename + rework for intra-repo | `.github/workflows/java-reference-impl-sync.md` + `.lock.yml` | -| `.github/workflows/agentics-maintenance.yml` | **DELETE** (monorepo has its own) | — | -| `.github/workflows/notes.template` | Copy | `.github/workflows/java-notes.template` | -| `.github/actions/setup-copilot/` | **Adapt** or merge | `.github/actions/java-setup-copilot/` or merge | -| `.github/actions/test-report/` | Copy | `.github/actions/java-test-report/` | -| `.github/scripts/*` | Copy + update paths | `.github/scripts/java/` (new subdirectory) | -| `.github/skills/agentic-merge-reference-impl/` | **Rework** for intra-repo (remove cross-repo clone, use local git diff) | `.github/skills/java-merge-reference-impl/` | -| `.github/skills/commit-as-pull-request/` | Check for duplicates | `.github/skills/commit-as-pull-request/` | -| `.github/skills/documentation-coverage/` | Copy | `.github/skills/java-documentation-coverage/` | -| `.github/prompts/*` | Copy + update | `.github/prompts/` (prefix with `java-` if needed) | -| `.github/dependabot.yml` | **Merge** into existing | `.github/dependabot.yaml` | -| `.github/CODEOWNERS` | **Merge** into existing | `.github/CODEOWNERS` | -| `.github/copilot-instructions.md` | **Merge** into existing | `.github/copilot-instructions.md` | -| `.github/release.yml` | **Merge** into existing | `.github/release.yml` (if it exists) | -| `.github/ISSUE_TEMPLATE/*` | Evaluate — likely skip | — | -| `.github/pull_request_template.md` | Evaluate — likely skip | — | -| `.github/templates/` | Copy | `java/.github/templates/` or `java/src/site/` | -| `instructions/` | Move | `java/instructions/` | -| `test` (file, not directory) | Copy if needed | `java/test` | +| Source File (copilot-sdk-java-00) | Action | Target Location (copilot-sdk-00) | +| -------------------------------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------------- | +| `src/` | Copy | `java/src/` | +| `config/` | Copy | `java/config/` | +| `pom.xml` | Copy + update paths | `java/pom.xml` | +| `CHANGELOG.md` | Copy | `java/CHANGELOG.md` | +| `README.md` | Copy + update links | `java/README.md` | +| `jbang-example.java` | Copy | `java/jbang-example.java` | +| `.lastmerge` | Copy | `java/.lastmerge` | +| `.githooks/pre-commit` | Copy + scope to Java changes | `java/.githooks/pre-commit` | +| `docs/adr/` | Copy | `java/docs/adr/` | +| `scripts/codegen/java.ts` | Copy | `java/scripts/codegen/java.ts` | +| `scripts/codegen/package.json` | Copy (Java keeps its own) | `java/scripts/codegen/package.json` | +| `.github/workflows/build-test.yml` | **Adapt** → rename | `.github/workflows/java-sdk-tests.yml` | +| `.github/workflows/publish-maven.yml` | **Adapt** → rename | `.github/workflows/java-publish.yml` | +| `.github/workflows/publish-snapshot.yml` | **Adapt** → rename | `.github/workflows/java-publish-snapshot.yml` | +| `.github/workflows/deploy-site.yml` | **Adapt** → rename | `.github/workflows/java-deploy-site.yml` | +| `.github/workflows/run-smoke-test.yml` | **Adapt** → rename | `.github/workflows/java-smoke-test.yml` | +| `.github/workflows/codegen-check.yml` | **Merge** into existing | `.github/workflows/codegen-check.yml` | +| `.github/workflows/codegen-agentic-fix.md` | **Adapt** → rename | `.github/workflows/java-codegen-fix.md` | +| `.github/workflows/update-copilot-dependency.yml` | **Merge** into existing | `.github/workflows/update-copilot-dependency.yml` | +| `.github/workflows/copilot-setup-steps.yml` | **Merge** into existing | `.github/workflows/copilot-setup-steps.yml` | +| `.github/workflows/reference-impl-sync.md` + `.lock.yml` | **Adapt** → rename + rework for intra-repo | `.github/workflows/java-reference-impl-sync.md` + `.lock.yml` | +| `.github/workflows/agentics-maintenance.yml` | **DELETE** (monorepo has its own) | — | +| `.github/workflows/notes.template` | Copy | `.github/workflows/java-notes.template` | +| `.github/actions/setup-copilot/` | **Adapt** or merge | `.github/actions/java-setup-copilot/` or merge | +| `.github/actions/test-report/` | Copy | `.github/actions/java-test-report/` | +| `.github/scripts/*` | Copy + update paths | `.github/scripts/java/` (new subdirectory) | +| `.github/skills/agentic-merge-reference-impl/` | **Rework** for intra-repo (remove cross-repo clone, use local git diff) | `.github/skills/java-merge-reference-impl/` | +| `.github/skills/commit-as-pull-request/` | Check for duplicates | `.github/skills/commit-as-pull-request/` | +| `.github/skills/documentation-coverage/` | Copy | `.github/skills/java-documentation-coverage/` | +| `.github/prompts/*` | Copy + update | `.github/prompts/` (prefix with `java-` if needed) | +| `.github/dependabot.yml` | **Merge** into existing | `.github/dependabot.yaml` | +| `.github/CODEOWNERS` | **Merge** into existing | `.github/CODEOWNERS` | +| `.github/copilot-instructions.md` | **Merge** into existing | `.github/copilot-instructions.md` | +| `.github/release.yml` | **Merge** into existing | `.github/release.yml` (if it exists) | +| `.github/ISSUE_TEMPLATE/*` | Evaluate — likely skip | — | +| `.github/pull_request_template.md` | Evaluate — likely skip | — | +| `.github/templates/` | Copy | `java/.github/templates/` or `java/src/site/` | +| `instructions/` | Move | `java/instructions/` | +| `test` (file, not directory) | Copy if needed | `java/test` | ## Appendix B: Unique Java Concerns vs Other Languages -| Concern | Java | Other Languages | Notes | -|---|---|---|---| -| **Build system** | Maven (`pom.xml`) | npm, pip, go mod, dotnet, cargo | Fully self-contained under `java/` | -| **Versioning** | `X.Y.Z-java.N` (independent) | Shared `X.Y.Z` across all others | **Must keep separate publish workflow** | -| **Code formatting** | Spotless (Eclipse formatter) | prettier, ruff, gofmt, dotnet format, rustfmt | Runs only on Java files | -| **Test framework** | JUnit + Surefire | Vitest, pytest, go test, xunit, cargo test | Standard; no conflicts | -| **E2E test harness** | Clones `copilot-sdk` at build time | References local `test/harness/` | **Major simplification** when in-repo | -| **Codegen** | Own `java.ts` + own `@github/copilot` dep | Shared codegen scripts + shared dep | Needs reconciliation | -| **CI runner** | JDK 17 + JDK 25 (smoke test) | Node 22, Python 3.12, Go 1.24, .NET 10, Rust 1.94 | Just another tool in `copilot-setup-steps.yml` | -| **Publishing** | Maven Central (GPG + Sonatype) | npm, PyPI, NuGet, crates.io, Go tags | Completely different mechanism | -| **Docs hosting** | GitHub Pages (Maven site) | Not clear if monorepo has its own | Potential conflict | -| **Reference impl tracking** | `.lastmerge` + scheduled sync + agentic merge skill | N/A (they ARE the reference impl) | `.lastmerge` stores monorepo SHA; sync becomes intra-repo but is still needed because Java maintainers ≠ .NET/Node maintainers | +| Concern | Java | Other Languages | Notes | +| --------------------------- | --------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | +| **Build system** | Maven (`pom.xml`) | npm, pip, go mod, dotnet, cargo | Fully self-contained under `java/` | +| **Versioning** | `X.Y.Z-java.N` (independent) | Shared `X.Y.Z` across all others | **Must keep separate publish workflow** | +| **Code formatting** | Spotless (Eclipse formatter) | prettier, ruff, gofmt, dotnet format, rustfmt | Runs only on Java files | +| **Test framework** | JUnit + Surefire | Vitest, pytest, go test, xunit, cargo test | Standard; no conflicts | +| **E2E test harness** | Clones `copilot-sdk` at build time | References local `test/harness/` | **Major simplification** when in-repo | +| **Codegen** | Own `java.ts` + own `@github/copilot` dep | Shared codegen scripts + shared dep | Needs reconciliation | +| **CI runner** | JDK 17 + JDK 25 (smoke test) | Node 22, Python 3.12, Go 1.24, .NET 10, Rust 1.94 | Just another tool in `copilot-setup-steps.yml` | +| **Publishing** | Maven Central (GPG + Sonatype) | npm, PyPI, NuGet, crates.io, Go tags | Completely different mechanism | +| **Docs hosting** | GitHub Pages (Maven site) | Not clear if monorepo has its own | Potential conflict | +| **Reference impl tracking** | `.lastmerge` + scheduled sync + agentic merge skill | N/A (they ARE the reference impl) | `.lastmerge` stores monorepo SHA; sync becomes intra-repo but is still needed because Java maintainers ≠ .NET/Node maintainers | --- @@ -582,11 +591,13 @@ Additionally, the monorepo's top-level README contains Quick Start code for **ot #### 1. Update `PROMPT-smoke-test.md` — change the README path Replace: + ``` Read the file `README.md` at the top level of this repository. ``` With: + ``` Read the file `java/README.md` in this repository. ``` @@ -614,23 +625,25 @@ The workflow steps that run `mvn` and reference `src/test/prompts/PROMPT-smoke-t #### 4. Update `build-test.yml` → `java-sdk-tests.yml` — smoke test call The current `build-test.yml` calls: + ```yaml uses: ./.github/workflows/run-smoke-test.yml ``` After rename, update to: + ```yaml uses: ./.github/workflows/java-smoke-test.yml ``` ### Risk Assessment -| Risk | Severity | Notes | -|---|---|---| -| Prompt reads wrong README | **HIGH** | If `PROMPT-smoke-test.md` still says "top level README," the AI agent reads the monorepo README and fails or extracts wrong-language code | -| `java/README.md` placeholder overwrites real content | **HIGH** | The monorepo already has a `java/README.md` with a different Quick Start. Must be replaced with the full Java SDK README during migration | -| `smoke-test/` directory created at wrong location | **MEDIUM** | Without `working-directory: ./java`, the smoke test project gets created at the monorepo root instead of under `java/` | -| `// JDK 25+:` comments missing from Quick Start | **MEDIUM** | The JDK 25 smoke test job relies on these comments to toggle virtual thread support. Missing comments → JDK 25 job builds without virtual threads and still passes (silent regression, not a failure) | +| Risk | Severity | Notes | +| ---------------------------------------------------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Prompt reads wrong README | **HIGH** | If `PROMPT-smoke-test.md` still says "top level README," the AI agent reads the monorepo README and fails or extracts wrong-language code | +| `java/README.md` placeholder overwrites real content | **HIGH** | The monorepo already has a `java/README.md` with a different Quick Start. Must be replaced with the full Java SDK README during migration | +| `smoke-test/` directory created at wrong location | **MEDIUM** | Without `working-directory: ./java`, the smoke test project gets created at the monorepo root instead of under `java/` | +| `// JDK 25+:` comments missing from Quick Start | **MEDIUM** | The JDK 25 smoke test job relies on these comments to toggle virtual thread support. Missing comments → JDK 25 job builds without virtual threads and still passes (silent regression, not a failure) | ### Verification Checklist From f67bcfc61940fae9a195127a36af0ff9e6368d07 Mon Sep 17 00:00:00 2001 From: Ed Burns Date: Wed, 13 May 2026 14:03:46 -0700 Subject: [PATCH 3/6] On branch edburns/80-java-monorepo-add-01 Put the plan first. modified: 80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md --- .../dd-2989727-move-java-to-monorepo-plan.md | 447 +++++++++--------- 1 file changed, 223 insertions(+), 224 deletions(-) diff --git a/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md b/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md index 1f533aaee..cfc3fffcb 100644 --- a/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md +++ b/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md @@ -2,12 +2,11 @@ ## Table of Contents -1. [Workflow Inventory Tables](#1-workflow-inventory-tables) -2. [Agents, Skills, Prompts, and Supporting Resources Inventory](#2-agents-skills-prompts-and-supporting-resources-inventory) -3. [Permissions and Secrets Challenges](#3-permissions-and-secrets-challenges) -4. [Naming Convention Proposal](#4-naming-convention-proposal) -5. [Current Language Separation Assessment](#5-current-language-separation-assessment) -6. [Migration Plan — Phases](#6-migration-plan--phases) +1. [Migration Plan — Phases](#1-migration-plan--phases) +2. [Permissions and Secrets Challenges](#2-permissions-and-secrets-challenges) +3. [Naming Convention Proposal](#3-naming-convention-proposal) +4. [Current Language Separation Assessment](#4-current-language-separation-assessment)5. [Workflow Inventory Tables](#5-workflow-inventory-tables) +6. [Agents, Skills, Prompts, and Supporting Resources Inventory](#6-agents-skills-prompts-and-supporting-resources-inventory) 7. [Pitfalls and Risk Register](#7-pitfalls-and-risk-register) 8. [Post-Migration Verification Checklist](#8-post-migration-verification-checklist) @@ -15,225 +14,9 @@ - [Appendix B: Unique Java Concerns vs Other Languages](#appendix-b-unique-java-concerns-vs-other-languages) - [Appendix C: Java Smoketest](#appendix-c-java-smoketest) ---- - -## 1. Workflow Inventory Tables - -### 1A. copilot-sdk-java-00 Workflows (Source) - -| YAML File Name | Brief Description | Primary Language | Complexity | -| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ---------- | -| `build-test.yml` | Main CI: Spotless, build, Javadoc, `mvn verify`, JaCoCo coverage badges | Java | L | -| `codegen-check.yml` | Re-runs Java codegen, commits regenerated files to PRs, triggers agentic fix on failure | Java | M | -| `codegen-agentic-fix.md` + `.lock.yml` | Agentic: auto-fixes compilation/test failures caused by codegen changes | Java | L | -| `reference-impl-sync.md` + `.lock.yml` | Agentic: checks for new commits in `github/copilot-sdk`, creates issue for Copilot agent to port | Java | L | -| `publish-maven.yml` | Publishes release to Maven Central via `maven-release-plugin`, GPG signing, GitHub Release creation | Java | XL | -| `publish-snapshot.yml` | Publishes SNAPSHOT builds to Maven Central Snapshots on a weekday schedule | Java | M | -| `deploy-site.yml` | Builds/deploys versioned Maven site docs to GitHub Pages | Java | M | -| `run-smoke-test.yml` | Builds SDK, installs locally, runs Copilot CLI smoke test on JDK 17 + JDK 25 (see [Appendix C](#appendix-c-java-smoketest)) | Java | M | -| `update-copilot-dependency.yml` | Updates `@github/copilot` npm dep in codegen, re-runs generator, creates PR | Java | M | -| `copilot-setup-steps.yml` | Environment setup for Copilot coding agent (JDK 17, Node 22, gh-aw, pre-commit hooks) | Java | S | -| `agentics-maintenance.yml` | Auto-generated gh-aw maintenance: closes expired discussions/issues/PRs | Cross-language (infra) | S | -| `notes.template` | Release notes template for Maven Central (not a workflow) | Java | S | - -### 1B. copilot-sdk-00 Workflows (Target Monorepo) - -| YAML File Name | Brief Description | Primary Language | Complexity | -| -------------------------------------------- | ------------------------------------------------------------------------------- | ---------------------- | ---------- | -| `nodejs-sdk-tests.yml` | Build + test Node.js SDK on 3 OS, prettier, ESLint, typecheck, E2E | Node.js | L | -| `dotnet-sdk-tests.yml` | Build + test .NET SDK on 3 OS, format check, E2E via replay proxy | .NET | L | -| `go-sdk-tests.yml` | Build + test Go SDK on 3 OS, gofmt, golangci-lint, E2E | Go | L | -| `python-sdk-tests.yml` | Build + test Python SDK on 3 OS, ruff, ty, E2E via pytest | Python | L | -| `rust-sdk-tests.yml` | Build + test Rust SDK on 3 OS, nightly fmt, clippy, cargo test | Rust | L | -| `codegen-check.yml` | Verifies generated files across Node, .NET, Python, Go, Rust | Cross-language | M | -| `publish.yml` | Publishes all SDKs (npm, NuGet, PyPI, Go tags, crates.io) from a single version | Cross-language | XL | -| `scenario-builds.yml` | Verifies example scenarios build for each language | Cross-language | M | -| `docs-validation.yml` | Extracts and validates code snippets from `docs/` | Cross-language | M | -| `update-copilot-dependency.yml` | Updates `@github/copilot` dep, re-runs codegen, opens PR | Cross-language | M | -| `copilot-setup-steps.yml` | Agent env setup: Node, Python, Go, .NET, Rust, just, gh-aw | Cross-language | M | -| `verify-compiled.yml` | Ensures `.lock.yml` files match `.md` sources | Cross-language (infra) | S | -| `collect-corrections.yml` | Collects triage agent feedback | Cross-language (infra) | S | -| `corrections-tests.yml` | Tests for triage correction scripts | Cross-language (infra) | S | -| `issue-classification.md` + `.lock.yml` | Agentic: classifies issues → routes to handle-\* handlers | Cross-language | M | -| `issue-triage.md` + `.lock.yml` | Agentic: labels, acknowledges, requests clarification, closes dupes | Cross-language | L | -| `handle-bug.md` + `.lock.yml` | Agentic: investigates bug issues | Cross-language | M | -| `handle-documentation.md` + `.lock.yml` | Agentic: handles doc-related issues | Cross-language | S | -| `handle-enhancement.md` + `.lock.yml` | Agentic: labels enhancement issues | Cross-language | S | -| `handle-question.md` + `.lock.yml` | Agentic: labels question issues | Cross-language | S | -| `cross-repo-issue-analysis.md` + `.lock.yml` | Agentic: checks if issue root cause is in copilot-agent-runtime | Cross-language | M | -| `release-changelog.md` + `.lock.yml` | Agentic: generates release notes, updates CHANGELOG | Cross-language | M | -| `sdk-consistency-review.md` + `.lock.yml` | Agentic: reviews PRs for cross-SDK feature parity | Cross-language | L | - ---- - -## 2. Agents, Skills, Prompts, and Supporting Resources Inventory - -### 2A. copilot-sdk-java-00 - -| Resource | Location | Purpose | Must Migrate? | -| ---------------------------------------------------------------- | -------------------------------------------- | -------------------------------------------- | ------------------------------------------------- | -| **Agent:** `agentic-workflows.agent.md` | `.github/agents/` | Dispatcher for gh-aw workflow creation/debug | Yes (merge with monorepo version) | -| **Skill:** `agentic-merge-reference-impl` | `.github/skills/` + `.github/prompts/` | Merges reference impl changes into Java | Yes — **must be reworked** (no longer cross-repo) | -| **Skill:** `commit-as-pull-request` | `.github/skills/` + `.github/prompts/` | Creates branch, pushes, opens PR | Yes (may already exist in monorepo) | -| **Skill:** `documentation-coverage` | `.github/skills/` + `.github/prompts/` | Assesses Java docs coverage | Yes | -| **Prompt:** `coding-agent-merge-reference-impl-instructions.md` | `.github/prompts/` | Instructions for coding agent merge | Yes | -| **Prompt:** `test-coverage-assessment.prompt.md` | `.github/prompts/` | Test coverage assessment | Yes | -| **Composite Action:** `setup-copilot` | `.github/actions/setup-copilot/` | Sets up Copilot CLI for Java tests | Yes — **adapt paths** | -| **Composite Action:** `test-report` | `.github/actions/test-report/` | Test report generation | Yes | -| **Scripts:** `release/`, `ci/`, `build/`, `reference-impl-sync/` | `.github/scripts/` | Release, CI, sync automation | Yes — **path rewrites** | -| **Dependabot:** `dependabot.yml` | `.github/` | Maven + GitHub Actions updates | Merge into monorepo's `dependabot.yaml` | -| **CODEOWNERS** | `.github/` | `@github/copilot-sdk-java` | Merge into monorepo's CODEOWNERS | -| **Issue Templates:** bug, documentation, feature, maintenance | `.github/ISSUE_TEMPLATE/` | Issue forms | Assess whether monorepo issue triage covers this | -| **PR Template** | `.github/pull_request_template.md` | PR form | Merge or keep per-language | -| **Release Config** | `.github/release.yml` | Auto-generated release notes config | Merge | -| **copilot-instructions.md** | `.github/` | Agent instructions for Java SDK | Merge (scoped to `java/`) | -| **Site templates** | `.github/templates/` | HTML/CSS for GitHub Pages | Migrate to `java/` | -| **Coverage badge script** | `.github/scripts/generate-coverage-badge.sh` | JaCoCo badge generation | Migrate | -| **`.lastmerge`** | repo root | Tracks last merged ref-impl commit | **This concept changes** — see §6 | -| **`.githooks/pre-commit`** | repo root | Runs `mvn spotless:check` | Migrate to `java/.githooks/` | -| **`instructions/copilot-sdk-java.instructions.md`** | `instructions/` | VS Code copilot instructions | Move to `java/` | - -### 2B. copilot-sdk-00 - -| Resource | Location | Purpose | -| --------------------------------------- | -------------------------------- | ----------------------------------------------------- | -| **Agent:** `agentic-workflows.agent.md` | `.github/agents/` | Same dispatcher (newer version with more routing) | -| **Agent:** `docs-maintenance.agent.md` | `.github/agents/` | Docs auditor agent | -| **Skill:** `rust-coding-skill` | `.github/skills/` | Rust-specific coding skill | -| **Composite Action:** `setup-copilot` | `.github/actions/setup-copilot/` | Sets up Copilot CLI from nodejs package | -| **Command:** `triage_feedback.yml` | `.github/commands/` | Repository dispatch for triage feedback | -| **LSP Config:** `lsp.json` | `.github/` | C#, Go language server configs | -| **Dependabot:** `dependabot.yaml` | `.github/` | npm, pip, gomod, nuget, github-actions, devcontainers | -| **CODEOWNERS** | `.github/` | `@github/copilot-sdk` | -| **copilot-instructions.md** | `.github/` | Monorepo-wide agent instructions | - ---- - -## 3. Permissions and Secrets Challenges - -### 3A. Secrets That Must Be Provisioned in copilot-sdk - -The Java SDK publish workflow requires secrets that **do not currently exist** in the `copilot-sdk` repo: - -| Secret | Used By | Notes | -| ------------------------ | ------------------------------------------------ | ------------------------------------------------------------------------------ | -| `RELEASE_TOKEN` | `publish-maven.yml` | PAT with `contents:write` for pushing tags/commits during maven-release-plugin | -| `GPG_SECRET_KEY` | `publish-maven.yml` | GPG private key for signing Maven artifacts | -| `GPG_PASSPHRASE` | `publish-maven.yml` | Passphrase for the GPG key | -| `MAVEN_CENTRAL_USERNAME` | `publish-maven.yml`, `publish-snapshot.yml` | Sonatype/Maven Central credentials | -| `MAVEN_CENTRAL_PASSWORD` | `publish-maven.yml`, `publish-snapshot.yml` | Sonatype/Maven Central credentials | -| `COPILOT_GITHUB_TOKEN` | `build-test.yml`, `codegen-agentic-fix.lock.yml` | Token for Copilot CLI in CI | - -### 3B. Existing Secrets in copilot-sdk That May Conflict - -| Secret | Used By | Concern | -| ------------------------------------------------------ | -------------------- | ------------------------------------------------------------ | -| `CARGO_REGISTRY_TOKEN` | `publish.yml` (Rust) | No conflict | -| `GH_AW_GITHUB_TOKEN` / `GH_AW_GITHUB_MCP_SERVER_TOKEN` | Agentic workflows | Likely already present; Java agentic workflows need the same | - -### 3C. Permissions / Access to Provision - -- [ ] **Repository secrets**: File a ticket to add the 6 Java-specific secrets to `github/copilot-sdk`. -- [ ] **CODEOWNERS team**: Ensure `@github/copilot-sdk-java` team has access to `github/copilot-sdk` and is added to CODEOWNERS for `java/**`. -- [ ] **Maven Central Trusted Publisher**: Currently configured for `github/copilot-sdk-java`. Must be updated to also allow publishing from `github/copilot-sdk` (or create a new namespace mapping). **This is the highest-risk permission issue** — Maven Central's Trusted Publisher setup ties the repository name to the publish flow. -- [ ] **GitHub Pages**: If `deploy-site.yml` moves, check if GitHub Pages is enabled on the monorepo and whether Java docs can coexist with any existing docs deployment. -- [ ] **Branch protection**: Ensure `main` branch protection rules in copilot-sdk permit the Java CI workflows (merge queues, required status checks, etc.). -- [ ] **Copilot coding agent**: Ensure the agent is enabled for `github/copilot-sdk` and the `copilot-setup-steps.yml` is updated to include Java tooling. - ---- - -## 4. Naming Convention Proposal - -### Current State - -The monorepo already uses a partially consistent pattern: - -- **Test workflows**: `{language}-sdk-tests.yml` (e.g., `dotnet-sdk-tests.yml`, `go-sdk-tests.yml`) -- **Cross-language workflows**: descriptive kebab-case names (e.g., `codegen-check.yml`, `publish.yml`) -- **Agentic workflows**: descriptive kebab-case (e.g., `issue-triage.md`, `handle-bug.md`) - -### Proposed Convention - -**Use kebab-case throughout. Language-specific workflows start with the language name.** - -#### Language-specific workflow naming: `{language}-{purpose}.yml` - -| Current (copilot-sdk) | Current (copilot-sdk-java) | Proposed New Name | -| ---------------------- | ------------------------------- | ------------------------------------------------------------------------------- | -| `nodejs-sdk-tests.yml` | — | `nodejs-sdk-tests.yml` (keep) | -| `dotnet-sdk-tests.yml` | — | `dotnet-sdk-tests.yml` (keep) | -| `go-sdk-tests.yml` | — | `go-sdk-tests.yml` (keep) | -| `python-sdk-tests.yml` | — | `python-sdk-tests.yml` (keep) | -| `rust-sdk-tests.yml` | — | `rust-sdk-tests.yml` (keep) | -| — | `build-test.yml` | **`java-sdk-tests.yml`** | -| — | `publish-maven.yml` | **`java-publish.yml`** | -| — | `publish-snapshot.yml` | **`java-publish-snapshot.yml`** | -| — | `deploy-site.yml` | **`java-deploy-site.yml`** | -| — | `run-smoke-test.yml` | **`java-smoke-test.yml`** | -| — | `codegen-check.yml` | **Merge into existing `codegen-check.yml`** (add Java paths + job) | -| — | `codegen-agentic-fix.md` | **`java-codegen-fix.md`** + `.lock.yml` | -| — | `reference-impl-sync.md` | **`java-reference-impl-sync.md`** + `.lock.yml` (reworked for intra-repo) | -| — | `update-copilot-dependency.yml` | **Merge into existing `update-copilot-dependency.yml`** (add Java codegen step) | -| — | `copilot-setup-steps.yml` | **Merge into existing** (add JDK 17 + Maven setup) | -| — | `agentics-maintenance.yml` | Already exists via gh-aw in the monorepo; **do not duplicate** | - -#### Cross-language workflow naming: `{purpose}.yml` (no language prefix) - -Keep existing names: `publish.yml`, `codegen-check.yml`, `scenario-builds.yml`, `docs-validation.yml`, etc. - -#### Summary of naming rules - -1. **Language-specific** workflows: `{language}-{purpose}.yml` / `.md` -2. **Cross-language** workflows: `{purpose}.yml` / `.md` (no prefix) -3. **Kebab-case** throughout (already the convention) -4. **Agentic workflows**: same pattern but with `.md` extension -5. **Lock files**: auto-generated, always `{name}.lock.yml` - ---- - -## 5. Current Language Separation Assessment - -### Are the languages in copilot-sdk-00 already sufficiently separated? - -**Mostly yes, with a few cross-cutting concerns:** - -#### Well-separated - -- **Source code**: Each language lives in its own top-level directory (`nodejs/`, `python/`, `go/`, `dotnet/`, `rust/`). Java will go in `java/`. -- **Test workflows**: Each has its own `{language}-sdk-tests.yml` with path-scoped triggers (only fires on changes to that language's directory + `test/`). -- **Dependabot**: Already per-ecosystem, per-directory entries. - -#### Cross-cutting concerns (potential friction points) - -| Concern | Current State | Impact on Java | -| --------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| **Shared test harness** (`test/harness/`) | Node.js-based replay proxy used by all E2E tests | Java already uses this (clones it at build time from `copilot-sdk` repo). When in-repo, can reference it directly — **simpler**. | -| **Shared test snapshots** (`test/snapshots/`) | YAML snapshot files consumed by all languages | Java can share these — **positive change**. | -| **Unified codegen** (`scripts/codegen/`) | One `package.json` with generators for TS, C#, Python, Go, Rust | Java codegen (`java.ts`) must be **merged in**. The Java codegen currently has its own `package.json` with a direct `@github/copilot` dependency; the monorepo codegen gets it via `nodejs/node_modules`. This needs reconciliation. | -| **`justfile`** | Has per-language targets (`format-go`, `test-dotnet`, etc.) | Must add `format-java`, `lint-java`, `test-java`, `install-java` targets. | -| **Unified `publish.yml`** | Single workflow publishes all languages with one version number | **Java CANNOT join this** — Java has its own versioning scheme (`X.Y.Z-java.N`). Java must keep a separate `java-publish.yml`. | -| **`sdk-consistency-review`** agentic workflow | Reviews PRs for cross-SDK parity (currently watches nodejs, python, go, dotnet) | Must add `java/` to the path triggers and update the agent prompt to include Java. | -| **`copilot-setup-steps.yml`** | Sets up Node, Python, Go, .NET, Rust | Must add JDK 17 + Maven. | -| **`copilot-instructions.md`** | Monorepo-wide instructions | Must incorporate Java-specific guidance. | -| **`CODEOWNERS`** | Single `* @github/copilot-sdk` | Must add `java/ @github/copilot-sdk-java` line. | -| **`lsp.json`** | Configures C# and Go language servers for Copilot agent | May want to add Java LSP (jdtls or similar) — **optional**. | - -### The Big Question: `reference-impl-sync` - -Currently, the Java SDK has a scheduled workflow that polls `github/copilot-sdk` for new commits and creates issues for the Copilot agent to port. **This workflow is still needed** when Java lives in the same repo — the primary maintainers of `dotnet/` and `nodejs/` are not Java experts, and changes to those SDKs still need to be detected and ported into `java/`. - -What changes is the **mechanism**: instead of polling a remote repository, the workflow watches for commits that land on `main` touching `dotnet/src/` or `nodejs/src/` and compares against `java/.lastmerge` (which now stores a monorepo commit SHA rather than a cross-repo one). - -**Recommendation**: - -1. **Keep `java/.lastmerge`** — it stores the last monorepo commit SHA whose `dotnet/`/`nodejs/` changes have been ported into Java. This is the anchor for diffing. -2. **Keep `reference-impl-sync` as `java-reference-impl-sync.md`** — reworked for intra-repo operation (see §6 Phase 4 for details). -3. **Keep `agentic-merge-reference-impl` skill** — reworked so that instead of cloning a remote repo, it reads diffs from the local `dotnet/` and `nodejs/` directories relative to the SHA in `java/.lastmerge`. -4. The `sdk-consistency-review` workflow provides an additional safety net on PRs, but is **not a replacement** for the scheduled sync — it only fires on PRs, not when changes land on `main` without Java updates. - ---- +--- -## 6. Migration Plan — Phases +## 1. Migration Plan — Phases ### Phase 0: Pre-Flight (Before Writing Any Code) @@ -406,6 +189,222 @@ What changes is the **mechanism**: instead of polling a remote repository, the w --- +## 2. Permissions and Secrets Challenges + +### 2A. Secrets That Must Be Provisioned in copilot-sdk + +The Java SDK publish workflow requires secrets that **do not currently exist** in the `copilot-sdk` repo: + +| Secret | Used By | Notes | +| ------------------------ | ------------------------------------------------ | ------------------------------------------------------------------------------ | +| `RELEASE_TOKEN` | `publish-maven.yml` | PAT with `contents:write` for pushing tags/commits during maven-release-plugin | +| `GPG_SECRET_KEY` | `publish-maven.yml` | GPG private key for signing Maven artifacts | +| `GPG_PASSPHRASE` | `publish-maven.yml` | Passphrase for the GPG key | +| `MAVEN_CENTRAL_USERNAME` | `publish-maven.yml`, `publish-snapshot.yml` | Sonatype/Maven Central credentials | +| `MAVEN_CENTRAL_PASSWORD` | `publish-maven.yml`, `publish-snapshot.yml` | Sonatype/Maven Central credentials | +| `COPILOT_GITHUB_TOKEN` | `build-test.yml`, `codegen-agentic-fix.lock.yml` | Token for Copilot CLI in CI | + +### 2B. Existing Secrets in copilot-sdk That May Conflict + +| Secret | Used By | Concern | +| ------------------------------------------------------ | -------------------- | ------------------------------------------------------------ | +| `CARGO_REGISTRY_TOKEN` | `publish.yml` (Rust) | No conflict | +| `GH_AW_GITHUB_TOKEN` / `GH_AW_GITHUB_MCP_SERVER_TOKEN` | Agentic workflows | Likely already present; Java agentic workflows need the same | + +### 2C. Permissions / Access to Provision + +- [ ] **Repository secrets**: File a ticket to add the 6 Java-specific secrets to `github/copilot-sdk`. +- [ ] **CODEOWNERS team**: Ensure `@github/copilot-sdk-java` team has access to `github/copilot-sdk` and is added to CODEOWNERS for `java/**`. +- [ ] **Maven Central Trusted Publisher**: Currently configured for `github/copilot-sdk-java`. Must be updated to also allow publishing from `github/copilot-sdk` (or create a new namespace mapping). **This is the highest-risk permission issue** — Maven Central's Trusted Publisher setup ties the repository name to the publish flow. +- [ ] **GitHub Pages**: If `deploy-site.yml` moves, check if GitHub Pages is enabled on the monorepo and whether Java docs can coexist with any existing docs deployment. +- [ ] **Branch protection**: Ensure `main` branch protection rules in copilot-sdk permit the Java CI workflows (merge queues, required status checks, etc.). +- [ ] **Copilot coding agent**: Ensure the agent is enabled for `github/copilot-sdk` and the `copilot-setup-steps.yml` is updated to include Java tooling. + +--- + +## 3. Naming Convention Proposal + +### Current State + +The monorepo already uses a partially consistent pattern: + +- **Test workflows**: `{language}-sdk-tests.yml` (e.g., `dotnet-sdk-tests.yml`, `go-sdk-tests.yml`) +- **Cross-language workflows**: descriptive kebab-case names (e.g., `codegen-check.yml`, `publish.yml`) +- **Agentic workflows**: descriptive kebab-case (e.g., `issue-triage.md`, `handle-bug.md`) + +### Proposed Convention + +**Use kebab-case throughout. Language-specific workflows start with the language name.** + +#### Language-specific workflow naming: `{language}-{purpose}.yml` + +| Current (copilot-sdk) | Current (copilot-sdk-java) | Proposed New Name | +| ---------------------- | ------------------------------- | ------------------------------------------------------------------------------- | +| `nodejs-sdk-tests.yml` | — | `nodejs-sdk-tests.yml` (keep) | +| `dotnet-sdk-tests.yml` | — | `dotnet-sdk-tests.yml` (keep) | +| `go-sdk-tests.yml` | — | `go-sdk-tests.yml` (keep) | +| `python-sdk-tests.yml` | — | `python-sdk-tests.yml` (keep) | +| `rust-sdk-tests.yml` | — | `rust-sdk-tests.yml` (keep) | +| — | `build-test.yml` | **`java-sdk-tests.yml`** | +| — | `publish-maven.yml` | **`java-publish.yml`** | +| — | `publish-snapshot.yml` | **`java-publish-snapshot.yml`** | +| — | `deploy-site.yml` | **`java-deploy-site.yml`** | +| — | `run-smoke-test.yml` | **`java-smoke-test.yml`** | +| — | `codegen-check.yml` | **Merge into existing `codegen-check.yml`** (add Java paths + job) | +| — | `codegen-agentic-fix.md` | **`java-codegen-fix.md`** + `.lock.yml` | +| — | `reference-impl-sync.md` | **`java-reference-impl-sync.md`** + `.lock.yml` (reworked for intra-repo) | +| — | `update-copilot-dependency.yml` | **Merge into existing `update-copilot-dependency.yml`** (add Java codegen step) | +| — | `copilot-setup-steps.yml` | **Merge into existing** (add JDK 17 + Maven setup) | +| — | `agentics-maintenance.yml` | Already exists via gh-aw in the monorepo; **do not duplicate** | + +#### Cross-language workflow naming: `{purpose}.yml` (no language prefix) + +Keep existing names: `publish.yml`, `codegen-check.yml`, `scenario-builds.yml`, `docs-validation.yml`, etc. + +#### Summary of naming rules + +1. **Language-specific** workflows: `{language}-{purpose}.yml` / `.md` +2. **Cross-language** workflows: `{purpose}.yml` / `.md` (no prefix) +3. **Kebab-case** throughout (already the convention) +4. **Agentic workflows**: same pattern but with `.md` extension +5. **Lock files**: auto-generated, always `{name}.lock.yml` + +--- + +## 4. Current Language Separation Assessment + +### Are the languages in copilot-sdk-00 already sufficiently separated? + +**Mostly yes, with a few cross-cutting concerns:** + +#### Well-separated + +- **Source code**: Each language lives in its own top-level directory (`nodejs/`, `python/`, `go/`, `dotnet/`, `rust/`). Java will go in `java/`. +- **Test workflows**: Each has its own `{language}-sdk-tests.yml` with path-scoped triggers (only fires on changes to that language's directory + `test/`). +- **Dependabot**: Already per-ecosystem, per-directory entries. + +#### Cross-cutting concerns (potential friction points) + +| Concern | Current State | Impact on Java | +| --------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **Shared test harness** (`test/harness/`) | Node.js-based replay proxy used by all E2E tests | Java already uses this (clones it at build time from `copilot-sdk` repo). When in-repo, can reference it directly — **simpler**. | +| **Shared test snapshots** (`test/snapshots/`) | YAML snapshot files consumed by all languages | Java can share these — **positive change**. | +| **Unified codegen** (`scripts/codegen/`) | One `package.json` with generators for TS, C#, Python, Go, Rust | Java codegen (`java.ts`) must be **merged in**. The Java codegen currently has its own `package.json` with a direct `@github/copilot` dependency; the monorepo codegen gets it via `nodejs/node_modules`. This needs reconciliation. | +| **`justfile`** | Has per-language targets (`format-go`, `test-dotnet`, etc.) | Must add `format-java`, `lint-java`, `test-java`, `install-java` targets. | +| **Unified `publish.yml`** | Single workflow publishes all languages with one version number | **Java CANNOT join this** — Java has its own versioning scheme (`X.Y.Z-java.N`). Java must keep a separate `java-publish.yml`. | +| **`sdk-consistency-review`** agentic workflow | Reviews PRs for cross-SDK parity (currently watches nodejs, python, go, dotnet) | Must add `java/` to the path triggers and update the agent prompt to include Java. | +| **`copilot-setup-steps.yml`** | Sets up Node, Python, Go, .NET, Rust | Must add JDK 17 + Maven. | +| **`copilot-instructions.md`** | Monorepo-wide instructions | Must incorporate Java-specific guidance. | +| **`CODEOWNERS`** | Single `* @github/copilot-sdk` | Must add `java/ @github/copilot-sdk-java` line. | +| **`lsp.json`** | Configures C# and Go language servers for Copilot agent | May want to add Java LSP (jdtls or similar) — **optional**. | + +### The Big Question: `reference-impl-sync` + +Currently, the Java SDK has a scheduled workflow that polls `github/copilot-sdk` for new commits and creates issues for the Copilot agent to port. **This workflow is still needed** when Java lives in the same repo — the primary maintainers of `dotnet/` and `nodejs/` are not Java experts, and changes to those SDKs still need to be detected and ported into `java/`. + +What changes is the **mechanism**: instead of polling a remote repository, the workflow watches for commits that land on `main` touching `dotnet/src/` or `nodejs/src/` and compares against `java/.lastmerge` (which now stores a monorepo commit SHA rather than a cross-repo one). + +**Recommendation**: + +1. **Keep `java/.lastmerge`** — it stores the last monorepo commit SHA whose `dotnet/`/`nodejs/` changes have been ported into Java. This is the anchor for diffing. +2. **Keep `reference-impl-sync` as `java-reference-impl-sync.md`** — reworked for intra-repo operation (see §6 Phase 4 for details). +3. **Keep `agentic-merge-reference-impl` skill** — reworked so that instead of cloning a remote repo, it reads diffs from the local `dotnet/` and `nodejs/` directories relative to the SHA in `java/.lastmerge`. +4. The `sdk-consistency-review` workflow provides an additional safety net on PRs, but is **not a replacement** for the scheduled sync — it only fires on PRs, not when changes land on `main` without Java updates. + +--- + +## 5. Workflow Inventory Tables + +### 5A. copilot-sdk-java-00 Workflows (Source) + +| YAML File Name | Brief Description | Primary Language | Complexity | +| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ---------- | +| `build-test.yml` | Main CI: Spotless, build, Javadoc, `mvn verify`, JaCoCo coverage badges | Java | L | +| `codegen-check.yml` | Re-runs Java codegen, commits regenerated files to PRs, triggers agentic fix on failure | Java | M | +| `codegen-agentic-fix.md` + `.lock.yml` | Agentic: auto-fixes compilation/test failures caused by codegen changes | Java | L | +| `reference-impl-sync.md` + `.lock.yml` | Agentic: checks for new commits in `github/copilot-sdk`, creates issue for Copilot agent to port | Java | L | +| `publish-maven.yml` | Publishes release to Maven Central via `maven-release-plugin`, GPG signing, GitHub Release creation | Java | XL | +| `publish-snapshot.yml` | Publishes SNAPSHOT builds to Maven Central Snapshots on a weekday schedule | Java | M | +| `deploy-site.yml` | Builds/deploys versioned Maven site docs to GitHub Pages | Java | M | +| `run-smoke-test.yml` | Builds SDK, installs locally, runs Copilot CLI smoke test on JDK 17 + JDK 25 (see [Appendix C](#appendix-c-java-smoketest)) | Java | M | +| `update-copilot-dependency.yml` | Updates `@github/copilot` npm dep in codegen, re-runs generator, creates PR | Java | M | +| `copilot-setup-steps.yml` | Environment setup for Copilot coding agent (JDK 17, Node 22, gh-aw, pre-commit hooks) | Java | S | +| `agentics-maintenance.yml` | Auto-generated gh-aw maintenance: closes expired discussions/issues/PRs | Cross-language (infra) | S | +| `notes.template` | Release notes template for Maven Central (not a workflow) | Java | S | + +### 5B. copilot-sdk-00 Workflows (Target Monorepo) + +| YAML File Name | Brief Description | Primary Language | Complexity | +| -------------------------------------------- | ------------------------------------------------------------------------------- | ---------------------- | ---------- | +| `nodejs-sdk-tests.yml` | Build + test Node.js SDK on 3 OS, prettier, ESLint, typecheck, E2E | Node.js | L | +| `dotnet-sdk-tests.yml` | Build + test .NET SDK on 3 OS, format check, E2E via replay proxy | .NET | L | +| `go-sdk-tests.yml` | Build + test Go SDK on 3 OS, gofmt, golangci-lint, E2E | Go | L | +| `python-sdk-tests.yml` | Build + test Python SDK on 3 OS, ruff, ty, E2E via pytest | Python | L | +| `rust-sdk-tests.yml` | Build + test Rust SDK on 3 OS, nightly fmt, clippy, cargo test | Rust | L | +| `codegen-check.yml` | Verifies generated files across Node, .NET, Python, Go, Rust | Cross-language | M | +| `publish.yml` | Publishes all SDKs (npm, NuGet, PyPI, Go tags, crates.io) from a single version | Cross-language | XL | +| `scenario-builds.yml` | Verifies example scenarios build for each language | Cross-language | M | +| `docs-validation.yml` | Extracts and validates code snippets from `docs/` | Cross-language | M | +| `update-copilot-dependency.yml` | Updates `@github/copilot` dep, re-runs codegen, opens PR | Cross-language | M | +| `copilot-setup-steps.yml` | Agent env setup: Node, Python, Go, .NET, Rust, just, gh-aw | Cross-language | M | +| `verify-compiled.yml` | Ensures `.lock.yml` files match `.md` sources | Cross-language (infra) | S | +| `collect-corrections.yml` | Collects triage agent feedback | Cross-language (infra) | S | +| `corrections-tests.yml` | Tests for triage correction scripts | Cross-language (infra) | S | +| `issue-classification.md` + `.lock.yml` | Agentic: classifies issues → routes to handle-\* handlers | Cross-language | M | +| `issue-triage.md` + `.lock.yml` | Agentic: labels, acknowledges, requests clarification, closes dupes | Cross-language | L | +| `handle-bug.md` + `.lock.yml` | Agentic: investigates bug issues | Cross-language | M | +| `handle-documentation.md` + `.lock.yml` | Agentic: handles doc-related issues | Cross-language | S | +| `handle-enhancement.md` + `.lock.yml` | Agentic: labels enhancement issues | Cross-language | S | +| `handle-question.md` + `.lock.yml` | Agentic: labels question issues | Cross-language | S | +| `cross-repo-issue-analysis.md` + `.lock.yml` | Agentic: checks if issue root cause is in copilot-agent-runtime | Cross-language | M | +| `release-changelog.md` + `.lock.yml` | Agentic: generates release notes, updates CHANGELOG | Cross-language | M | +| `sdk-consistency-review.md` + `.lock.yml` | Agentic: reviews PRs for cross-SDK feature parity | Cross-language | L | + +--- + +## 6. Agents, Skills, Prompts, and Supporting Resources Inventory + +### 6A. copilot-sdk-java-00 + +| Resource | Location | Purpose | Must Migrate? | +| ---------------------------------------------------------------- | -------------------------------------------- | -------------------------------------------- | ------------------------------------------------- | +| **Agent:** `agentic-workflows.agent.md` | `.github/agents/` | Dispatcher for gh-aw workflow creation/debug | Yes (merge with monorepo version) | +| **Skill:** `agentic-merge-reference-impl` | `.github/skills/` + `.github/prompts/` | Merges reference impl changes into Java | Yes — **must be reworked** (no longer cross-repo) | +| **Skill:** `commit-as-pull-request` | `.github/skills/` + `.github/prompts/` | Creates branch, pushes, opens PR | Yes (may already exist in monorepo) | +| **Skill:** `documentation-coverage` | `.github/skills/` + `.github/prompts/` | Assesses Java docs coverage | Yes | +| **Prompt:** `coding-agent-merge-reference-impl-instructions.md` | `.github/prompts/` | Instructions for coding agent merge | Yes | +| **Prompt:** `test-coverage-assessment.prompt.md` | `.github/prompts/` | Test coverage assessment | Yes | +| **Composite Action:** `setup-copilot` | `.github/actions/setup-copilot/` | Sets up Copilot CLI for Java tests | Yes — **adapt paths** | +| **Composite Action:** `test-report` | `.github/actions/test-report/` | Test report generation | Yes | +| **Scripts:** `release/`, `ci/`, `build/`, `reference-impl-sync/` | `.github/scripts/` | Release, CI, sync automation | Yes — **path rewrites** | +| **Dependabot:** `dependabot.yml` | `.github/` | Maven + GitHub Actions updates | Merge into monorepo's `dependabot.yaml` | +| **CODEOWNERS** | `.github/` | `@github/copilot-sdk-java` | Merge into monorepo's CODEOWNERS | +| **Issue Templates:** bug, documentation, feature, maintenance | `.github/ISSUE_TEMPLATE/` | Issue forms | Assess whether monorepo issue triage covers this | +| **PR Template** | `.github/pull_request_template.md` | PR form | Merge or keep per-language | +| **Release Config** | `.github/release.yml` | Auto-generated release notes config | Merge | +| **copilot-instructions.md** | `.github/` | Agent instructions for Java SDK | Merge (scoped to `java/`) | +| **Site templates** | `.github/templates/` | HTML/CSS for GitHub Pages | Migrate to `java/` | +| **Coverage badge script** | `.github/scripts/generate-coverage-badge.sh` | JaCoCo badge generation | Migrate | +| **`.lastmerge`** | repo root | Tracks last merged ref-impl commit | **This concept changes** — see §6 | +| **`.githooks/pre-commit`** | repo root | Runs `mvn spotless:check` | Migrate to `java/.githooks/` | +| **`instructions/copilot-sdk-java.instructions.md`** | `instructions/` | VS Code copilot instructions | Move to `java/` | + +### 6B. copilot-sdk-00 + +| Resource | Location | Purpose | +| --------------------------------------- | -------------------------------- | ----------------------------------------------------- | +| **Agent:** `agentic-workflows.agent.md` | `.github/agents/` | Same dispatcher (newer version with more routing) | +| **Agent:** `docs-maintenance.agent.md` | `.github/agents/` | Docs auditor agent | +| **Skill:** `rust-coding-skill` | `.github/skills/` | Rust-specific coding skill | +| **Composite Action:** `setup-copilot` | `.github/actions/setup-copilot/` | Sets up Copilot CLI from nodejs package | +| **Command:** `triage_feedback.yml` | `.github/commands/` | Repository dispatch for triage feedback | +| **LSP Config:** `lsp.json` | `.github/` | C#, Go language server configs | +| **Dependabot:** `dependabot.yaml` | `.github/` | npm, pip, gomod, nuget, github-actions, devcontainers | +| **CODEOWNERS** | `.github/` | `@github/copilot-sdk` | +| **copilot-instructions.md** | `.github/` | Monorepo-wide agent instructions | + +--- + ## 7. Pitfalls and Risk Register ### HIGH RISK From 235a088c6c94e0e1be67709f3813041aec99da5c Mon Sep 17 00:00:00 2001 From: Ed Burns Date: Wed, 13 May 2026 14:33:39 -0700 Subject: [PATCH 4/6] On branch edburns/80-java-monorepo-add-01 https://github.com/github/copilot-sdk-partners/issues/89 modified: .github/CODEOWNERS - Add row mapping `java` to `@github/copilot-sdk-java`. modified: 80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md - Fix reference. new: 80-java-monorepo-add-01-remove-before-merge/20260513-prompts.md - Today's prompts. --- .github/CODEOWNERS | 1 + .../20260513-prompts.md | 189 ++++++++++++++++++ .../dd-2989727-move-java-to-monorepo-plan.md | 2 +- 3 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 80-java-monorepo-add-01-remove-before-merge/20260513-prompts.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index c6959d308..3ff90f1e4 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1,2 @@ * @github/copilot-sdk +java/ @github/copilot-sdk-java diff --git a/80-java-monorepo-add-01-remove-before-merge/20260513-prompts.md b/80-java-monorepo-add-01-remove-before-merge/20260513-prompts.md new file mode 100644 index 000000000..09545aae8 --- /dev/null +++ b/80-java-monorepo-add-01-remove-before-merge/20260513-prompts.md @@ -0,0 +1,189 @@ +### 14:07 Prompt + +The plan calls for + +``` +6. Update `CODEOWNERS`: + - Add `java/ @github/copilot-sdk-java` +``` + +Every human member of the `copilot-sdk-java` team is already a member of `@github/copilot-sdk-java`. So I assert no further action is necessary on this file in `copilot-sdk-00`. Do you agree? + +### 14:09 Response + +I’m going to inspect the existing `CODEOWNERS` entry and the surrounding repo setup so I can answer your assertion against what the plan item is actually doing. + +Searched for files matching `copilot-sdk-00` · `**/CODEOWNERS`, 1 match + +Searched for regex `copilot-sdk-java|java/` (`copilot-sdk-00`), 50 results + +I’ve confirmed the plan item is specifically about path ownership in the monorepo, not about whether the same humans are already covered indirectly; next I’m reading the current CODEOWNERS file itself. + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/CODEOWNERS) + +I don’t agree. + +Right now CODEOWNERS contains only: + +```text +* @github/copilot-sdk +``` + +So adding `java/ @github/copilot-sdk-java` would still change behavior in an important way: it makes java reviews route to the Java team explicitly, rather than relying on broad ownership by `@github/copilot-sdk`. The fact that the human members overlap today doesn’t make the entry redundant, because CODEOWNERS is about repository policy and future-proof routing, not just current membership coincidence. + +Two practical reasons the explicit java entry still matters: +- it documents that java has a distinct ownership boundary inside the monorepo +- it preserves the intended reviewers if team membership diverges later, or if branch protection / required review rules key off CODEOWNERS matches + +So my recommendation is: keep the plan item, unless your actual policy decision is that Java should remain owned by the general monorepo team with no special routing. + +### 14:11 Prompt + +Is this correct: + +The purpose of the `CODEOWNERS` file is to establish an explicit per-path mapping between paths and teams responsible for maintaining the content within those paths. + +### 14:12 Response + +Yes, that’s basically correct. + +A slightly tighter version would be: + +CODEOWNERS establishes explicit ownership rules that map repository paths to users or teams, mainly so GitHub can automatically request reviews and apply code-owner-based branch protection behavior for changes to those paths. + +That wording matters because “responsible for maintaining” is true in a social sense, but the file’s concrete function is operational: review routing and policy enforcement. + +### 14:12 Prompt + +But does it make sense for path entries in `CODEOWNERS` to "reach out" of the current repo in which the `CODEOWNERS` file resides? + +### 14:13 Response + +No. That would not make sense. + +CODEOWNERS only has meaning within the repository that contains it. Its path patterns match paths in that same repo, and its owners must be users or teams that GitHub can resolve for that repo. It does not express ownership for files in some other repository, and it does not “reach out” across repo boundaries. + +So if a CODEOWNERS entry in `github/copilot-sdk` says `java/ @github/copilot-sdk-java`, that is still about ownership of the java directory inside `github/copilot-sdk`, not about the separate `github/copilot-sdk-java` repository. The team name may happen to reference the Java maintainers, but the scope of the rule remains local to the monorepo. + +### 14:13 Prompt + +So what is the meaning of the RHS of an entry in `CODEOWNERS`, if it's not a repo identifier? + +### 14:14 Response + +The RHS is an owner specifier, not a repository identifier. + +In GitHub CODEOWNERS, the right-hand side names the users or teams who own matching paths for that repository’s review/policy purposes. Those values are things like: + +- `@username` +- `@org/team-name` +- sometimes an email address, depending on GitHub context, though teams/users are the common case + +So in: + +```text +java/ @github/copilot-sdk-java +``` + +- java means “the java path inside this repository” +- `@github/copilot-sdk-java` means “the GitHub team named `copilot-sdk-java` in the `github` organization” + +That RHS does not point to a repo. It points to a principal GitHub can use as a code owner for matching files in the current repo. + +### 14:15 Prompt + +So how does one browse the teams registry within the `github` organization? + +### 14:15 Response + +If you have the right GitHub org permissions, the usual way is in the GitHub web UI: + +`github` organization page -> `Teams` + +From there you can browse the team list, search by name, and open a team like `copilot-sdk-java`. + +Direct URL shape is usually: + +```text +https://github.com/orgs/github/teams +https://github.com/orgs/github/teams/copilot-sdk-java +``` + +A couple of practical wrinkles: +- whether you can actually view the full team registry depends on your org visibility and permissions +- some teams may be secret or partially hidden, so you might not see everything even inside the org +- for a repo-specific check, the more relevant question is whether `@github/copilot-sdk-java` has access to `github/copilot-sdk`, not just whether the team exists + +If you want, I can help you phrase the exact criterion for the migration plan: “team exists,” “team is visible,” or “team has sufficient repo access.” + +### 14:24 Prompt + +Review the change to this file for syntactic and semantic correctness. + +### 14:25 Response + +I’m going to inspect the current CODEOWNERS diff and the surrounding repo state so I can review both syntax and what the new rule would actually do. + +Read changed files in [](file:///e%3A/workareas/copilot-sdk-00) + +Read [](file:///e%3A/workareas/copilot-sdk-00/.github/CODEOWNERS) + +Findings first: I don’t see a syntax problem in CODEOWNERS. + +Semantically, the new line is correct if your intent is “files under java in this monorepo should be code-owned by the `@github/copilot-sdk-java` team.” In GitHub CODEOWNERS, the later, more specific rule wins, so: + +```text +* @github/copilot-sdk +java/ @github/copilot-sdk-java +``` + +means the whole repo defaults to `@github/copilot-sdk`, while java is explicitly owned by the Java team. That is valid and coherent. + +Open question / assumption: this only works operationally if `@github/copilot-sdk-java` is a resolvable team and has the necessary access to the `github/copilot-sdk` repository. If that team is missing, hidden in a way GitHub can’t use here, or lacks repo access, the entry can be semantically wrong in practice even though the file syntax is fine. + +Change summary: the edit is syntactically fine and semantically appropriate for a monorepo path-specific ownership rule. The only external dependency is team existence plus repo access. + +### 14:25 Prompt + +I created the `@github/copilot-sdk-java` team as a "child" of `@github/copilot-sdk`. Does that guarantee path access? + +### 14:28 Response + +No, that does not guarantee it. + +A parent/child team relationship in GitHub mainly helps with organization and inherited membership/visibility patterns, but it does not by itself guarantee that the child team is usable as a code owner for a repo unless that team also has appropriate access to that repository. + +For CODEOWNERS, the practical check is still: +- does `@github/copilot-sdk-java` exist as a team in the `github` org? +- does that team have access to the `github/copilot-sdk` repository? +- is the team visible/usable enough for GitHub to resolve it in code owner rules? + +So making `copilot-sdk-java` a child of `copilot-sdk` is suggestive and often helpful administratively, but I would not treat it as proof. The thing you want to verify is explicit repo access on `github/copilot-sdk` for that child team. + +### 14:28 Prompt + +You stated + +> - does `@github/copilot-sdk-java` exist as a team in the `github` org? + +Yes. I created it. + +> - does that team have access to the `github/copilot-sdk` repository? + +Well, I do. But that's probably because I have been added to that repo. How can I make sure the "team" entity has access? + +### 14:29 Response + +You want to check the team-to-repo grant directly, not infer it from your personal access. + +In the GitHub UI, the cleanest path is to open the team and inspect its repositories: +`Organization` -> `Teams` -> `copilot-sdk-java` -> `Repositories` + +If `github/copilot-sdk` appears there, the team has been granted access. If it does not, the team itself does not currently have repo access, even if you personally do. + +The inverse view also works: +`github/copilot-sdk` -> `Settings` -> `Collaborators and teams` + +That page should list `copilot-sdk-java` as a team with a permission level such as `Read`, `Write`, `Maintain`, or `Admin`. For CODEOWNERS, the important thing is that GitHub can resolve the team for that repo; in practice, checking that it appears there is the reliable test. + +So the short answer is: look for the team on the repo’s `Collaborators and teams` page, or look for the repo on the team’s `Repositories` page. That tells you about the team entity, not just you as an individual. diff --git a/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md b/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md index cfc3fffcb..1b7ac04ae 100644 --- a/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md +++ b/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md @@ -20,7 +20,7 @@ ### Phase 0: Pre-Flight (Before Writing Any Code) -- [ ] **Provision secrets** in `github/copilot-sdk` (see §3A) +- [ ] **Provision secrets** in `github/copilot-sdk` (see §2A) - [ ] **Verify CODEOWNERS team** access - [ ] **Check Maven Central Trusted Publisher** — can `github/copilot-sdk` publish to `com.github:copilot-sdk-java`? - [ ] **Check GitHub Pages** — is it enabled? Can Java docs coexist? From 052ba27f2933713b1e4ff841420b769fc4cb4df8 Mon Sep 17 00:00:00 2001 From: Ed Burns Date: Wed, 13 May 2026 14:51:38 -0700 Subject: [PATCH 5/6] test: verify gpg signing From 5963904e40b45dfc5b5d4a030f764f6538209ceb Mon Sep 17 00:00:00 2001 From: Ed Burns Date: Wed, 13 May 2026 16:30:17 -0700 Subject: [PATCH 6/6] On branch edburns/80-java-monorepo-add-01 modified: 80-java-monorepo-add-01-remove-before-merge/20260513-prompts.md modified: 80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md - WIP Phase 0. .github/workflows/java-publish-maven.yml .github/workflows/java-publish-snapshot.yml - Copy over from `copilot-sdk-java-00`. 80-java-monorepo-add-01-remove-before-merge/ghcpsp-90-gpg-key-archive.sh 80-java-monorepo-add-01-remove-before-merge/ghcpsp-90-gpg-key-import.sh - Durable way to hand off the ability to publish to maven central. Currently resides with @edburns. --- .github/workflows/java-publish-maven.yml | 256 ++++++++++++++++++ .github/workflows/java-publish-snapshot.yml | 55 ++++ .../20260513-prompts.md | 253 +++++++++++++++++ .../dd-2989727-move-java-to-monorepo-plan.md | 32 +-- .../ghcpsp-90-gpg-key-archive.sh | 165 +++++++++++ .../ghcpsp-90-gpg-key-import.sh | 161 +++++++++++ 6 files changed, 906 insertions(+), 16 deletions(-) create mode 100644 .github/workflows/java-publish-maven.yml create mode 100644 .github/workflows/java-publish-snapshot.yml create mode 100644 80-java-monorepo-add-01-remove-before-merge/ghcpsp-90-gpg-key-archive.sh create mode 100644 80-java-monorepo-add-01-remove-before-merge/ghcpsp-90-gpg-key-import.sh diff --git a/.github/workflows/java-publish-maven.yml b/.github/workflows/java-publish-maven.yml new file mode 100644 index 000000000..e98060a45 --- /dev/null +++ b/.github/workflows/java-publish-maven.yml @@ -0,0 +1,256 @@ +name: Publish to Maven Central + +env: + # Disable Husky Git hooks in CI to prevent local development hooks + # (e.g., pre-commit formatting checks) from running during automated + # workflows that perform git commits and pushes. + HUSKY: 0 + +on: + workflow_dispatch: + inputs: + releaseVersion: + description: "Release version (e.g., 1.0.0). If empty, derives from pom.xml by removing -SNAPSHOT" + required: false + type: string + developmentVersion: + description: "Next development version (e.g., 1.0.1-SNAPSHOT). If empty, increments patch version" + required: false + type: string + prerelease: + description: "Is this a prerelease?" + type: boolean + required: false + default: false + +permissions: + contents: write + id-token: write + +concurrency: + group: publish-maven + cancel-in-progress: false + +jobs: + publish-maven: + name: Publish Java SDK to Maven Central + runs-on: ubuntu-latest + outputs: + version: ${{ steps.versions.outputs.release_version }} + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + token: ${{ secrets.JAVA_RELEASE_TOKEN }} + + - name: Configure Git for Maven Release + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + - uses: ./.github/actions/setup-copilot + + - name: Set up JDK 17 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: "17" + distribution: "microsoft" + cache: "maven" + server-id: central + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + gpg-private-key: ${{ secrets.JAVA_GPG_SECRET_KEY }} + gpg-passphrase: JAVA_GPG_PASSPHRASE + + - name: Determine versions + id: versions + run: | + CURRENT_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) + echo "Current pom.xml version: $CURRENT_VERSION" + + # Determine release version + if [ -n "${{ inputs.releaseVersion }}" ]; then + RELEASE_VERSION="${{ inputs.releaseVersion }}" + else + # Remove -SNAPSHOT suffix if present + RELEASE_VERSION="${CURRENT_VERSION%-SNAPSHOT}" + fi + echo "Release version: $RELEASE_VERSION" + + # Determine next development version + if [ -n "${{ inputs.developmentVersion }}" ]; then + DEV_VERSION="${{ inputs.developmentVersion }}" + if [[ "$DEV_VERSION" != *-SNAPSHOT ]]; then + echo "::error::developmentVersion '${DEV_VERSION}' must end with '-SNAPSHOT' (e.g., '${DEV_VERSION}-SNAPSHOT'). The maven-release-plugin requires the next development version to be a snapshot." + exit 1 + fi + else + # Split version: supports "0.1.32", "0.1.32-java.0", and "0.1.32-java-preview.0" formats + # Validate RELEASE_VERSION format explicitly to provide clear errors + if ! echo "$RELEASE_VERSION" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(-java(-preview)?\.[0-9]+)?$'; then + echo "Error: RELEASE_VERSION '$RELEASE_VERSION' is invalid. Expected format: M.M.P, M.M.P-java.N, or M.M.P-java-preview.N (e.g., 1.2.3, 1.2.3-java.0, or 1.2.3-java-preview.0)." >&2 + exit 1 + fi + # Extract the base M.M.P portion (before any qualifier) + BASE_VERSION=$(echo "$RELEASE_VERSION" | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+') + QUALIFIER=$(echo "$RELEASE_VERSION" | sed "s|^${BASE_VERSION}||") + IFS='.' read -r MAJOR MINOR PATCH <<< "$BASE_VERSION" + NEXT_PATCH=$((PATCH + 1)) + DEV_VERSION="${MAJOR}.${MINOR}.${NEXT_PATCH}${QUALIFIER}-SNAPSHOT" + fi + echo "Next development version: $DEV_VERSION" + + echo "release_version=$RELEASE_VERSION" >> $GITHUB_OUTPUT + echo "dev_version=$DEV_VERSION" >> $GITHUB_OUTPUT + + echo "### Version Summary" >> $GITHUB_STEP_SUMMARY + echo "- **Release version:** $RELEASE_VERSION" >> $GITHUB_STEP_SUMMARY + echo "- **Next development version:** $DEV_VERSION" >> $GITHUB_STEP_SUMMARY + + - name: Update documentation with release version + id: update-docs + 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/scripts/release/update-changelog.sh "${VERSION}" "${REFERENCE_IMPL_HASH}" + + # Update version in README.md (supports versions like 1.0.0, 0.1.32-java.0, and 0.3.0-java-preview.0) + sed -i "s|[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\(-java\(-preview\)\{0,1\}\.[0-9][0-9]*\)\{0,1\}|${VERSION}|g" README.md + sed -i "s|copilot-sdk-java:[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\(-java\(-preview\)\{0,1\}\.[0-9][0-9]*\)\{0,1\}|copilot-sdk-java:${VERSION}|g" README.md + + # Update snapshot version in README.md + DEV_VERSION="${{ steps.versions.outputs.dev_version }}" + sed -i "s|[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\(-java\(-preview\)\{0,1\}\.[0-9][0-9]*\)\{0,1\}-SNAPSHOT|${DEV_VERSION}|g" README.md + + # Update version in jbang-example.java + sed -i "s|copilot-sdk-java:[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\(-java\(-preview\)\{0,1\}\.[0-9][0-9]*\)\{0,1\}|copilot-sdk-java:${VERSION}|g" jbang-example.java + sed -i 's|copilot-sdk-java:${project\.version}|copilot-sdk-java:'"${VERSION}"'|g' jbang-example.java + + # Update version in cookbook files (hardcoded for direct GitHub browsing and JBang usage) + find src/site/markdown/cookbook -name "*.md" -type f -exec \ + sed -i "s|copilot-sdk-java:[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\(-java\(-preview\)\{0,1\}\.[0-9][0-9]*\)\{0,1\}|copilot-sdk-java:${VERSION}|g" {} \; + + # Commit the documentation changes before release:prepare (requires clean working directory) + git add CHANGELOG.md README.md jbang-example.java src/site/markdown/cookbook/ + git commit -m "docs: update version references to ${VERSION}" + + # Save the commit SHA for potential rollback + echo "docs_commit_sha=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT + + git push origin main + + - name: Prepare Release + run: | + mvn -B release:prepare \ + -DreleaseVersion=${{ steps.versions.outputs.release_version }} \ + -DdevelopmentVersion=${{ steps.versions.outputs.dev_version }} \ + -DtagNameFormat=v@{project.version} \ + -DpushChanges=true \ + -Darguments="-DskipTests" + env: + MAVEN_USERNAME: ${{ secrets.JAVA_MAVEN_CENTRAL_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.JAVA_MAVEN_CENTRAL_PASSWORD }} + JAVA_GPG_PASSPHRASE: ${{ secrets.JAVA_GPG_PASSPHRASE }} + + - name: Perform Release and Deploy to Maven Central + run: | + mvn -B release:perform \ + -Dgoals="deploy" \ + -Darguments="-DskipTests -Prelease" + env: + MAVEN_USERNAME: ${{ secrets.JAVA_MAVEN_CENTRAL_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.JAVA_MAVEN_CENTRAL_PASSWORD }} + JAVA_GPG_PASSPHRASE: ${{ secrets.JAVA_GPG_PASSPHRASE }} + + - name: Rollback documentation commit on failure + if: failure() && steps.update-docs.outputs.docs_commit_sha != '' + run: | + echo "Release failed, rolling back documentation commit..." + git revert --no-edit ${{ steps.update-docs.outputs.docs_commit_sha }} + git push origin main + + # Also run Maven release:rollback to clean up any partial release state + mvn -B release:rollback || true + + github-release: + name: Create GitHub Release + needs: publish-maven + if: github.ref == 'refs/heads/main' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + - name: Create GitHub Release + run: | + VERSION="${{ needs.publish-maven.outputs.version }}" + GROUP_ID="com.github" + ARTIFACT_ID="copilot-sdk-java" + CURRENT_TAG="v${VERSION}" + + if gh release view "${CURRENT_TAG}" >/dev/null 2>&1; then + echo "Release ${CURRENT_TAG} already exists. Skipping creation." + exit 0 + fi + + # Generate release notes from template + export VERSION GROUP_ID ARTIFACT_ID + RELEASE_NOTES=$(envsubst < .github/workflows/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]+)?$' \ + | grep -Fxv "${CURRENT_TAG}" \ + | head -n 1) + + echo "Current tag: ${CURRENT_TAG}" + echo "Previous tag: ${PREV_TAG}" + + # Build the gh release command + GH_ARGS=("${CURRENT_TAG}") + GH_ARGS+=("--title" "GitHub Copilot SDK for Java ${VERSION}") + GH_ARGS+=("--notes" "${RELEASE_NOTES}") + GH_ARGS+=("--generate-notes") + + if [ -n "$PREV_TAG" ]; then + GH_ARGS+=("--notes-start-tag" "$PREV_TAG") + fi + + ${{ inputs.prerelease == true && 'GH_ARGS+=("--prerelease")' || '' }} + + 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 new file mode 100644 index 000000000..d7720ceb2 --- /dev/null +++ b/.github/workflows/java-publish-snapshot.yml @@ -0,0 +1,55 @@ +name: Publish Snapshot to Maven Central + +env: + HUSKY: 0 + +on: + schedule: + - cron: "0 7 * * 1-5" # Mon-Fri at 07:00 UTC + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: publish-snapshot + cancel-in-progress: false + +jobs: + publish-snapshot: + name: Publish SNAPSHOT to Maven Central + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + + - uses: ./.github/actions/setup-copilot + + - name: Set up JDK 17 + uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5 + with: + java-version: "17" + distribution: "microsoft" + cache: "maven" + server-id: central + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + + - name: Verify version is a SNAPSHOT + run: | + VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout) + echo "Publishing version: $VERSION" + if [[ "$VERSION" != *"-SNAPSHOT" ]]; then + echo "ERROR: This workflow only publishes SNAPSHOT versions. Current version: $VERSION" + exit 1 + fi + echo "### Snapshot Publish" >> $GITHUB_STEP_SUMMARY + echo "- **Version:** $VERSION" >> $GITHUB_STEP_SUMMARY + echo "- **Repository:** Maven Central Snapshots" >> $GITHUB_STEP_SUMMARY + + - name: Deploy Snapshot + run: mvn -B deploy -DskipTests + env: + MAVEN_USERNAME: ${{ secrets.JAVA_MAVEN_CENTRAL_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.JAVA_MAVEN_CENTRAL_PASSWORD }} diff --git a/80-java-monorepo-add-01-remove-before-merge/20260513-prompts.md b/80-java-monorepo-add-01-remove-before-merge/20260513-prompts.md index 09545aae8..b509025e8 100644 --- a/80-java-monorepo-add-01-remove-before-merge/20260513-prompts.md +++ b/80-java-monorepo-add-01-remove-before-merge/20260513-prompts.md @@ -187,3 +187,256 @@ The inverse view also works: That page should list `copilot-sdk-java` as a team with a permission level such as `Read`, `Write`, `Maintain`, or `Admin`. For CODEOWNERS, the important thing is that GitHub can resolve the team for that repo; in practice, checking that it appears there is the reliable test. So the short answer is: look for the team on the repo’s `Collaborators and teams` page, or look for the repo on the team’s `Repositories` page. That tells you about the team entity, not just you as an individual. + +### 15:01 Prompt + +I am working on https://github.com/github/copilot-sdk-partners/issues/90 now. Use `gh` to inspect this work item. + +I come to the `RELEASE_TOKEN` secret. + +I expect it would be wise to scope this token so its name is `JAVA_RELEASE_TOKEN`. I expct this would require changes in the workflow files in `copilot-sdk-java-00` as they are moved to `copilot-sdk-00`. Inspect the workflow files in the former and tell me what must change to honor `JAVA_RELEASE_TOKEN` instead of the unscoped `RELEASE_TOKEN`. + +### 15:04 Response + +I’ll search for workflow files in copilot-sdk-java-00 that reference `RELEASE_TOKEN` and identify what would need to change to use `JAVA_RELEASE_TOKEN` instead. + +Searched for text `RELEASE_TOKEN` (`copilot-sdk-java-00` · `.github/workflows/**`), 1 result + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/.github/workflows/publish-maven.yml#30-30), lines 30 to 60 + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/.github/workflows/publish-maven.yml#1-1), lines 1 to 30 + +The only workflow reference to `RELEASE_TOKEN` is in the publish-maven.yml file, specifically as the `token` for the `actions/checkout` step. + +To switch to `JAVA_RELEASE_TOKEN`, you must: +- Change all instances of `${{ secrets.RELEASE_TOKEN }}` to `${{ secrets.JAVA_RELEASE_TOKEN }}` in publish-maven.yml. + +No other workflow files reference `RELEASE_TOKEN`, so only this change is required. If you move or adapt this workflow into the monorepo, ensure the secret is set as `JAVA_RELEASE_TOKEN` in the repo’s GitHub Actions secrets. + +### 15:12 Prompt + +We must do the same thing with `GPG_SECRET_KEY` and `GPG_PASSPHRASE`. Those should have the `JAVA` prefix. Analyze the workflows in `copilot-sdk-java-00` and list what needs to change. + +### 15:22 Response + +I’ll search for all workflow references to `GPG_SECRET_KEY` and `GPG_PASSPHRASE` in copilot-sdk-java-00 to identify what must be updated to use `JAVA_GPG_SECRET_KEY` and `JAVA_GPG_PASSPHRASE`. + +Searched for text `GPG_SECRET_KEY` (`copilot-sdk-java-00` · `.github/workflows/**`), 1 result + +Searched for text `GPG_PASSPHRASE` (`copilot-sdk-java-00` · `.github/workflows/**`), 5 results + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/.github/workflows/publish-maven.yml#60-60), lines 60 to 180 + +To use `JAVA_GPG_SECRET_KEY` and `JAVA_GPG_PASSPHRASE` instead of the unscoped names, you must: + +- Change all instances of `${{ secrets.GPG_SECRET_KEY }}` to `${{ secrets.JAVA_GPG_SECRET_KEY }}` +- Change all instances of `${{ secrets.GPG_PASSPHRASE }}` to `${{ secrets.JAVA_GPG_PASSPHRASE }}` + +in the following places in publish-maven.yml: +- The `gpg-private-key` input to `actions/checkout` (or any other action using it) +- All `env:` blocks that set `GPG_PASSPHRASE` for Maven commands + +Summary of lines to update: +- Line 62: `gpg-private-key: ${{ secrets.GPG_SECRET_KEY }}` +- Line 160, 170: `GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}` (in two steps) +- Any other direct references to these secrets in the workflow + +No other workflow files reference these secrets, so only this file needs updating. Also, ensure the new secrets are set in the repo’s GitHub Actions secrets. + +### 15:39 Prompt + +Given that I just used this command to obtain the value for the new `JAVA_GPG_SECRET_KEY` secret, how would I correctly archive the full set of information needed to hand off this keypair to another party, assuming full trust. + +### 15:42 Response + +For a complete, transferable handoff of a GPG signing identity, archive all of these items together: + +1. Secret key material +- Export the secret key in armored form. +- If you have subkeys, export the full secret key bundle, not just a single subkey. + +2. Public key +- Export the corresponding public key (armored). +- This lets the recipient re-import and verify identity metadata cleanly. + +3. Fingerprint and key metadata +- Record full fingerprint, key ID, creation date, expiration date, and UID(s). +- Include the expected signing subkey fingerprint if different. + +4. Revocation certificate +- Include the pre-generated revocation certificate. +- This is critical if compromise is later suspected. + +5. Trust/ownertrust data (optional but useful) +- Export ownertrust so recipient can restore trust settings quickly. + +6. Passphrase handling +- If passphrase-protected, provide the passphrase separately from the key archive, even in a full-trust handoff. +- Best practice is two channels (for example: file transfer for key archive, voice/secure chat for passphrase). + +7. Operational notes +- What this key is used for (for example, Maven release signing). +- Where it is expected to be installed (CI secret name, local keyring use, etc.). +- Rotation/expiry policy and who owns lifecycle management. + +Recommended packaging flow: +1. Put exported files plus a README into one folder. +2. Create a tar/zip archive. +3. Encrypt that archive to the recipient (or recipients) with their public key. +4. Sign the encrypted archive with your current signing key. +5. Transfer. +6. Recipient verifies your signature and fingerprint out-of-band before use. + +Minimal file set to include: +- secret-key.asc +- public-key.asc +- fingerprint.txt +- revocation.asc +- ownertrust.txt +- handoff-notes.txt + +If you want, I can draft a concrete Windows PowerShell command sequence for creating this bundle and producing an encrypted handoff artifact end-to-end. + +### 15:45 Prompt + +Write it as a bash script to `80-java-monorepo-add-01-remove-before-merge/ghcpsp-90-gpg-key-archive.sh` + +### 15:46 Response + +I’m going to check whether that script file already exists, then I’ll create it with an end-to-end export, bundle, encrypt, and sign flow you can run directly. + +Searched for files matching `copilot-sdk-00` · `80-java-monorepo-add-01-remove-before-merge/ghcpsp-90-gpg-key-archive.sh`, no matches + +I’m creating the script now in the requested path with sane defaults, argument validation, and all artifacts needed for a trusted handoff package. + +Created [](file:///e%3A/workareas/copilot-sdk-00/80-java-monorepo-add-01-remove-before-merge/ghcpsp-90-gpg-key-archive.sh) + +Created the script at ghcpsp-90-gpg-key-archive.sh. + +What it does: +- Validates required tools and arguments +- Exports secret key, public key, ownertrust, fingerprint details +- Includes revocation certificate if found in the standard GnuPG location +- Writes handoff notes with operational guidance +- Produces both: + - plain tar.gz bundle + - armored encrypted+signed bundle for transfer + +Usage: +ghcpsp-90-gpg-key-archive.sh [output-dir] + +If you want, I can also add a companion verify/import script for the receiving party. + +Made changes. + +### 15:59 Prompt + +Consider this secret from the plan file. + +``` +| `COPILOT_GITHUB_TOKEN` | `build-test.yml`, `codegen-agentic-fix.lock.yml` | || Token for Copilot CLI in CI | +``` + +Is there anything special about that secret name? Is it some kind of well-known implicit secret name in the agentic machinery? Or can we safely treat it as "local" and therefore safely scope it to Java? + +### 16:01 Response + +I’ll trace where `COPILOT_GITHUB_TOKEN` is referenced in both repos and check whether it’s treated as a convention or just an ordinary secret wiring choice. + +Searched for text `COPILOT_GITHUB_TOKEN` (`copilot-sdk-00`), 153 results + +Searched for text `COPILOT_GITHUB_TOKEN` (`copilot-sdk-java-00`), 200 results + +I found strong evidence that the *environment variable* `COPILOT_GITHUB_TOKEN` is conventional for the CLI, while the *GitHub secret* name is workflow-configurable; I’ll grab the exact lines so the recommendation is concrete. + +Read [](file:///e%3A/workareas/copilot-sdk-00/docs/auth/authenticate.md#232-232), lines 232 to 312 + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/.github/workflows/codegen-agentic-fix.lock.yml#120-120), lines 120 to 145 + +Read [](file:///e%3A/workareas/copilot-sdk-java-00/.github/workflows/build-test.yml#20-20), lines 20 to 40 + +Short answer: it is not a GitHub Actions implicit secret name, but it is a strong convention in Copilot/agentic workflows. + +What is special: +- The SDK/CLI auth lookup explicitly prioritizes the environment variable COPILOT_GITHUB_TOKEN. See authenticate.md and authenticate.md. +- Agentic lock workflows explicitly validate and wire that name. See codegen-agentic-fix.lock.yml and codegen-agentic-fix.lock.yml. +- Non-agentic Java CI also passes that name through workflow secrets today. See build-test.yml. + +So can you scope the repository secret name to Java? +- Yes, safely, if you keep the runtime environment variable name as COPILOT_GITHUB_TOKEN. +- In practice: map secrets.JAVA_COPILOT_GITHUB_TOKEN into env.COPILOT_GITHUB_TOKEN (or equivalent secret pass-through in reusable workflows). + +Guidance for migration: +1. Treat the GitHub secret name as local/configurable. +2. Preserve COPILOT_GITHUB_TOKEN as the env var presented to CLI/agent steps. +3. For agentic workflows, update source workflow definitions and recompile lock files rather than hand-editing lock files. + +### 16:02 Prompt + +Is that secret name used in `copilot-sdk-00`? + +### 16:03 Response + +Yes. + +`COPILOT_GITHUB_TOKEN` is used extensively in copilot-sdk-00, including in multiple workflow lock files and docs. Examples: + +- handle-question.lock.yml +- handle-question.lock.yml +- release-changelog.lock.yml +- authenticate.md +- README.md + +So in this repo it is definitely an actively used name. + +### 16:03 Prompt + +Given its existing use, I will opt to not change its name or usage during the migration. Does this seem sound? + +### 16:04 Response + +Yes, that is a sound choice. + +Keeping `COPILOT_GITHUB_TOKEN` unchanged during migration is low risk because: +- it is already widely used in `copilot-sdk-00` +- it matches existing agentic workflow conventions +- it avoids churn across workflow source + lock files + docs at the same time as the Java move + +This is a good “stabilize first, rename later if needed” decision. + +### 16:25 Prompt + +I'm back now to `80-java-monorepo-add-01-remove-before-merge/ghcpsp-90-gpg-key-archive.sh` + +Please do write the script that the recipient must run to bring the archived key into their environment. Name it appropriately. + +### 16:27 Response + +I’m going to inspect the archive script you already have, then I’ll add a matching recipient-side import script in the same folder that verifies, decrypts, extracts, and imports the key material safely. + +Read [](file:///e%3A/workareas/copilot-sdk-00/80-java-monorepo-add-01-remove-before-merge/ghcpsp-90-gpg-key-archive.sh) + +I’m adding a companion recipient script now that validates signature/decryption status, checks the expected fingerprint, imports keys, and optionally imports ownertrust. + +Created [](file:///e%3A/workareas/copilot-sdk-00/80-java-monorepo-add-01-remove-before-merge/ghcpsp-90-gpg-key-import.sh) + +Implemented. I added the recipient-side script at ghcpsp-90-gpg-key-import.sh. + +What it does: +- Decrypts and verifies the signed archive with GPG +- Confirms signature validity via GPG status output +- Extracts the bundle safely +- Parses and reports the expected fingerprint from bundle metadata +- Imports public key, then secret key +- Optionally imports ownertrust when requested +- Verifies imported secret key fingerprint matches metadata + +Usage: +- ghcpsp-90-gpg-key-import.sh +- ghcpsp-90-gpg-key-import.sh +- ghcpsp-90-gpg-key-import.sh --import-ownertrust + +Natural next step: +1. Add execute permissions to both scripts if needed and run a dry test with a non-production keypair. + +Made changes. diff --git a/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md b/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md index 1b7ac04ae..81598c44d 100644 --- a/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md +++ b/80-java-monorepo-add-01-remove-before-merge/dd-2989727-move-java-to-monorepo-plan.md @@ -20,10 +20,10 @@ ### Phase 0: Pre-Flight (Before Writing Any Code) -- [ ] **Provision secrets** in `github/copilot-sdk` (see §2A) -- [ ] **Verify CODEOWNERS team** access -- [ ] **Check Maven Central Trusted Publisher** — can `github/copilot-sdk` publish to `com.github:copilot-sdk-java`? -- [ ] **Check GitHub Pages** — is it enabled? Can Java docs coexist? +- [✅] **Provision secrets** in `github/copilot-sdk` (see §2A) See https://github.com/github/copilot-sdk-partners/issues/90 +- [⌛] **Verify CODEOWNERS team** access. See https://github.com/github/copilot-sdk-partners/issues/89 +- [⌛] **Check Maven Central Trusted Publisher** — can `github/copilot-sdk` publish to `com.github:copilot-sdk-java`? See +- [⌛] **Check GitHub Pages** — is it enabled? Can Java docs coexist? See https://github.com/github/copilot-sdk-partners/issues/85 - [ ] **Confirm branch protection** — will new required status checks be accepted? - [ ] **Create tracking issue** in `github/copilot-sdk` for this migration - [ ] **Freeze Java SDK changes** — declare a short freeze window in `copilot-sdk-java` to avoid merge conflicts during migration @@ -195,14 +195,14 @@ The Java SDK publish workflow requires secrets that **do not currently exist** in the `copilot-sdk` repo: -| Secret | Used By | Notes | -| ------------------------ | ------------------------------------------------ | ------------------------------------------------------------------------------ | -| `RELEASE_TOKEN` | `publish-maven.yml` | PAT with `contents:write` for pushing tags/commits during maven-release-plugin | -| `GPG_SECRET_KEY` | `publish-maven.yml` | GPG private key for signing Maven artifacts | -| `GPG_PASSPHRASE` | `publish-maven.yml` | Passphrase for the GPG key | -| `MAVEN_CENTRAL_USERNAME` | `publish-maven.yml`, `publish-snapshot.yml` | Sonatype/Maven Central credentials | -| `MAVEN_CENTRAL_PASSWORD` | `publish-maven.yml`, `publish-snapshot.yml` | Sonatype/Maven Central credentials | -| `COPILOT_GITHUB_TOKEN` | `build-test.yml`, `codegen-agentic-fix.lock.yml` | Token for Copilot CLI in CI | +| Old Secret | Old Used By | New Secret | New Used By | Notes | +| ------------------------ | ------------------------------------------------ | -----------|-------------|---------------------------------------------------- | +| `RELEASE_TOKEN` | `publish-maven.yml` | `JAVA_RELEASE_TOKEN` | `java-publish-maven.yml` | PAT with `contents:write` for pushing tags/commits during maven-release-plugin | +| `GPG_SECRET_KEY` | `publish-maven.yml` | `JAVA_GPG_SECRET_KEY` | `java-publish-maven.yml` | GPG private key for signing Maven artifacts | +| `GPG_PASSPHRASE` | `publish-maven.yml` | `JAVA_GPG_PASSPHRASE` | `java-publish-maven.yml` | Passphrase for the GPG key | +| `MAVEN_CENTRAL_USERNAME` | `publish-maven.yml`, `publish-snapshot.yml` | `JAVA_MAVEN_CENTRAL_USERNAME` | `java-publish-maven.yml`, `java-publish-snapshot.yml` | Sonatype/Maven Central credentials | +| `MAVEN_CENTRAL_PASSWORD` | `publish-maven.yml`, `publish-snapshot.yml` | `JAVA_MAVEN_CENTRAL_PASSWORD` | `java-publish-maven.yml`, `java-publish-snapshot.yml` | Sonatype/Maven Central credentials | +| `COPILOT_GITHUB_TOKEN` | `build-test.yml`, `codegen-agentic-fix.lock.yml` | unchanged | | Token for Copilot CLI in CI | ### 2B. Existing Secrets in copilot-sdk That May Conflict @@ -213,10 +213,10 @@ The Java SDK publish workflow requires secrets that **do not currently exist** i ### 2C. Permissions / Access to Provision -- [ ] **Repository secrets**: File a ticket to add the 6 Java-specific secrets to `github/copilot-sdk`. -- [ ] **CODEOWNERS team**: Ensure `@github/copilot-sdk-java` team has access to `github/copilot-sdk` and is added to CODEOWNERS for `java/**`. -- [ ] **Maven Central Trusted Publisher**: Currently configured for `github/copilot-sdk-java`. Must be updated to also allow publishing from `github/copilot-sdk` (or create a new namespace mapping). **This is the highest-risk permission issue** — Maven Central's Trusted Publisher setup ties the repository name to the publish flow. -- [ ] **GitHub Pages**: If `deploy-site.yml` moves, check if GitHub Pages is enabled on the monorepo and whether Java docs can coexist with any existing docs deployment. +- [✅] **Repository secrets**: File a ticket to add the 6 Java-specific secrets to `github/copilot-sdk`. See https://github.com/github/copilot-sdk-partners/issues/90 +- [⌛] **CODEOWNERS team**: Ensure `@github/copilot-sdk-java` team has access to `github/copilot-sdk` and is added to CODEOWNERS for `java/**`. See https://github.com/github/copilot-sdk-partners/issues/89 . +- [⌛] **Maven Central Trusted Publisher**: Currently configured for `github/copilot-sdk-java`. Must be updated to also allow publishing from `github/copilot-sdk` (or create a new namespace mapping). **This is the highest-risk permission issue** — Maven Central's Trusted Publisher setup ties the repository name to the publish flow. See https://github.com/github/copilot-sdk-partners/issues/91 +- [⌛] **GitHub Pages**: If `deploy-site.yml` moves, check if GitHub Pages is enabled on the monorepo and whether Java docs can coexist with any existing docs deployment. See https://github.com/github/copilot-sdk-partners/issues/85 - [ ] **Branch protection**: Ensure `main` branch protection rules in copilot-sdk permit the Java CI workflows (merge queues, required status checks, etc.). - [ ] **Copilot coding agent**: Ensure the agent is enabled for `github/copilot-sdk` and the `copilot-setup-steps.yml` is updated to include Java tooling. diff --git a/80-java-monorepo-add-01-remove-before-merge/ghcpsp-90-gpg-key-archive.sh b/80-java-monorepo-add-01-remove-before-merge/ghcpsp-90-gpg-key-archive.sh new file mode 100644 index 000000000..238cf768b --- /dev/null +++ b/80-java-monorepo-add-01-remove-before-merge/ghcpsp-90-gpg-key-archive.sh @@ -0,0 +1,165 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Create an encrypted, signed handoff package for a GPG keypair. +# +# Usage: +# ./ghcpsp-90-gpg-key-archive.sh [output-dir] +# +# Example: +# ./ghcpsp-90-gpg-key-archive.sh 0123ABCD jane@example.com ./out + +usage() { + cat <<'EOF' +Usage: + ghcpsp-90-gpg-key-archive.sh [output-dir] + +Arguments: + key-id-or-fingerprint The secret key to export and hand off. + recipient-key-id-or-email Recipient key used to encrypt the bundle. + output-dir Optional output directory (default: current directory). + +Outputs: + .tar.gz Plain archive containing transfer files. + .tar.gz.asc Encrypted + signed archive for transfer. + +Notes: + - Share the passphrase over a separate channel. + - Keep the plain archive only as long as needed, then securely delete it. +EOF +} + +require_cmd() { + local cmd="$1" + if ! command -v "$cmd" >/dev/null 2>&1; then + echo "Error: required command not found: $cmd" >&2 + exit 1 + fi +} + +if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then + usage + exit 0 +fi + +if [[ $# -lt 2 || $# -gt 3 ]]; then + usage >&2 + exit 1 +fi + +KEY_ID="$1" +RECIPIENT="$2" +OUTPUT_DIR="${3:-.}" + +require_cmd gpg +require_cmd tar +require_cmd awk +require_cmd sed +require_cmd date + +mkdir -p "$OUTPUT_DIR" + +# Confirm key material is available locally. +if ! gpg --list-secret-keys "$KEY_ID" >/dev/null 2>&1; then + echo "Error: no secret key found for: $KEY_ID" >&2 + exit 1 +fi + +# Confirm recipient key exists locally for encryption. +if ! gpg --list-keys "$RECIPIENT" >/dev/null 2>&1; then + echo "Error: recipient public key not found locally: $RECIPIENT" >&2 + exit 1 +fi + +FPR="$(gpg --list-secret-keys --with-colons "$KEY_ID" | awk -F: '/^fpr:/ {print $10; exit}')" +if [[ -z "$FPR" ]]; then + echo "Error: unable to determine fingerprint for key: $KEY_ID" >&2 + exit 1 +fi + +SHORT_FPR="${FPR: -16}" +STAMP="$(date -u +%Y%m%dT%H%M%SZ)" +PREFIX="gpg-key-handoff-${SHORT_FPR}-${STAMP}" + +WORK_DIR="$(mktemp -d)" +cleanup() { + rm -rf "$WORK_DIR" +} +trap cleanup EXIT + +BUNDLE_DIR="$WORK_DIR/$PREFIX" +mkdir -p "$BUNDLE_DIR" + +SECRET_ASC="$BUNDLE_DIR/secret-key.asc" +PUBLIC_ASC="$BUNDLE_DIR/public-key.asc" +FINGERPRINT_TXT="$BUNDLE_DIR/fingerprint.txt" +OWNERTRUST_TXT="$BUNDLE_DIR/ownertrust.txt" +NOTES_TXT="$BUNDLE_DIR/handoff-notes.txt" + +# Export key material. +gpg --armor --export-secret-keys "$KEY_ID" > "$SECRET_ASC" +gpg --armor --export "$KEY_ID" > "$PUBLIC_ASC" +gpg --export-ownertrust > "$OWNERTRUST_TXT" + +# Capture key identity details. +{ + echo "Primary fingerprint: $FPR" + echo + echo "Secret key listing:" + gpg --list-secret-keys --keyid-format LONG "$KEY_ID" + echo + echo "Public key listing:" + gpg --list-keys --keyid-format LONG "$KEY_ID" +} > "$FINGERPRINT_TXT" + +# Try to locate an existing revocation certificate (GnuPG default layout). +REVOCATION_ASC="$BUNDLE_DIR/revocation.asc" +REVOCATION_SOURCE="${GNUPGHOME:-$HOME/.gnupg}/openpgp-revocs.d/${FPR}.rev" +if [[ -f "$REVOCATION_SOURCE" ]]; then + cp "$REVOCATION_SOURCE" "$REVOCATION_ASC" +else + { + echo "Revocation certificate was not found at:" + echo " $REVOCATION_SOURCE" + echo + echo "If needed, generate one manually on a trusted host and add it to this bundle." + } > "$BUNDLE_DIR/revocation-missing.txt" +fi + +cat > "$NOTES_TXT" < [output-dir] [--import-ownertrust] +# +# Example: +# ./ghcpsp-90-gpg-key-import.sh ./gpg-key-handoff-....tar.gz.asc ./out --import-ownertrust + +usage() { + cat <<'EOF' +Usage: + ghcpsp-90-gpg-key-import.sh [output-dir] [--import-ownertrust] + +Arguments: + sealed-archive.asc Armored encrypted+signed archive produced by the sender. + output-dir Optional output directory for extracted files (default: ./recipient-import). + --import-ownertrust Optional: import ownertrust.txt from the bundle. + +What this script does: +1. Decrypts and validates the signed archive with gpg. +2. Extracts bundle contents. +3. Verifies fingerprint metadata exists. +4. Imports public and secret keys. +5. Optionally imports ownertrust. + +Important: +- Verify the reported fingerprint out-of-band before using the key. +- Key passphrase is required when the secret key is used, not necessarily at import. +EOF +} + +require_cmd() { + local cmd="$1" + if ! command -v "$cmd" >/dev/null 2>&1; then + echo "Error: required command not found: $cmd" >&2 + exit 1 + fi +} + +if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then + usage + exit 0 +fi + +if [[ $# -lt 1 || $# -gt 3 ]]; then + usage >&2 + exit 1 +fi + +SEALED_ARCHIVE="$1" +OUTPUT_DIR="./recipient-import" +IMPORT_OWNERTRUST="false" + +for arg in "${@:2}"; do + case "$arg" in + --import-ownertrust) + IMPORT_OWNERTRUST="true" + ;; + *) + OUTPUT_DIR="$arg" + ;; + esac +done + +require_cmd gpg +require_cmd tar +require_cmd awk +require_cmd grep +require_cmd sed +require_cmd mkdir + +if [[ ! -f "$SEALED_ARCHIVE" ]]; then + echo "Error: archive not found: $SEALED_ARCHIVE" >&2 + exit 1 +fi + +umask 077 +mkdir -p "$OUTPUT_DIR" + +WORK_DIR="$(mktemp -d)" +cleanup() { + rm -rf "$WORK_DIR" +} +trap cleanup EXIT + +DECRYPTED_TAR="$WORK_DIR/handoff.tar.gz" +STATUS_LOG="$WORK_DIR/gpg-status.log" + +# Decrypt and capture machine-readable GPG status for integrity checks. +if ! gpg --batch --status-fd=1 --decrypt --output "$DECRYPTED_TAR" "$SEALED_ARCHIVE" > "$STATUS_LOG"; then + echo "Error: failed to decrypt/verify archive. Confirm recipient key and signer key are present." >&2 + exit 1 +fi + +if ! grep -q "^\[GNUPG:\] VALIDSIG " "$STATUS_LOG"; then + echo "Error: archive decrypted but signature validity could not be confirmed." >&2 + echo "Status log: $STATUS_LOG" >&2 + exit 1 +fi + +TOP_DIR="$(tar -tzf "$DECRYPTED_TAR" | awk -F/ 'NR==1 {print $1}')" +if [[ -z "$TOP_DIR" ]]; then + echo "Error: could not determine top-level bundle directory." >&2 + exit 1 +fi + +tar -xzf "$DECRYPTED_TAR" -C "$OUTPUT_DIR" +BUNDLE_DIR="$OUTPUT_DIR/$TOP_DIR" + +SECRET_ASC="$BUNDLE_DIR/secret-key.asc" +PUBLIC_ASC="$BUNDLE_DIR/public-key.asc" +FINGERPRINT_TXT="$BUNDLE_DIR/fingerprint.txt" +OWNERTRUST_TXT="$BUNDLE_DIR/ownertrust.txt" + +if [[ ! -f "$SECRET_ASC" || ! -f "$PUBLIC_ASC" || ! -f "$FINGERPRINT_TXT" ]]; then + echo "Error: bundle is missing expected files (secret/public/fingerprint)." >&2 + exit 1 +fi + +EXPECTED_FPR="$(awk -F': ' '/^Primary fingerprint:/ {print $2; exit}' "$FINGERPRINT_TXT" | sed 's/[[:space:]]*$//')" +if [[ -z "$EXPECTED_FPR" ]]; then + echo "Error: could not parse expected fingerprint from $FINGERPRINT_TXT" >&2 + exit 1 +fi + +echo "Expected fingerprint from bundle metadata: $EXPECTED_FPR" +echo "Verify this fingerprint out-of-band with the sender before trusting key usage." + +# Import public first, then secret material. +gpg --import "$PUBLIC_ASC" +gpg --import "$SECRET_ASC" + +if [[ "$IMPORT_OWNERTRUST" == "true" ]]; then + if [[ -f "$OWNERTRUST_TXT" ]]; then + gpg --import-ownertrust "$OWNERTRUST_TXT" + echo "Ownertrust imported from bundle." + else + echo "Warning: --import-ownertrust requested, but ownertrust.txt was not found." + fi +fi + +IMPORTED_FPR="$(gpg --with-colons --list-secret-keys "$EXPECTED_FPR" | awk -F: '/^fpr:/ {print $10; exit}')" +if [[ "$IMPORTED_FPR" != "$EXPECTED_FPR" ]]; then + echo "Error: imported key fingerprint does not match bundle metadata." >&2 + echo "Expected: $EXPECTED_FPR" >&2 + echo "Actual: ${IMPORTED_FPR:-}" >&2 + exit 1 +fi + +echo +echo "Import successful." +echo "Bundle extracted to: $BUNDLE_DIR" +echo "Imported fingerprint: $IMPORTED_FPR" +echo +echo "Recommended next steps:" +echo "1) Confirm fingerprint with sender through an independent channel." +echo "2) Store revocation certificate from the bundle in offline secure storage." +echo "3) Securely delete extracted secret-key material after operational handoff."