-
-
Notifications
You must be signed in to change notification settings - Fork 0
91 lines (86 loc) · 3.83 KB
/
Copy pathalign-develop.yml
File metadata and controls
91 lines (86 loc) · 3.83 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
name: Align develop
# main is production; develop, the work in progress. Everything that lands on
# main — a published release, an urgent fix, the daily sync's data — is carried
# over to develop right away, never with a merge commit:
#
# - develop behind main: fast-forward;
# - develop carries unpublished commits: they are replayed on top of main
# (rebase), then develop is pushed again. History stays linear and the next
# release is a plain fast-forward of main.
#
# The push goes through the SYNC_DEPLOY_KEY deploy key, allowed to bypass
# develop's protection (force push after a rebase).
on:
push:
branches: [main]
workflow_call:
secrets:
SYNC_DEPLOY_KEY:
required: false
workflow_dispatch:
permissions:
contents: write
concurrency:
group: align-develop
cancel-in-progress: false
jobs:
align:
name: Carry main over to develop
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
# Credentials kept: develop is pushed at the end.
with: # zizmor: ignore[artipacked]
fetch-depth: 0
# When empty, checkout falls back to GITHUB_TOKEN.
ssh-key: ${{ secrets.SYNC_DEPLOY_KEY }}
- name: Fast-forward or replay develop on main
run: |
if ! git ls-remote --exit-code --heads origin develop > /dev/null; then
echo "No develop branch yet: nothing to align."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git fetch -q origin main develop
before=$(git rev-parse origin/develop)
if git merge-base --is-ancestor origin/main origin/develop; then
echo "develop already contains main."
exit 0
fi
git checkout -q -B develop origin/develop
if git merge-base --is-ancestor origin/develop origin/main; then
git merge -q --ff-only origin/main
git push -q origin HEAD:develop
echo "develop fast-forwarded to $(git rev-parse --short HEAD)."
exit 0
fi
# The nightly sync commits generated data on main, with main's scripts.
# When develop changed the same files (a schema change, typically),
# replaying develop conflicts every night and blocks publishing. That
# data is regenerated at the next sync, so develop's version wins;
# a conflict on anything else still needs a human.
if ! git rebase -q origin/main; then
while git rev-parse -q --verify REBASE_HEAD > /dev/null; do
conflicts=$(git diff --name-only --diff-filter=U)
others=$(printf '%s\n' "$conflicts" | grep -vE '^(src/data/|public/visuels/|scripts/[^/]+\.json$)' || true)
if [ -z "$conflicts" ] || [ -n "$others" ]; then
git rebase --abort
echo "::error::develop's commits conflict with main: rebase develop onto main by hand."
exit 1
fi
for f in $conflicts; do
if git cat-file -e "REBASE_HEAD:$f" 2> /dev/null; then
git checkout REBASE_HEAD -- "$f"
git add -- "$f"
else
git rm -q -- "$f"
fi
done
echo "::warning::Generated data conflict, develop's version kept: $(printf '%s\n' "$conflicts" | tr '\n' ' ')"
GIT_EDITOR=true git rebase --continue > /dev/null || true
done
fi
# The lease refuses to overwrite a push that reached develop during the rebase.
git push -q --force-with-lease="develop:$before" origin HEAD:develop
echo "develop replayed on main: $(git rev-list --count origin/main..HEAD) commit(s) to publish."