Skip to content

Commit d86ab16

Browse files
authored
Add upstream sync workflows for clean git history (#17)
1 parent 08da75c commit d86ab16

3 files changed

Lines changed: 572 additions & 0 deletions

File tree

.github/workflows/fork-build.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: "Fork Build"
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
pull_request:
7+
branches: [ master ]
8+
schedule:
9+
- cron: '20 9 * * 2'
10+
11+
jobs:
12+
build:
13+
name: Build
14+
runs-on: ubuntu-latest
15+
permissions:
16+
actions: read
17+
contents: read
18+
security-events: write
19+
20+
strategy:
21+
fail-fast: false
22+
matrix:
23+
language: [ 'java' ]
24+
25+
steps:
26+
- name: Checkout repository
27+
uses: actions/checkout@v4
28+
- name: Set up Maven
29+
uses: stCarolas/setup-maven@d6af6abeda15e98926a57b5aa970a96bb37f97d1 # v5
30+
with:
31+
maven-version: 3.9.9
32+
- name: Setup Java JDK
33+
uses: actions/setup-java@v4
34+
with:
35+
distribution: 'temurin'
36+
java-version: '21'
37+
38+
- name: Initialize CodeQL
39+
uses: github/codeql-action/init@v3
40+
with:
41+
languages: ${{ matrix.language }}
42+
43+
- name: Build with Maven
44+
run: mvn -B package -Pbuild-individual-bundles --file pom.xml
45+
46+
- name: Perform CodeQL Analysis
47+
uses: github/codeql-action/analyze@v3
48+
env:
49+
CODEQL_ACTION_EXTRA_OPTIONS: '{"database":{"interpret-results":["--max-paths", 1]}}'
Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
name: Rebase Upstream
2+
3+
on:
4+
issue_comment:
5+
types: [created]
6+
pull_request:
7+
types: [opened]
8+
9+
jobs:
10+
add-rebase-button:
11+
name: Add Rebase Instructions
12+
if: github.event_name == 'pull_request'
13+
runs-on: ubuntu-latest
14+
permissions:
15+
pull-requests: write
16+
steps:
17+
- name: Add comment with rebase instructions
18+
uses: actions/github-script@v8
19+
with:
20+
script: |
21+
const repoUrl = context.payload.repository.html_url;
22+
const workflowUrl = `${repoUrl}/actions/workflows/rebase-upstream.yml`;
23+
24+
const comment = `## 🔄 Rebase onto Upstream
25+
26+
To rebase this PR onto the latest \`eclipse-jdt/eclipse.jdt.core:master\`, comment:
27+
28+
\`\`\`
29+
/rebase-upstream
30+
\`\`\`
31+
32+
This will rebase your PR branch onto the upstream repository's master branch.
33+
34+
📋 [View Workflow](${workflowUrl})`;
35+
36+
github.rest.issues.createComment({
37+
owner: context.repo.owner,
38+
repo: context.repo.repo,
39+
issue_number: context.issue.number,
40+
body: comment
41+
});
42+
43+
rebase-upstream:
44+
name: Rebase onto Upstream Master
45+
if: |
46+
github.event_name == 'issue_comment' &&
47+
github.event.issue.pull_request &&
48+
contains(github.event.comment.body, '/rebase-upstream')
49+
runs-on: ubuntu-latest
50+
permissions:
51+
contents: write
52+
pull-requests: write
53+
steps:
54+
- name: Check user permission
55+
id: check
56+
uses: actions/github-script@v8
57+
with:
58+
result-encoding: string
59+
script: |
60+
const authorAssociation = context.payload.comment.author_association;
61+
const allowedRoles = ['OWNER', 'MEMBER', 'COLLABORATOR'];
62+
63+
if (allowedRoles.includes(authorAssociation)) {
64+
return 'true';
65+
} else {
66+
return 'false';
67+
}
68+
69+
- name: Add unauthorized reaction
70+
if: steps.check.outputs.result != 'true'
71+
uses: actions/github-script@v8
72+
with:
73+
script: |
74+
github.rest.reactions.createForIssueComment({
75+
owner: context.repo.owner,
76+
repo: context.repo.repo,
77+
comment_id: context.payload.comment.id,
78+
content: '-1'
79+
});
80+
81+
github.rest.issues.createComment({
82+
owner: context.repo.owner,
83+
repo: context.repo.repo,
84+
issue_number: context.issue.number,
85+
body: '❌ Only repository collaborators can trigger the rebase.'
86+
});
87+
88+
- name: Exit if unauthorized
89+
if: steps.check.outputs.result != 'true'
90+
run: exit 1
91+
92+
- name: Add rocket reaction
93+
uses: actions/github-script@v8
94+
with:
95+
script: |
96+
github.rest.reactions.createForIssueComment({
97+
owner: context.repo.owner,
98+
repo: context.repo.repo,
99+
comment_id: context.payload.comment.id,
100+
content: 'rocket'
101+
});
102+
103+
- name: Get PR branch info
104+
id: pr
105+
uses: actions/github-script@v8
106+
with:
107+
script: |
108+
const { data: pr } = await github.rest.pulls.get({
109+
owner: context.repo.owner,
110+
repo: context.repo.repo,
111+
pull_number: context.issue.number
112+
});
113+
114+
core.setOutput('head_ref', pr.head.ref);
115+
core.setOutput('head_repo', pr.head.repo.full_name);
116+
core.setOutput('head_clone_url', pr.head.repo.clone_url);
117+
118+
// Get the number of commits in the PR
119+
// Note: per_page is set to 250, which covers most PRs.
120+
// For PRs with >250 commits, manual rebasing would be required.
121+
const { data: commits } = await github.rest.pulls.listCommits({
122+
owner: context.repo.owner,
123+
repo: context.repo.repo,
124+
pull_number: context.issue.number,
125+
per_page: 250
126+
});
127+
core.setOutput('commit_count', commits.length);
128+
129+
- name: Checkout PR branch
130+
uses: actions/checkout@v4
131+
with:
132+
repository: ${{ steps.pr.outputs.head_repo }}
133+
ref: ${{ steps.pr.outputs.head_ref }}
134+
token: ${{ secrets.GITHUB_TOKEN }}
135+
fetch-depth: 0
136+
137+
- name: Configure Git
138+
run: |
139+
git config user.name "github-actions[bot]"
140+
git config user.email "github-actions[bot]@users.noreply.github.com"
141+
142+
- name: Add upstream remote and rebase
143+
id: rebase
144+
run: |
145+
git remote add upstream https://github.com/eclipse-jdt/eclipse.jdt.core.git
146+
git fetch upstream master
147+
148+
# Get the number of commits in the PR
149+
PR_COMMIT_COUNT=${{ steps.pr.outputs.commit_count }}
150+
echo "PR has $PR_COMMIT_COUNT commits"
151+
152+
# Validate commit count
153+
if [ "$PR_COMMIT_COUNT" -eq 0 ]; then
154+
echo "Error: PR has 0 commits"
155+
echo "success=false" >> $GITHUB_OUTPUT
156+
exit 0
157+
fi
158+
159+
# Rebase only the PR commits onto upstream/master
160+
if git rebase --onto upstream/master HEAD~${PR_COMMIT_COUNT}; then
161+
echo "success=true" >> $GITHUB_OUTPUT
162+
else
163+
echo "success=false" >> $GITHUB_OUTPUT
164+
git rebase --abort
165+
fi
166+
167+
- name: Push rebased branch
168+
if: steps.rebase.outputs.success == 'true'
169+
run: |
170+
git push --force-with-lease origin ${{ steps.pr.outputs.head_ref }}
171+
172+
- name: Add success comment
173+
if: steps.rebase.outputs.success == 'true'
174+
uses: actions/github-script@v8
175+
with:
176+
script: |
177+
github.rest.reactions.createForIssueComment({
178+
owner: context.repo.owner,
179+
repo: context.repo.repo,
180+
comment_id: context.payload.comment.id,
181+
content: '+1'
182+
});
183+
184+
github.rest.issues.createComment({
185+
owner: context.repo.owner,
186+
repo: context.repo.repo,
187+
issue_number: context.issue.number,
188+
body: '✅ Successfully rebased onto `eclipse-jdt/eclipse.jdt.core:master`'
189+
});
190+
191+
- name: Add failure comment
192+
if: steps.rebase.outputs.success == 'false'
193+
uses: actions/github-script@v8
194+
with:
195+
script: |
196+
github.rest.reactions.createForIssueComment({
197+
owner: context.repo.owner,
198+
repo: context.repo.repo,
199+
comment_id: context.payload.comment.id,
200+
content: '-1'
201+
});
202+
203+
const comment = `❌ Rebase failed due to conflicts.
204+
205+
To resolve manually:
206+
207+
\`\`\`bash
208+
# Add upstream remote
209+
git remote add upstream https://github.com/eclipse-jdt/eclipse.jdt.core.git
210+
211+
# Fetch upstream
212+
git fetch upstream master
213+
214+
# Count the number of commits in your PR (check GitHub PR page)
215+
# For example, if your PR has 3 commits:
216+
PR_COMMIT_COUNT=3
217+
218+
# Rebase only your PR commits onto upstream/master
219+
git rebase --onto upstream/master HEAD~\${PR_COMMIT_COUNT}
220+
221+
# Resolve conflicts, then:
222+
git add .
223+
git rebase --continue
224+
225+
# Force push when done
226+
git push --force-with-lease
227+
\`\`\``;
228+
229+
github.rest.issues.createComment({
230+
owner: context.repo.owner,
231+
repo: context.repo.repo,
232+
issue_number: context.issue.number,
233+
body: comment
234+
});
235+
236+
- name: Fail workflow if rebase failed
237+
if: steps.rebase.outputs.success == 'false'
238+
run: exit 1

0 commit comments

Comments
 (0)