Skip to content

Create new Node.js patch #266

Create new Node.js patch

Create new Node.js patch #266

Workflow file for this run

name: Create new Node.js patch
on:
workflow_dispatch:
inputs:
nodeVersion:
description: 'Node.js version (e.g. 20.11.0)'
default: ''
type: string
required: true
patchFile:
description: 'Patch version to use (e.g. 20.11.0). Leave empty to use the matching major patch'
default: ''
type: string
required: false
jobs:
build:
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Checkout nodejs and create new patch
run: |
set +e # Don't exit on errors, we want to handle them ourselves
# find the patch file by checking the patch file matching major version input node version
MAJOR_VERSION=$(echo ${{ inputs.nodeVersion }} | cut -d'.' -f1)
echo "Node.js major version: $MAJOR_VERSION"
if [ -z "${{ inputs.patchFile }}" ]; then
PATCH_FILE=$(ls patches/node.v$MAJOR_VERSION.*.patch)
else
PATCH_FILE=patches/node.v${{ inputs.patchFile }}.cpp.patch
fi
# extract patch version from PATCH_FILE. E.g. node.v20.11.1.cpp.patch --> 20.11.1
PATCH_VERSION=$(echo $PATCH_FILE | grep -oP 'node.v\K[0-9]+\.[0-9]+\.[0-9]+')
echo "Patch file: $PATCH_FILE"
# check if patch file exists
if [ ! -f "$PATCH_FILE" ]; then
echo "No patch file found for Node.js version ${{ inputs.nodeVersion }}"
exit 1
fi
cd ..
echo "Cloning Node.js repository"
git clone -b v${{ inputs.nodeVersion }} --single-branch https://github.com/nodejs/node.git
cd node
# Try to apply the patch cleanly first
echo "Applying patch $PATCH_FILE"
git apply --check ../pkg-fetch/$PATCH_FILE
PATCH_CHECK_RESULT=$?
if [ $PATCH_CHECK_RESULT -eq 0 ]; then
echo "✅ Patch $PATCH_FILE applies cleanly"
git apply ../pkg-fetch/$PATCH_FILE
echo "PATCH_STATUS=clean" >> $GITHUB_ENV
else
echo "⚠️ Patch $PATCH_FILE does not apply cleanly, attempting conflict resolution"
# Apply patch with --reject to create .rej files
git apply --reject ../pkg-fetch/$PATCH_FILE || true
# Check if we have any .rej files
REJECT_COUNT=$(find . -name "*.rej" -type f | wc -l)
if [ $REJECT_COUNT -eq 0 ]; then
echo "ℹ️ No reject files found, patch applied partially"
echo "PATCH_STATUS=partial" >> $GITHUB_ENV
else
echo "🤖 Found $REJECT_COUNT reject files, using AI to resolve conflicts"
# Use our Python script to resolve conflicts
if [ -n "${{ secrets.OPENAI_KEY }}" ]; then
echo "Using OpenAI API for conflict resolution"
python3 ../pkg-fetch/.github/scripts/openai_resolver.py . "${{ secrets.OPENAI_KEY }}" > resolution_output.txt 2>&1
RESOLUTION_RESULT=$?
else
echo "No OpenAI API key found, creating manual resolution files only"
python3 ../pkg-fetch/.github/scripts/openai_resolver.py . "dummy" "create_manual_only" > resolution_output.txt 2>&1
RESOLUTION_RESULT=1
fi
# Extract results from Python script output
CONFLICTS_RESOLVED=$(grep "CONFLICTS_RESOLVED=" resolution_output.txt | cut -d'=' -f2)
TOTAL_CONFLICTS=$(grep "TOTAL_CONFLICTS=" resolution_output.txt | cut -d'=' -f2)
HAS_UNRESOLVED=$(grep "HAS_UNRESOLVED=" resolution_output.txt | cut -d'=' -f2)
FAILED_FILES_LINE=$(grep "FAILED_FILES=" resolution_output.txt | cut -d'=' -f2)
echo "PATCH_STATUS=conflicts" >> $GITHUB_ENV
echo "CONFLICTS_RESOLVED=${CONFLICTS_RESOLVED:-0}" >> $GITHUB_ENV
echo "TOTAL_CONFLICTS=${TOTAL_CONFLICTS:-0}" >> $GITHUB_ENV
# Show resolution summary
cat resolution_output.txt
# Check if we have unresolved conflicts - if so, exit without creating PR
if [ "${HAS_UNRESOLVED:-false}" = "True" ]; then
echo "❌ There are unresolved conflicts. Exiting without creating PR."
echo "Please resolve the conflicts manually and re-run the workflow."
exit 1
fi
fi
fi
# Only proceed with patch creation if we got here (no unresolved conflicts)
echo "✅ All conflicts resolved or patch applied successfully. Creating new patch file."
# Store resolution output for PR body if it exists
if [ -f "../node/resolution_output.txt" ]; then
echo "RESOLUTION_OUTPUT<<EOF" >> $GITHUB_ENV
cat ../node/resolution_output.txt >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
# delete resolution output file
rm -f ../node/resolution_output.txt
else
echo "RESOLUTION_OUTPUT=" >> $GITHUB_ENV
fi
# delete old patch file and create new one
rm -rf ../pkg-fetch/$PATCH_FILE
git add -A
git diff --staged --src-prefix=node/ --dst-prefix=node/ > ../pkg-fetch/patches/node.v${{ inputs.nodeVersion }}.cpp.patch
# Update patches.json
echo "Updating patches.json"
cd ../pkg-fetch/patches
sed -i "s/\"v$PATCH_VERSION\": \[\"node.v$PATCH_VERSION.cpp.patch\"\]/\"v${{ inputs.nodeVersion }}\": \[\"node.v${{ inputs.nodeVersion }}.cpp.patch\"\]/" patches.json
# Set default values for environment variables if not already set
echo "PATCH_STATUS=${PATCH_STATUS:-clean}" >> $GITHUB_ENV
echo "HAS_UNRESOLVED=${HAS_UNRESOLVED:-false}" >> $GITHUB_ENV
echo "CREATE_PR=true" >> $GITHUB_ENV
cd ..
- name: Create Pull Request
if: env.CREATE_PR == 'true'
uses: peter-evans/create-pull-request@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "feat: add v${{ inputs.nodeVersion }} patch"
title: "feat: add v${{ inputs.nodeVersion }} patch"
body: |
## Node.js Patch Update to v${{ inputs.nodeVersion }}
This PR updates the Node.js patch to version ${{ inputs.nodeVersion }}.
The workflow automatically attempts to resolve patch conflicts using AI when the OpenAI API key is available.
${{ env.RESOLUTION_OUTPUT && '### AI Resolution Details' || '' }}
${{ env.RESOLUTION_OUTPUT }}
branch: "nodejs-v${{ inputs.nodeVersion }}"
base: "main"
delete-branch: true
labels: "enhancement,nodejs"
draft: false