Skip to content

Commit fe24e30

Browse files
committed
Add utility scripts for upstream merge process and update .gitignore
- Introduced `merge-upstream-start.sh` to prepare workspace for upstream merges. - Added `merge-upstream-diff.sh` for detailed diff analysis of upstream changes. - Created `merge-upstream-finish.sh` to finalize merges and push branches. - Added `format-and-test.sh` for running formatting and testing in one command. - Updated `.gitignore` to exclude the generated `.merge-env` file.
1 parent 64ccbe3 commit fe24e30

File tree

6 files changed

+324
-87
lines changed

6 files changed

+324
-87
lines changed

.github/prompts/agentic-merge-upstream.prompt.md

Lines changed: 51 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -13,100 +13,74 @@ You are an expert Java developer tasked with porting changes from the official C
1313

1414
Before making any changes, **read and understand the existing Java SDK implementation** to ensure new code integrates seamlessly.
1515

16-
## Workflow Overview
17-
18-
1. Create a new branch from main
19-
2. Update Copilot CLI to latest version
20-
3. Update README with minimum CLI version requirement
21-
4. Clone upstream repository
22-
5. Analyze diff since last merge
23-
6. Apply changes to Java SDK (commit as you go)
24-
7. Test and fix issues
25-
8. Update documentation
26-
9. Push branch to remote for Pull Request review
27-
28-
---
16+
## Utility Scripts
2917

30-
## Step 1: Create a New Branch
18+
The `.github/scripts/` directory contains helper scripts that automate the repeatable parts of this workflow. **Use these scripts instead of running the commands manually.**
3119

32-
Before starting any work, create a new branch from `main` to isolate the merge changes:
20+
| Script | Purpose |
21+
|---|---|
22+
| `.github/scripts/merge-upstream-start.sh` | Creates branch, updates CLI, clones upstream, reads `.lastmerge`, prints commit summary |
23+
| `.github/scripts/merge-upstream-diff.sh` | Detailed diff analysis grouped by area (`.NET src`, tests, snapshots, docs, etc.) |
24+
| `.github/scripts/merge-upstream-finish.sh` | Runs format + test + build, updates `.lastmerge`, commits, pushes branch |
25+
| `.github/scripts/format-and-test.sh` | Standalone `spotless:apply` + `mvn clean verify` (useful during porting too) |
3326

34-
```bash
35-
# Ensure we're on main and up to date
36-
git checkout main
37-
git pull origin main
38-
39-
# Create a new branch with a descriptive name including the date
40-
BRANCH_NAME="merge-upstream-$(date +%Y%m%d)"
41-
git checkout -b "$BRANCH_NAME"
42-
echo "Created branch: $BRANCH_NAME"
43-
```
27+
All scripts write/read a `.merge-env` file (git-ignored) to share state (branch name, upstream dir, last-merge commit).
4428

45-
**Important:** All changes will be committed to this branch as you work. This allows for proper review via Pull Request.
29+
## Workflow Overview
4630

47-
## Step 2: Update Copilot CLI
31+
1. Run `./.github/scripts/merge-upstream-start.sh` (creates branch, clones upstream, shows summary)
32+
2. Run `./.github/scripts/merge-upstream-diff.sh` (analyze changes)
33+
3. Update README with minimum CLI version requirement
34+
4. Port changes to Java SDK (commit as you go)
35+
5. Run `./.github/scripts/format-and-test.sh` frequently while porting
36+
6. Update documentation
37+
7. Run `./.github/scripts/merge-upstream-finish.sh` (final test + push)
38+
8. Create Pull Request
4839

49-
Update the locally installed GitHub Copilot CLI to the latest version:
40+
---
5041

51-
```bash
52-
copilot update
53-
```
42+
## Steps 1-2: Initialize and Analyze
5443

55-
After updating, capture the new version and update the README.md to reflect the minimum version requirement:
44+
Run the start script to create a branch, update the CLI, clone the upstream repo, and see a summary of new commits:
5645

5746
```bash
58-
# Get the current version
59-
CLI_VERSION=$(copilot --version | head -n 1 | awk '{print $NF}')
60-
echo "Updated Copilot CLI to version: $CLI_VERSION"
47+
./.github/scripts/merge-upstream-start.sh
6148
```
6249

