Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/test-matrix.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
# Node.js versions tested on Linux in every PR's test matrix.
# The minimum version should stay aligned with package.json `engines.node`.
# Used by: unit-tests.yml, integration-tests.yml, e2e-tests.yml
node_versions: ['20.12.2', '22', '24']

# Additional operating systems added to the full test matrix on release-please
# PRs and scheduled (cron) E2E runs. Only the primary Node version (see below)
# is tested on these platforms to keep the job count manageable.
# Do NOT include ubuntu here — Linux is always covered by `node_versions` above.
# Used by: unit-tests.yml, integration-tests.yml, e2e-tests.yml
extra_oses_on_release: ['macOS-latest', 'windows-2025']

# The "primary" Node.js version. Two uses:
# 1. Paired with each of `extra_oses_on_release` in the full matrix.
# 2. The pinned version for all single-version workflows.
# Must be present in `node_versions` above.
# Used by: unit-tests.yml, integration-tests.yml, e2e-tests.yml,
# release-please.yml, pre-release.yml, pre-release-sha.yml,
# benchmark.yml, lint.yml, typecheck.yml, format.yml, verify-docs.yml
primary_node_version: '24'
6 changes: 5 additions & 1 deletion .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ jobs:
- name: Git checkout
uses: actions/checkout@v6

- name: Read primary Node version
id: node
run: echo "version=$(yq eval '.primary_node_version' .github/test-matrix.yml)" >> "$GITHUB_OUTPUT"

- name: Use Node.js
uses: actions/setup-node@v6
with:
node-version: '24'
node-version: ${{ steps.node.outputs.version }}
cache: npm

- name: Install dependencies
Expand Down
146 changes: 84 additions & 62 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,80 @@
name: E2E Tests

on:
push:
branches: [main]
pull_request:
branches:
- '**'
- '!release-please--**'
branches: ['**']
schedule:
# check daily to notice potential package manager issues
- cron: '0 1 * * *' # At 01:00 daily

jobs:
e2e-windows:
name: E2E Windows tests
setup:
name: Setup
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.matrix.outputs.value }}
has-code-changes: ${{ steps.filter.outputs.code || 'true' }}
steps:
- name: Git checkout
uses: actions/checkout@v6

- name: Detect code changes
uses: dorny/paths-filter@v3
if: github.event_name == 'pull_request'
id: filter
with:
filters: |
code:
- '**'
- '!**/*.md'
- '!LICENSE'
- '!docs/**'
- '!.vale.ini'
- '!.github/ISSUE_TEMPLATE/**'
- '!.github/PULL_REQUEST_TEMPLATE.md'

- name: Compute matrix
id: matrix
env:
HEAD_REF: ${{ github.head_ref }}
EVENT_NAME: ${{ github.event_name }}
run: |
node_versions=$(yq eval '.node_versions | join(" ")' .github/test-matrix.yml)
extra_oses=$(yq eval '.extra_oses_on_release | join(" ")' .github/test-matrix.yml)
primary=$(yq eval '.primary_node_version' .github/test-matrix.yml)

OS_NODE=()
for node in $node_versions; do
OS_NODE+=("ubuntu-latest:$node")
done
if [[ "$EVENT_NAME" == "schedule" ]] || [[ "$HEAD_REF" == release-please--* ]]; then
for os in $extra_oses; do
OS_NODE+=("$os:$primary")
done
fi

entries=()
for combo in "${OS_NODE[@]}"; do
os="${combo%:*}"
node="${combo##*:}"
entries+=("{\"os\":\"$os\",\"node-version\":\"$node\"}")
done
joined=$(IFS=,; echo "${entries[*]}")
echo "value={\"include\":[$joined]}" >> "$GITHUB_OUTPUT"

e2e:
name: E2E
needs: setup
if: needs.setup.outputs.has-code-changes == 'true'
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
matrix:
os: [windows-2025]
# Pinning 20.x version as a temporary workaround due to this https://github.com/nodejs/node/issues/52884
node-version: ['20.12.2', '22', '24']
fail-fast: false
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
steps:
# This improves Windows network performance. We need this since we open many ports in our tests.
- name: Increase Windows port limit and reduce time wait delay
if: matrix.os == 'windows-2025'
run: |
netsh int ipv4 set dynamicport tcp start=1025 num=64511
REG ADD HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters /v TcpTimedWaitDelay /t REG_DWORD /d 30 /f
Expand All @@ -42,59 +92,14 @@ jobs:
cache: npm
check-latest: true

