170 lines
7.8 KiB
YAML
170 lines
7.8 KiB
YAML
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
|
||
|