63-
Update the Requirements section in `README.md` to specify the minimum CLI version requirement. Locate the line mentioning "GitHub Copilot CLI installed" and update it to include the version information.
50+
This writes a `.merge-env` file used by the other scripts. It outputs:
51+
- The branch name created
52+
- The Copilot CLI version
53+
- The upstream dir path
54+
- A short log of upstream commits since `.lastmerge`
6455

65-
Commit this change before proceeding:
56+
Then run the diff script for a detailed breakdown by area:
6657

6758
```bash
68-
git add README.md
69-
git commit -m "Update Copilot CLI minimum version requirement to $CLI_VERSION"
59+
./.github/scripts/merge-upstream-diff.sh # stat only
60+
./.github/scripts/merge-upstream-diff.sh --full # full diffs
7061
```
7162

72-
## Step 3: Clone Upstream Repository
73-
74-
Clone the official Copilot SDK repository into a temporary folder:
63+
The diff script groups changes into: .NET source, .NET tests, test snapshots, documentation, protocol/config, Go/Node.js/Python SDKs, and other files.
7564

76-
```bash
77-
UPSTREAM_REPO="https://github.com/github/copilot-sdk.git"
78-
TEMP_DIR=$(mktemp -d)
79-
git clone --depth=100 "$UPSTREAM_REPO" "$TEMP_DIR/copilot-sdk"
80-
```
65+
## Step 3: Update README with CLI Version
8166

82-
## Step 4: Read Last Merge Commit
67+
After the start script runs, check the CLI version it printed (also saved in `.merge-env` as `CLI_VERSION`). Update the Requirements section in `README.md` and `src/site/markdown/index.md` to specify the minimum CLI version requirement.
8368

84-
Read the commit hash from `.lastmerge` file in the Java SDK root:
69+
Commit this change before proceeding:
8570

8671
```bash
87-
LAST_MERGE_COMMIT=$(cat .lastmerge)
88-
echo "Last merged commit: $LAST_MERGE_COMMIT"
72+
git add README.md src/site/markdown/index.md
73+
git commit -m "Update Copilot CLI minimum version requirement"
8974
```
9075

91-
## Step 5: Analyze Changes
92-
93-
Generate a diff between the last merged commit and HEAD of main:
76+
## Step 4: Identify Changes to Port
9477

95-
```bash
96-
cd "$TEMP_DIR/copilot-sdk"
97-
git fetch origin main
98-
git log --oneline "$LAST_MERGE_COMMIT"..origin/main
99-
git diff "$LAST_MERGE_COMMIT"..origin/main --stat
100-
```
101-
102-
Focus on analyzing:
78+
Using the output from `merge-upstream-diff.sh`, focus on:
10379
- `dotnet/src/` - Primary reference implementation
10480
- `dotnet/test/` - Test cases to port
10581
- `docs/` - Documentation updates
10682
- `sdk-protocol-version.json` - Protocol version changes
10783

108-
## Step 6: Identify Changes to Port
109-
11084
For each change in the upstream diff, determine:
11185

11286
1. **New Features**: New methods, classes, or capabilities added to the SDK
@@ -243,14 +217,19 @@ Commit tests separately or together with their corresponding implementation chan
243217

244218
## Step 8: Format and Run Tests
245219

246-
After applying changes, format the code and run the test suite:
220+
After applying changes, use the convenience script:
247221

248222
```bash
249-
mvn spotless:apply
250-
mvn clean test
223+
./.github/scripts/format-and-test.sh # format + full verify
224+
./.github/scripts/format-and-test.sh --debug # with debug logging
251225
```
252226

253-
**Important:** Always run `mvn spotless:apply` before testing to ensure code formatting is consistent with project standards.
227+
Or for quicker iteration during porting:
228+
229+
```bash
230+
./.github/scripts/format-and-test.sh --format-only # just spotless
231+
./.github/scripts/format-and-test.sh --test-only # skip formatting
232+
```
254233

255234
### If Tests Fail
256235

@@ -337,28 +316,13 @@ Ensure consistency across all documentation files:
337316
- Code examples should use the same patterns and be tested
338317
- Links to Javadoc should use correct paths (`apidocs/...`)
339318

340-
## Step 11: Update Last Merge Reference
341-
342-
Update the `.lastmerge` file with the new HEAD commit and commit this change:
343-
344-
```bash
345-
cd "$TEMP_DIR/copilot-sdk"
346-
NEW_COMMIT=$(git rev-parse origin/main)
347-
cd - # Return to Java SDK directory
348-
echo "$NEW_COMMIT" > .lastmerge
349-
350-
# Commit the .lastmerge update
351-
git add .lastmerge
352-
git commit -m "Update .lastmerge to $NEW_COMMIT"
353-
```
354-
355-
## Step 12: Push Branch and Create Pull Request
319+
## Steps 11-12: Finish, Push, and Create Pull Request
356320