# Let corepack manage npm, pnpm, and yarn versions for E2E tests
- name: Enable corepack
# Let corepack manage npm, pnpm, and yarn versions on Windows.
- name: Enable corepack (Windows)
if: matrix.os == 'windows-2025'
run: corepack enable

- name: Install dependencies
run: npm ci --no-audit

- name: Build project
run: npm run build

- name: Run E2E tests
run: npm run test:e2e

- name: Notify Slack
uses: 8398a7/action-slack@v3
if: ${{ github.event_name == 'schedule' && failure() }}
with:
status: custom
fields: workflow
custom_payload: |
{
attachments: [{
title: 'E2E Test Failed! (${{ matrix.os }},node-${{ matrix.node-version }}',
color: 'danger',
text: `${process.env.AS_WORKFLOW}\n\nEither something broke or a test is flaky.\n\nConsider doing something about it :fire_engine:`,
}]
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

e2e-linux-based-os:
name: E2E
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
matrix:
os: [ubuntu-latest, macOS-latest]
node-version: ['20.12.2', '22', '24']
fail-fast: false
steps:
- name: Git checkout
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Setup node
uses: actions/setup-node@v6
with:
node-version: ${{ matrix.node-version }}
cache: npm
check-latest: true

- uses: pnpm/action-setup@v4
- name: Setup pnpm (non-Windows)
if: matrix.os != 'windows-2025'
uses: pnpm/action-setup@v4
with:
version: 10

Expand Down Expand Up @@ -123,3 +128,20 @@ jobs:
}
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

status:
name: E2E Tests Status
needs: [setup, e2e]
if: always()
runs-on: ubuntu-latest
steps:
- name: Verify result
run: |
if [[ "${{ needs.setup.result }}" != "success" ]]; then
echo "Setup job failed"
exit 1
fi
if [[ "${{ needs.e2e.result }}" == "failure" || "${{ needs.e2e.result }}" == "cancelled" ]]; then
echo "E2E tests failed"
exit 1
fi
6 changes: 5 additions & 1 deletion .github/workflows/format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ jobs:
steps:
- uses: actions/checkout@v6

- name: Read primary Node version
id: node
run: echo "version=$(yq eval '.primary_node_version' .github/test-matrix.yml)" >> "$GITHUB_OUTPUT"

- uses: actions/setup-node@v6
with:
node-version: '24'
node-version: ${{ steps.node.outputs.version }}
cache: npm

- name: Install dependencies
Expand Down
87 changes: 76 additions & 11 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,74 @@
name: Integration Tests

on:
push:
branches:
- main
pull_request:
branches:
- '**'
- '!release-please--**'
branches: ['**']

jobs:
setup:
name: Setup
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.matrix.outputs.value }}
has-code-changes: ${{ steps.filter.outputs.code || 'true' }}
steps:
- name: Git checkout
uses: actions/checkout@v6

- name: Detect code changes
uses: dorny/paths-filter@v3
if: github.event_name == 'pull_request'
id: filter
with:
filters: |
code:
- '**'
- '!**/*.md'
- '!LICENSE'
- '!docs/**'
- '!.vale.ini'
- '!.github/ISSUE_TEMPLATE/**'
- '!.github/PULL_REQUEST_TEMPLATE.md'

- name: Compute matrix
id: matrix
env:
HEAD_REF: ${{ github.head_ref }}
run: |
node_versions=$(yq eval '.node_versions | join(" ")' .github/test-matrix.yml)
extra_oses=$(yq eval '.extra_oses_on_release | join(" ")' .github/test-matrix.yml)
primary=$(yq eval '.primary_node_version' .github/test-matrix.yml)

OS_NODE=()
for node in $node_versions; do
OS_NODE+=("ubuntu-latest:$node")
done
if [[ "$HEAD_REF" == release-please--* ]]; then
for os in $extra_oses; do
OS_NODE+=("$os:$primary")
Comment on lines +36 to +49

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Use a same-repo check before expanding the integration matrix.

This branch-prefix check is spoofable on forked PRs for the same reason as in the unit workflow: github.head_ref only carries the PR source branch name, and forked pull_request events run in the base repository. Here the impact is larger because each extra OS also fans out across 4 shards. (docs.github.com)

🔧 Suggested guard
       - name: Compute matrix
         id: matrix
         env:
           HEAD_REF: ${{ github.head_ref }}
+          HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
+          BASE_REPO: ${{ github.repository }}
         run: |
           node_versions=$(yq eval '.node_versions | join(" ")' .github/test-matrix.yml)
           extra_oses=$(yq eval '.extra_oses_on_release | join(" ")' .github/test-matrix.yml)
           primary=$(yq eval '.primary_node_version' .github/test-matrix.yml)

           OS_NODE=()
           for node in $node_versions; do
             OS_NODE+=("ubuntu-latest:$node")
           done
