Skip to content
Open
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
16 changes: 12 additions & 4 deletions .github/workflows/cd-built-branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ on:
type: string
default: ""
node-version:
description: "Default Node.js version for every target, overridable per target."
description: "Default Node.js version for every target, overridable per target. Leave empty to read the target's .nvmrc, then the repo root's, falling back to 22."
type: string
default: "22"
default: ""
php-version:
description: "Default PHP version for every target, overridable per target."
type: string
Expand Down Expand Up @@ -230,6 +230,13 @@ jobs:

php_version="$(jq -r --arg d "$INPUT_PHP_VERSION" '.["php-version"] // $d' <<<"$item")"
node_version="$(jq -r --arg d "$INPUT_NODE_VERSION" '.["node-version"] // $d' <<<"$item")"
node_version_file=""
if [ -z "$node_version" ]; then
if [ -s "$dir/.nvmrc" ]; then node_version_file="$dir/.nvmrc"
elif [ -s .nvmrc ]; then node_version_file=".nvmrc"
else node_version="22"
fi
fi
composer_flags="$(jq -r --arg d "$INPUT_COMPOSER_FLAGS" '.["composer-flags"] // $d' <<<"$item")"
build_command="$(jq -r --arg d "$INPUT_BUILD_COMMAND" '.["build-command"] // $d' <<<"$item")"
[ -n "$build_command" ] || build_command="npm run build:prod"
Expand All @@ -254,12 +261,12 @@ jobs:
entry="$(jq -nc \
--arg name "$name" --arg dir "$dir" \
--arg composer "$composer" --arg node "$node" \
--arg php "$php_version" --arg nodever "$node_version" \
--arg php "$php_version" --arg nodever "$node_version" --arg nodefile "$node_version_file" \
--arg cflags "$composer_flags" --arg bcmd "$build_command" \
--arg lock "${dir%/}/package-lock.json" \
--arg pp "$publish_abs" --arg vp "$verify_abs" \
'{name:$name, dir:$dir, composer:$composer, node:$node,
"php-version":$php, "node-version":$nodever,
"php-version":$php, "node-version":$nodever, "node-version-file":$nodefile,
"composer-flags":$cflags, "build-command":$bcmd,
lockfile:$lock, "publish-paths":$pp, "verify-paths":$vp}')"
items="$(jq -c --argjson e "$entry" '. + [$e]' <<<"$items")"
Expand Down Expand Up @@ -332,6 +339,7 @@ jobs:
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: ${{ matrix.node-version }}
node-version-file: ${{ matrix.node-version-file }}
Comment on lines 341 to +342
cache: npm
# setup-node is a JS action and ignores defaults.run.working-directory, so without
# this it looks for the lockfile at the repo root.
Expand Down
42 changes: 33 additions & 9 deletions .github/workflows/ci-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,23 @@ on:
type: boolean
default: true
node-version:
description: "Node.js version (used only when install-node-deps is true)."
description: "Node.js version, used only when install-node-deps is true. Leave empty to read .nvmrc from working-dir, then the repo root, falling back to 22."
type: string
default: "22"
default: ""
install-composer-deps:
description: "Install Composer dependencies before the build."
type: boolean
default: false
php-version:
description: "PHP version (used only when install-composer-deps is true)."
description: "PHP version, used only when install-composer-deps is true. Leave empty for 8.3."
type: string
default: "8.3"
default: ""
composer-flags:
description: "Flags passed to composer install."
description: >-
Flags passed to composer install. Leave empty for '--no-dev --prefer-dist
--optimize-autoloader --no-progress --no-interaction --no-scripts'.
type: string
default: "--no-dev --prefer-dist --optimize-autoloader --no-progress --no-interaction --no-scripts"
default: ""
build-command:
description: "Shell command that produces the production build. When empty, defaults to 'npm run build:prod' if install-node-deps is true, otherwise 'composer run-script build'."
type: string
Expand Down Expand Up @@ -66,11 +68,33 @@ jobs:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

# Node version: the input, else .nvmrc (working-dir, then repo root), else 22.
- name: Resolve Node.js version
id: node
if: ${{ inputs.install-node-deps }}
shell: bash
env:
NODE_VERSION: ${{ inputs.node-version }}
WORKING_DIR: ${{ inputs.working-dir }}
run: |
set -euo pipefail
# setup-node reads the file path from the repo root.
if [ -n "$NODE_VERSION" ]; then
echo "version=$NODE_VERSION" >> "$GITHUB_OUTPUT"
elif [ -s .nvmrc ]; then
echo "file=$WORKING_DIR/.nvmrc" >> "$GITHUB_OUTPUT"
elif [ -s "$GITHUB_WORKSPACE/.nvmrc" ]; then
echo "file=.nvmrc" >> "$GITHUB_OUTPUT"
else
echo "version=22" >> "$GITHUB_OUTPUT"
fi
Comment on lines +71 to +90

