Skip to content

Commit

Permalink
tools: add a backport queue cron action
Browse files Browse the repository at this point in the history
  • Loading branch information
aduh95 committed Nov 30, 2024
1 parent 03ec900 commit e58a1c2
Showing 1 changed file with 137 additions and 0 deletions.
137 changes: 137 additions & 0 deletions .github/workflows/backport-queue.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
name: Backport Commit Queue

on:
schedule:
- cron: '0 0 * * *' # Every day at midnight
workflow_dispatch:

concurrency: ${{ github.workflow }}

env:
NODE_VERSION: lts/*

permissions:
contents: write

jobs:
commitQueue:
runs-on: ubuntu-latest
if: github.repository == 'nodejs/node' || github.event_name == 'workflow_dispatch'
strategy:
matrix:
branch:
- { release-line: v23.x, base-branch: main }
- { release-line: v22.x, base-branch: v23.x }
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
# Needs the whole git history for ncu to work
# See https://github.com/nodejs/node-core-utils/pull/486
fetch-depth: 0
ref: ${{ matrix.branch.release-line }}-staging

# Install dependencies
- name: Install Node.js
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: ${{ env.NODE_VERSION }}
- name: Install @node-core/utils
run: npm install -g @node-core/utils branch-diff

- name: Setup git author
run: |
git config --local user.email "[email protected]"
git config --local user.name "Node.js GitHub Bot"
- name: Fetch base branch
run: |
git remote set-branches --add origin "$BASE_BRANCH"
git fetch origin "$BASE_BRANCH"
env:
BASE_BRANCH: ${{ matrix.branch.base-branch }}

- name: Fetch auto-backport branch if it exists
id: fetch
run: |
if git fetch origin "$BACKPORT_BRANCH"; then
STAGING_BRANCH_TIP="$(git rev-parse HEAD)"
WORKING_BRANCH_TIP="$(git rev-parse FETCH_HEAD)"
echo "WORKING_BRANCH_TIP=$WORKING_BRANCH_TIP" >> "$GITHUB_OUTPUT"
if [ "$WORKING_BRANCH_TIP" != "$STAGING_BRANCH_TIP" ]; then
git reset "$WORKING_BRANCH_TIP" --hard
git rebase "$STAGING_BRANCH_TIP" --empty=drop || git reset "$STAGING_BRANCH_TIP" --hard
else
else
echo "Branch doesn't exist yet"
fi
env:
BACKPORT_BRANCH: ${{ matrix.branch.release-branch }}-staging-auto-backport

- name: Run the queue
id: queue
run: |
backport() {
COMMIT="$1"
git cherry-pick "$COMMIT"
NODE="$(command -v node)" make lint-js
NODE="$(command -v node)" make test-doc "-j${PARALLELIZATION}"
make jstest "-j${PARALLELIZATION}"
}
[ "$MAX_COMMITS" != "0" ] &&\
branch-diff "${CURRENT_RELEASE_LINE}-staging" "$BASE_REF" \
--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}"\
--filter-release --format=sha --reverse | while read -r COMMIT ; do
if backport "$COMMIT" 2>&1 >output; then
MAX_COMMITS="$((MAX_COMMITS-1))"
else
{
EOF="$(node -p 'crypto.randomUUID()')"
echo "$COMMIT<<$EOF"
cat output
echo "$EOF"
} >> "$GITHUB_OUTPUT"
git cherry-pick --skip || true
fi
cat output
[ "$MAX_COMMITS" = "0" ] && break
done
rm output
env:
MAX_COMMITS: 9 # backport commits 9 at a time to limit the risk of timeout
CURRENT_RELEASE_LINE: ${{ matrix.branch.release-branch }}
BASE_REF: ${{ matrix.branch.base-branch }}
BACKPORT_BRANCH: ${{ matrix.branch.release-branch }}-staging-auto-backport

- name: Get local HEAD
id: head
run: echo "HEAD=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"

- name: Push to working branch
if: ${{ steps.fetch.outputs.WORKING_BRANCH_TIP != steps.head.outputs.HEAD }}
run: git push origin "HEAD:refs/heads/$BACKPORT_BRANCH" --force
env:
BACKPORT_BRANCH: ${{ matrix.branch.release-branch }}-staging-auto-backport

- name: Report errors
if: ${{
steps.fetch.outputs.WORKING_BRANCH_TIP != steps.head.outputs.HEAD &&
toJson(steps.queue.outputs) != '{}'
}}
run: |
node | gh issue create --repo "$GITHUB_REPOSITORY_OWNER/Releast"\
-t "Autobackport is failing on $CURRENT_RELEASE_LINE" --file-body -<<'EOF'
console.log('<ul>');
for (const {sha, output} of Object.entries(JSON.parse(process.env.FAILED_BACKPORTS))) {
console.log('<li><details>');
console.log(`<summary>${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/commit/${sha}</summary>`);
console.log(`\n${'```'}\n${output}\n${'```'}\n`);
console.log('</details></li>');
}
console.log('</ul>');
EOF
env:
GH_TOKEN: ${{ secrets.GH_USER_TOKEN }}
FAILED_BACKPORTS: ${{ toJson(steps.queue.outputs) }}
CURRENT_RELEASE_LINE: ${{ matrix.branch.release-branch }}

0 comments on commit e58a1c2

Please sign in to comment.