forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 4
115 lines (97 loc) · 4.51 KB
/
Copy pathsync-linux-next.yml
File metadata and controls
115 lines (97 loc) · 4.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
name: Sync linux-next -> master (replay fork commits)
on:
schedule:
- cron: "0 2 * * *" # every day at 02:00 UTC
workflow_dispatch: {}
permissions:
contents: write
concurrency:
group: sync-linux-next
cancel-in-progress: false
jobs:
sync:
runs-on: ubuntu-latest
steps:
- name: Checkout fork
uses: actions/checkout@v7
with:
ref: master
fetch-depth: 0
- name: Configure upstream
run: |
git remote remove upstream || true
git remote add upstream https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
git fetch --no-tags upstream --prune
- name: Replay fork commits on top of upstream/master
run: |
set -euo pipefail
git checkout master
# REQUIRED for cherry-pick commit creation (runner has no identity by default)
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
UP_BASE="upstream/master"
git show -s --oneline "$UP_BASE" >/dev/null
# ------------------------------------------------------------------
# Find the upstream snapshot that master's fork commits sit on.
#
# Anchor: the empty marker commit "ogc: linux-unstable: first
# commit" is always the first fork commit ever made. Its parent is
# therefore the upstream snapshot the fork was built on.
# ------------------------------------------------------------------
MARKER="$(git log --format="%H" --grep="^ogc: linux-unstable: first commit$" master)"
if [ -z "$MARKER" ]; then
echo "::error::Could not find the 'ogc: linux-unstable: first commit' marker; refusing to touch master."
exit 1
fi
BASE="$(git rev-parse "${MARKER}^")"
echo "Upstream base: $(git show -s --oneline "$BASE")"
# If master already sits on the current upstream tip there is
# nothing to sync: replaying would only churn the fork commits'
# hashes for identical content.
if [ "$(git rev-parse "$BASE")" = "$(git rev-parse "$UP_BASE")" ]; then
echo "master is already based on the current linux-next tip; nothing to do."
exit 0
fi
# Everything on master on top of the upstream base = the fork
# commits (including non-"ogc:"-prefixed ones, e.g. squash-merged
# PRs). --no-merges matches the cherry-pick loop below and makes
# merge commits replay as their constituent commits.
MY_COMMITS="$(git rev-list --reverse --no-merges "${BASE}..master")"
if [ -z "${MY_COMMITS// }" ]; then
echo "::error::No commits found on top of the upstream base; refusing to reset master (that would delete the fork)."
exit 1
fi
# Safety net: a mis-detected base would replay days of upstream
# history. The fork accumulates its own commits over time (and PR
# squash-merges add to that), so allow a generous 150; anything
# beyond that is far more likely a mis-detected base than real fork
# commits, so bail out and ask for a manual look instead of
# corrupting master.
N="$(echo "$MY_COMMITS" | wc -l)"
if [ "$N" -gt 150 ]; then
echo "::error::Refusing to replay ${N} commits (expected only fork commits). Check master's history (all fork commits must carry the 'ogc:' subject prefix)."
exit 1
fi
echo "Replaying ${N} commit(s):"
for c in $MY_COMMITS; do
echo " $c $(git show -s --format=%s "$c")"
done
echo
# Reset master to the new upstream tip, then replay the fork commits.
git reset --hard "$UP_BASE"
for c in $MY_COMMITS; do
echo "Cherry-picking: $c $(git show -s --format=%s "$c")"
if ! git cherry-pick -x --allow-empty "$c"; then
git status || true
# If we're left mid-cherry-pick, abort to avoid a broken
# working state. Nothing was pushed, so master on origin is
# still intact.
if [ -f .git/CHERRY_PICK_HEAD ]; then
git cherry-pick --abort || true
fi
echo "::error::Cherry-pick failed for $c; nothing was pushed."
exit 1
fi
done
echo "Done. Pushing updated master."
git push --force-with-lease origin master