- name: Set up Node.js
if: ${{ inputs.install-node-deps }}
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: ${{ inputs.node-version }}
node-version: ${{ steps.node.outputs.version }}
node-version-file: ${{ steps.node.outputs.file }}
cache: npm
# setup-node is a JS action: without this it looks for the lockfile at the repo root.
cache-dependency-path: ${{ inputs.working-dir != '.' && format('{0}/package-lock.json', inputs.working-dir) || '' }}
Expand All @@ -79,15 +103,15 @@ jobs:
if: ${{ inputs.install-composer-deps }}
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # 2.37.0
with:
php-version: ${{ inputs.php-version }}
php-version: ${{ inputs.php-version || '8.3' }}
coverage: none
tools: composer

- name: Install Composer dependencies
if: ${{ inputs.install-composer-deps }}
shell: bash
env:
COMPOSER_FLAGS: ${{ inputs.composer-flags }}
COMPOSER_FLAGS: ${{ inputs.composer-flags || '--no-dev --prefer-dist --optimize-autoloader --no-progress --no-interaction --no-scripts' }}
run: |
set -euo pipefail
read -r -a composer_args <<< "$COMPOSER_FLAGS" || true
Expand Down
61 changes: 46 additions & 15 deletions .github/workflows/ci-lint-css.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,20 @@ on:
type: string
default: '"ubuntu-latest"'
node-version:
description: "Node.js version."
description: "Node.js version. Leave empty to read .nvmrc from working-dir, then the repo root, falling back to 22."
type: string
default: "22"
default: ""
lint-command:
description: "Shell command that runs Stylelint over the whole project. Used when changed-files is empty."
description: >-
Shell command that runs Stylelint. The changed files are appended as arguments, so a
custom command must pass them on, as npm run does. Leave empty for 'npm run lint:css'.
type: string
default: "npm run lint:css"
default: ""
changed-files:
description: "Newline-separated changed files (ci-detect-changes' css-files). Stylesheets are linted file by file; if the list is empty or holds anything else (package.json, package-lock.json), lint-command runs over the whole project."
description: >-
Newline-separated changed files (ci-detect-changes' css-files). Only stylesheets that
still exist are linted, and a list of only deleted stylesheets skips Stylelint. No list,
or a change to package.json or package-lock.json, lints the whole project.
type: string
default: ""
working-dir:
Expand All @@ -38,10 +43,31 @@ jobs:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

# Node version: the input, else .nvmrc (working-dir, then repo root), else 22.
- name: Resolve Node.js version
id: node
shell: bash
env:
NODE_VERSION: ${{ inputs.node-version }}
WORKING_DIR: ${{ inputs.working-dir }}
run: |
set -euo pipefail
# setup-node reads the file path from the repo root.
if [ -n "$NODE_VERSION" ]; then
echo "version=$NODE_VERSION" >> "$GITHUB_OUTPUT"
elif [ -s .nvmrc ]; then
echo "file=$WORKING_DIR/.nvmrc" >> "$GITHUB_OUTPUT"
elif [ -s "$GITHUB_WORKSPACE/.nvmrc" ]; then
echo "file=.nvmrc" >> "$GITHUB_OUTPUT"
else
echo "version=22" >> "$GITHUB_OUTPUT"
fi

- name: Set up Node.js
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: ${{ inputs.node-version }}
node-version: ${{ steps.node.outputs.version }}
node-version-file: ${{ steps.node.outputs.file }}
cache: npm
# setup-node is a JS action: without this it looks for the lockfile at the repo root.
cache-dependency-path: ${{ inputs.working-dir != '.' && format('{0}/package-lock.json', inputs.working-dir) || '' }}
Expand All @@ -53,15 +79,20 @@ jobs:
shell: bash
env:
CHANGED_FILES: ${{ inputs.changed-files }}
LINT_COMMAND: ${{ inputs.lint-command }}
LINT_COMMAND: ${{ inputs.lint-command || 'npm run lint:css' }}
Comment thread
Adi-ty marked this conversation as resolved.
run: |
# css-files also lists package.json and package-lock.json, so a dependency
# change re-runs this job. Stylelint cannot parse them, and a dependency
# change can affect every stylesheet, so lint the whole project then.
stylesheets=$(printf '%s\n' "$CHANGED_FILES" | grep -E '\.s?css$' || true)
set -eo pipefail
# Lint only the changed stylesheets that still exist; "./" keeps a name like -x.css a path.
# No list, or a package.json/lockfile change, lints the whole project.
stylesheets=$(printf '%s\n' "$CHANGED_FILES" | grep -E '\.s?css$' \
| while IFS= read -r file; do [ ! -f "$file" ] || printf './%s\n' "$file"; done || true)
others=$(printf '%s\n' "$CHANGED_FILES" | grep -vE '^$|\.s?css$' || true)
if [ -n "$stylesheets" ] && [ -z "$others" ]; then
printf '%s\n' "$stylesheets" | xargs -d '\n' --no-run-if-empty npx --no-install stylelint --
else
bash -eo pipefail -c "$LINT_COMMAND"
files=()
if [ -n "$CHANGED_FILES" ] && [ -z "$others" ]; then
if [ -z "$stylesheets" ]; then
echo "::notice::Nothing to lint: the changed stylesheets were deleted."
exit 0
fi
mapfile -t files <<< "$stylesheets"
fi
bash -eo pipefail -c "$LINT_COMMAND \"\$@\"" _ "${files[@]}"
Comment thread
Adi-ty marked this conversation as resolved.
59 changes: 48 additions & 11 deletions .github/workflows/ci-lint-js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,20 @@ on:
type: string
default: '"ubuntu-latest"'
node-version:
description: "Node.js version."
description: "Node.js version. Leave empty to read .nvmrc from working-dir, then the repo root, falling back to 22."
type: string
default: "22"
default: ""
lint-command:
description: "Shell command that runs ESLint over the whole project. Used when changed-files is empty."
description: >-
Shell command that runs ESLint. The changed files are appended as arguments, so a custom
command must pass them on, as npm run does. Leave empty for 'npm run lint:js'.
type: string
default: "npm run lint:js"
default: ""
changed-files:
description: "Newline-separated list of JS files to lint. Empty = run lint-command over the whole project."
description: >-
Newline-separated changed files (ci-detect-changes' js-files). Only JS files that still
exist are linted, and a list with nothing to lint (deleted files, Jest snapshots) skips
ESLint. No list, or a change to package.json or package-lock.json, lints the whole project.
type: string
default: ""
validate-package-json:
Expand All @@ -42,10 +47,31 @@ jobs:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

# Node version: the input, else .nvmrc (working-dir, then repo root), else 22.
- name: Resolve Node.js version
id: node
shell: bash
env:
NODE_VERSION: ${{ inputs.node-version }}
WORKING_DIR: ${{ inputs.working-dir }}
run: |
set -euo pipefail
# setup-node reads the file path from the repo root.
if [ -n "$NODE_VERSION" ]; then
echo "version=$NODE_VERSION" >> "$GITHUB_OUTPUT"
elif [ -s .nvmrc ]; then
echo "file=$WORKING_DIR/.nvmrc" >> "$GITHUB_OUTPUT"
elif [ -s "$GITHUB_WORKSPACE/.nvmrc" ]; then
echo "file=.nvmrc" >> "$GITHUB_OUTPUT"
else
echo "version=22" >> "$GITHUB_OUTPUT"
fi

- name: Set up Node.js
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
with:
node-version: ${{ inputs.node-version }}
node-version: ${{ steps.node.outputs.version }}
node-version-file: ${{ steps.node.outputs.file }}
cache: npm
# setup-node is a JS action: without this it looks for the lockfile at the repo root.
cache-dependency-path: ${{ inputs.working-dir != '.' && format('{0}/package-lock.json', inputs.working-dir) || '' }}
Expand All @@ -57,14 +83,25 @@ jobs:
if: ${{ inputs.validate-package-json }}
run: npm run lint:package-json --if-present

# ESLint errors become PR annotations through setup-node's problem matcher.
- name: Run ESLint
shell: bash
env:
CHANGED_FILES: ${{ inputs.changed-files }}
LINT_COMMAND: ${{ inputs.lint-command }}
LINT_COMMAND: ${{ inputs.lint-command || 'npm run lint:js' }}
Comment thread
Adi-ty marked this conversation as resolved.
run: |
if [ -n "$CHANGED_FILES" ]; then
printf '%s\n' "$CHANGED_FILES" | xargs -d '\n' --no-run-if-empty npx --no-install eslint --
else
bash -eo pipefail -c "$LINT_COMMAND"
set -eo pipefail
# Lint only the changed JS files that still exist; "./" keeps a name like -x.js a path.
# No list, or a package.json/lockfile change, lints the whole project.
scripts=$(printf '%s\n' "$CHANGED_FILES" | grep -E '\.[cm]?[jt]sx?$' \
| while IFS= read -r file; do [ ! -f "$file" ] || printf './%s\n' "$file"; done || true)
others=$(printf '%s\n' "$CHANGED_FILES" | grep -vE '^$|\.[cm]?[jt]sx?$|\.snap$' || true)
files=()
if [ -n "$CHANGED_FILES" ] && [ -z "$others" ]; then
if [ -z "$scripts" ]; then
echo "::notice::Nothing to lint: the changed JS files were deleted or are Jest snapshots."
exit 0
fi
mapfile -t files <<< "$scripts"
fi
bash -eo pipefail -c "$LINT_COMMAND \"\$@\"" _ "${files[@]}"
Comment thread
Adi-ty marked this conversation as resolved.
26 changes: 14 additions & 12 deletions .github/workflows/ci-lint-php.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,33 +8,35 @@ on:
type: string
default: '"ubuntu-latest"'
php-version:
description: "PHP version."
description: "PHP version. Leave empty for 8.3."
type: string
default: "8.3"
default: ""
enable-phpstan:
description: "Run PHPStan after PHPCS."
type: boolean
default: false
phpcs-command:
description: "PHPCS binary path or custom command."
description: "PHPCS binary path or custom command. Leave empty for 'vendor/bin/phpcs'."
type: string
default: "vendor/bin/phpcs"
default: ""
changed-files:
description: "Newline-separated changed files (ci-detect-changes' php-files). PHP files that still exist are linted file by file; if the list is empty or holds anything else (composer.json, composer.lock, PHPStan config), PHPCS lints the whole project. PHPStan always runs whole-project — it analyses cross-file dependencies."
type: string
default: ""
phpstan-command:
description: "Shell command that runs PHPStan."
description: "Shell command that runs PHPStan. Leave empty for 'vendor/bin/phpstan analyse'."
type: string
default: "vendor/bin/phpstan analyse"
default: ""
phpstan-level:
description: "Override PHPStan level. Empty uses the level from phpstan.neon.dist."
type: string
default: ""
composer-flags:
description: "Flags passed to `composer install`. Default includes `--no-scripts` for supply-chain hygiene."
description: >-
Flags passed to `composer install`. Leave empty for '--prefer-dist --optimize-autoloader
--no-progress --no-interaction --no-scripts'; `--no-scripts` is there for supply-chain hygiene.
type: string
default: "--prefer-dist --optimize-autoloader --no-progress --no-interaction --no-scripts"
default: ""
validate-composer:
description: "Run `composer validate` before installing. Disable for packages without composer.lock."
type: boolean
Expand All @@ -61,7 +63,7 @@ jobs:
- name: Set up PHP
uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # 2.37.0
with:
php-version: ${{ inputs.php-version }}
php-version: ${{ inputs.php-version || '8.3' }}
tools: composer, cs2pr
coverage: none
# Raises the GitHub API rate limit when composer install resolves a VCS repo.
Expand All @@ -88,7 +90,7 @@ jobs:
- name: Install Composer dependencies
shell: bash
env:
COMPOSER_FLAGS: ${{ inputs.composer-flags }}
COMPOSER_FLAGS: ${{ inputs.composer-flags || '--prefer-dist --optimize-autoloader --no-progress --no-interaction --no-scripts' }}
run: |
set -euo pipefail
read -r -a composer_args <<< "$COMPOSER_FLAGS" || true
Expand All @@ -98,7 +100,7 @@ jobs:
shell: bash
env:
CHANGED_FILES: ${{ inputs.changed-files }}
PHPCS_COMMAND: ${{ inputs.phpcs-command }}
PHPCS_COMMAND: ${{ inputs.phpcs-command || 'vendor/bin/phpcs' }}
run: |
set -euo pipefail
# phpcs-command is a command and runs as shell; the report flags are appended as "$@" so
Expand All @@ -125,7 +127,7 @@ jobs:
if: ${{ inputs.enable-phpstan }}
shell: bash
env:
PHPSTAN_COMMAND: ${{ inputs.phpstan-command }}
PHPSTAN_COMMAND: ${{ inputs.phpstan-command || 'vendor/bin/phpstan analyse' }}
PHPSTAN_LEVEL: ${{ inputs.phpstan-level }}
run: |
set -eo pipefail
Expand Down
Loading
Loading