-          if [[ "$HEAD_REF" == release-please--* ]]; then
+          if [[ "$HEAD_REPO" == "$BASE_REPO" && "$HEAD_REF" == release-please--* ]]; then
             for os in $extra_oses; do
               OS_NODE+=("$os:$primary")
             done
           fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
env:
HEAD_REF: ${{ github.head_ref }}
run: |
node_versions=$(yq eval '.node_versions | join(" ")' .github/test-matrix.yml)
extra_oses=$(yq eval '.extra_oses_on_release | join(" ")' .github/test-matrix.yml)
primary=$(yq eval '.primary_node_version' .github/test-matrix.yml)
OS_NODE=()
for node in $node_versions; do
OS_NODE+=("ubuntu-latest:$node")
done
if [[ "$HEAD_REF" == release-please--* ]]; then
for os in $extra_oses; do
OS_NODE+=("$os:$primary")
env:
HEAD_REF: ${{ github.head_ref }}
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
BASE_REPO: ${{ github.repository }}
run: |
node_versions=$(yq eval '.node_versions | join(" ")' .github/test-matrix.yml)
extra_oses=$(yq eval '.extra_oses_on_release | join(" ")' .github/test-matrix.yml)
primary=$(yq eval '.primary_node_version' .github/test-matrix.yml)
OS_NODE=()
for node in $node_versions; do
OS_NODE+=("ubuntu-latest:$node")
done
if [[ "$HEAD_REPO" == "$BASE_REPO" && "$HEAD_REF" == release-please--* ]]; then
for os in $extra_oses; do
OS_NODE+=("$os:$primary")
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/integration-tests.yml around lines 36 - 49, Before
expanding the OS matrix (the block that builds OS_NODE using HEAD_REF and
extra_oses), add a same-repo guard that verifies the PR source repo is the base
repo: extract the pull_request head repo full name from the event payload (e.g.,
via GITHUB_EVENT_PATH/.pull_request.head.repo.full_name) and compare it to
GITHUB_REPOSITORY, and only if they match proceed to run the existing
branch-prefix check that uses HEAD_REF (the existing if [[ "$HEAD_REF" ==
release-please--* ]] block); this ensures the extra_oses / OS_NODE expansion
(and subsequent sharding) runs only for same-repo PRs.

done
fi

entries=()
for combo in "${OS_NODE[@]}"; do
os="${combo%:*}"
node="${combo##*:}"
for shard in "1/4" "2/4" "3/4" "4/4"; do
entries+=("{\"os\":\"$os\",\"node-version\":\"$node\",\"shard\":\"$shard\"}")
done
done
joined=$(IFS=,; echo "${entries[*]}")
echo "value={\"include\":[$joined]}" >> "$GITHUB_OUTPUT"

integration:
name: Integration
needs: setup
if: needs.setup.outputs.has-code-changes == 'true'
runs-on: ${{ matrix.os }}
timeout-minutes: 40
strategy:
matrix:
os: [ubuntu-latest, macOS-latest, windows-2025]
# Pinning 20.x version as a temporary workaround due to this https://github.com/nodejs/node/issues/52884
node-version: ['20.12.2', '22', '24']
shard: ['1/4', '2/4', '3/4', '4/4']
fail-fast: false
matrix: ${{ fromJson(needs.setup.outputs.matrix) }}
steps:
# This improves Windows network performance, we need this since we open many ports in our tests
- name: Increase Windows port limit and reduce time wait delay
Expand Down Expand Up @@ -104,3 +152,20 @@ jobs:
with:
flags: ${{ steps.test-coverage-flags.outputs.os }},${{ steps.test-coverage-flags.outputs.node }}
token: ${{ secrets.CODECOV_TOKEN }}

status:
name: Integration Tests Status
needs: [setup, integration]
if: always()
runs-on: ubuntu-latest
steps:
- name: Verify result
run: |
if [[ "${{ needs.setup.result }}" != "success" ]]; then
echo "Setup job failed"
exit 1
fi
if [[ "${{ needs.integration.result }}" == "failure" || "${{ needs.integration.result }}" == "cancelled" ]]; then
echo "Integration tests failed"
exit 1
fi
6 changes: 5 additions & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,13 @@ jobs:
steps:
- uses: actions/checkout@v6

- name: Read primary Node version
id: node
run: echo "version=$(yq eval '.primary_node_version' .github/test-matrix.yml)" >> "$GITHUB_OUTPUT"

