Skip to content

Commit 38125cf

Browse files
committed
tools: add a backport queue cron action
1 parent 03ec900 commit 38125cf

File tree

1 file changed

+166
-0
lines changed

1 file changed

+166
-0
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
name: Backport Commit Queue
2+
3+
on:
4+
schedule:
5+
- cron: '0 0 * * *' # Every day at midnight
6+
workflow_dispatch:
7+
8+
concurrency: ${{ github.workflow }}
9+
10+
env:
11+
NODE_VERSION: lts/*
12+
PYTHON_VERSION: '3.12'
13+
FLAKY_TESTS: keep_retrying
14+
CC: sccache clang
15+
CXX: sccache clang++
16+
SCCACHE_GHA_ENABLED: 'true'
17+
18+
permissions:
19+
contents: write
20+
21+
jobs:
22+
commitQueue:
23+
runs-on: ubuntu-latest
24+
if: github.repository == 'nodejs/node' || github.event_name == 'workflow_dispatch'
25+
strategy:
26+
fail-fast: false
27+
matrix:
28+
branch:
29+
- { release-line: v23.x, base-branch: main }
30+
- { release-line: v22.x, base-branch: v23.x }
31+
steps:
32+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
33+
with:
34+
# Needs the whole git history for ncu to work
35+
# See https://github.com/nodejs/node-core-utils/pull/486
36+
fetch-depth: 0
37+
ref: ${{ matrix.branch.release-line }}-staging
38+
39+
- name: Set up Python ${{ env.PYTHON_VERSION }}
40+
uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
41+
with:
42+
python-version: ${{ env.PYTHON_VERSION }}
43+
- name: Set up sccache
44+
uses: mozilla-actions/sccache-action@9e326ebed976843c9932b3aa0e021c6f50310eb4 # v0.0.6
45+
with:
46+
version: v0.8.1
47+
48+
# Install dependencies
49+
- name: Install Node.js
50+
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
51+
with:
52+
node-version: ${{ env.NODE_VERSION }}
53+
- name: Install branch-diff
54+
run: npm install -g branch-diff
55+
56+
- name: Setup git author
57+
run: |
58+
git config --local user.email "[email protected]"
59+
git config --local user.name "Node.js GitHub Bot"
60+
61+
- name: Set up ghauth config (Ubuntu)
62+
run: |
63+
mkdir -p "${XDG_CONFIG_HOME:-~/.config}/changelog-maker"
64+
echo '{}' | jq '{user: env.USERNAME, token: env.TOKEN}' > "${XDG_CONFIG_HOME:-~/.config}/changelog-maker/config.json"
65+
env:
66+
USERNAME: ${{ secrets.JENKINS_USER }}
67+
TOKEN: ${{ github.token }}
68+
69+
- name: Fetch base branch
70+
run: |
71+
git remote set-branches --add origin "$BASE_BRANCH"
72+
git fetch origin "$BASE_BRANCH"
73+
env:
74+
BASE_BRANCH: ${{ matrix.branch.base-branch }}
75+
76+
- name: Fetch auto-backport branch if it exists
77+
id: fetch
78+
run: |
79+
if git fetch origin "$BACKPORT_BRANCH"; then
80+
STAGING_BRANCH_TIP="$(git rev-parse HEAD)"
81+
WORKING_BRANCH_TIP="$(git rev-parse FETCH_HEAD)"
82+
echo "WORKING_BRANCH_TIP=$WORKING_BRANCH_TIP" >> "$GITHUB_OUTPUT"
83+
if [ "$WORKING_BRANCH_TIP" != "$STAGING_BRANCH_TIP" ]; then
84+
git reset "$WORKING_BRANCH_TIP" --hard
85+
git rebase "$STAGING_BRANCH_TIP" --empty=drop || git reset "$STAGING_BRANCH_TIP" --hard
86+
fi
87+
else
88+
echo "Branch doesn't exist yet"
89+
fi
90+
env:
91+
BACKPORT_BRANCH: ${{ matrix.branch.release-line }}-staging-auto-backport
92+
93+
- name: Run the queue
94+
id: queue
95+
run: |
96+
set -xe
97+
98+
backport() (
99+
set -xe
100+
COMMIT="$1"
101+
git cherry-pick "$COMMIT"
102+
NODE="$(command -v node)" make lint-js
103+
make build-ci -j4 V=1 CONFIG_FLAGS="--error-on-warn"
104+
make run-ci -j4 V=1 TEST_CI_ARGS="-p actions --node-args='--test-reporter=spec' --node-args='--test-reporter-destination=stdout' --measure-flakiness 9"
105+
NODE="$(command -v node)" make test-doc "-j${PARALLELIZATION}"
106+
)
107+
108+
[ "$MAX_COMMITS" != "0" ] &&\
109+
branch-diff "${CURRENT_RELEASE_LINE}-staging" "$BASE_REF" \
110+
--exclude-label="semver-major,dont-land-on-${CURRENT_RELEASE_LINE},backport-requested-${CURRENT_RELEASE_LINE},backport-blocked-${CURRENT_RELEASE_LINE},backport-open-${CURRENT_RELEASE_LINE},backported-to-${CURRENT_RELEASE_LINE}"\
111+
--filter-release --format=sha --reverse | while read -r COMMIT ; do
112+
if backport "$COMMIT" 2>&1 >output; then
113+
MAX_COMMITS="$((MAX_COMMITS-1))"
114+
else
115+
{
116+
EOF="$(node -p 'crypto.randomUUID()')"
117+
echo "$COMMIT<<$EOF"
118+
echo "…"
119+
tail output # Cutting the output to avoid exceeding memory.
120+
echo "$EOF"
121+
} >> "$GITHUB_OUTPUT"
122+
git cherry-pick --skip || true
123+
fi
124+
cat output
125+
[ "$MAX_COMMITS" = "0" ] && break
126+
done
127+
rm output
128+
env:
129+
MAX_COMMITS: 9 # backport commits 9 at a time to limit the risk of timeout
130+
CURRENT_RELEASE_LINE: ${{ matrix.branch.release-line }}
131+
BASE_REF: origin/${{ matrix.branch.base-branch }}
132+
BACKPORT_BRANCH: ${{ matrix.branch.release-line }}-staging-auto-backport
133+
134+
- name: Get local HEAD
135+
id: head
136+
run: echo "HEAD=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
137+
138+
- name: Push to working branch
139+
if: ${{ steps.fetch.outputs.WORKING_BRANCH_TIP != steps.head.outputs.HEAD }}
140+
run: git push origin "HEAD:refs/heads/$BACKPORT_BRANCH" --force
141+
env:
142+
BACKPORT_BRANCH: ${{ matrix.branch.release-line }}-staging-auto-backport
143+
144+
- name: Report errors
145+
if: ${{
146+
steps.fetch.outputs.WORKING_BRANCH_TIP != steps.head.outputs.HEAD &&
147+
toJson(steps.queue.outputs) != '{}'
148+
}}
149+
run: |
150+
node | gh issue create --repo "$GITHUB_REPOSITORY_OWNER/Releast"\
151+
-t "Autobackport is failing on $CURRENT_RELEASE_LINE" --file-body -<<'EOF'
152+
console.log(`Workflow URL: <${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}>`);
153+
console.log('\n<ul>');
154+
for (const {sha, output} of Object.entries(JSON.parse(process.env.FAILED_BACKPORTS))) {
155+
console.log('<li><details>');
156+
console.log(`<summary>${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/commit/${sha}</summary>`);
157+
console.log(`\n${'```'}\n${output}\n${'```'}\n`);
158+
console.log('</details></li>');
159+
}
160+
console.log('</ul>');
161+
EOF
162+
env:
163+
GH_TOKEN: ${{ secrets.GH_USER_TOKEN }}
164+
FAILED_BACKPORTS: ${{ toJson(steps.queue.outputs) }}
165+
CURRENT_RELEASE_LINE: ${{ matrix.branch.release-line }}
166+

0 commit comments

Comments
 (0)