Skip to content

Commit 5166fd9

Browse files
authored
Merge branch 'main' into jb/otel_ctx
2 parents 9bbf480 + 0d2637d commit 5166fd9

5 files changed

Lines changed: 1085 additions & 478 deletions

File tree

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
---
2+
description: Analyze divergences from upstream async-profiler, propose grouped PRs, and open draft PRs.
3+
---
4+
5+
# Contribute Upstream Workflow
6+
7+
You are orchestrating the contribution of java-profiler divergences back to the upstream async-profiler project. These are all changes in our repo relative to upstream — not just uncommitted local modifications. Follow these steps precisely.
8+
9+
## Configuration
10+
11+
- **Fork repo**: `git@github.com:DataDog/async-profiler.git`
12+
- **Upstream repo**: `async-profiler/async-profiler` (for PR target)
13+
- **Upstream branch**: `master`
14+
- **Analysis script**: `utils/check_contribution_candidates.sh`
15+
- **Report dir**: `build/contribution-reports/`
16+
17+
## Step 1: Run Analysis
18+
19+
Execute the analysis script to generate reports:
20+
21+
```bash
22+
./utils/check_contribution_candidates.sh
23+
```
24+
25+
If it fails, diagnose and report the error to the user. Do not proceed.
26+
27+
## Step 2: Parse Results
28+
29+
Find the most recent JSON report in `build/contribution-reports/` (highest timestamp). Read it to get the list of files with contributable hunks.
30+
31+
Also read the corresponding markdown report to understand the actual diff hunks for each file.
32+
33+
If there are zero candidates, tell the user and stop.
34+
35+
## Step 3: Filter Out Existing PRs
36+
37+
Before proposing new PRs, check what's already open from the DataDog fork against upstream. Note: `--author DataDog` does not work because fork PRs are authored by the pushing user, not the org. Instead, query the API and filter by head repo:
38+
39+
```bash
40+
gh api 'repos/async-profiler/async-profiler/pulls?state=open&per_page=100' \
41+
--jq '.[] | select(.head.repo.full_name == "DataDog/async-profiler") | {number, title}'
42+
```
43+
44+
Then for each matching PR, fetch the files it touches:
45+
46+
```bash
47+
gh api 'repos/async-profiler/async-profiler/pulls/<number>/files' --jq '.[].filename'
48+
```
49+
50+
For each open PR, extract the list of files it touches. Then cross-reference with the candidate files from Step 2:
51+
52+
- If a candidate file is already fully covered by an open PR (i.e., the PR touches that file and addresses the same type of change), **exclude it** from proposals
53+
- If a candidate file is only partially covered (the open PR addresses some hunks but not others), keep the uncovered hunks as candidates
54+
- When presenting proposals in Step 4, mention any skipped files and the existing PR that covers them, so the user has full visibility
55+
56+
Analyze the remaining contributable hunks across candidate files and group them into logical PR proposals. Guidelines:
57+
58+
- **Related changes go together**: e.g., a bug fix touching `stackWalker.cpp` and `vmStructs.cpp` for the same issue = one PR
59+
- **Independent changes are separate**: unrelated fixes in different files = separate PRs
60+
- **Each PR should be self-contained**: it should make sense on its own, compile on its own, and have a clear rationale
61+
- **Keep PRs small**: prefer multiple small PRs over one large one
62+
63+
For each proposed PR, prepare:
64+
- A descriptive title (e.g., "Fix null pointer check in stackWalker", "Add bounds validation in VMStruct")
65+
- The list of files and hunks it covers
66+
- A brief rationale explaining why this change benefits upstream
67+
68+
## Step 5: Present Proposals to User
69+
70+
Show the user a numbered list of proposed PRs with:
71+
- Title
72+
- Files involved
73+
- Brief description of the change
74+
- Number of hunks
75+
76+
Use `AskUserQuestion` with `multiSelect: true` to let the user pick which PRs to create. Offer all proposals as options.
77+
78+
If the user selects none, stop.
79+
80+
## Step 6: Create Selected PRs
81+
82+
For each selected PR, perform the following:
83+
84+
### 6a. Clone the Fork (once)
85+
86+
Clone `git@github.com:DataDog/async-profiler.git` to a temp directory. Reuse this clone for all PRs.
87+
88+
```bash
89+
FORK_DIR=$(mktemp -d "${TMPDIR:-/tmp}/async-profiler-fork.XXXXXX")
90+
git clone git@github.com:DataDog/async-profiler.git "$FORK_DIR"
91+
cd "$FORK_DIR"
92+
git remote add upstream https://github.com/async-profiler/async-profiler.git
93+
git fetch upstream
94+
git checkout -b temp upstream/master
95+
git branch -D master 2>/dev/null || true
96+
git checkout -b master
97+
git branch -D temp
98+
```
99+
100+
### 6b. Create Feature Branch
101+
102+
For each PR, create a branch from upstream master:
103+
104+
```bash
105+
cd "$FORK_DIR"
106+
git checkout master
107+
BRANCH_NAME="contribute/<slug>-$(date +%Y%m%d)"
108+
git checkout -b "$BRANCH_NAME"
109+
```
110+
111+
Where `<slug>` is a short kebab-case description derived from the PR title.
112+
113+
### 6c. Port Changes
114+
115+
Apply only the relevant contributable hunks for this PR to the upstream files:
116+
117+
1. For each file in the PR, find the corresponding upstream file in `src/` of the fork
118+
2. Apply the contributable hunks using careful manual editing (use the Edit tool)
119+
3. **Critical**: Ensure NO Datadog-specific references leak through (DD_, ddprof, Datadog, datadog, DDPROF, context.h, counters.h, tagger, QueueItem)
120+
4. If a hunk cannot be cleanly applied because the upstream file diverged, skip it and note it for the user
121+
122+
### 6d. Verify Build
123+
124+
Attempt a basic build check:
125+
126+
```bash
127+
cd "$FORK_DIR"
128+
make
129+
```
130+
131+
If the build fails, analyze the error. If it's a simple fix (e.g., missing include), fix it. If it's complex, note it for the user and proceed anyway (the PR is draft).
132+
133+
### 6e. Commit and Push
134+
135+
```bash
136+
cd "$FORK_DIR"
137+
git add -A
138+
git commit -m "<concise description of the change>"
139+
git push origin "$BRANCH_NAME"
140+
```
141+
142+
### 6f. Open Draft PR
143+
144+
Use `gh` to create a draft PR against upstream. **Important**: Before creating the first PR, fetch the target project's PR template from the upstream repo (`gh api repos/async-profiler/async-profiler/contents/.github/PULL_REQUEST_TEMPLATE.md` and decode the base64 content). The PR body **must** follow that template exactly — use all its sections, checkboxes, and footer verbatim. Fill in each section with the relevant content for this change.
145+
146+
```bash
147+
gh pr create \
148+
--repo async-profiler/async-profiler \
149+
--base master \
150+
--head "DataDog:$BRANCH_NAME" \
151+
--draft \
152+
--title "<PR title>" \
153+
--body "<body following the upstream PR template>"
154+
```
155+
156+
## Step 7: Report
157+
158+
After all selected PRs are created, show the user:
159+
- A summary table of created PRs with their URLs
160+
- Any hunks that could not be applied
161+
- Any build issues encountered
162+
- The temp directory path in case manual follow-up is needed
163+
164+
## Error Handling
165+
166+
- If `gh` is not authenticated, tell the user to run `gh auth login` and stop
167+
- If the fork clone fails, check SSH key setup and report
168+
- If a branch already exists on the fork, append a counter suffix (e.g., `-2`)
169+
- Always clean up on fatal errors (remove temp directory)

0 commit comments

Comments
 (0)