357-
Push the branch to remote and create a Pull Request automatically:
321+
Run the finish script which updates `.lastmerge`, runs a final build, and pushes the branch:
358322

359323
```bash
360-
# Push the branch to remote
361-
git push -u origin "$BRANCH_NAME"
324+
./.github/scripts/merge-upstream-finish.sh # full format + test + push
325+
./.github/scripts/merge-upstream-finish.sh --skip-tests # if tests already passed
362326
```
363327

364328
**After pushing, create the Pull Request using the GitHub MCP tool (`mcp_github_create_pull_request`).**

.github/scripts/format-and-test.sh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/env bash
2+
# ──────────────────────────────────────────────────────────────
3+
# format-and-test.sh
4+
#
5+
# Convenience script that runs the full quality pipeline:
6+
# 1. spotless:apply (auto-format code)
7+
# 2. mvn clean verify (compile + test + checkstyle + spotbugs)
8+
#
9+
# Usage: ./.github/scripts/format-and-test.sh
10+
# ./.github/scripts/format-and-test.sh --format-only
11+
# ./.github/scripts/format-and-test.sh --test-only
12+
# ./.github/scripts/format-and-test.sh --debug (uses -Pdebug)
13+
# ──────────────────────────────────────────────────────────────
14+
set -euo pipefail
15+
16+
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
17+
cd "$ROOT_DIR"
18+
19+
FORMAT=true
20+
TEST=true
21+
MVN_PROFILE=""
22+
23+
for arg in "$@"; do
24+
case "$arg" in
25+
--format-only) TEST=false ;;
26+
--test-only) FORMAT=false ;;
27+
--debug) MVN_PROFILE="-Pdebug" ;;
28+
*) echo "Unknown option: $arg"; exit 1 ;;
29+
esac
30+
done
31+
32+
if $FORMAT; then
33+
echo "▸ Running Spotless (format)…"
34+
mvn spotless:apply
35+
fi
36+
37+
if $TEST; then
38+
echo "▸ Running mvn clean verify $MVN_PROFILE"
39+
mvn clean verify $MVN_PROFILE
40+
echo ""
41+
echo "✅ All checks passed."
42+
else
43+
echo "✅ Formatting complete."
44+
fi
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#!/usr/bin/env bash
2+
# ──────────────────────────────────────────────────────────────
3+
# merge-upstream-diff.sh
4+
#
5+
# Generates a detailed diff analysis of upstream changes since
6+
# the last merge, grouped by area of interest:
7+
# • .NET source (primary reference)
8+
# • .NET tests
9+
# • Test snapshots
10+
# • Documentation
11+
# • Protocol / config files
12+
#
13+
# Usage: ./.github/scripts/merge-upstream-diff.sh [--full]
14+
# --full Show actual diffs, not just stats
15+
#
16+
# Requires: .merge-env written by merge-upstream-start.sh
17+
# ──────────────────────────────────────────────────────────────
18+
set -euo pipefail
19+
20+
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
21+
ENV_FILE="$ROOT_DIR/.merge-env"
22+
23+
if [[ ! -f "$ENV_FILE" ]]; then
24+
echo "$ENV_FILE not found. Run ./.github/scripts/merge-upstream-start.sh first."
25+
exit 1
26+
fi
27+
28+
# shellcheck source=/dev/null
29+
source "$ENV_FILE"
30+
31+
SHOW_FULL=false
32+
if [[ "${1:-}" == "--full" ]]; then
33+
SHOW_FULL=true
34+
fi
35+
36+
cd "$UPSTREAM_DIR"
37+
git fetch origin main 2>/dev/null
38+
39+
RANGE="$LAST_MERGE_COMMIT..origin/main"
40+
41+
echo "════════════════════════════════════════════════════════════"
42+
echo " Upstream diff analysis: $RANGE"
43+
echo "════════════════════════════════════════════════════════════"
44+
45+
# ── Commit log ────────────────────────────────────────────────
46+
echo ""
47+
echo "── Commit log ──"
48+
git log --oneline --no-decorate "$RANGE"
49+
echo ""
50+
51+
# Helper to print a section
52+
section() {
53+
local title="$1"; shift
54+
local paths=("$@")
55+
56+
echo "── $title ──"
57+
local stat
58+
stat=$(git diff "$RANGE" --stat -- "${paths[@]}" 2>/dev/null || true)
59+
if [[ -z "$stat" ]]; then
60+
echo " (no changes)"
61+
else
62+
echo "$stat"
63+
if $SHOW_FULL; then
64+
echo ""
65+
git diff "$RANGE" -- "${paths[@]}" 2>/dev/null || true
66+
fi
67+
fi
68+
echo ""
69+
}
70+
71+
# ── Sections ──────────────────────────────────────────────────
72+
section ".NET source (dotnet/src)" "dotnet/src/"
73+
section ".NET tests (dotnet/test)" "dotnet/test/"
74+
section "Test snapshots" "test/snapshots/"
75+
section "Documentation (docs/)" "docs/"
76+
section "Protocol & config" "sdk-protocol-version.json" "package.json" "justfile"
77+
section "Go SDK" "go/"
78+
section "Node.js SDK" "nodejs/"
79+
section "Python SDK" "python/"
80+
section "Other files" "README.md" "CONTRIBUTING.md" "SECURITY.md" "SUPPORT.md"
81+
82+
echo "════════════════════════════════════════════════════════════"
83+
echo " To see full diffs: $0 --full"
84+
echo " To see a specific path:"
85+
echo " cd $UPSTREAM_DIR && git diff $RANGE -- <path>"
86+
echo "════════════════════════════════════════════════════════════"
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/usr/bin/env bash
2+
# ──────────────────────────────────────────────────────────────
3+
# merge-upstream-finish.sh
4+
#
5+
# Finalises an upstream merge:
6+
# 1. Runs format + test + build (via format-and-test.sh)
7+
# 2. Updates .lastmerge to upstream HEAD
8+
# 3. Commits the .lastmerge update
9+
# 4. Pushes the branch to origin
10+
#
11+
# Usage: ./.github/scripts/merge-upstream-finish.sh
12+
# ./.github/scripts/merge-upstream-finish.sh --skip-tests
13+
#
14+
# Requires: .merge-env written by merge-upstream-start.sh
15+
# ──────────────────────────────────────────────────────────────
16+
set -euo pipefail
17+
18+
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
19+
ENV_FILE="$ROOT_DIR/.merge-env"
20+
21+
if [[ ! -f "$ENV_FILE" ]]; then
22+
echo "$ENV_FILE not found. Run ./.github/scripts/merge-upstream-start.sh first."
23+
exit 1
24+
fi
25+
26+
# shellcheck source=/dev/null
27+
source "$ENV_FILE"
28+
29+
SKIP_TESTS=false
30+
if [[ "${1:-}" == "--skip-tests" ]]; then
31+
SKIP_TESTS=true
32+
fi
33+
34+
cd "$ROOT_DIR"
35+
36+
# ── 1. Format, test, build ───────────────────────────────────
37+
if $SKIP_TESTS; then
38+
echo "▸ Formatting only (tests skipped)…"
39+
mvn spotless:apply
40+
mvn clean package -DskipTests
41+
else
42+
echo "▸ Running format + test + build…"
43+
"$ROOT_DIR/.github/scripts/format-and-test.sh"
44+
fi
45+
46+
# ── 2. Update .lastmerge ─────────────────────────────────────
47+
echo "▸ Updating .lastmerge…"
48+
NEW_COMMIT=$(cd "$UPSTREAM_DIR" && git rev-parse origin/main)
49+
echo "$NEW_COMMIT" > "$ROOT_DIR/.lastmerge"
50+
51+
git add .lastmerge
52+
git commit -m "Update .lastmerge to $NEW_COMMIT"
53+
54+
# ── 3. Push branch ───────────────────────────────────────────
55+
echo "▸ Pushing branch $BRANCH_NAME to origin…"
56+
git push -u origin "$BRANCH_NAME"
57+
58+
echo ""
59+
echo "✅ Branch pushed. Next step:"
60+
echo " Create a Pull Request (base: main, head: $BRANCH_NAME)"
61+
echo ""
62+
echo " Suggested title: Merge upstream SDK changes ($(date +%Y-%m-%d))"
63+
echo " Don't forget to add the 'upstream-sync' label."

0 commit comments

Comments
 (0)