Skip to content

Commit 5a32803

Browse files
committed
Add rebase CI
1 parent 01217ac commit 5a32803

File tree

3 files changed

+123
-0
lines changed

3 files changed

+123
-0
lines changed

.github/scripts/push.sh

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#!/bin/bash
2+
3+
set -eux
4+
5+
upstream_repo=$1
6+
base_repo=$2
7+
output_branches=$3
8+
9+
git remote add upstream "${upstream_repo}" || true
10+
git fetch upstream master
11+
12+
# push each branch
13+
while IFS= read -r branch || [[ -n $branch ]]; do
14+
git checkout "${branch}"
15+
git push -f "${base_repo}" "${branch}"
16+
done < <(echo "${output_branches}")
17+

.github/scripts/rebase.sh

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
#!/bin/bash
2+
3+
set -eux
4+
5+
upstream_repo=$1
6+
7+
git remote add upstream "${upstream_repo}" || true
8+
git fetch upstream master
9+
10+
output_branches=()
11+
12+
# rebase each branch
13+
mkdir -p rebase
14+
while IFS= read -r branch || [[ -n $branch ]]; do
15+
(
16+
git checkout "${branch}"
17+
common_ancestor=$(git merge-base "${branch}" "master")
18+
[ -e rebase/"${branch}" ] && exit 1
19+
mkdir -p rebase/"${branch}"
20+
cd rebase/"${branch}"
21+
echo "${common_ancestor}" > BASE_COMMIT
22+
git format-patch "${common_ancestor}".."${branch}"
23+
if compgen -G "*.patch" > /dev/null; then
24+
git reset --hard "upstream/master"
25+
git am --3way *.patch
26+
fi
27+
)
28+
output_branches+=( "${branch}" )
29+
done < <(gh pr list --label rebase --state open --json headRefName --template '{{range .}}{{tablerow .headRefName}}{{end}}')
30+
31+
# sync master with upstream
32+
git checkout master
33+
git reset --hard upstream/master
34+
output_branches+=( "master" )
35+
36+
(
37+
IFS=$'\n'
38+
echo "${output_branches[*]}"
39+
)
40+

.github/workflows/rebase.yaml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: Rebase against upstream
2+
3+
on:
4+
schedule:
5+
- cron: '0 0 * * *'
6+
7+
permissions:
8+
contents: write
9+
issues: write
10+
11+
jobs:
12+
rebase:
13+
name: Rebase now!
14+
runs-on: ubuntu-latest
15+
env:
16+
UPSTREAM_REPO: https://github.com/haskell/cabal.git
17+
steps:
18+
- name: Checkout code
19+
uses: actions/checkout@v4
20+
with:
21+
ref: master
22+
fetch-depth: 0
23+
persist-credentials: false
24+
25+
- run: |
26+
set -eux
27+
28+
# required to apply patches
29+
git config user.email "[email protected]"
30+
git config user.name "GitHub CI"
31+
32+
# this does not push
33+
branches=$(bash .github/scripts/rebase.sh ${{ env.UPSTREAM_REPO }})
34+
35+
# now push
36+
bash .github/scripts/push.sh ${{ env.UPSTREAM_REPO }} https://${{ secrets.REBASE_PAT }}@github.com/${{ github.repository }}.git "${branches}"
37+
shell: bash
38+
39+
# create an issue with a link to the workflow run on failure
40+
- if: failure()
41+
run: |
42+
set -eux
43+
gh repo set-default stable-haskell/cabal
44+
for issue in $(gh issue list --label rebase-failure --json url -q '.[] | .url') ; do
45+
gh issue close "${issue}"
46+
done
47+
gh issue create --title "Rebase failed on $(date -u +"%Y-%m-%d")" --label rebase-failure --body "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
48+
env:
49+
GH_TOKEN: ${{ github.token }}
50+
51+
# we always want the original repo and the patches that were applied
52+
# for debugging and backup reasons
53+
- if: always()
54+
run: |
55+
git checkout -f master
56+
git archive master > backup.tar
57+
tar -rf backup.tar .git rebase
58+
- if: always()
59+
name: Upload backup
60+
uses: actions/upload-artifact@v4
61+
with:
62+
if-no-files-found: error
63+
retention-days: 7
64+
name: backup
65+
path: |
66+
./backup.tar

0 commit comments

Comments
 (0)