From ca262518275adcb7ae2439b89ee0d91eec9d84a5 Mon Sep 17 00:00:00 2001 From: d3xter666 Date: Thu, 9 Apr 2026 14:27:57 +0300 Subject: [PATCH 1/3] feat: Add engine compatibility check for PRs --- .github/workflows/engine-compat.yml | 71 +++++++++++++++++++++++++++++ .github/workflows/github-ci.yml | 8 +++- 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/engine-compat.yml diff --git a/.github/workflows/engine-compat.yml b/.github/workflows/engine-compat.yml new file mode 100644 index 00000000000..6a85da1559a --- /dev/null +++ b/.github/workflows/engine-compat.yml @@ -0,0 +1,71 @@ +name: Node Packages Engine Compatibility Check + +on: + workflow_call: + inputs: + node-versions: + description: 'Comma-separated Node.js versions, e.g. 22.20.0, 22, 24.0.0, 24' + required: true + type: string + +permissions: + contents: read + pull-requests: write + +jobs: + engine-compat: + name: Engine compatibility + runs-on: ubuntu-24.04 + steps: + + - uses: actions/checkout@v6 + + - name: Check engines and report + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NODE_VERSIONS: ${{ inputs.node-versions }} + run: | + export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" + + PR="${{ github.event.pull_request.number }}" + MARKER="" + FAILED=false + TABLE="| Node | Result | Incompatible Packages |\n|---|---|---|" + + IFS=',' read -ra VERSIONS <<< "$NODE_VERSIONS" + for V in "${VERSIONS[@]}"; do + V=$(echo "$V" | xargs) # trim whitespace + nvm install "$V" --no-progress > /dev/null 2>&1 + nvm use "$V" > /dev/null 2>&1 + VER=$(node --version) + + PKGS=$(npm ci --dry-run 2>&1 \ + | awk -F"'" '/EBADENGINE.*package:/{pkg=$2} /EBADENGINE.*node:/{if(pkg){print pkg" (node "$2")"; pkg=""}}' \ + | sort -u | tr '\n' ',' | sed 's/,$//' | sed 's/,/, /g') + + if [ -n "$PKGS" ]; then + FAILED=true + SAFE=$(echo "$PKGS" | sed 's/|/\\|/g') + TABLE="$TABLE\n| $VER | ❌ Fail | $SAFE |" + else + TABLE="$TABLE\n| $VER | ✅ Pass | — |" + fi + done + + if [ "$FAILED" = true ]; then ICON="❌"; else ICON="✅"; fi + printf '%s\n## %s Engine Compatibility\n\n%b\n' "$MARKER" "$ICON" "$TABLE" > /tmp/comment.md + + OLD=$(gh api "repos/${{ github.repository }}/issues/${PR}/comments" \ + --jq "[.[] | select(.body | contains(\"$MARKER\"))][0].id" 2>/dev/null || true) + if [ -n "$OLD" ] && [ "$OLD" != "null" ]; then + gh api --method PATCH "repos/${{ github.repository }}/issues/comments/$OLD" -F body=@/tmp/comment.md + else + gh pr comment "$PR" --body-file /tmp/comment.md + fi + + if [ "$FAILED" = true ]; then + gh label create blocked --color D93F0B 2>/dev/null || true + gh pr edit "$PR" --add-label blocked + else + gh pr edit "$PR" --remove-label blocked 2>/dev/null || true + fi diff --git a/.github/workflows/github-ci.yml b/.github/workflows/github-ci.yml index 18cf8c99bd5..2e8966b9eec 100644 --- a/.github/workflows/github-ci.yml +++ b/.github/workflows/github-ci.yml @@ -24,8 +24,14 @@ jobs: with: node-version: 22.20.0 + - name: Engine compatibility check + if: github.event_name == 'pull_request' + uses: ./.github/workflows/engine-compat.yml + with: + node-versions: '22.20.0, 22, 24.0.0, 24' + - name: Install dependencies - run: npm ci --engine-strict # --engine-strict is used to fail-fast if deps require node versions unsupported by the repo + run: npm ci - name: Check package.json "engines" consistency run: | From 5882a81ff2f2df4ec915147dfb182aee34331213 Mon Sep 17 00:00:00 2001 From: d3xter666 Date: Thu, 9 Apr 2026 14:35:10 +0300 Subject: [PATCH 2/3] fix: GH workflow file --- .github/workflows/github-ci.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/github-ci.yml b/.github/workflows/github-ci.yml index 2e8966b9eec..7269e7bbf3a 100644 --- a/.github/workflows/github-ci.yml +++ b/.github/workflows/github-ci.yml @@ -10,8 +10,15 @@ on: permissions: contents: read + pull-requests: write jobs: + engine-compat: + if: github.event_name == 'pull_request' + uses: ./.github/workflows/engine-compat.yml + with: + node-versions: '22.20.0, 22, 24.0.0, 24' + test: name: General checks and tests runs-on: ubuntu-24.04 @@ -24,12 +31,6 @@ jobs: with: node-version: 22.20.0 - - name: Engine compatibility check - if: github.event_name == 'pull_request' - uses: ./.github/workflows/engine-compat.yml - with: - node-versions: '22.20.0, 22, 24.0.0, 24' - - name: Install dependencies run: npm ci From 1b99e027ae82bd32e1fef371d21d46d85240fec6 Mon Sep 17 00:00:00 2001 From: d3xter666 Date: Thu, 9 Apr 2026 14:50:51 +0300 Subject: [PATCH 3/3] docs: Give context and rationale for each command --- .github/workflows/engine-compat.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/engine-compat.yml b/.github/workflows/engine-compat.yml index 6a85da1559a..b9ff942d38a 100644 --- a/.github/workflows/engine-compat.yml +++ b/.github/workflows/engine-compat.yml @@ -25,6 +25,7 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} NODE_VERSIONS: ${{ inputs.node-versions }} run: | + # Load nvm (pre-installed on GitHub runners) export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" PR="${{ github.event.pull_request.number }}" @@ -32,6 +33,7 @@ jobs: FAILED=false TABLE="| Node | Result | Incompatible Packages |\n|---|---|---|" + # Loop through each requested Node version IFS=',' read -ra VERSIONS <<< "$NODE_VERSIONS" for V in "${VERSIONS[@]}"; do V=$(echo "$V" | xargs) # trim whitespace @@ -39,12 +41,16 @@ jobs: nvm use "$V" > /dev/null 2>&1 VER=$(node --version) + # Dry-run install to collect EBADENGINE warnings without actually installing. + # awk extracts "package@version (node range)" from multi-line warning blocks. + # sort -u deduplicates (npm may warn about the same package multiple times). PKGS=$(npm ci --dry-run 2>&1 \ | awk -F"'" '/EBADENGINE.*package:/{pkg=$2} /EBADENGINE.*node:/{if(pkg){print pkg" (node "$2")"; pkg=""}}' \ | sort -u | tr '\n' ',' | sed 's/,$//' | sed 's/,/, /g') if [ -n "$PKGS" ]; then FAILED=true + # Escape pipe characters so they don't break the markdown table SAFE=$(echo "$PKGS" | sed 's/|/\\|/g') TABLE="$TABLE\n| $VER | ❌ Fail | $SAFE |" else @@ -52,9 +58,11 @@ jobs: fi done + # Build the comment body if [ "$FAILED" = true ]; then ICON="❌"; else ICON="✅"; fi printf '%s\n## %s Engine Compatibility\n\n%b\n' "$MARKER" "$ICON" "$TABLE" > /tmp/comment.md + # Update existing comment (matched by HTML marker) or create a new one OLD=$(gh api "repos/${{ github.repository }}/issues/${PR}/comments" \ --jq "[.[] | select(.body | contains(\"$MARKER\"))][0].id" 2>/dev/null || true) if [ -n "$OLD" ] && [ "$OLD" != "null" ]; then @@ -63,6 +71,7 @@ jobs: gh pr comment "$PR" --body-file /tmp/comment.md fi + # Add "blocked" label on failure, remove it on success if [ "$FAILED" = true ]; then gh label create blocked --color D93F0B 2>/dev/null || true gh pr edit "$PR" --add-label blocked