- uses: actions/setup-node@v6
with:
node-version: '24'
node-version: ${{ steps.node.outputs.version }}
cache: npm

- name: Install dependencies
Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/pre-release-sha.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,13 @@ jobs:
with:
ref: ${{ inputs.ref }}

- name: Read primary Node version
id: node
run: echo "version=$(yq eval '.primary_node_version' .github/test-matrix.yml)" >> "$GITHUB_OUTPUT"
Comment on lines +23 to +25

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Verify whether commits before matrix-file introduction exist (and would fail current logic)
intro_commit=$(git log --diff-filter=A --format=%H -- .github/test-matrix.yml | head -n1 || true)

if [[ -z "${intro_commit}" ]]; then
  echo "No introduction commit for .github/test-matrix.yml found in available history."
  exit 0
fi

parent_commit=$(git rev-parse "${intro_commit}^")

echo "Matrix file introduced at: ${intro_commit}"
echo "Parent commit to test:     ${parent_commit}"

if git cat-file -e "${parent_commit}:.github/test-matrix.yml" 2>/dev/null; then
  echo "Unexpected: matrix file exists in parent commit."
else
  echo "Confirmed: parent commit lacks .github/test-matrix.yml."
  echo "Current pre-release-sha logic would fail for that SHA."
fi

Repository: netlify/cli

Length of output: 278


🏁 Script executed:

#!/bin/bash
# Find when .github/test-matrix.yml was introduced using git log
git log --follow --format="%H %ai %s" -- .github/test-matrix.yml | tail -5
echo "---"
# Check if file exists in current HEAD
if [[ -f .github/test-matrix.yml ]]; then
  echo "File exists in current HEAD"
  head -5 .github/test-matrix.yml
else
  echo "File does not exist in current HEAD"
fi

Repository: netlify/cli

Length of output: 419


🏁 Script executed:

#!/bin/bash
# Check what would happen if yq tries to read a non-existent file
if ! command -v yq &> /dev/null; then
  echo "yq not available in sandbox"
else
  # Test yq behavior with non-existent file
  yq eval '.primary_node_version' /nonexistent/path.yml 2>&1 || true
fi

Repository: netlify/cli

Length of output: 82


🏁 Script executed:

#!/bin/bash
# Read the workflow file to see full context around lines 18-29
cat -n .github/workflows/pre-release-sha.yml | sed -n '15,35p'

Repository: netlify/cli

Length of output: 919


Handle SHAs that predate .github/test-matrix.yml introduction.

Line 23 reads config from the checked-out ref (line 18), but the file was only recently added (2026-04-23). Any older SHA will fail the yq read, breaking setup-node at line 29. This makes the SHA-based prerelease workflow fail for historical commits.

Add a conditional fallback to handle missing file:

Proposed fix
-      - name: Read primary Node version
-        id: node
-        run: echo "version=$(yq eval '.primary_node_version' .github/test-matrix.yml)" >> "$GITHUB_OUTPUT"
+      - name: Read primary Node version
+        id: node
+        run: |
+          if [[ -f .github/test-matrix.yml ]]; then
+            version="$(yq eval '.primary_node_version' .github/test-matrix.yml)"
+          else
+            # fallback for historical SHAs that predate the matrix file
+            version="24"
+          fi
+          echo "version=$version" >> "$GITHUB_OUTPUT"

Also applies to: 29-29

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/pre-release-sha.yml around lines 23 - 25, The workflow
step named "Read primary Node version" currently unconditionally runs yq against
.github/test-matrix.yml which will fail for historical SHAs that don't contain
that file; modify that step's run so it first checks for the file's existence
(test -f .github/test-matrix.yml) and only runs yq if present, otherwise emit a
safe fallback like echo "version=" (or a default version) to GITHUB_OUTPUT and
optionally a warning; ensure the same conditional/fallback logic is applied to
any other step that reads the same file (e.g., the subsequent "setup-node"
usage), so missing .github/test-matrix.yml does not break the prerelease
workflow for older commits.


- uses: actions/setup-node@v6
with:
node-version: '24'
node-version: ${{ steps.node.outputs.version }}
cache: npm
registry-url: 'https://registry.npmjs.org'

Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/pre-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@ jobs:
steps:
- uses: actions/checkout@v6

- name: Read primary Node version
id: node
run: echo "version=$(yq eval '.primary_node_version' .github/test-matrix.yml)" >> "$GITHUB_OUTPUT"

- uses: actions/setup-node@v6
with:
node-version: '24'
node-version: ${{ steps.node.outputs.version }}
cache: npm
registry-url: 'https://registry.npmjs.org'

Expand Down
Loading
Loading