Compare commits

...
58 Commits
Author SHA1 Message Date
Shivam Mathur e3f88f3ca7 Enable fileinfo for Laravel Cloud CLI 2026-09-16 18:18:36 +05:30
Shivam Mathur 870fe79ecc Verify cached Windows extensions load before reusing them 2026-09-16 18:18:09 +05:30
Shivam Mathur 25618cc48e Cache replaced Windows extensions by their installed version 2026-09-16 11:25:07 +05:30
Shivam Mathur 5eaed2e30b Validate restored versioned extensions before reporting success 2026-09-16 09:16:04 +05:30
Shivam Mathur 85dc78fbb0 Preserve Composer checksum pins for full version suffixes 2026-09-16 05:37:39 +05:30
Shivam Mathur 83c9e52793 docs: deprecate macOS 14 arm64 runners in support note 2026-09-16 04:14:38 +05:30
Shivam Mathur 9af3b52286 Document deprecated Intel macOS runner support 2026-09-12 00:33:02 +05:30
Shivam Mathur 0e80ac5270 Restore explicit TypeScript checking in CI 2026-09-12 00:33:02 +05:30
Shivam Mathur ea331059db Try the expected extension version before unpinned PECL fallback 2026-09-12 00:33:02 +05:30
Shivam Mathur 3ad6232c89 Preserve PowerShell return values in verbose mode 2026-09-12 00:32:55 +05:30
Shivam Mathur 2ec764e0ab Compare complete Windows extension versions 2026-09-12 00:32:42 +05:30
Shivam Mathur e6ee35895b Require full tool versions for checksum pinning 2026-09-11 20:49:43 +05:30
Shivam Mathur 0c6410c670 Fix Homebrew timeout cleanup and retry propagation 2026-09-11 14:20:07 +05:30
Shivam Mathur 250924180e Add configurable verbosity and guarded shell tracing 2026-09-10 01:29:39 +05:30
Shivam Mathur 63b8b6feda Stop Intel macOS installs when the package cache fails 2026-09-09 09:01:18 +05:30
Shivam Mathur de306754b1 Support php-darwin cache on Intel macOS 2026-09-08 18:05:05 +05:30
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 1e29d2af9f Bump the github-actions group with 3 updates (#1114)
Bumps the github-actions group with 3 updates: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/autobuild](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.37.8 to 4.37.9
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28...cdf488f595d80d6e07e03d4674febd5ab45fa938)

Updates `github/codeql-action/autobuild` from 4.37.8 to 4.37.9
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28...cdf488f595d80d6e07e03d4674febd5ab45fa938)

Updates `github/codeql-action/analyze` from 4.37.8 to 4.37.9
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28...cdf488f595d80d6e07e03d4674febd5ab45fa938)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.37.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-09-07 18:14:58 +05:30
Shivam Mathur 52fea29a50 Run cached PHP install in PhpManager scope 2026-09-04 11:25:34 +05:30
Shivam Mathur 1d62418c5a Validate cached Xdebug 2 on macOS 2026-09-03 20:10:28 +05:30
Shivam Mathur e4c0f64cb6 Suppress PECL info warnings 2026-09-03 15:39:00 +05:30
Shivam Mathur 4de6f6f4a5 Install cached Windows PHP builds directly 2026-09-03 13:59:30 +05:30
Shivam Mathur c482204203 Update dependencies 2026-09-03 09:58:11 +05:30
Shivam Mathur 02e8f2dc92 Fix npm audit 2026-09-03 09:54:39 +05:30
Shivam Mathur 14d457bbef Drop Intel macOS support 2026-09-01 10:42:02 +05:30
Shivam Mathur 9fe8278c96 Skip php-darwin cache on Intel macOS 2026-09-01 10:36:34 +05:30
Shivam Mathur b8123f29e1 Reuse the PHP Windows download URL 2026-08-29 23:24:25 +05:30
Shivam Mathur 3cd644eeae Use manifests for Windows PHP release assets 2026-08-29 23:16:02 +05:30
Shivam Mathur 047d693cbc Use php-darwin caches on macOS 2026-08-29 22:32:59 +05:30
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 084a79c9b8 Bump the github-actions group with 4 updates (#1110)
Bumps the github-actions group with 4 updates: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/autobuild](https://github.com/github/codeql-action), [github/codeql-action/analyze](https://github.com/github/codeql-action) and [shivammathur/cache-extensions](https://github.com/shivammathur/cache-extensions).


Updates `github/codeql-action/init` from 4.37.7 to 4.37.8
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd...db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28)

Updates `github/codeql-action/autobuild` from 4.37.7 to 4.37.8
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd...db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28)

Updates `github/codeql-action/analyze` from 4.37.7 to 4.37.8
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd...db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28)

Updates `shivammathur/cache-extensions` from 1.15.0 to 1.15.1
- [Release notes](https://github.com/shivammathur/cache-extensions/releases)
- [Commits](https://github.com/shivammathur/cache-extensions/compare/50000e7030dd3fa176964a8fbbbd9e4b560fe4d4...de3c642a5fce0ef91581a1c9831e229f525196d6)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.37.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: shivammathur/cache-extensions
  dependency-version: 1.15.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-29 18:26:12 +05:30
Shivam Mathur 159772ba0f Use homebrew-extensions for lua on PHP 8.0 and above [skip ci] 2026-08-23 11:36:38 +05:30
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> c9e91c1e82 Bump the github-actions group with 4 updates (#1109)
Bumps the github-actions group with 4 updates: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/autobuild](https://github.com/github/codeql-action), [github/codeql-action/analyze](https://github.com/github/codeql-action) and [shivammathur/cache-extensions](https://github.com/shivammathur/cache-extensions).


Updates `github/codeql-action/init` from 4.37.6 to 4.37.7
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/5595ccaf912efad79be6eef63a5619ff05969be3...ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd)

Updates `github/codeql-action/autobuild` from 4.37.6 to 4.37.7
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/5595ccaf912efad79be6eef63a5619ff05969be3...ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd)

Updates `github/codeql-action/analyze` from 4.37.6 to 4.37.7
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/5595ccaf912efad79be6eef63a5619ff05969be3...ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd)

Updates `shivammathur/cache-extensions` from 1.14.6 to 1.15.0
- [Release notes](https://github.com/shivammathur/cache-extensions/releases)
- [Commits](https://github.com/shivammathur/cache-extensions/compare/9b476298b44f2e4d4268dd103ff4c3e216314e27...50000e7030dd3fa176964a8fbbbd9e4b560fe4d4)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.37.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: shivammathur/cache-extensions
  dependency-version: 1.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-22 17:34:40 +05:30
Shivam Mathur 12cc6a507b Fix versioned extension caching 2026-08-19 14:35:13 +05:30
Ibrahim Lawal 33139dbaea Honor a cache-restored build when a versioned extension mismatches (#1108)
* fix: honor a cache-restored build when a versioned extension mismatches

When a PHP package install bundles its own default build of a versioned
extension (e.g. redis ships with its own recent version pre-enabled),
add_pecl_extension correctly detects the version mismatch against the
pinned version and falls back to pecl_install - but it does this even
when a matching build has already been restored from a CI cache into a
separate directory, since shared_extension only checks that *some* file
exists at ext_dir, not which version it is.

This adds an opt-in CACHED_EXTENSIONS_DIR: when set and a mismatch is
detected, look for extension.so there, and if found, copy it into
ext_dir and re-check before falling back to a full pecl_install. When
CACHED_EXTENSIONS_DIR is unset, behavior is unchanged.

Related to shivammathur/cache-extensions#21 and #37, where a cached
build of a versioned PECL extension is silently ignored and
recompiled on every run regardless of caching.

* fix: preserve versioned builds in ext_dir instead of a separate cache dir

Per @shivammathur's review on the PR: drop the opt-in
CACHED_EXTENSIONS_DIR env var. Instead, after installing a versioned
extension, keep a second copy of the built .so in ext_dir itself under
a name with no .so suffix (e.g. redis-5.3.7), so it can't be mistaken
for the active extension and rides along in the same ext_dir that
cache-extensions already caches wholesale - no separate cache
directory, key, or workflow step required. On a version mismatch,
restore that preserved build over the active binary and re-check
before falling back to a full pecl_install.
2026-08-19 13:21:10 +05:30
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 1adbee900f Bump the github-actions group with 3 updates (#1107)
Bumps the github-actions group with 3 updates: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/autobuild](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.37.4 to 4.37.6
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/f205ea1c3313d32999d8d6a48b4f6530d4437b38...5595ccaf912efad79be6eef63a5619ff05969be3)

Updates `github/codeql-action/autobuild` from 4.37.4 to 4.37.6
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/f205ea1c3313d32999d8d6a48b4f6530d4437b38...5595ccaf912efad79be6eef63a5619ff05969be3)

Updates `github/codeql-action/analyze` from 4.37.4 to 4.37.6
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/f205ea1c3313d32999d8d6a48b4f6530d4437b38...5595ccaf912efad79be6eef63a5619ff05969be3)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.37.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-15 17:52:32 +05:30
damiantw 7d04f5ee7e Add Laravel Cloud CLI Tool (#1106)
* Add Laravel Cloud CLI Tool

* Fix extensions
2026-08-12 21:41:33 +05:30
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 19bc37cbe5 Bump the github-actions group across 1 directory with 3 updates (#1105)
Bumps the github-actions group with 3 updates in the / directory: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/autobuild](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.37.3 to 4.37.4
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81...f205ea1c3313d32999d8d6a48b4f6530d4437b38)

Updates `github/codeql-action/autobuild` from 4.37.3 to 4.37.4
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81...f205ea1c3313d32999d8d6a48b4f6530d4437b38)

Updates `github/codeql-action/analyze` from 4.37.3 to 4.37.4
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81...f205ea1c3313d32999d8d6a48b4f6530d4437b38)

---
updated-dependencies:
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.37.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-08 16:41:24 +05:30
Shivam Mathur b52e51b078 Fix npm audit for js-yaml [skip ci] 2026-08-08 16:26:45 +05:30
Wendell Adriel a6c520081f Add support for cpx (#1104)
* Add support for cpx

* README: add cpx to tools list
2026-08-05 15:42:46 +05:30
Shivam Mathur ced9161b13 Fix npm audit 2026-08-05 15:38:46 +05:30
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 858ddd7182 Bump the github-actions group with 3 updates (#1103)
Bumps the github-actions group with 3 updates: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/autobuild](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.37.1 to 4.37.3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/7188fc363630916deb702c7fdcf4e481b751f97a...e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81)

Updates `github/codeql-action/autobuild` from 4.37.1 to 4.37.3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/7188fc363630916deb702c7fdcf4e481b751f97a...e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81)

Updates `github/codeql-action/analyze` from 4.37.1 to 4.37.3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/7188fc363630916deb702c7fdcf4e481b751f97a...e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.37.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-01 19:40:34 +05:30
Shivam Mathur 2608ba9a1a Fix geos patch URLs 2026-07-27 11:36:12 +05:30
Julietteandjrfnl 7d83587834 README: minor documentation fix (#1102)
Co-authored-by: jrfnl <jrfnl@users.noreply.github.com>
2026-07-26 21:47:51 +05:30
Shivam Mathur a75416c329 Upgrade build to TypeScript 7 2026-07-26 01:22:48 +05:30
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 0c0c27b4cb Bump the github-actions group across 1 directory with 5 updates (#1100)
Bumps the github-actions group with 5 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [actions/checkout](https://github.com/actions/checkout) | `7.0.0` | `7.0.1` |
| [github/codeql-action/init](https://github.com/github/codeql-action) | `4.37.0` | `4.37.1` |
| [github/codeql-action/autobuild](https://github.com/github/codeql-action) | `4.37.0` | `4.37.1` |
| [github/codeql-action/analyze](https://github.com/github/codeql-action) | `4.37.0` | `4.37.1` |
| [actions/setup-node](https://github.com/actions/setup-node) | `6.4.0` | `7.0.0` |



Updates `actions/checkout` from 7.0.0 to 7.0.1
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0...3d3c42e5aac5ba805825da76410c181273ba90b1)

Updates `github/codeql-action/init` from 4.37.0 to 4.37.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/99df26d4f13ea111d4ec1a7dddef6063f76b97e9...7188fc363630916deb702c7fdcf4e481b751f97a)

Updates `github/codeql-action/autobuild` from 4.37.0 to 4.37.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/99df26d4f13ea111d4ec1a7dddef6063f76b97e9...7188fc363630916deb702c7fdcf4e481b751f97a)

Updates `github/codeql-action/analyze` from 4.37.0 to 4.37.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/99df26d4f13ea111d4ec1a7dddef6063f76b97e9...7188fc363630916deb702c7fdcf4e481b751f97a)

Updates `actions/setup-node` from 6.4.0 to 7.0.0
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e...820762786026740c76f36085b0efc47a31fe5020)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: actions/setup-node
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.37.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-25 18:53:11 +05:30
Shivam Mathur 5a9d09b8e0 Fix npm audit 2026-07-25 18:32:47 +05:30
Shivam Mathur 8e6e5267e7 Harden tool checksum verification (#1099) 2026-07-23 19:24:32 +05:30
Keisuke MaedaandClaude Fable 5 8ca9579834 Add support for pinning tools to a checksum (#1098)
Tools in the tools input can now be pinned to a checksum using the
tool:version@sha256:<hash> or tool:version@sha512:<hash> syntax.
The downloaded tool is verified against the checksum on all platforms,
including when it is served from the tools cache, and it is removed
along with its cache entry if the verification fails.

Checksum verification is supported for tools downloaded as phar
archives. Specifying a checksum for tools set up using composer
packages or custom package scripts results in an error.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-23 18:15:59 +05:30
Shivam Mathur b9ef68088b Bump Node.js packages
Add allowScripts for 3 packages
2026-07-21 18:21:48 +05:30
Shivam Mathur fffd6b1db6 Fix support for install krb5 on linux using PECL 2026-07-21 01:50:08 +05:30
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> d64d1a1275 Bump the github-actions group with 3 updates (#1094)
Bumps the github-actions group with 3 updates: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/autobuild](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.36.3 to 4.37.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/54f647b7e1bb85c95cddabcd46b0c578ec92bc1a...99df26d4f13ea111d4ec1a7dddef6063f76b97e9)

Updates `github/codeql-action/autobuild` from 4.36.3 to 4.37.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/54f647b7e1bb85c95cddabcd46b0c578ec92bc1a...99df26d4f13ea111d4ec1a7dddef6063f76b97e9)

Updates `github/codeql-action/analyze` from 4.36.3 to 4.37.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/54f647b7e1bb85c95cddabcd46b0c578ec92bc1a...99df26d4f13ea111d4ec1a7dddef6063f76b97e9)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-18 19:25:55 +05:30
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> add91f08e1 Bump the github-actions group with 3 updates (#1092)
Bumps the github-actions group with 3 updates: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/autobuild](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.36.2 to 4.36.3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/8aad20d150bbac5944a9f9d289da16a4b0d87c1e...54f647b7e1bb85c95cddabcd46b0c578ec92bc1a)

Updates `github/codeql-action/autobuild` from 4.36.2 to 4.36.3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/8aad20d150bbac5944a9f9d289da16a4b0d87c1e...54f647b7e1bb85c95cddabcd46b0c578ec92bc1a)

Updates `github/codeql-action/analyze` from 4.36.2 to 4.36.3
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/8aad20d150bbac5944a9f9d289da16a4b0d87c1e...54f647b7e1bb85c95cddabcd46b0c578ec92bc1a)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.36.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/autobuild
  dependency-version: 4.36.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.36.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-11 16:36:32 +05:30
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 93f351c169 Bump actions/cache from 5.0.5 to 6.1.0 in the github-actions group (#1091)
Bumps the github-actions group with 1 update: [actions/cache](https://github.com/actions/cache).


Updates `actions/cache` from 5.0.5 to 6.1.0
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](https://github.com/actions/cache/compare/27d5ce7f107fe9357f9df03efb73ab90386fccae...55cc8345863c7cc4c66a329aec7e433d2d1c52a9)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-04 18:52:12 +05:30
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 529ee057c4 Bump actions/checkout from 6.0.3 to 7.0.0 in the github-actions group (#1090)
Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout).


Updates `actions/checkout` from 6.0.3 to 7.0.0
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/df4cb1c069e1874edd31b4311f1884172cec0e10...9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-27 16:20:13 +05:30
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 3fa88f2494 Bump the github-actions group across 1 directory with 2 updates (#1088)
Bumps the github-actions group with 2 updates in the / directory: [shivammathur/setup-php](https://github.com/shivammathur/setup-php) and [shivammathur/cache-extensions](https://github.com/shivammathur/cache-extensions).


Updates `shivammathur/setup-php` from 2.37.1 to 2.37.2
- [Release notes](https://github.com/shivammathur/setup-php/releases)
- [Commits](https://github.com/shivammathur/setup-php/compare/7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc...f3e473d116dcccaddc5834248c87452386958240)

Updates `shivammathur/cache-extensions` from 1.14.5 to 1.14.6
- [Release notes](https://github.com/shivammathur/cache-extensions/releases)
- [Commits](https://github.com/shivammathur/cache-extensions/compare/256729b5fef535345e27904657f78048c0990f81...9b476298b44f2e4d4268dd103ff4c3e216314e27)

---
updated-dependencies:
- dependency-name: shivammathur/cache-extensions
  dependency-version: 1.14.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: shivammathur/setup-php
  dependency-version: 2.37.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-20 19:54:30 +05:30
Shivam Mathur 0c10338998 Update Node.js dependencies 2026-06-20 18:43:15 +05:30
Shivam Mathur 805dfa40c1 Improve README [skip ci] 2026-06-18 10:13:14 +05:30
Shivam Mathur 1b1cce8c66 Add initial support for Ubuntu 26.04 [skip ci] 2026-06-18 04:28:47 +05:30
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 95edd72557 Bump the github-actions group with 3 updates (#1087)
Bumps the github-actions group with 3 updates: [actions/checkout](https://github.com/actions/checkout), [github/codeql-action](https://github.com/github/codeql-action) and [codecov/codecov-action](https://github.com/codecov/codecov-action).


Updates `actions/checkout` from 6.0.2 to 6.0.3
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/de0fac2e4500dabe0009e67214ff5f5447ce83dd...df4cb1c069e1874edd31b4311f1884172cec0e10)

Updates `github/codeql-action` from 4.36.0 to 4.36.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/7211b7c8077ea37d8641b6271f6a365a22a5fbfa...8aad20d150bbac5944a9f9d289da16a4b0d87c1e)

Updates `codecov/codecov-action` from 6.0.1 to 7.0.0
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/e79a6962e0d4c0c17b229090214935d2e33f8354...fb8b3582c8e4def4969c97caa2f19720cb33a72f)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: 6.0.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action
  dependency-version: 4.36.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: codecov/codecov-action
  dependency-version: 7.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-06-13 18:06:26 +05:30
35 changed files with 2806 additions and 1051 deletions
+4 -4
View File
@@ -20,19 +20,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 2
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4
uses: github/codeql-action/init@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
with:
config-file: ./.github/codeql/codeql-configuration.yml
languages: javascript
- name: Autobuild
uses: github/codeql-action/autobuild@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4
uses: github/codeql-action/autobuild@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4
uses: github/codeql-action/analyze@cdf488f595d80d6e07e03d4674febd5ab45fa938 # v4
+5 -5
View File
@@ -19,11 +19,11 @@ jobs:
strategy:
fail-fast: false
matrix:
operating-system: [ubuntu-24.04, ubuntu-22.04, windows-2022, macos-15-intel]
operating-system: [ubuntu-24.04, ubuntu-22.04, windows-2022, macos-15]
php-versions: ['5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5', '8.6']
steps:
- name: Setup PHP
uses: shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc # v2
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2
with:
php-version: ${{ matrix.php-versions }}
tools: none
@@ -42,7 +42,7 @@ jobs:
run: |
php -m | Out-File -FilePath "$env:file.all" -Append
- name: Setup PHP
uses: shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc # v2
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # v2
with:
php-version: ${{ matrix.php-versions }}
extensions: none
@@ -104,7 +104,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: ${{ github.repository }}.wiki
persist-credentials: false
@@ -127,7 +127,7 @@ jobs:
echo "These are extensions which are loaded by default on the following PHP versions. More extensions which are available as packages and available on pecl are supported by setup-php. Refer to [php extension support](https://github.com/shivammathur/setup-php#heavy_plus_sign-php-extension-support) for more details." > Php-extensions-loaded-on-"$os".md
for version in 5.3 5.4 5.5 5.6 7.0 7.1 7.2 7.3 7.4 8.0 8.1 8.2 8.3 8.4 8.5 8.6; do
if [[ "${os%-*}" = "macos" ]]; then
cat lists/php"$version"-macos-15-intel.md >> Php-extensions-loaded-on-"$os".md
cat lists/php"$version"-macos-15.md >> Php-extensions-loaded-on-"$os".md
elif [ "${os%-*}" = "windows" ]; then
cat lists/php"$version"-windows-2022.md >> Php-extensions-loaded-on-"$os".md
else
+6 -3
View File
@@ -33,13 +33,13 @@ jobs:
operating-system: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 2
persist-credentials: false
- name: Setup Node.js 24.x
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version: 24.x
@@ -52,6 +52,9 @@ jobs:
- name: ESLint Check
run: npm run lint
- name: TypeScript Check
run: npm run typecheck
- name: Run tests
run: npm test
@@ -59,7 +62,7 @@ jobs:
run: npm audit
- name: Send Coverage
uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v6
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: coverage/lcov.info
+4 -4
View File
@@ -31,7 +31,7 @@ jobs:
strategy:
fail-fast: false
matrix:
operating-system: [ubuntu-24.04, ubuntu-22.04, windows-2022, macos-15-intel]
operating-system: [ubuntu-24.04, ubuntu-22.04, windows-2022, macos-15]
php-versions: ['5.3', '5.4', '5.5', '5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5', '8.6']
include:
- operating-system: ubuntu-24.04
@@ -42,20 +42,20 @@ jobs:
key: cache-v5
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup cache environment
id: cache-env
uses: shivammathur/cache-extensions@256729b5fef535345e27904657f78048c0990f81 # v1
uses: shivammathur/cache-extensions@de3c642a5fce0ef91581a1c9831e229f525196d6 # v1
with:
php-version: ${{ matrix.php-versions || env.default-php-version }}
extensions: ${{ env.extensions }}
key: ${{ env.key }}
- name: Cache extensions
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v5
with:
path: ${{ steps.cache-env.outputs.dir }}
key: ${{ steps.cache-env.outputs.key }}
+4 -4
View File
@@ -26,19 +26,19 @@ jobs:
steps:
- name: Checkout release
if: github.event_name != 'workflow_dispatch'
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Checkout tag
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
if: github.event_name == 'workflow_dispatch'
with:
ref: ${{ github.event.inputs.tag }}
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
node-version: '24.x'
registry-url: https://registry.npmjs.org
@@ -55,7 +55,7 @@ jobs:
run: npm publish --access public
- name: Change to GitHub Packages registry
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v6
with:
registry-url: https://npm.pkg.github.com
package-manager-cache: false
+65 -31
View File
@@ -18,7 +18,7 @@
<a href="https://status.setup-php.com" title="setup-php status"><img alt="setup-php status" src="https://img.shields.io/badge/status-subscribe-28A745?logo=statuspage&logoColor=28A745&labelColor=555555"></a>
</p>
Setup PHP with required extensions, php.ini configuration, code-coverage support and various tools like composer in [GitHub Actions](https://github.com/features/actions "GitHub Actions"). This action gives you a cross-platform interface to set up the PHP environment you need to test your application. Refer to [Usage](#memo-usage "How to use this") section and [examples](#examples "Examples of use") to see how to use this.
Setup PHP with required extensions, php.ini configuration, code-coverage support, and various tools like composer in [GitHub Actions](https://github.com/features/actions "GitHub Actions"). This action gives you a cross-platform interface to set up the PHP environment you need to test your application. Refer to the [Usage](#memo-usage "How to use this") section and [examples](#examples "Examples of use") to see how to use this.
## Contents
@@ -70,8 +70,10 @@ Both `GitHub-hosted` and `self-hosted` runners are supported by `setup-php` on t
| Virtual environment | Arch | YAML workflow label | Pre-installed PHP |
|---------------------|---------|------------------------------------|-------------------|
| Ubuntu 26.04 | x86_64 | `ubuntu-26.04` | `PHP 8.5` |
| Ubuntu 24.04 | x86_64 | `ubuntu-latest` or `ubuntu-24.04` | `PHP 8.3` |
| Ubuntu 22.04 | x86_64 | `ubuntu-22.04` | `PHP 8.1` |
| Ubuntu 26.04 | aarch64 | `ubuntu-26.04-arm` | `PHP 8.5` |
| Ubuntu 24.04 | aarch64 | `ubuntu-24.04-arm` | `PHP 8.3` |
| Ubuntu 22.04 | aarch64 | `ubuntu-22.04-arm` | `PHP 8.1` |
| Windows Server 2025 | x64 | `windows-2025` | `PHP 8.5` |
@@ -82,10 +84,14 @@ Both `GitHub-hosted` and `self-hosted` runners are supported by `setup-php` on t
| macOS Tahoe 26.x | x86_64 | `macos-26-intel` | `PHP 8.5` |
| macOS Sequoia 15.x | x86_64 | `macos-15-intel` | `PHP 8.5` |
> [!NOTE]
> Support for Intel (`x86_64`) macOS runners and macOS Sonoma 14.x (`macos-14`) arm64 runners is deprecated and will be removed completely in a future release of `setup-php`. We recommend migrating to arm64-based macOS runners running macOS 15 or newer, such as `macos-26` or `macos-15`.
### Self-Hosted Runners
| Host OS/Virtual environment | YAML workflow label |
|----------------------------------|----------------------------|
| Ubuntu 26.04 | `self-hosted` or `Linux` |
| Ubuntu 24.04 | `self-hosted` or `Linux` |
| Ubuntu 22.04 | `self-hosted` or `Linux` |
| Debian 13 | `self-hosted` or `Linux` |
@@ -98,7 +104,7 @@ Both `GitHub-hosted` and `self-hosted` runners are supported by `setup-php` on t
| macOS Sonoma 14.x x86_64/arm64 | `self-hosted` or `macOS` |
- Refer to the [self-hosted setup](#self-hosted-setup) to use the action on self-hosted runners.
- Operating systems based on the above Ubuntu and Debian versions are also supported on best effort basis.
- Operating systems based on the above Ubuntu and Debian versions are also supported on a best effort basis.
- If the requested PHP version is pre-installed, `setup-php` switches to it, otherwise it installs the PHP version.
## :tada: PHP Support
@@ -155,7 +161,7 @@ PHP extensions can be set up using the `extensions` input. It accepts a `string`
- Extensions installed along with PHP if specified are enabled.
- Specific versions of extensions available on `PECL` can be set up by suffixing the extension's name with the version. This is useful for installing old versions of extensions which support end of life PHP versions.
- Specific versions of extensions available on `PECL` can be set up by suffixing the extension's name with the version. This is useful for installing old versions of extensions which support end-of-life PHP versions.
```yaml
- name: Setup PHP with specific version of PECL extension
@@ -180,14 +186,14 @@ PHP extensions can be set up using the `extensions` input. It accepts a `string`
- Shared extensions can be disabled by prefixing them with a `:`. All extensions depending on the specified extension will also be disabled.
```yaml
- name: Setup PHP and disable opcache
- name: Setup PHP and disable mbstring
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
extensions: :mbstring
```
- All shared extensions can be disabled by specifying `none`. When `none` is specified along with other extensions, it is hoisted to the start of the input. So, all the shared extensions will be disabled first, then rest of the extensions in the input will be processed.
- All shared extensions can be disabled by specifying `none`. When `none` is specified along with other extensions, it is hoisted to the start of the input. So, all the shared extensions will be disabled first, then the rest of the extensions in the input will be processed.
This disables all core and third-party shared extensions and thus, can break some tools that need them. Required extensions are enabled again when the tools are set up on a best-effort basis. So it is recommended to add the extensions required for your tools after `none` in the `extensions` input to avoid any issues.
@@ -216,7 +222,7 @@ This disables all core and third-party shared extensions and thus, can break som
- `event`, `gearman`, `geos` and `relay` on `Ubuntu` and `macOS`.
- `blackfire`, `couchbase`, `ibm_db2`, `ioncube`, `oci8`, `pdo_firebird`, `pdo_ibm`, `pdo_oci`, `pecl_http`, `phalcon3`, `phalcon4`, `phalcon5`, and `zephir_parser` on all supported OS.
- By default, extensions which cannot be added or disabled gracefully leave an error message in the logs, the execution is not interrupted. To change this behaviour you can set `fail-fast` flag to `true`.
- By default, extensions which cannot be added or disabled gracefully leave an error message in the logs. The execution is not interrupted. To change this behaviour you can set `fail-fast` flag to `true`.
```yaml
- name: Setup PHP with fail-fast
@@ -232,7 +238,7 @@ This disables all core and third-party shared extensions and thus, can break som
These tools can be set up globally using the `tools` input. It accepts a string in csv-format.
[`backward-compatibility-check`], [`behat`], [`blackfire`], [`blackfire-player`], [`box`], [`castor`], [`churn`], [`codeception`], [`composer`], [`composer-dependency-analyser`], [`composer-normalize`], [`composer-prefetcher`], [`composer-require-checker`], [`composer-unused`], [`cs2pr`], [`deployer`], [`ecs`], [`flex`], [`grpc_php_plugin`], [`infection`], [`mago`], [`name-collision-detector`], [`parallel-lint`], [`pecl`], [`phan`], [`phing`], [`phinx`], [`phive`], [`php-config`], [`php-cs-fixer`], [`php-scoper`], [`phpcbf`], [`phpcpd`], [`phpcs`], [`phpdoc`] or [`phpDocumentor`], [`phpize`], [`phplint`], [`phpmd`], [`phpspec`], [`phpstan`], [`phpunit`], [`phpunit-bridge`], [`phpunit-polyfills`], [`pie`], [`pint`], [`prestissimo`], [`protoc`], [`psalm`], [`rector`], [`symfony`] or [`symfony-cli`], [`vapor`] or [`vapor-cli`], [`wp`] or [`wp-cli`]
[`backward-compatibility-check`], [`behat`], [`blackfire`], [`blackfire-player`], [`box`], [`castor`], [`churn`], [`codeception`], [`composer`], [`composer-dependency-analyser`], [`composer-normalize`], [`composer-prefetcher`], [`composer-require-checker`], [`composer-unused`], [`cpx`], [`cs2pr`], [`deployer`], [`ecs`], [`flex`], [`grpc_php_plugin`], [`infection`], [`laravel-cloud`] or [`cloud-cli`], [`mago`], [`name-collision-detector`], [`parallel-lint`], [`pecl`], [`phan`], [`phing`], [`phinx`], [`phive`], [`php-config`], [`php-cs-fixer`], [`php-scoper`], [`phpcbf`], [`phpcpd`], [`phpcs`], [`phpdoc`] or [`phpDocumentor`], [`phpize`], [`phplint`], [`phpmd`], [`phpspec`], [`phpstan`], [`phpunit`], [`phpunit-bridge`], [`phpunit-polyfills`], [`pie`], [`pint`], [`prestissimo`], [`protoc`], [`psalm`], [`rector`], [`symfony`] or [`symfony-cli`], [`vapor`] or [`vapor-cli`], [`wp`] or [`wp-cli`]
```yaml
- name: Setup PHP with tools
@@ -242,7 +248,7 @@ These tools can be set up globally using the `tools` input. It accepts a string
tools: php-cs-fixer, phpunit
```
- In addition to above tools any composer tool or package can also be set up globally by specifying it as `vendor/package` matching the listing on Packagist. This format accepts the same [version constraints](https://getcomposer.org/doc/articles/versions.md#writing-version-constraints "Composer version constraints") as `composer`.
- In addition to the above tools, any composer tool or package can also be set up globally by specifying it as `vendor/package` matching the listing on Packagist. This format accepts the same [version constraints](https://getcomposer.org/doc/articles/versions.md#writing-version-constraints "Composer version constraints") as `composer`.
```yaml
- name: Setup PHP with tools
@@ -259,7 +265,19 @@ These tools can be set up globally using the `tools` input. It accepts a string
- Major version. For example `tool:1` or `tool:1.x`.
- Major and minor version. For example `tool:1.2` or `tool:1.2.x`.
When you specify just the major version or the version in `major.minor` format, the latest patch version matching the input will be setup.
When you specify just the major version or the version in `major.minor` format, the latest patch version matching the input will be set up.
- To harden your workflow against supply chain attacks, you can pin a tool to a checksum in the form `tool:version@sha256:<hash>` or `tool:version@sha512:<hash>`. The downloaded tool is verified against the checksum and it is not set up if the verification fails, even if the tool is served from the tools cache.
```yaml
- name: Setup PHP with tools pinned to a checksum
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
tools: composer:2.9.8@sha256:59b2c50e10cafa0d8efc19ede9a326d782f096c674a26baf98cf042ce23de890
```
Checksum verification is supported only for tools downloaded as phar archives with a full version, such as `tool:1.2.3` or `tool:1.2.3-beta1`. Specifying a checksum with an omitted version, a variable tag such as `latest`, `stable`, `preview` or `snapshot`, or a partial version such as `2`, `2.x`, `2.9` or `2.9.x` results in an error. These versions can resolve to different releases with different checksums. Checksum verification is not supported for tools set up using `composer` packages or custom package scripts; specifying a checksum for these tools also results in an error.
- The latest stable version of `composer` is set up by default. You can set up the required `composer` version by specifying the major version `v1` or `v2`, or the version in `major.minor` or `semver` format. Additionally, for composer `snapshot` and `preview` can also be specified to set up the respective releases.
@@ -299,10 +317,10 @@ These tools can be set up globally using the `tools` input. It accepts a string
fail-fast: true
```
- By default, `composer` blocks all its plugins. If you are using the `tools` input to install a composer plugin it will be added to the allow list, alternatively if your dependencies have composer plugins, you can allow them by setting `COMPOSER_ALLOW_PLUGINS` that accepts a csv string of plugin names.
- By default, `composer` blocks all its plugins. If you are using the `tools` input to install a composer plugin it will be added to the allowlist, alternatively if your dependencies have composer plugins, you can allow them by setting `COMPOSER_ALLOW_PLUGINS` that accepts a csv string of plugin names.
```yaml
- name: Setup PHP with fail-fast
- name: Setup PHP with allow composer plugins
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
@@ -342,7 +360,7 @@ Runs on all [PHP versions supported](#tada-php-support "List of PHP versions sup
```
- When you specify `coverage: xdebug`, the latest version of Xdebug compatible with the PHP version is set up by default.
- If you need Xdebug 2.x on PHP 7.2, 7.3 or 7.4, you can specify `coverage: xdebug2`.
- If you need Xdebug 2.x on PHP 7.2, 7.3, or 7.4, you can specify `coverage: xdebug2`.
```yaml
- name: Setup PHP with Xdebug 2.x
@@ -353,7 +371,7 @@ Runs on all [PHP versions supported](#tada-php-support "List of PHP versions sup
```
> [!NOTE]
> Xdebug is enabled by default on Ubuntu GitHub Actions images, so if you are not using it in your workflow it is recommended to disable it as that will have a positive impact on your PHP performance. Please refer to the [disable coverage](#disable-coverage) section for details.
> Xdebug is enabled by default on Ubuntu GitHub Actions images, so if you are not using it in your workflows, it is recommended to disable it as that will have a positive impact on your PHP performance. Please refer to the [disable coverage](#disable-coverage) section for details.
### PCOV
@@ -372,7 +390,7 @@ Runs on PHP 7.1 and newer PHP versions.
```
- PHPUnit 8.x and above support PCOV out of the box.
- If you are using PHPUnit 5.x, 6.x or 7.x, you need to set up `pcov/clobber` before executing your tests.
- If you are using PHPUnit 5.x, 6.x, or 7.x, you need to set up `pcov/clobber` before executing your tests.
```yaml
- name: Setup PCOV
@@ -390,7 +408,7 @@ Disable coverage for these reasons:
- You are not generating coverage reports while testing.
- You are using `phpdbg` for running your tests.
- You are profiling your code using `blackfire`.
- You are using PHP in JIT mode. Please refer to [JIT configuration](#jit-configuration) section for more details.
- You are using PHP in JIT mode. Please refer to the [JIT configuration](#jit-configuration) section for more details.
```yaml
- name: Setup PHP with no coverage driver
@@ -514,6 +532,13 @@ On GitHub Actions you can assign the `setup-php` step an `id`, you can use the s
- By default, it is set to `false`.
- See [force update setup](#force-update-setup) for more info.
#### `verbose` (optional)
- Specify to enable verbose output.
- Accepts `true`, `false`, `v`, `vv` and `vvv`.
- By default, it is set to `false`.
- See [verbose setup](#verbose-setup) for more info.
See below for more info.
### Basic Setup
@@ -642,18 +667,24 @@ jobs:
> Debug your workflow
To debug any issues, you can use the `verbose` tag instead of `v2`.
- Set the `verbose` environment variable to `true` or `v` to show command output.
- Set `verbose` to `vv` or `vvv` to also enable `set -x` on Linux and macOS.
- On Windows, `vv` enables `Set-PSDebug -Trace 1` and `vvv` enables `Set-PSDebug -Trace 2`.
- Enabling [GitHub Actions debug logging](https://docs.github.com/en/actions/how-tos/monitor-workflows/enable-debug-logging) (`RUNNER_DEBUG=1`) also enables verbose mode.
- The `verbose` and `more-verbose` tags have been deprecated and will be discontinued in the next major release.
```yaml
- name: Setup PHP with logs
uses: shivammathur/setup-php@verbose
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
env:
verbose: true
```
### Multi-Arch Setup
> Set up PHP on multiple architecture on Ubuntu GitHub Runners.
> Set up PHP on multiple architectures on Ubuntu GitHub Runners.
- `PHP 5.6` to `PHP 8.5` are supported by `setup-php` on multiple architecture on `Ubuntu` and `Debian`.
- For this, you can use `shivammathur/node` images as containers. These have compatible `Nodejs` and `PHP` installed for `setup-php`.
@@ -683,7 +714,7 @@ jobs:
> Set up PHP on a self-hosted runner.
- To set up a containerised self-hosted runner, refer to the following guides as per your base operating system.
- To set up a containerized self-hosted runner, refer to the following guides as per your base operating system.
- [Linux](https://github.com/shivammathur/setup-php/wiki/Dockerized-self-hosted-runner-on-Linux)
- [Windows](https://github.com/shivammathur/setup-php/wiki/Dockerized-self-hosted-runner-on-Windows)
@@ -710,7 +741,7 @@ jobs:
```
> [!NOTE]
> - Do not set up multiple self-hosted runners on a single server instance as parallel workflow will conflict with each other.
> - Do not set up multiple self-hosted runners on a single server instance as parallel workflows will conflict with each other.
> - Do not set up self-hosted runners on the side of your development environment or your production server.
> - Avoid using the same labels for your `self-hosted` runners which are used by `GitHub-hosted` runners.
@@ -753,7 +784,7 @@ act -P ubuntu-22.04=shivammathur/node:22.04
- By default, `opcache.jit=1235` and `opcache.jit_buffer_size=256M` (`opcache.jit_buffer_size=128M` on ARM-based environments) are set which can be changed using `ini-values` input.
- For detailed information about JIT related directives refer to the [`official PHP documentation`](https://www.php.net/manual/en/opcache.configuration.php#ini.opcache.jit "opcache.jit documentation").
For example to enable JIT in `tracing` mode with buffer size of `64 MB`.
For example, to enable JIT in `tracing` mode with buffer size of `64 MB`.
```yaml
- name: Setup PHP with JIT in tracing mode
@@ -833,7 +864,7 @@ If you use Private Packagist for your private composer dependencies, you can set
### Manual Composer Authentication
In addition to GitHub or Private Packagist, if you want to authenticate private repositories hosted elsewhere, you can set the `COMPOSER_AUTH_JSON` environment variable with the authentication methods and the credentials in json format.
In addition to GitHub or Private Packagist, if you want to authenticate private repositories hosted elsewhere, you can set the `COMPOSER_AUTH_JSON` environment variable with the authentication methods and the credentials in JSON format.
Please refer to the authentication section in [`composer documentation`](https://getcomposer.org/doc/articles/authentication-for-private-packages.md "composer documentation") for more details.
```yaml
@@ -879,7 +910,7 @@ Problem matchers are `json` configurations which identify errors and warnings in
#### PHP
Setup problem matchers for your `PHP` output by adding this step after the `setup-php` step.
Set up problem matchers for your `PHP` output by adding this step after the `setup-php` step.
```yaml
- name: Setup problem matchers for PHP
@@ -888,7 +919,7 @@ Setup problem matchers for your `PHP` output by adding this step after the `setu
#### PHPUnit
Setup problem matchers for your `PHPUnit` output by adding this step after the `setup-php` step.
Set up problem matchers for your `PHPUnit` output by adding this step after the `setup-php` step.
```yaml
- name: Setup problem matchers for PHPUnit
@@ -970,7 +1001,7 @@ Examples of using `setup-php` with various PHP frameworks and packages.
| Symfony with `PostgreSQL` | `ubuntu` | [symfony-postgres.yml](./examples/symfony-postgres.yml "GitHub Action for Symfony with PostgreSQL") |
| Symfony without services | `macOS`, `ubuntu` and `windows` | [symfony.yml](./examples/symfony.yml "GitHub Action for Symfony without services") |
| WordPress plugin | `ubuntu` | [wordpress.yml](./examples/wordpress.yml "GitHub Action for WordPress plugins") |
| WordPress with Roots/Bedrock | `ubuntu` | [bedrock.yml](./examples/bedrock.yml "GitHub Action for WordPress development using @roots/bedrock") |
| WordPress with Roots/Bedrock | `ubuntu` | [bedrock.yml](./examples/bedrock.yml "GitHub Action for WordPress development using @roots/bedrock") |
| WordPress with Roots/Sage | `ubuntu` | [sage.yml](./examples/sage.yml "GitHub Action for WordPress development using @roots/sage") |
| Yii3 web application with `MySQL` | `ubuntu` | [yii3-mysql.yml](./examples/yii3-mysql.yml "GitHub Action for Yii3 web application with MySQL") |
| Yii3 web application with `PostgreSQL` | `ubuntu` | [yii3-postgres.yml](./examples/yii3-postgres.yml "GitHub Action for Yii3 web application with PostgreSQL") |
@@ -978,12 +1009,12 @@ Examples of using `setup-php` with various PHP frameworks and packages.
## :bookmark: Versioning
- Use the `v2` tag as `setup-php` version. It is a rolling tag and is synced with the latest minor and patch releases. With `v2` you automatically get the bug fixes, security patches, new features and support for latest PHP releases.
- Use the `v2` tag as `setup-php` version. It is a rolling tag and is synced with the latest minor and patch releases. With `v2` you automatically get the bug fixes, security patches, new features, and support for latest PHP releases.
- Semantic release versions can also be used. It is recommended to [use dependabot](https://docs.github.com/en/github/administering-a-repository/keeping-your-actions-up-to-date-with-github-dependabot "Setup Dependabot with GitHub Actions") with semantic versioning to keep the actions in your workflows up to date.
- Commit SHA can also be used, but are not recommended unless you set up tooling to update them with each release of the action.
- A new major version of the action will only be tagged when there are breaking changes in the setup-php API i.e. inputs, outputs, and environment flags.
- For debugging any issues `verbose` tag can be used temporarily. It outputs all the logs and is also synced with the latest releases.
- It is highly discouraged to use the `main` branch as version, it might break your workflow after major releases as they have breaking changes.
- Commit SHA can also be used, but is not recommended unless you set up tooling to update them with each release of the action.
- A new major version of the action will only be tagged when there are breaking changes in the setup-php API i.e. - inputs, outputs, and environment flags.
- For debugging any issues, use the [`verbose` environment variable](#verbose-setup).
- It is highly discouraged to use the `main` branch as the version, it might break your workflow after major releases as they have breaking changes.
- If you are using the `v1` tag or a `1.x.y` version, you should [switch to v2](https://github.com/shivammathur/setup-php/wiki/Switch-to-v2 "Guide for switching from setup-php v1 to v2") as `v1` is not supported anymore.
## :scroll: License
@@ -1045,7 +1076,7 @@ Many users and organizations support setup-php via [GitHub Sponsors](https://git
<a href="https://github.com/sponsors/shivammathur"><img src="https://setup-php.com/sponsors.svg?" alt="Sponsor shivammathur"></a>
- If you use setup-php, please consider starring the project and share it.
- If you use setup-php, please consider starring the project and sharing it.
- If you blog, please share your experience of using `setup-php`.
- Please [reach out](mailto:contact@setup-php.com) if you have any questions about sponsoring setup-php.
@@ -1081,6 +1112,7 @@ Many users and organizations support setup-php via [GitHub Sponsors](https://git
[`box`]: https://github.com/humbug/box
[`castor`]: https://github.com/jolicode/castor
[`churn`]: https://github.com/bmitch/churn-php
[`cloud-cli`]: https://cloud.laravel.com/docs/api/cli
[`codeception`]: https://codeception.com/
[`composer`]: https://getcomposer.org/
[`composer-dependency-analyser`]: https://github.com/shipmonk-rnd/composer-dependency-analyser
@@ -1088,12 +1120,14 @@ Many users and organizations support setup-php via [GitHub Sponsors](https://git
[`composer-prefetcher`]: https://github.com/narrowspark/automatic-composer-prefetcher
[`composer-require-checker`]: https://github.com/maglnet/ComposerRequireChecker
[`composer-unused`]: https://github.com/composer-unused/composer-unused
[`cpx`]: https://github.com/laravel/cpx
[`cs2pr`]: https://github.com/staabm/annotate-pull-request-from-checkstyle
[`deployer`]: https://deployer.org/
[`ecs`]: https://github.com/easy-coding-standard/easy-coding-standard
[`flex`]: https://github.com/symfony/flex
[`grpc_php_plugin`]: https://grpc.io/
[`infection`]: https://infection.github.io/
[`laravel-cloud`]: https://cloud.laravel.com/docs/api/cli
[`mago`]: https://github.com/carthage-software/mago
[`name-collision-detector`]: https://github.com/shipmonk/name-collision-detector
[`parallel-lint`]: https://github.com/php-parallel-lint/PHP-Parallel-Lint
+1 -1
View File
@@ -21,7 +21,7 @@ describe('Config tests', () => {
${'xdebug'} | ${'7.4'} | ${'linux'} | ${'Xdebug $xdebug_version enabled as coverage driver'}
${'xdebug'} | ${'7.4'} | ${'darwin'} | ${'add_brew_extension xdebug'}
${'xdebug3'} | ${'7.1'} | ${'darwin'} | ${'xdebug3 is not supported on PHP 7.1'}
${'xdebug2'} | ${'7.4'} | ${'darwin'} | ${'add_brew_extension xdebug2'}
${'xdebug2'} | ${'7.4'} | ${'darwin'} | ${'add_brew_extension xdebug2 zend_extension 2.9.8'}
${'xdebug2'} | ${'8.0'} | ${'darwin'} | ${'xdebug2 is not supported on PHP 8.0'}
${'none'} | ${'7.4'} | ${'win32'} | ${'Disable-Extension xdebug false,Disable-Extension pcov false'}
${'none'} | ${'7.4'} | ${'linux'} | ${'disable_extension xdebug false,disable_extension pcov false'}
+1
View File
@@ -107,6 +107,7 @@ describe('Extension tests', () => {
${'pecl_http'} | ${'7.3'} | ${'add_http'}
${'relay-1.2.3'} | ${'7.4'} | ${'add_relay relay-1.2.3'}
${'sqlite'} | ${'7.2'} | ${'add_extension sqlite3'}
${'xdebug2'} | ${'7.4'} | ${'add_brew_extension xdebug2 zend_extension 2.9.8'}
${'zephir_parser-v1.2.3'} | ${'7.2'} | ${'add_zephir_parser zephir_parser-v1.2.3'}
`(
'checking addExtensionOnDarwin for extension $extension on version $version',
+166 -15
View File
@@ -222,17 +222,51 @@ describe('Tools tests', () => {
});
it.each`
input_list | filtered_list
${'a, b'} | ${'composer, a, b'}
${'a, b, composer'} | ${'composer, a, b'}
${'a, b, composer:1.2.3'} | ${'composer:1.2.3, a, b'}
${'a, b, composer:v1.2.3'} | ${'composer:1.2.3, a, b'}
${'a, b, composer:snapshot'} | ${'composer:snapshot, a, b'}
${'a, b, composer:preview'} | ${'composer:preview, a, b'}
${'a, b, composer:1'} | ${'composer:1, a, b'}
${'a, b, composer:2'} | ${'composer:2, a, b'}
${'a, b, composer:v1'} | ${'composer:1, a, b'}
${'a, b, composer:v2'} | ${'composer:2, a, b'}
release | expected_release | checksum | error
${'tool:1.2.3'} | ${'tool:1.2.3'} | ${undefined} | ${undefined}
${'tool:1.2.3@sha256:' + 'a'.repeat(64)} | ${'tool:1.2.3'} | ${'sha256:' + 'a'.repeat(64)} | ${undefined}
${'tool:1.2.3@sha256:' + 'A'.repeat(64)} | ${'tool:1.2.3'} | ${'sha256:' + 'a'.repeat(64)} | ${undefined}
${'tool:1.2.3@SHA256:' + 'a'.repeat(64)} | ${'tool:1.2.3'} | ${'sha256:' + 'a'.repeat(64)} | ${undefined}
${'tool:1.2.3@sha512:' + 'b'.repeat(128)} | ${'tool:1.2.3'} | ${'sha512:' + 'b'.repeat(128)} | ${undefined}
${'tool:v1.2.3-beta.1+build.2@sha256:' + 'a'.repeat(64)} | ${'tool:v1.2.3-beta.1+build.2'} | ${'sha256:' + 'a'.repeat(64)} | ${undefined}
${'composer:2.9.8@sha256:' + 'c'.repeat(64)} | ${'composer:2.9.8'} | ${'sha256:' + 'c'.repeat(64)} | ${undefined}
${'tool:1.2.3@sha256:xyz'} | ${'tool:1.2.3'} | ${undefined} | ${'Invalid sha256 checksum, expected 64 hexadecimal characters'}
${'tool:1.2.3@sha256:' + 'a'.repeat(63)} | ${'tool:1.2.3'} | ${undefined} | ${'Invalid sha256 checksum, expected 64 hexadecimal characters'}
${'tool:1.2.3@sha512:' + 'b'.repeat(64)} | ${'tool:1.2.3'} | ${undefined} | ${'Invalid sha512 checksum, expected 128 hexadecimal characters'}
${'tool:1.2.3@sha384:' + 'b'.repeat(96)} | ${'tool:1.2.3'} | ${undefined} | ${'Unsupported checksum algorithm sha384, expected sha256 or sha512'}
${'tool:1.2.3@md5:' + 'b'.repeat(32)} | ${'tool:1.2.3'} | ${undefined} | ${'Unsupported checksum algorithm md5, expected sha256 or sha512'}
${'tool:1.2.3@sha256' + 'a'.repeat(64)} | ${'tool:1.2.3'} | ${undefined} | ${'Invalid checksum syntax, expected @sha256:<hash> or @sha512:<hash>'}
${'tool:1.0@dev'} | ${'tool:1.0@dev'} | ${undefined} | ${undefined}
`(
'checking extractChecksum: $release',
({release, expected_release, checksum, error}) => {
expect(tools.extractChecksum(release)).toStrictEqual({
release: expected_release,
...(checksum !== undefined && {checksum}),
...(error !== undefined && {error})
});
}
);
it.each`
input_list | filtered_list
${'a, b'} | ${'composer, a, b'}
${'a, b, composer'} | ${'composer, a, b'}
${'a, b, composer:1.2.3'} | ${'composer:1.2.3, a, b'}
${'a, b, composer:v1.2.3'} | ${'composer:1.2.3, a, b'}
${'a, b, composer:snapshot'} | ${'composer:snapshot, a, b'}
${'a, b, composer:preview'} | ${'composer:preview, a, b'}
${'a, b, composer:1'} | ${'composer:1, a, b'}
${'a, b, composer:2'} | ${'composer:2, a, b'}
${'a, b, composer:v1'} | ${'composer:1, a, b'}
${'a, b, composer:v2'} | ${'composer:2, a, b'}
${'a, b, composer:2.7.1@sha256:' + 'a'.repeat(64)} | ${'composer:2.7.1@sha256:' + 'a'.repeat(64) + ', a, b'}
${'a, b, composer:v2.7.1@sha256:' + 'a'.repeat(64)} | ${'composer:2.7.1@sha256:' + 'a'.repeat(64) + ', a, b'}
${'a, b, composer:2.7.1@SHA256:' + 'a'.repeat(64)} | ${'composer:2.7.1@SHA256:' + 'a'.repeat(64) + ', a, b'}
${'a, b, composer:2.7.1@sha384:' + 'a'.repeat(96)} | ${'composer:2.7.1@sha384:' + 'a'.repeat(96) + ', a, b'}
${'a, b, composer:2.7.1@md5:' + 'a'.repeat(32)} | ${'composer:2.7.1@md5:' + 'a'.repeat(32) + ', a, b'}
${'a, b, composer:2.7.1@sha256' + 'a'.repeat(64)} | ${'composer:2.7.1@sha256' + 'a'.repeat(64) + ', a, b'}
${'a, b, composer@sha256:' + 'a'.repeat(64)} | ${'composer@sha256:' + 'a'.repeat(64) + ', a, b'}
`('checking filterList $input_list', async ({input_list, filtered_list}) => {
expect(await tools.filterList(input_list.split(', '))).toStrictEqual(
filtered_list.split(', ')
@@ -304,6 +338,23 @@ describe('Tools tests', () => {
expect(await tools.addArchive(data)).toContain(script);
});
it.each`
os | script
${'linux'} | ${'add_tool https://example.com/tool.phar tool "-v" sha256:' + 'a'.repeat(64)}
${'darwin'} | ${'add_tool https://example.com/tool.phar tool "-v" sha256:' + 'a'.repeat(64)}
${'win32'} | ${'Add-Tool https://example.com/tool.phar tool "-v" sha256:' + 'a'.repeat(64)}
`('checking addArchive with checksum: $os', async ({os, script}) => {
const data = getData({
tool: 'tool',
version: '1.2.3',
version_parameter: JSON.stringify('-v'),
os: os,
url: 'https://example.com/tool.phar'
});
data.checksum = 'sha256:' + 'a'.repeat(64);
expect(await tools.addArchive(data)).toContain(script);
});
it.each`
os | release | scope | script
${'linux'} | ${'tool:1.2.3'} | ${'global'} | ${'add_composer_tool tool tool:1.2.3 user/ global'}
@@ -494,7 +545,7 @@ describe('Tools tests', () => {
);
}
}));
const isolatedTools = await import('../src/tools');
const isolatedTools = jest.requireActual<typeof tools>('../src/tools');
affected = isolatedTools.skipGitHubAuthForComposerVersion('2.9.7');
fixed = isolatedTools.skipGitHubAuthForComposerVersion('2.9.8');
});
@@ -585,13 +636,15 @@ describe('Tools tests', () => {
it.each([
[
'blackfire, blackfire-player, box, churn, cs2pr, flex, grpc_php_plugin, mago, name-collision-detector, parallel-lint, php-cs-fixer, php-scoper, phpDocumentor, phplint, phpstan, phpunit, pecl, phing, phinx, phinx:1.2.3, phive, phpunit-bridge, phpunit-polyfills, pint, php-config, phpize, protoc, symfony, vapor, wp, pie',
'blackfire, blackfire-player, box, churn, cloud-cli, cpx, cs2pr, flex, grpc_php_plugin, mago, name-collision-detector, parallel-lint, php-cs-fixer, php-scoper, phpDocumentor, phplint, phpstan, phpunit, pecl, phing, phinx, phinx:1.2.3, phive, phpunit-bridge, phpunit-polyfills, pint, php-config, phpize, protoc, symfony, vapor, wp, pie',
[
'add_tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-stable.phar,https://artifacts.setup-php.com/composer/composer-7.4-stable.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-stable.phar,https://getcomposer.org/composer-stable.phar composer',
'add_blackfire',
'add_tool https://get.blackfire.io/blackfire-player-v1.22.0.phar blackfire-player "-V"',
'add_tool https://github.com/box-project/box/releases/latest/download/box.phar box "--version"',
'add_tool https://github.com/bmitch/churn-php/releases/latest/download/churn.phar churn "-V"',
'add_composer_tool cloud-cli cloud-cli laravel/ scoped',
'add_tool https://github.com/laravel/cpx/releases/latest/download/cpx cpx "--version"',
'add_tool https://github.com/staabm/annotate-pull-request-from-checkstyle/releases/latest/download/cs2pr cs2pr "-V"',
'add_composer_tool flex flex symfony/ global',
'add_grpc_php_plugin latest',
@@ -630,7 +683,7 @@ describe('Tools tests', () => {
it.each([
[
'backward-compatibility-check, behat, blackfire, blackfire-player, churn, composer-dependency-analyser, composer-normalize, composer-require-checker, composer-unused, cs2pr:1.2.3, ecs, flex, grpc_php_plugin:1.2.3, infection, mago:0.26.1, name-collision-detector, phan, phan:1.2.3, phing:1.2.3, phinx, phive:1.2.3, php-config, phpcbf, phpcpd, phpcs, phpdoc, phpize, phpmd, phpspec, phpunit-bridge:5.6, phpunit-polyfills:1.0.1, protoc:v1.2.3, psalm, rector, symfony-cli, vapor-cli, wp-cli, pie',
'backward-compatibility-check, behat, blackfire, blackfire-player, churn, composer-dependency-analyser, composer-normalize, composer-require-checker, composer-unused, cpx:2.0.0, cs2pr:1.2.3, ecs, flex, grpc_php_plugin:1.2.3, infection, laravel-cloud, mago:0.26.1, name-collision-detector, phan, phan:1.2.3, phing:1.2.3, phinx, phive:1.2.3, php-config, phpcbf, phpcpd, phpcs, phpdoc, phpize, phpmd, phpspec, phpunit-bridge:5.6, phpunit-polyfills:1.0.1, protoc:v1.2.3, psalm, rector, symfony-cli, vapor-cli, wp-cli, pie',
[
'add_tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-stable.phar,https://artifacts.setup-php.com/composer/composer-7.4-stable.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-stable.phar,https://getcomposer.org/composer-stable.phar composer',
'add_composer_tool behat behat behat/ scoped',
@@ -641,10 +694,12 @@ describe('Tools tests', () => {
'add_composer_tool composer-dependency-analyser composer-dependency-analyser shipmonk/ scoped',
'add_composer_tool composer-require-checker composer-require-checker maglnet/ scoped',
'add_tool https://github.com/composer-unused/composer-unused/releases/latest/download/composer-unused.phar composer-unused "-V"',
'add_tool https://github.com/laravel/cpx/releases/download/v2.0.0/cpx cpx "--version"',
'add_tool https://github.com/staabm/annotate-pull-request-from-checkstyle/releases/download/1.2.3/cs2pr cs2pr "-V"',
'add_composer_tool flex flex symfony/ global',
'add_grpc_php_plugin 1.2.3',
'add_tool https://github.com/infection/infection/releases/latest/download/infection.phar infection "-V"',
'add_composer_tool cloud-cli cloud-cli laravel/ scoped',
'add_mago 0.26.1',
'add_composer_tool name-collision-detector name-collision-detector shipmonk/ scoped',
'add_tool https://github.com/phan/phan/releases/latest/download/phan.phar phan "-v"',
@@ -774,6 +829,102 @@ describe('Tools tests', () => {
expect(await tools.addTools(tools_csv, '7.4', 'linux')).toContain(script);
});
it.each`
tools_csv | os | script
${'phpunit:9.5.0@sha256:' + 'a'.repeat(64)} | ${'linux'} | ${'add_tool https://phar.phpunit.de/phpunit-9.5.0.phar,https://phar.phpunit.de/phpunit-9.phar phpunit "--version" sha256:' + 'a'.repeat(64)}
${'phpunit:9.5.0@sha256:' + 'a'.repeat(64)} | ${'win32'} | ${'Add-Tool https://phar.phpunit.de/phpunit-9.5.0.phar,https://phar.phpunit.de/phpunit-9.phar phpunit "--version" sha256:' + 'a'.repeat(64)}
${'composer:2.9.8@sha256:' + 'b'.repeat(64)} | ${'linux'} | ${'composer 2.9.8 sha256:' + 'b'.repeat(64)}
${'cs2pr:1.2.3@sha256:' + 'd'.repeat(64)} | ${'linux'} | ${'add_tool https://github.com/staabm/annotate-pull-request-from-checkstyle/releases/download/1.2.3/cs2pr cs2pr "-V" sha256:' + 'd'.repeat(64)}
${'phive:0.15.3@sha512:' + 'c'.repeat(128)} | ${'darwin'} | ${'add_tool https://github.com/phar-io/phive/releases/download/0.15.3/phive-0.15.3.phar phive "status" sha512:' + 'c'.repeat(128)}
${'phinx:1.2.3@sha256:' + 'a'.repeat(64)} | ${'linux'} | ${'add_log "$cross" "phinx" "Checksum verification is not supported for phinx"'}
${'pecl:1.2.3@sha256:' + 'a'.repeat(64)} | ${'linux'} | ${'add_log "$cross" "pecl" "Checksum verification is not supported for pecl"'}
${'phpunit:9.5.0@sha256:invalid'} | ${'linux'} | ${'add_log "$cross" "phpunit" "Invalid sha256 checksum, expected 64 hexadecimal characters"'}
${'composer:2.9.8@SHA256:' + 'b'.repeat(64)} | ${'linux'} | ${'composer 2.9.8 sha256:' + 'b'.repeat(64)}
${'composer:2.9.8@sha384:' + 'b'.repeat(96)} | ${'linux'} | ${'add_log "$cross" "composer" "Unsupported checksum algorithm sha384, expected sha256 or sha512"'}
${'composer:2.9.8@md5:' + 'b'.repeat(32)} | ${'linux'} | ${'add_log "$cross" "composer" "Unsupported checksum algorithm md5, expected sha256 or sha512"'}
${'composer:2.9.8@sha256' + 'b'.repeat(64)} | ${'linux'} | ${'add_log "$cross" "composer" "Invalid checksum syntax, expected @sha256:<hash> or @sha512:<hash>"'}
`(
'checking addTools with checksum: $tools_csv, $os',
async ({tools_csv, os, script}) => {
expect(await tools.addTools(tools_csv, '7.4', os)).toContain(script);
}
);
describe.each(['linux', 'darwin', 'win32'])(
'Checksum version requirements on %s',
os => {
it.each(['2.9.8+build.1', '2.9.8-rc.1', '2.9.8-rc.1+build.2'])(
'preserves the exact Composer version and checksum for %s',
async version => {
const checksum = 'sha256:' + 'a'.repeat(64);
const release = `composer:${version}@${checksum}`;
expect(await tools.filterList([release])).toEqual([release]);
const script = await tools.addTools(release, '8.4', os);
expect(script).toContain(
`https://github.com/composer/composer/releases/download/${version}/composer.phar`
);
expect(script).toContain(
`https://getcomposer.org/download/${version}/composer.phar`
);
expect(script).toContain(`composer ${version} ${checksum}`);
expect(script).not.toContain('latest');
expect(script).not.toContain('composer-stable.phar');
}
);
it.each([
'',
':latest',
':stable',
':preview',
':snapshot',
':2',
':2.x',
':2.9',
':2.9.x',
':^2.9.8'
])(
'rejects a checksum on a non-full version %s without an unpinned install',
async version => {
for (const tool of ['composer', 'phpunit']) {
const release = `${tool}${version}@sha256:${'a'.repeat(64)}`;
const data = await tools.getData(release, '8.4', os);
expect(data.error).toBe(
'Checksum pinning requires a full version, for example tool:1.2.3'
);
expect(data.url).toBe('');
const script = await tools.addTools(release, '8.4', os);
expect(script).toContain(data.error);
const installations = script
.split('\n')
.filter(line => /^add[-_]tool /i.test(line));
expect(
installations.some(line => new RegExp(` ${tool}( |$)`).test(line))
).toBe(false);
}
}
);
}
);
it.each`
type | tool_function | supported
${'phar'} | ${undefined} | ${true}
${'custom-function'} | ${undefined} | ${true}
${'custom-function'} | ${'composer'} | ${true}
${'custom-function'} | ${'pecl'} | ${false}
${'custom-function'} | ${'dev_tools'} | ${false}
${'composer'} | ${undefined} | ${false}
${'custom-package'} | ${undefined} | ${false}
`(
'checking supportsChecksum: $type, $tool_function',
async ({type, tool_function, supported}) => {
const data = getData({tool: 'tool', type: type});
data.function = tool_function;
expect(await tools.supportsChecksum(data)).toBe(supported);
}
);
it.each`
tools_csv | token | script
${'cs2pr:1.2'} | ${'invalid_token'} | ${'add_log "$cross" "cs2pr" "Invalid token"'}
@@ -814,7 +965,7 @@ describe('Tools tests', () => {
);
}
}));
const isolatedTools = await import('../src/tools');
const isolatedTools = jest.requireActual<typeof tools>('../src/tools');
result = await isolatedTools.addTools('broken-tool', '7.4', 'linux');
});
+444
View File
@@ -1,4 +1,6 @@
import fs from 'fs';
import os from 'os';
import {spawnSync} from 'child_process';
import * as path from 'path';
import * as utils from '../src/utils';
import * as fetchModule from '../src/fetch';
@@ -395,3 +397,445 @@ describe('Utils tests', () => {
expect(script).toEqual('\n$var = command\n');
});
});
const hasPwsh =
spawnSync('pwsh', ['-NoProfile', '-Command', 'exit 0']).status === 0;
const scripts = path.join(__dirname, '../src/scripts');
const unixInit = fs.readFileSync(path.join(scripts, 'unix.sh'), 'utf8');
const windowsSource = fs.readFileSync(path.join(scripts, 'win32.ps1'), 'utf8');
const windowsInit = [
windowsSource.match(/Function Invoke-WithoutTrace[\s\S]*?\n}/)![0],
windowsSource.match(
/\$setup_php_trace = 0\r?\nif \(\$env:SETUP_PHP_TRACE[\s\S]*?\n}/
)![0]
].join('\n');
describe.each(['linux', 'darwin', 'win32'])(
'Verbose scripts on %s',
platform => {
let root: string;
let run: string;
let helper: string;
const env = {...process.env};
beforeEach(() => {
jest.restoreAllMocks();
root = fs.mkdtempSync(path.join(os.tmpdir(), 'setup-php-verbose-'));
const scripts = path.join(root, 'src', 'scripts');
const extension = platform === 'win32' ? '.ps1' : '.sh';
fs.mkdirSync(path.join(scripts, 'tools'), {recursive: true});
const init = path.join(scripts, 'init' + extension);
fs.writeFileSync(
init,
platform === 'win32'
? windowsInit
: unixInit + '\nrunner=self-hosted read_env\n'
);
helper = path.join(scripts, 'tools', 'helper' + extension);
run = path.join(scripts, 'run' + extension);
fs.writeFileSync(helper, 'echo helper-output\n');
fs.writeFileSync(
run,
`. '${init}'\n. '${helper}' ${platform === 'win32' ? '>$null' : '>/dev/null'} 2>&1\n`
);
delete process.env.verbose;
delete process.env.VERBOSE;
delete process.env.RUNNER_DEBUG;
});
afterEach(() => {
process.env = {...env};
fs.rmSync(root, {recursive: true, force: true});
});
it.each([undefined, '', 'false', 'true', 'v', 'vv', 'vvv', 'invalid'])(
'prepares scripts for verbose=%s',
async verbose => {
if (verbose !== undefined) process.env.verbose = verbose;
const original = fs.readFileSync(run, 'utf8');
const enabled = /^(true|v{1,3})$/.test(verbose || '');
const tracing = /^v{2,3}$/.test(verbose || '');
const prepared = await utils.addVerbose(run, platform);
const script = fs.readFileSync(prepared, 'utf8');
expect(prepared !== run).toBe(enabled);
expect(
script.includes(platform === 'win32' ? '>$null' : '>/dev/null')
).toBe(!enabled);
expect(script.includes('src-verbose')).toBe(enabled);
expect(script.startsWith('. ')).toBe(true);
expect(process.env.SETUP_PHP_TRACE).toBe(
tracing ? String(verbose!.length - 1) : '0'
);
expect(fs.readFileSync(run, 'utf8')).toBe(original);
if (platform === 'win32' ? hasPwsh : process.platform !== 'win32') {
const result = spawnSync(
platform === 'win32' ? 'pwsh' : 'bash',
platform === 'win32'
? ['-NoProfile', '-File', prepared]
: [prepared],
{encoding: 'utf8', env: process.env}
);
expect(result.status).toBe(0);
expect(/helper-output\r?\n/.test(result.stdout)).toBe(enabled);
expect(
platform === 'win32'
? result.stdout.includes('DEBUG:')
: result.stderr.includes('+ ')
).toBe(tracing);
}
}
);
it.each(['', ' ', '\t'])(
'handles pipe spacing %j and subsequent quiet runs',
async space => {
const target = platform === 'win32' ? '$null' : '/dev/null';
const pipe = `>${space}${target} 2>&1`;
const probe =
platform === 'win32'
? 'echo probe 2>$null'
: 'command -v sh >/dev/null';
fs.writeFileSync(helper, `echo nested-output ${pipe}\n${probe}\n`);
process.env.VERBOSE = 'true';
const prepared = await utils.addVerbose(run, platform);
expect(
fs.readFileSync(
path.join(path.dirname(prepared), 'tools', path.basename(helper)),
'utf8'
)
).toBe(
`echo nested-output ${platform === 'win32' ? '2>&1 | Out-Host' : ''}\n${probe}\n`
);
expect(fs.readFileSync(helper, 'utf8')).toContain(pipe);
const shell = platform === 'win32' ? 'pwsh' : 'bash';
if (platform === 'win32' ? hasPwsh : process.platform !== 'win32') {
const result = spawnSync(
shell,
platform === 'win32'
? ['-NoProfile', '-File', prepared]
: [prepared],
{encoding: 'utf8', env: process.env}
);
expect(result.status).toBe(0);
expect(result.stdout).toMatch(/nested-output\r?\n/);
}
process.env.verbose = 'false';
expect(await utils.addVerbose(run, platform)).toBe(run);
expect(process.env.SETUP_PHP_TRACE).toBe('0');
expect(fs.readFileSync(helper, 'utf8')).toContain(pipe);
}
);
it.each([undefined, 'false', 'true', 'v', 'vv', 'vvv'])(
'enables output for runner debug with verbose=%s',
async verbose => {
process.env.RUNNER_DEBUG = '1';
if (verbose !== undefined) process.env.verbose = verbose;
const prepared = await utils.addVerbose(run, platform);
expect(prepared).not.toBe(run);
expect(fs.readFileSync(prepared, 'utf8')).not.toMatch(
/>\s*(?:\/dev\/null|\$null)\s+2>&1/
);
expect(process.env.SETUP_PHP_TRACE).toBe(
/^v{2,3}$/.test(verbose || '') ? String(verbose!.length - 1) : '0'
);
}
);
it.each(['true', 'vv', 'vvv'])(
'protects nested sensitive calls and restores tracing for verbose=%s',
async verbose => {
const windows = platform === 'win32';
if (windows ? !hasPwsh : process.platform === 'win32') return;
process.env.verbose = verbose;
process.env.GITHUB_TOKEN = 'example-github-token';
process.env.TRACE_TEST_OUTPUT = path.join(root, 'tokens');
fs.writeFileSync(
helper,
windows
? `$result = 0
try {
Invoke-WithoutTrace {
Invoke-WithoutTrace {
$token = $env:GITHUB_TOKEN
Set-Content $env:TRACE_TEST_OUTPUT $token
}
$token = $env:GITHUB_TOKEN
Add-Content $env:TRACE_TEST_OUTPUT $token
if ($env:TRACE_TEST_STATUS -ne '0') { throw 'example-failure' }
}
} catch {
if ($_.Exception.Message -ne 'example-failure') { throw }
$result = [int]$env:TRACE_TEST_STATUS
}
$after_wrapper = 'after-wrapper'
Write-Output $after_wrapper
Write-Output "status=$result"
`
: `inner_sensitive() {
token="$GITHUB_TOKEN"
printf '%s\\n' "$token" > "$TRACE_TEST_OUTPUT"
return "$TRACE_TEST_STATUS"
}
outer_sensitive() {
without_trace inner_sensitive
local result=$?
token="$GITHUB_TOKEN"
printf '%s\\n' "$token" >> "$TRACE_TEST_OUTPUT"
return "$result"
}
without_trace outer_sensitive
result=$?
echo "\${token:+state-preserved}"
echo after-wrapper
exit "$result"
`
);
const prepared = await utils.addVerbose(run, platform);
for (const status of [0, 37]) {
const result = spawnSync(
windows ? 'pwsh' : 'bash',
windows ? ['-NoProfile', '-File', prepared] : [prepared],
{
encoding: 'utf8',
env: {...process.env, TRACE_TEST_STATUS: String(status)}
}
);
expect(result.status).toBe(windows ? 0 : status);
expect(result.stdout + result.stderr).not.toContain(
'example-github-token'
);
expect(result.stdout).toContain('after-wrapper');
expect(
windows
? /DEBUG:.*Write-Output \$after_wrapper/.test(result.stdout)
: result.stderr.includes('+ echo after-wrapper')
).toBe(verbose !== 'true');
if (windows) {
expect(result.stdout).toContain('status=' + status);
expect(/DEBUG:\s+!\s+SET \$after_wrapper/.test(result.stdout)).toBe(
verbose === 'vvv'
);
} else {
expect(result.stdout).toContain('state-preserved');
}
expect(
fs
.readFileSync(process.env.TRACE_TEST_OUTPUT!, 'utf8')
.trim()
.split(/\r?\n/)
).toEqual(['example-github-token', 'example-github-token']);
}
}
);
it.each(['true', 'vv', 'vvv'])(
'keeps Blackfire credentials out of traces for verbose=%s',
async verbose => {
const windows = platform === 'win32';
if (windows ? !hasPwsh : process.platform === 'win32') return;
process.env.verbose = verbose;
process.env.TRACE_TEST_OUTPUT = path.join(root, 'blackfire-config');
process.env.BLACKFIRE_SERVER_ID = 'example-blackfire-server-id';
process.env.BLACKFIRE_SERVER_TOKEN = 'example-blackfire-server-token';
process.env.BLACKFIRE_CLIENT_ID = 'example-blackfire-client-id';
process.env.BLACKFIRE_CLIENT_TOKEN = 'example-blackfire-client-token';
fs.writeFileSync(
helper,
fs.readFileSync(
path.join(
scripts,
'tools',
'blackfire' + (windows ? '.ps1' : '.sh')
),
'utf8'
) +
(windows
? `
function Invoke-RestMethod { @{cli='1.2.3'} }
function Get-File {}
function Expand-Archive {}
function Add-ToProfile {}
function Add-Log {}
function blackfire { Add-Content $env:TRACE_TEST_OUTPUT ($args -join ' ') }
$version = '8.4'
$bin_dir = 'unused'
Add-Blackfire
Write-Output after-blackfire
`
: `
blackfire() { printf '%s\\n' "$@" >> "$TRACE_TEST_OUTPUT"; }
os=Test
blackfire_config
echo after-blackfire
`)
);
const prepared = await utils.addVerbose(run, platform);
const result = spawnSync(
windows ? 'pwsh' : 'bash',
windows ? ['-NoProfile', '-File', prepared] : [prepared],
{encoding: 'utf8', env: process.env}
);
expect(result.status).toBe(0);
expect(result.stdout + result.stderr).not.toContain(
'example-blackfire-'
);
expect(result.stdout).toContain('after-blackfire');
expect(
windows
? /DEBUG:.*Write-Output after-blackfire/.test(result.stdout)
: result.stderr.includes('+ echo after-blackfire')
).toBe(verbose !== 'true');
const config = fs.readFileSync(process.env.TRACE_TEST_OUTPUT!, 'utf8');
for (const value of [
'server-id',
'server-token',
'client-id',
'client-token'
]) {
expect(config).toContain('example-blackfire-' + value);
}
}
);
it('keeps Composer credentials out of traces and resumes tracing', async () => {
if (platform === 'win32' ? !hasPwsh : process.platform === 'win32')
return;
process.env.verbose = 'vvv';
process.env.GITHUB_TOKEN = 'example-github-token';
process.env.COMPOSER_TOKEN = 'example-composer-token';
process.env.PACKAGIST_TOKEN = 'example-packagist-token';
process.env.COMPOSER_AUTH_JSON =
'{"bearer":{"example.org":"example-json-token"}}';
process.env.GITHUB_SERVER_URL = 'https://github.com';
const windows = platform === 'win32';
const source = fs.readFileSync(
path.join(scripts, 'tools', 'add_tools' + (windows ? '.ps1' : '.sh')),
'utf8'
);
fs.writeFileSync(
helper,
source +
(windows
? `\n$composer_home='${root}'\nSet-ComposerAuth\nWrite-Output after-auth\n`
: `\ncomposer_home='${root}'\nset_composer_auth\necho after-auth\n`)
);
const prepared = await utils.addVerbose(run, platform);
const result = spawnSync(
windows ? 'pwsh' : 'bash',
windows ? ['-NoProfile', '-File', prepared] : [prepared],
{encoding: 'utf8', env: process.env}
);
expect(result.status).toBe(0);
expect(result.stdout + result.stderr).not.toMatch(
/example-(github|composer|packagist|json)-token/
);
expect(windows ? result.stdout : result.stderr).toMatch(
windows ? /DEBUG:.*Write-Output after-auth/ : /\+ echo after-auth/
);
const auth = JSON.parse(
fs.readFileSync(path.join(root, 'auth.json'), 'utf8')
);
expect(auth['github-oauth']['github.com']).toBe('example-composer-token');
expect(auth['http-basic']['repo.packagist.com'].password).toBe(
'example-packagist-token'
);
expect(auth.bearer['example.org']).toBe('example-json-token');
});
if (platform !== 'win32') {
(process.platform === 'win32' ? it.skip : it).each([
['exit 37', 37],
['set -e\nfalse', 1]
])('preserves shell termination for %s', async (failure, status) => {
process.env.verbose = 'vvv';
process.env.GITHUB_TOKEN = 'example-github-token';
fs.writeFileSync(
helper,
`
sensitive_failure() {
token="$GITHUB_TOKEN"
${failure}
echo should-not-run
}
trap 'echo cleanup' EXIT
without_trace sensitive_failure
echo should-not-run
`
);
const prepared = await utils.addVerbose(run, platform);
const result = spawnSync('bash', [prepared], {
encoding: 'utf8',
env: process.env
});
expect(result.status).toBe(status);
expect(result.stdout).toBe('cleanup\n');
expect(result.stdout + result.stderr).not.toContain(
'example-github-token'
);
});
(process.platform === 'win32' ? it.skip : it).each(['true', 'vv', 'vvv'])(
'protects Relay credentials and preserves tracing and status for verbose=%s',
async verbose => {
process.env.verbose = verbose;
const ini = path.join(root, 'relay.ini');
fs.writeFileSync(
helper,
fs.readFileSync(path.join(scripts, 'extensions/relay.sh'), 'utf8') +
'\nsudo() { if [ "$1" = rm ]; then return "$RELAY_TEST_STATUS"; fi; "$@"; }\n' +
`init_relay_ini '${ini}'\nrelay_status=$?\necho after-relay\nexit "$relay_status"\n`
);
const prepared = await utils.addVerbose(run, platform);
for (const status of [0, 37]) {
fs.writeFileSync(ini, '; relay.key =\n');
const result = spawnSync('bash', [prepared], {
encoding: 'utf8',
env: {
...process.env,
RELAY_KEY: 'example-relay-key',
RELAY_TEST_STATUS: String(status)
}
});
expect(result.status).toBe(status);
expect(result.stdout + result.stderr).not.toContain(
'example-relay-key'
);
expect(result.stdout).toContain('after-relay');
expect(result.stderr.includes('+ echo after-relay')).toBe(
verbose !== 'true'
);
expect(fs.readFileSync(ini, 'utf8')).toBe(
'relay.key = example-relay-key\n'
);
}
}
);
}
(process.platform === 'win32' ? it.skip : it)(
'uses fresh copies without writing through source symlinks',
async () => {
const outside = path.join(root, path.basename(helper));
const original = 'echo original >/dev/null 2>&1\n';
fs.writeFileSync(outside, original);
fs.unlinkSync(helper);
fs.symlinkSync(outside, helper);
process.env.verbose = 'true';
const first = await utils.addVerbose(run, platform);
const second = await utils.addVerbose(run, platform);
expect(first).not.toBe(second);
expect(fs.readFileSync(outside, 'utf8')).toBe(original);
expect(fs.readFileSync(helper, 'utf8')).toBe(original);
expect(
fs.readFileSync(
path.join(path.dirname(first), 'tools', path.basename(helper)),
'utf8'
)
).toBe(
`echo original ${platform === 'win32' ? '2>&1 | Out-Host' : ''}\n`
);
}
);
}
);
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -5,7 +5,7 @@ module.exports = {
testMatch: ['**/*.test.ts'],
testRunner: 'jest-circus/runner',
transform: {
'^.+\\.ts$': 'ts-jest'
'^.+\\.ts$': ['ts-jest', {tsconfig: 'tsconfig.test.json'}]
},
verbose: true,
collectCoverage: true
+1510 -822
View File
File diff suppressed because it is too large Load Diff
+24 -15
View File
@@ -20,6 +20,7 @@
"format": "prettier --write **/src/*.ts **/__tests__/*.ts && git add -f __tests__/ ",
"format-check": "prettier --check **/src/*.ts **/__tests__/*.ts",
"release": "ncc build -m -o dist && git add -f dist/",
"typecheck": "tsc --project tsconfig.test.json --noEmit",
"test": "jest"
},
"repository": {
@@ -41,26 +42,29 @@
"@eslint/compat": "^2.1.0",
"@eslint/js": "^10.0.1",
"@types/jest": "^30.0.0",
"@types/node": "^25.9.2",
"@typescript-eslint/eslint-plugin": "^8.60.1",
"@typescript-eslint/parser": "^8.60.1",
"@vercel/ncc": "^0.38.4",
"eslint": "^10.4.1",
"@types/node": "^26.4.1",
"@typescript-eslint/eslint-plugin": "^8.69.0",
"@typescript-eslint/parser": "^8.69.0",
"@typescript/native": "npm:typescript@^7.0.2",
"@vercel/ncc": "^0.45.0",
"eslint": "^10.9.1",
"eslint-config-prettier": "^10.1.8",
"eslint-import-resolver-typescript": "^4.4.5",
"eslint-plugin-import-x": "^4.16.2",
"eslint-plugin-jest": "^29.15.2",
"eslint-plugin-import-x": "^4.17.1",
"eslint-plugin-jest": "^29.16.6",
"eslint-plugin-prettier": "^5.5.6",
"globals": "^17.6.0",
"jest": "^30.4.2",
"jest-circus": "^30.4.2",
"nock": "^14.0.15",
"prettier": "^3.8.3",
"simple-git-hooks": "^2.13.1",
"ts-jest": "^29.4.11",
"typescript": "^5.9.3"
"globals": "^17.12.0",
"jest": "^30.5.1",
"jest-circus": "^30.5.1",
"nock": "^14.0.17",
"prettier": "^3.9.6",
"simple-git-hooks": "^2.14.0",
"ts-jest": "^29.4.12",
"typescript": "npm:@typescript/typescript6@^6.0.2"
},
"overrides": {
"@babel/core": "^7.29.7",
"js-yaml": "^4.2.0",
"test-exclude": "^7.0.1",
"glob": "^13.0.6",
"minimatch": "^10.2.1"
@@ -70,5 +74,10 @@
},
"simple-git-hooks": {
"pre-commit": "npm run format && npm run lint && npm run test && npm run build && npm run release"
},
"allowScripts": {
"fsevents@2.3.3": true,
"simple-git-hooks@2.13.1": true,
"unrs-resolver@1.11.1": true
}
}
+1
View File
@@ -7,6 +7,7 @@ gmagick=graphicsmagick-libmagick-dev-compat
gnupg=libgpgme-dev
grpc=libgrpc-dev libprotobuf-dev protobuf-compiler
imagick=libmagickwand-dev libmagickcore-dev
krb5=libkrb5-dev
memcached=libmemcached-dev libevent-dev
protobuf=libprotobuf-dev protobuf-compiler
rdkafka=librdkafka-dev
+14
View File
@@ -42,6 +42,14 @@
"version_prefix": "",
"version_parameter": "diagnose"
},
"cpx": {
"type": "phar",
"repository": "laravel/cpx",
"extension": "",
"domain": "https://github.com",
"version_prefix": "v",
"version_parameter": "--version"
},
"cs2pr": {
"type": "phar",
"repository": "staabm/annotate-pull-request-from-checkstyle",
@@ -234,6 +242,12 @@
"repository": "laravel/vapor-cli",
"scope": "scoped"
},
"cloud-cli": {
"type": "composer",
"alias": "laravel-cloud",
"repository": "laravel/cloud-cli",
"scope": "scoped"
},
"rector": {
"type": "composer",
"repository": "rector/rector",
+11 -2
View File
@@ -84,12 +84,21 @@ export async function addExtensionDarwin(
case /(5\.[3-6]|7\.0)pcov/.test(version_extension):
add_script += await utils.getUnsupportedLog('pcov', version, 'darwin');
return;
// match 7.2xdebug2 to 7.4xdebug2
case /^7\.[2-4]xdebug2$/.test(version_extension):
add_script += await utils.joins(
'\nadd_brew_extension',
'xdebug2',
ext_prefix,
'2.9.8'
);
return;
// match brew extensions
case /(?<!5\.[3-5])(amqp|apcu|brotli|excimer|expect|gmagick|gnupg|grpc|igbinary|imagick|imap|interbase|mailparse|maxminddb|mcrypt|memcache|memcached|mongodb|mongodb1|msgpack|newrelic|oauth|opentelemetry|pdo_firebird|pinba|protobuf|psr|raphf|rdkafka|redis|scalar_objects|seaslog|snmp|spx|ssh2|swoole|uopz|uploadprogress|uuid|vld|xdebug|xdebug2|xhprof|yaml|zmq|zstd)/.test(
case /(?<!5\.[3-5])(amqp|apcu|brotli|excimer|expect|gmagick|gnupg|grpc|igbinary|imagick|imap|interbase|lua|mailparse|maxminddb|mcrypt|memcache|memcached|mongodb|mongodb1|msgpack|newrelic|oauth|opentelemetry|pdo_firebird|pinba|protobuf|psr|raphf|rdkafka|redis|scalar_objects|seaslog|snmp|spx|ssh2|swoole|uopz|uploadprogress|uuid|vld|xdebug|xdebug2|xhprof|yaml|zmq|zstd)/.test(
version_extension
):
case /(?<!5\.[3-6])(ds|v8js)/.test(version_extension):
case /(5\.6|7\.[0-4])(propro|lua)/.test(version_extension):
case /(5\.6|7\.[0-4])(propro)/.test(version_extension):
case /(?<!5\.[3-6]|7\.0)pcov/.test(version_extension):
case /(?<!5\.[3-6])(ast|vips|xlswriter)/.test(version_extension):
case /^(8\.[0-5])swow$/.test(version_extension):
+1 -1
View File
@@ -47,7 +47,7 @@ export async function getScript(os: string): Promise<string> {
fs.writeFileSync(run_path, script, {mode: 0o755});
return run_path;
return await utils.addVerbose(run_path, os);
}
/**
+38 -9
View File
@@ -75,9 +75,10 @@ copy_brew_extensions() {
add_brew_extension() {
formula=$1
prefix=$2
expected_version=${3:-}
extension="$(get_extension_from_formula "$formula")"
enable_extension "$extension" "$prefix"
if check_extension "$extension"; then
if check_extension "$extension" && { [ -z "$expected_version" ] || check_extension_version "$extension" "$expected_version"; }; then
add_log "${tick:?}" "$extension" "Enabled"
else
add_brew_tap "$php_tap"
@@ -89,7 +90,13 @@ add_brew_extension() {
safe_brew install --skip-link "${brew_opts[@]}" "$ext_tap/$formula@$version" >/dev/null 2>&1 &&
brew link --overwrite --force "$formula@$version" >/dev/null 2>&1 &&
copy_brew_extensions "$formula"
) || pecl_install "$extension" >/dev/null 2>&1
) || {
if [ -n "$expected_version" ]; then
pecl_install "$extension-$expected_version" || pecl_install "$extension"
else
pecl_install "$extension"
fi
} >/dev/null 2>&1
add_extension_log "$extension" "Installed and enabled"
fi
}
@@ -174,27 +181,43 @@ get_brewed_php() {
fi
}
# Function to setup PHP from the cached builds.
setup_cached_versions() {
latest="releases/download/php-$version" run_script \
"php-darwin" "$version" "${debug:?}" "${ts:?}" >/dev/null 2>&1
}
# Function to setup PHP 5.6 and newer using Homebrew.
add_php() {
local exit_code
action=$1
existing_version=$2
suffix="$(get_php_formula_suffix)"
php_keg="php@$version$suffix"
php_formula="shivammathur/php/$php_keg"
if [[ "$existing_version" = "false" || -n "$suffix" || "$action" = "upgrade" ]]; then
if [ "${runner:?}" != "self-hosted" ] && [ "${use_package_cache:-true}" != "false" ]; then
setup_cached_versions && return 0
[ "$(uname -m)" != "x86_64" ] || return 1
fi
update_dependencies
add_brew_tap "$php_tap"
fi
if [[ "$existing_version" != "false" && -z "$suffix" ]]; then
if [ "$action" = "upgrade" ]; then
safe_brew install --only-dependencies "$php_formula"
safe_brew upgrade -f --overwrite "$php_formula"
safe_brew install --only-dependencies "$php_formula" || return $?
safe_brew upgrade -f --overwrite "$php_formula" || return $?
else
brew unlink "$php_keg"
fi
else
safe_brew install --only-dependencies "$php_formula"
safe_brew install --skip-link -f --overwrite "$php_formula" 2>/dev/null || safe_brew upgrade -f --overwrite "$php_formula"
safe_brew install --only-dependencies "$php_formula" || return $?
safe_brew install --skip-link -f --overwrite "$php_formula" 2>/dev/null || {
exit_code=$?
# A timeout has exhausted its retries; do not start another build via upgrade.
[ "$exit_code" -ne 124 ] || return "$exit_code"
safe_brew upgrade -f --overwrite "$php_formula" || return $?
}
fi
brew link --force --overwrite "$php_keg" || (sudo chown -R "$(id -un)":"$(id -gn)" "$brew_prefix" && brew link --force --overwrite "$php_keg")
}
@@ -252,13 +275,19 @@ setup_php() {
if [[ "$version" =~ ${old_versions:?} ]]; then
run_script "php5-darwin" "${version/./}" >/dev/null 2>&1
status="Installed"
elif [ "${existing_version:0:3}" != "$version" ]; then
add_php "install" "$existing_version" >/dev/null 2>&1
elif [[ "${existing_version:0:3}" != "$version" || -n "$(get_php_formula_suffix)" ]]; then
add_php "install" "$existing_version" >/dev/null 2>&1 || {
add_log "${cross:?}" "PHP" "Could not install PHP $version"
exit 1
}
status="Installed"
elif [[ "${existing_version:0:3}" = "$version" && "${update:?}" = "true" ]]; then
brew_php_version="$(brew info --json "php@$version" 2>/dev/null | jq -r '.[].versions.stable')"
if [ "$brew_php_version" != "$existing_version" ]; then
add_php "upgrade" "$existing_version" >/dev/null 2>&1
add_php "upgrade" "$existing_version" >/dev/null 2>&1 || {
add_log "${cross:?}" "PHP" "Could not upgrade PHP $version"
exit 1
}
status="Upgraded"
fi
fi
+30 -3
View File
@@ -104,11 +104,29 @@ Function Add-Extension {
[string]
$extension_version = ''
)
$extension_backup = ''
try {
$extension_info = Get-PhpExtension -Path $php_dir | Where-Object { $_.Name -eq $extension -or $_.Handle -eq $extension }
$deps_dir = "$ext_dir\$extension-vc$($installed.VCVersion)-$arch"
New-Item $deps_dir -Type Directory -Force > $null 2>&1
if ($null -ne $extension_info) {
if($extension_version -ne '' -and (Test-Path "$ext_dir\$extension-$extension_version")) {
Copy-Item "$ext_dir\$extension-$extension_version" "$ext_dir\php_$extension.dll" -Force
try {
Enable-ExtensionDependencies $extension
Enable-PhpExtension -Extension $extension -Path $php_dir
Set-ExtensionPrerequisites $extension
$cached_extension = Get-PhpExtension -Path $php_dir | Where-Object { ($_.Name -eq $extension -or $_.Handle -eq $extension) -and $_.State -eq 'Enabled' }
if($null -ne $cached_extension) {
Add-Log $tick $extension "Enabled"
return
}
} catch {
Write-Verbose "Could not enable cached ${extension}: $_"
}
# A cached DLL may target another PHP build; install it again if it did not load.
Remove-Item "$ext_dir\php_$extension.dll" -Force
}
$extension_info = Get-PhpExtension -Path $php_dir | Where-Object { $_.Name -eq $extension -or $_.Handle -eq $extension }
if ($null -ne $extension_info -and ($extension_version -eq '' -or $extension_info.Version -eq $extension_version)) {
switch ($extension_info.State) {
'Builtin' {
Add-Log $tick $extension "Enabled"
@@ -138,14 +156,23 @@ Function Add-Extension {
}
# If extension for a different version exists
if(Test-Path $ext_dir\php_$extension.dll) {
Move-Item $ext_dir\php_$extension.dll $ext_dir\php_$extension.bak.dll -Force
# Keep backups outside PhpManager's DLL scan and reuse known versions as cache entries.
$backup_name = if($extension_info.Version) { "$extension-$($extension_info.Version)" } else { "$extension.bak" }
Move-Item $ext_dir\php_$extension.dll "$ext_dir\$backup_name" -Force -ErrorAction Stop
$extension_backup = "$ext_dir\$backup_name"
}
Install-PhpExtension @params
Set-ExtensionPrerequisites $extension
}
Add-Log $tick $extension "Installed and enabled"
}
if($extension_version -ne '' -and (Test-Path "$ext_dir\php_$extension.dll")) {
Copy-Item "$ext_dir\php_$extension.dll" "$ext_dir\$extension-$extension_version" -Force
}
} catch {
if($extension_backup -ne '') {
Copy-Item $extension_backup "$ext_dir\php_$extension.dll" -Force
}
Add-Log $cross $extension "Could not install $extension on PHP $( $installed.FullVersion )"
}
}
+20 -3
View File
@@ -21,6 +21,13 @@ check_extension() {
fi
}
# Function to test the loaded version of an extension.
check_extension_version() {
local extension=$1
local ext_version=$2
php -d display_errors=0 -r "exit(phpversion(\$argv[1]) === \$argv[2] ? 0 : 1);" -- "$extension" "$ext_version" >/dev/null 2>&1
}
# Function to check if extension is shared
shared_extension() {
[ -e "${ext_dir:?}/$1.so" ]
@@ -198,7 +205,7 @@ pecl_install() {
yes '' 2>/dev/null | sudo "$prefix_opts" pecl install -f -D "$(parse_pecl_configure_options "$suffix_opts")" "$extension" >/dev/null 2>&1
fi
local exit_code=$?
sudo pecl info "$extension" | grep -iq 'zend extension' && prefix=zend_extension
sudo pecl info "$extension" 2>/dev/null | grep -iq 'zend extension' && prefix=zend_extension
enable_extension "${extension%-*}" "$prefix"
return "$exit_code"
fi
@@ -209,17 +216,27 @@ add_pecl_extension() {
local extension=$1
local pecl_version=$2
local prefix=$3
enable_extension "$extension" "$prefix"
if [[ $pecl_version =~ .*(alpha|beta|rc|snapshot|preview).* ]]; then
pecl_version=$(get_pecl_version "$extension" "$pecl_version")
fi
ext_version=$(php -r "echo phpversion('$extension');")
# Cache versioned extensions using suffixless copies in extension_dir.
if [ -n "$pecl_version" ] && [ -e "${ext_dir:?}/$extension-$pecl_version" ]; then
sudo cp "${ext_dir:?}/$extension-$pecl_version" "${ext_dir:?}/$extension.so"
sudo rm -f /tmp/php"${version:?}"_extensions
fi
enable_extension "$extension" "$prefix"
ext_version=$(php -d display_errors=0 -r "echo phpversion('$extension');" 2>/dev/null)
if check_extension "$extension" && [[ -z "$pecl_version" || (-n "$pecl_version" && "${ext_version/-/}" == "$pecl_version") ]]; then
[ -n "$pecl_version" ] && sudo cp "${ext_dir:?}/$extension.so" "${ext_dir:?}/$extension-$pecl_version" 2>/dev/null || true
add_log "${tick:?}" "$extension" "Enabled"
else
[ -n "$pecl_version" ] && sudo rm -f "${ext_dir:?}/$extension-$pecl_version"
[ -n "$pecl_version" ] && pecl_version="-$pecl_version"
pecl_install "$extension$pecl_version" || ( [ "${fail_fast:?}" = "false" ] && add_extension "$extension" "$(get_extension_prefix "$extension")" >/dev/null 2>&1)
extension_version="$(php -r "echo phpversion('$extension');")"
if [ -n "$pecl_version" ] && [ "${extension_version/-/}" = "${pecl_version#-}" ]; then
sudo cp "${ext_dir:?}/$extension.so" "${ext_dir:?}/$extension-$extension_version" 2>/dev/null || true
fi
[ -n "$extension_version" ] && extension_version="-$extension_version"
add_extension_log "$extension$extension_version" "Installed and enabled"
fi
+2 -2
View File
@@ -2,8 +2,8 @@ patch_geos() {
if [[ $(printf '%s\n%s\n' "${version:?}" "7.0" | sort -V | head -n1) == "7.0" ]]; then
sed -i~ -e "s/, ce->name/, ZSTR_VAL(ce->name)/; s/ulong /zend_ulong /" geos.c
fi
get -q -n /tmp/php8.patch https://git.remirepo.net/cgit/rpms/php/php-geos.git/plain/0003-add-all-arginfo-and-fix-build-with-PHP-8.patch
get -q -n /tmp/toString.patch https://git.remirepo.net/cgit/rpms/php/php-geos.git/plain/0006-fix-__toString-with-8.2.patch
get -q -n /tmp/php8.patch https://src.fedoraproject.org/rpms/php-geos/raw/2021845a362752948dd0338920f0a0e6b1031b4d/f/0003-add-all-arginfo-and-fix-build-with-PHP-8.patch
get -q -n /tmp/toString.patch https://src.fedoraproject.org/rpms/php-geos/raw/2021845a362752948dd0338920f0a0e6b1031b4d/f/0006-fix-__toString-with-8.2.patch
patch -p1 < /tmp/php8.patch 2>/dev/null || true
patch -p1 < /tmp/toString.patch 2>/dev/null || true
}
+4
View File
@@ -63,6 +63,10 @@ add_relay_dependencies() {
# Initialize relay extension ini configuration
init_relay_ini() {
without_trace init_relay_ini_helper "$@"
}
init_relay_ini_helper() {
relay_ini=$1
if [ -e "$relay_ini" ]; then
if [[ -n "$RELAY_KEY" ]]; then
+78 -30
View File
@@ -87,35 +87,37 @@ Function Write-ComposerGhAuthNoOpWarning() {
# Function to setup authentication in composer.
Function Set-ComposerAuth() {
$token = if ($env:COMPOSER_TOKEN) { $env:COMPOSER_TOKEN } else { $env:GITHUB_TOKEN }
if(Test-Path env:COMPOSER_AUTH_JSON) {
if(Test-Json -JSON $env:COMPOSER_AUTH_JSON) {
Set-Content -Path $composer_home\auth.json -Value $env:COMPOSER_AUTH_JSON
} else {
Add-Log "$cross" "composer" "Could not parse COMPOSER_AUTH_JSON as valid JSON"
Invoke-WithoutTrace {
$token = if ($env:COMPOSER_TOKEN) { $env:COMPOSER_TOKEN } else { $env:GITHUB_TOKEN }
if(Test-Path env:COMPOSER_AUTH_JSON) {
if(Test-Json -JSON $env:COMPOSER_AUTH_JSON) {
Set-Content -Path $composer_home\auth.json -Value $env:COMPOSER_AUTH_JSON
} else {
Add-Log "$cross" "composer" "Could not parse COMPOSER_AUTH_JSON as valid JSON"
}
}
}
if($skip_composer_github_auth) {
Write-ComposerGhAuthNoOpWarning
}
$composer_auth = @()
if(Test-Path env:PACKAGIST_TOKEN) {
$composer_auth += '"http-basic": {"repo.packagist.com": { "username": "token", "password": "' + $env:PACKAGIST_TOKEN + '"}}'
}
$write_token = $true
if ($token) {
if ($skip_composer_github_auth) {
$write_token = $false
if($skip_composer_github_auth) {
Write-ComposerGhAuthNoOpWarning
}
if ($env:GITHUB_SERVER_URL -ne "https://github.com" -and -not(Test-GitHubPublicAccess $token)) {
$write_token = $false
$composer_auth = @()
if(Test-Path env:PACKAGIST_TOKEN) {
$composer_auth += '"http-basic": {"repo.packagist.com": { "username": "token", "password": "' + $env:PACKAGIST_TOKEN + '"}}'
}
if($write_token) {
$composer_auth += '"github-oauth": {"github.com": "' + $token + '"}'
$write_token = $true
if ($token) {
if ($skip_composer_github_auth) {
$write_token = $false
}
if ($env:GITHUB_SERVER_URL -ne "https://github.com" -and -not(Test-GitHubPublicAccess $token)) {
$write_token = $false
}
if($write_token) {
$composer_auth += '"github-oauth": {"github.com": "' + $token + '"}'
}
}
if($composer_auth.length) {
Update-AuthJson $composer_auth
}
}
if($composer_auth.length) {
Update-AuthJson $composer_auth
}
}
@@ -144,6 +146,21 @@ Function Test-MutableToolUrl() {
return ($Url -match $mutableUrlRegex) -or (($Url -match '\.phar([?#].*)?$') -and -not ($Url -match $versionLikeRegex))
}
# Function to verify the checksum of a file.
Function Test-ToolChecksum() {
Param(
[Parameter(Position = 0, Mandatory = $true)]
[string]
$Path,
[Parameter(Position = 1, Mandatory = $true)]
[string]
$Checksum
)
$checksum_parts = $Checksum -split ':'
$actual_checksum = (Get-FileHash -Path $Path -Algorithm $checksum_parts[0]).Hash
return $actual_checksum -eq $checksum_parts[1]
}
# Function to extract tool version.
Function Get-ToolVersion() {
Param (
@@ -206,6 +223,9 @@ Function Add-ToolsHelper() {
$extensions += @('dom', 'json', 'libxml', 'mbstring', 'xml', 'xmlwriter')
} elseif($tool -eq "phpunit-bridge") {
$extensions += @('dom', 'pdo', 'tokenizer', 'xmlwriter')
} elseif($tool -eq "cloud-cli") {
$extensions += @('fileinfo', 'sockets')
Copy-Item $env:cloud_cli_bin\cloud.bat -Destination $env:cloud_cli_bin\cloud-cli.bat
} elseif($tool -eq "vapor-cli") {
$extensions += @('fileinfo', 'json', 'mbstring', 'zip', 'simplexml')
Copy-Item $env:vapor_cli_bin\vapor.bat -Destination $env:vapor_cli_bin\vapor-cli.bat
@@ -229,8 +249,18 @@ Function Add-Tool() {
[Parameter(Position = 2, Mandatory = $false)]
$ver_param,
[Parameter(Position = 3, Mandatory = $false)]
$skip_composer_github_auth
$skip_composer_github_auth,
[Parameter(Position = 4, Mandatory = $false)]
$checksum
)
$checksum_regex = '^sha(256|512):[0-9a-fA-F]+$'
if("$ver_param" -match $checksum_regex) {
$checksum = $ver_param
$ver_param = $null
} elseif("$skip_composer_github_auth" -match $checksum_regex) {
$checksum = $skip_composer_github_auth
$skip_composer_github_auth = $null
}
if($tool -eq "composer") {
$script:skip_composer_github_auth = $skip_composer_github_auth -eq 'true'
}
@@ -245,7 +275,12 @@ Function Add-Tool() {
$use_cache = -not (Test-MutableToolUrl $urls[0])
$status_code = 200
if ($use_cache -and (Test-Path $cache_path -PathType Leaf)) {
Copy-Item $cache_path -Destination $tool_path -Force
if($checksum -and -not(Test-ToolChecksum $cache_path $checksum)) {
Remove-Item $cache_path -Force -ErrorAction SilentlyContinue
$status_code = 'checksum_mismatch'
} else {
Copy-Item $cache_path -Destination $tool_path -Force
}
} else {
$backup_path = "$tool_path.bak"
if (Test-Path $tool_path) { Copy-Item $tool_path -Destination $backup_path -Force }
@@ -265,18 +300,31 @@ Function Add-Tool() {
}
}
if($status_code -eq 200 -and (Test-Path $tool_path)) {
if ($use_cache) {
Copy-Item $tool_path -Destination $cache_path -Force
}
break
}
}
if($status_code -eq 200 -and (Test-Path $tool_path)) {
if($checksum -and -not(Test-ToolChecksum $tool_path $checksum)) {
Remove-Item @($tool_path, $cache_path) -Force -ErrorAction SilentlyContinue
$status_code = 'checksum_mismatch'
} elseif($use_cache) {
Copy-Item $tool_path -Destination $cache_path -Force
}
}
if ($status_code -ne 200 -and (Test-Path $backup_path)) {
Copy-Item $backup_path -Destination $tool_path -Force
}
Remove-Item $backup_path -Force -ErrorAction SilentlyContinue
}
if($status_code -eq 'checksum_mismatch') {
if($tool -eq "composer") {
$env:fail_fast = 'true'
}
Add-Log $cross $tool "Checksum verification failed for $tool"
return
}
$escaped_tool = [regex]::Escape($tool)
if (((Get-ChildItem -Path $bin_dir/* | Where-Object Name -Match "^$escaped_tool(\.exe|\.phar)?$").Count -gt 0)) {
$bat_content = @()
+31 -4
View File
@@ -85,6 +85,10 @@ composer_gh_auth_no_op() {
# Function to setup authentication in composer.
set_composer_auth() {
without_trace set_composer_auth_helper
}
set_composer_auth_helper() {
token="${COMPOSER_TOKEN:-$GITHUB_TOKEN}"
if [ -n "${COMPOSER_AUTH_JSON:-}" ]; then
if printf '%s' "$COMPOSER_AUTH_JSON" | jq -e . >/dev/null; then
@@ -185,6 +189,9 @@ add_tools_helper() {
if [ -e "$tool_path_dir"/phpunit ] && [ -d "$composer_bin" ]; then
sudo cp "$tool_path_dir"/phpunit "$composer_bin"
fi
elif [ "$tool" = "cloud-cli" ]; then
extensions+=(dom fileinfo iconv sockets tokenizer)
sudo ln -s "$scoped_dir"/vendor/bin/cloud "$scoped_dir"/vendor/bin/cloud-cli 2>/dev/null || true
elif [ "$tool" = "vapor-cli" ]; then
extensions+=(fileinfo json mbstring zip simplexml)
sudo ln -s "$scoped_dir"/vendor/bin/vapor "$scoped_dir"/vendor/bin/vapor-cli 2>/dev/null || true
@@ -201,8 +208,15 @@ add_tool() {
url=$1
tool=$2
ver_param=$3
checksum=
local arg
for arg in "$@"; do
[[ "$arg" =~ ^sha(256|512):[0-9a-fA-F]+$ ]] && checksum="$arg"
done
[[ "$ver_param" =~ ^sha(256|512): ]] && ver_param=
if [ "$tool" = "composer" ]; then
skip_composer_github_auth="${4:-false}"
[[ "$skip_composer_github_auth" =~ ^sha(256|512): ]] && skip_composer_github_auth=false
fi
tool_path="$tool_path_dir/$tool"
if ! [ -d "$tool_path_dir" ]; then
@@ -220,7 +234,12 @@ add_tool() {
is_mutable_tool_url "${url[0]}" && use_cache=false
status_code="200"
if [ "$use_cache" = "true" ] && [ -f "$cache_path" ]; then
sudo cp -a "$cache_path" "$tool_path"
if [ -n "$checksum" ] && ! verify_checksum "$cache_path" "$checksum"; then
sudo rm -f "$cache_path"
status_code="checksum_mismatch"
else
sudo cp -a "$cache_path" "$tool_path"
fi
else
[ -f "$tool_path" ] && sudo cp -a "$tool_path" "$tool_path.bak"
status_code=$(get -v -e "$tool_path" "${url[@]}")
@@ -229,8 +248,14 @@ add_tool() {
status_code=$(get -v -e "$tool_path" "${url[0]}")
fi
if [ "$status_code" = "200" ]; then
[ "$use_cache" = "true" ] && sudo cp -a "$tool_path" "$cache_path"
elif [ -f "$tool_path.bak" ]; then
if [ -n "$checksum" ] && ! verify_checksum "$tool_path" "$checksum"; then
sudo rm -f "$tool_path" "$cache_path"
status_code="checksum_mismatch"
elif [ "$use_cache" = "true" ]; then
sudo cp -a "$tool_path" "$cache_path"
fi
fi
if [ "$status_code" != "200" ] && [ -f "$tool_path.bak" ]; then
sudo mv "$tool_path.bak" "$tool_path"
fi
sudo rm -f "$tool_path.bak"
@@ -244,7 +269,9 @@ add_tool() {
if [ "$tool" = "composer" ]; then
export fail_fast=true
fi
if [ "$status_code" = "404" ]; then
if [ "$status_code" = "checksum_mismatch" ]; then
add_log "$cross" "$tool" "Checksum verification failed for $tool"
elif [ "$status_code" = "404" ]; then
add_log "$cross" "$tool" "Failed to download $tool from ${url[*]}"
else
add_log "$cross" "$tool" "Could not setup $tool"
+7 -5
View File
@@ -9,11 +9,13 @@ Function Add-Blackfire() {
Get-File -Url $url -OutFile $bin_dir\blackfire.zip >$null 2>&1
Expand-Archive -Path $bin_dir\blackfire.zip -DestinationPath $bin_dir -Force >$null 2>&1
Add-ToProfile $current_profile 'blackfire' "New-Alias blackfire $bin_dir\blackfire.exe"
if ((Test-Path env:BLACKFIRE_SERVER_ID) -and (Test-Path env:BLACKFIRE_SERVER_TOKEN)) {
blackfire agent:config --server-id=$env:BLACKFIRE_SERVER_ID --server-token=$env:BLACKFIRE_SERVER_TOKEN >$null 2>&1
}
if ((Test-Path env:BLACKFIRE_CLIENT_ID) -and (Test-Path env:BLACKFIRE_CLIENT_TOKEN)) {
blackfire client:config --client-id=$env:BLACKFIRE_CLIENT_ID --client-token=$env:BLACKFIRE_CLIENT_TOKEN --ca-cert=$php_dir\ssl\cacert.pem >$null 2>&1
Invoke-WithoutTrace {
if ((Test-Path env:BLACKFIRE_SERVER_ID) -and (Test-Path env:BLACKFIRE_SERVER_TOKEN)) {
blackfire agent:config --server-id=$env:BLACKFIRE_SERVER_ID --server-token=$env:BLACKFIRE_SERVER_TOKEN >$null 2>&1
}
if ((Test-Path env:BLACKFIRE_CLIENT_ID) -and (Test-Path env:BLACKFIRE_CLIENT_TOKEN)) {
blackfire client:config --client-id=$env:BLACKFIRE_CLIENT_ID --client-token=$env:BLACKFIRE_CLIENT_TOKEN --ca-cert=$php_dir\ssl\cacert.pem >$null 2>&1
}
}
Add-Log $tick "blackfire" "Added blackfire $cli_version"
}
+4
View File
@@ -12,6 +12,10 @@ add_blackfire_darwin() {
}
blackfire_config() {
without_trace blackfire_config_helper
}
blackfire_config_helper() {
if [[ -n $BLACKFIRE_SERVER_ID ]] && [[ -n $BLACKFIRE_SERVER_TOKEN ]]; then
blackfire agent:config --server-id="$BLACKFIRE_SERVER_ID" --server-token="$BLACKFIRE_SERVER_TOKEN"
if [ "$os" = "Linux" ]; then
+51 -25
View File
@@ -55,25 +55,45 @@ get_file_mtime() {
fi
}
# Function to terminate a process and its direct children.
terminate_process_tree() {
# Function to list descendants before their parents, including separate sessions.
get_process_tree() {
local pid=$1
local children child
children=$(pgrep -P "$pid" 2>/dev/null || true)
kill -TERM "$pid" >/dev/null 2>&1 || true
for child in $children; do
terminate_process_tree "$child"
get_process_tree "$child"
done
echo "$pid"
}
# Function to detect Homebrew's source-build worker, even with buffered output.
is_brew_building_from_source() {
local pid
for pid in $(get_process_tree "$1"); do
if ps -ww -p "$pid" -o command= 2>/dev/null | grep -qE '/Homebrew/build[.]rb([[:space:]]|$)'; then
return 0
fi
done
return 1
}
# Function to terminate the entire tree captured before any parents can exit.
terminate_process_tree() {
local pids pid
pids=$(get_process_tree "$1")
for pid in $pids; do
kill -TERM "$pid" >/dev/null 2>&1 || true
done
sleep 2
kill -KILL "$pid" >/dev/null 2>&1 || true
for child in $children; do
terminate_process_tree "$child"
for pid in $pids; do
kill -KILL "$pid" >/dev/null 2>&1 || true
done
}
# Function to run a command with an inactivity watchdog.
run_with_inactivity_watchdog() {
local timeout_secs="${SETUP_PHP_BREW_INACTIVITY_TIMEOUT:-180}"
local source_timeout_secs="${SETUP_PHP_BREW_SOURCE_INACTIVITY_TIMEOUT:-1800}"
local poll_secs="${SETUP_PHP_BREW_WATCHDOG_POLL:-5}"
local tmp_dir stdout_fifo stderr_fifo stdout_log stderr_log timeout_file
local command_pid stdout_reader_pid stderr_reader_pid monitor_pid exit_code
@@ -93,36 +113,39 @@ run_with_inactivity_watchdog() {
("$@" >"$stdout_fifo" 2>"$stderr_fifo") &
command_pid=$!
(
while IFS= read -r line || [ -n "$line" ]; do
printf '%s\n' "$line"
printf '%s\n' "$line" >>"$stdout_log"
done <"$stdout_fifo"
) &
tee "$stdout_log" <"$stdout_fifo" &
stdout_reader_pid=$!
(
while IFS= read -r line || [ -n "$line" ]; do
printf '%s\n' "$line" >&2
printf '%s\n' "$line" >>"$stderr_log"
done <"$stderr_fifo"
) &
tee "$stderr_log" <"$stderr_fifo" >&2 &
stderr_reader_pid=$!
(
local last_activity current_activity current_err_activity now
local building_from_source=false was_building_from_source=false active_timeout_secs
last_activity=$(get_file_mtime "$stdout_log")
current_err_activity=$(get_file_mtime "$stderr_log")
[ "$current_err_activity" -gt "$last_activity" ] && last_activity="$current_err_activity"
while kill -0 "$command_pid" >/dev/null 2>&1; do
sleep "$poll_secs"
kill -0 "$command_pid" >/dev/null 2>&1 || break
now=$(date +%s)
active_timeout_secs="$timeout_secs"
building_from_source=false
if is_brew_building_from_source "$command_pid"; then
building_from_source=true
active_timeout_secs="$source_timeout_secs"
fi
if [ "$building_from_source" != "$was_building_from_source" ]; then
last_activity="$now"
was_building_from_source="$building_from_source"
fi
current_activity=$(get_file_mtime "$stdout_log")
[ "$current_activity" -gt "$last_activity" ] && last_activity="$current_activity"
current_err_activity=$(get_file_mtime "$stderr_log")
[ "$current_err_activity" -gt "$last_activity" ] && last_activity="$current_err_activity"
now=$(date +%s)
if [ $((now - last_activity)) -ge "$timeout_secs" ]; then
printf "\nsetup-php: brew produced no output for %ss; terminating and retrying...\n" "$timeout_secs" >&2
if [ $((now - last_activity)) -ge "$active_timeout_secs" ]; then
printf "\nsetup-php: brew produced no output for %ss; terminating...\n" "$active_timeout_secs" >&2
: >"$timeout_file"
terminate_process_tree "$command_pid"
break
@@ -131,12 +154,15 @@ run_with_inactivity_watchdog() {
) &
monitor_pid=$!
wait "$command_pid"
exit_code=$?
exit_code=0
wait "$command_pid" || exit_code=$?
# Let timeout cleanup finish killing source-build descendants before retrying.
if [ ! -e "$timeout_file" ]; then
kill "$monitor_pid" >/dev/null 2>&1 || true
fi
wait "$monitor_pid" 2>/dev/null || true
wait "$stdout_reader_pid" 2>/dev/null || true
wait "$stderr_reader_pid" 2>/dev/null || true
kill "$monitor_pid" >/dev/null 2>&1 || true
wait "$monitor_pid" 2>/dev/null || true
if [ -e "$timeout_file" ]; then
rm -rf "$tmp_dir"
+18 -9
View File
@@ -343,23 +343,32 @@ add_ppa_sp_mirror() {
add_list sp/"$ppa_name" "$ppa_sp/$ppa/ubuntu" "$ppa_sp/$ppa/ubuntu/key.gpg"
}
add_sury_list() {
ppa=${1:-ondrej/php}
[ "${debug:?}" = "debug" ] && add_list "$ppa" "$sury"/"${ppa##*/}"/ "$sury"/"${ppa##*/}"/apt.gpg "$VERSION_CODENAME" "main/debug"
add_list "$ppa" "$sury"/"${ppa##*/}"/ "$sury"/"${ppa##*/}"/apt.gpg
}
# Function to add a PPA.
add_ppa() {
set_base_version
ppa=${1:-ondrej/php}
if [[ "$ID" = "ubuntu" || "$ID_LIKE" =~ ubuntu ]] && [[ "$ppa" =~ "ondrej/" ]]; then
if is_ubuntu_ppa_up "$ppa" ; then
[ "${runner:?}" = "self-hosted" ] && find "$list_dir" -type f -name 'sp*' -exec grep -qF "${sp/https:\/\/}" {} \; -delete
[ "${debug:?}" = "debug" ] && add_list "$ppa" "$lpc_ppa/$ppa/ubuntu" "$lpc_ppa/$ppa/ubuntu" "$VERSION_CODENAME" "main/debug"
add_list "$ppa"
elif [ "$ppa" = "ondrej/php" ]; then
add_ppa_sp_mirror "$ppa"
if [ "$VERSION_ID" = "26.04" ]; then
add_sury_list
else
add_log "${cross:?}" "$ppa" "PPA $ppa is not available"
if is_ubuntu_ppa_up "$ppa" ; then
[ "${runner:?}" = "self-hosted" ] && find "$list_dir" -type f -name 'sp*' -exec grep -qF "${sp/https:\/\/}" {} \; -delete
[ "${debug:?}" = "debug" ] && add_list "$ppa" "$lpc_ppa/$ppa/ubuntu" "$lpc_ppa/$ppa/ubuntu" "$VERSION_CODENAME" "main/debug"
add_list "$ppa"
elif [ "$ppa" = "ondrej/php" ]; then
add_ppa_sp_mirror "$ppa"
else
add_log "${cross:?}" "$ppa" "PPA $ppa is not available"
fi
fi
elif [[ "$ID" = "debian" || "$ID_LIKE" =~ debian ]] && [[ "$ppa" =~ "ondrej/" ]]; then
[ "${debug:?}" = "debug" ] && add_list "$ppa" "$sury"/"${ppa##*/}"/ "$sury"/"${ppa##*/}"/apt.gpg "$VERSION_CODENAME" "main/debug"
add_list "$ppa" "$sury"/"${ppa##*/}"/ "$sury"/"${ppa##*/}"/apt.gpg
add_sury_list
else
add_list "$ppa"
fi
+32
View File
@@ -48,8 +48,21 @@ set_output() {
fi
}
# Function to run sensitive code without tracing. Expand tokens inside the function, not its arguments.
without_trace() {
local setup_php_trace_flags=$-
set +x
"$@"
local setup_php_trace_status=$?
[[ "$setup_php_trace_flags" == *x* ]] && set -x
return "$setup_php_trace_status"
}
# Function to read env inputs.
read_env() {
if [[ "${SETUP_PHP_TRACE:-0}" =~ ^[12]$ ]]; then
set -x
fi
update="${update:-${UPDATE:-false}}"
[ "${debug:-${DEBUG:-false}}" = "true" ] && debug=debug && update=true || debug=release
[[ "${phpts:-${PHPTS:-nts}}" = "ts" || "${phpts:-${PHPTS:-nts}}" = "zts" ]] && ts=zts && update=true || ts=nts
@@ -122,6 +135,25 @@ get_sha256() {
fi
}
# Function to verify the checksum of a file.
# checksum format: sha256:<hash> or sha512:<hash>
verify_checksum() {
local file_path=$1
local checksum=$2
local algo="${checksum%%:*}"
local expected="${checksum#*:}"
local actual=
local hash_command=
if hash_command="$(command -v "${algo}sum")"; then
actual="$(sudo "$hash_command" "$file_path" | cut -d' ' -f1)"
elif hash_command="$(command -v shasum)"; then
actual="$(sudo "$hash_command" -a "${algo#sha}" "$file_path" | cut -d' ' -f1)"
elif hash_command="$(command -v openssl)"; then
actual="$(sudo "$hash_command" dgst -"$algo" "$file_path" | awk '{print $NF}')"
fi
[ -n "$actual" ] && [ "$(echo "$actual" | tr '[:upper:]' '[:lower:]')" = "$(echo "$expected" | tr '[:upper:]' '[:lower:]')" ]
}
# Function to download a file using cURL.
# mode: -s pipe to stdout, -v save file and return status code
# execute: -e save file as executable
+65 -43
View File
@@ -28,6 +28,18 @@ Function Add-Log($mark, $subject, $message) {
}
}
# Function to run sensitive code without tracing. Expand tokens inside the script block.
Function Invoke-WithoutTrace([scriptblock]$Script) {
Set-PSDebug -Off
$previous_trace = $setup_php_trace
$setup_php_trace = 0
try {
& $Script
} finally {
Set-PSDebug -Trace $previous_trace
}
}
# Function to set output on GitHub Actions.
Function Set-Output() {
param(
@@ -167,6 +179,26 @@ Function Get-File {
}
}
# Function to get an asset name from the PHP builder release manifest.
Function Get-PhpReleaseAsset {
param (
[ValidateSet('php', 'debug')]
[string]$Type,
[ValidateSet('stable', 'dev')]
[string]$Stability = 'stable'
)
if($null -eq $script:php_manifest) {
$script:php_manifest = Invoke-RestMethod "$php_builder/releases/download/php$version/manifest.json"
}
$thread_safety = if($ts) { 'ts' } else { 'nts' }
$asset = $script:php_manifest.$Stability.$Type.$thread_safety.$arch
if($null -eq $asset) {
throw "Asset not found in the php$version release manifest"
}
return $asset
}
# Function to make sure printf is in PATH.
Function Add-Printf {
if (-not(Test-Path "C:\Program Files\Git\usr\bin\printf.exe")) {
@@ -258,51 +290,30 @@ Function Add-PhpConfig {
Get-Content -Path $ini_files | Add-Content -Path $php_dir\php.ini
}
# Function to get PHP from GitHub releases cache
Function Set-PhpCache {
try {
try {
$release = Invoke-RestMethod https://api.github.com/repos/shivammathur/php-builder-windows/releases/tags/php$version
$asset = $release.assets | ForEach-Object {
if($_.name -match "php-$version.[0-9]+$env:PHPTS-Win32-.*-$arch.zip") {
return $_.name
}
} | Select-Object -Last 1
if($null -eq $asset) {
throw "Asset not found"
}
} catch {
$release = Get-File -Url $php_builder/releases/expanded_assets/php$version
$asset = $release.links.href | ForEach-Object {
if($_ -match "php-$version.[0-9]+$env:PHPTS-Win32-.*-$arch.zip") {
return $_.split('/')[-1]
}
} | Select-Object -Last 1
}
Get-File -Url $php_builder/releases/download/php$version/$asset -OutFile $php_dir\$asset
Set-PhpDownloadCache -Path $php_dir CurrentUser
} catch { }
# Function to install PHP directly from the GitHub releases cache.
Function Install-PhpFromCache {
$asset = Get-PhpReleaseAsset -Type php
$url = "$php_builder/releases/download/php$version/$asset"
Get-File -Url $url -FallbackUrl $php_windows/releases/archives/$asset -OutFile $php_dir\$asset
Set-PhpDownloadCache -Path $php_dir CurrentUser
$php_manager = Get-Module PhpManager
& $php_manager {
param($url, $path)
$php_version = Get-PhpVersionFromUrl -Url $url -ReleaseState Release
Install-PhpFromUrl -Url $url -Path $path -PhpVersion $php_version -InstallVCRedist $true
} $url $php_dir
$ini_path = "$php_dir\php.ini"
Copy-Item -Path $php_dir\php.ini-production -Destination $ini_path -Force
Set-PhpIniKey -Key date.timezone -Value UTC -Path $ini_path
Set-PhpIniKey -Key default_charset -Value UTF-8 -Path $ini_path
Set-PhpIniKey -Key extension_dir -Value $ext_dir -Path $ini_path
}
# Function to add debug symbols to PHP.
Function Add-DebugSymbols {
$dev = if ($version -match $nightly_versions) { '-dev' } else { '' }
try {
$release = Invoke-RestMethod https://api.github.com/repos/shivammathur/php-builder-windows/releases/tags/php$version
$asset = $release.assets | ForEach-Object {
if($_.name -match "php-debug-pack-$version.[0-9]+$dev$env:PHPTS-Win32-.*-$arch.zip") {
return $_.name
}
} | Select-Object -Last 1
} catch {
$release = Get-File -Url $php_builder/releases/expanded_assets/php$version
$asset = $release.links.href | ForEach-Object {
if($_ -match "php-debug-pack-$version.[0-9]+$dev$env:PHPTS-Win32-.*-$arch.zip") {
return $_.split('/')[-1]
}
} | Select-Object -Last 1
}
Get-File -Url $php_builder/releases/download/php$version/$asset -OutFile $php_dir\$asset
$stability = if ($version -match $nightly_versions) { 'dev' } else { 'stable' }
$asset = Get-PhpReleaseAsset -Type debug -Stability $stability
Get-File -Url $php_builder/releases/download/php$version/$asset -FallbackUrl $php_windows/releases/archives/$asset -OutFile $php_dir\$asset
Expand-Archive -Path $php_dir\$asset -DestinationPath $php_dir -Force
Get-ChildItem -Path $php_dir -Filter php_*.pdb | Move-Item -Destination $ext_dir
}
@@ -325,6 +336,8 @@ $ext_dir = "$php_dir\ext"
$bin_dir = $php_dir
$github = 'https://github.com'
$php_builder = "$github/shivammathur/php-builder-windows"
$php_windows = 'https://downloads.php.net/~windows'
$php_manifest = $null
$current_profile = "$env:TEMP\setup-php.ps1"
$ProgressPreference = 'SilentlyContinue'
$jit_versions = '8.[0-9]'
@@ -332,6 +345,12 @@ $nightly_versions = '8.[6-9]'
$xdebug3_versions = "7.[2-4]|8.[0-9]"
$enable_extensions = ('openssl', 'curl', 'mbstring')
$setup_php_trace = 0
if ($env:SETUP_PHP_TRACE -match '^[12]$') {
$setup_php_trace = [int]$env:SETUP_PHP_TRACE
Set-PSDebug -Trace $setup_php_trace
}
$arch = 'x64'
if(-not([Environment]::Is64BitOperatingSystem) -or $version -lt '7.0') {
$arch = 'x86'
@@ -424,8 +443,11 @@ if ($null -eq $installed -or -not("$($installed.Version).".StartsWith(($version
if ($version -match $nightly_versions) {
$extra_version = Install-PhpNightly
} else {
Set-PhpCache
Install-Php -Version $version -Architecture $arch -ThreadSafe $ts -InstallVC -Path $php_dir -TimeZone UTC -InitialPhpIni production -Force > $null 2>&1
try {
Install-PhpFromCache > $null 2>&1
} catch {
Install-Php -Version $version -Architecture $arch -ThreadSafe $ts -InstallVC -Path $php_dir -TimeZone UTC -InitialPhpIni production -Force > $null 2>&1
}
}
Add-PhpConfig
} catch { }
+100 -4
View File
@@ -27,6 +27,7 @@ type ToolFunction =
export interface ToolData {
tool: string;
version: string;
checksum?: string;
os: string;
php_version: string;
github: string;
@@ -73,6 +74,59 @@ interface ToolConfig {
packagist?: string;
}
/**
* Regex to match a checksum suffix in a tool release - tool:version@sha256:<hash>
*/
const checksum_suffix_regex = /@([a-z][a-z0-9-]*):([^@]*)$/i;
const checksum_like_suffix_regex = /@sha[^@]*$/i;
/**
* Function to parse the checksum suffix in the tool release
*
* @param release
*/
export function extractChecksum(release: string): {
release: string;
checksum?: string;
error?: string;
} {
const matches = release.match(checksum_suffix_regex);
if (!matches) {
const checksum_like_matches = release.match(checksum_like_suffix_regex);
if (checksum_like_matches) {
return {
release: release.slice(0, -checksum_like_matches[0].length),
error:
'Invalid checksum syntax, expected @sha256:<hash> or @sha512:<hash>'
};
}
return {release};
}
release = release.slice(0, -matches[0].length);
const algo = matches[1].toLowerCase();
if (!['sha256', 'sha512'].includes(algo)) {
return {
release,
error: `Unsupported checksum algorithm ${algo}, expected sha256 or sha512`
};
}
const hash = matches[2].toLowerCase();
const hash_length = algo === 'sha256' ? 64 : 128;
if (!new RegExp(`^[a-f0-9]{${hash_length}}$`).test(hash)) {
return {
release,
error: `Invalid ${algo} checksum, expected ${hash_length} hexadecimal characters`
};
}
if (!/^[^:]+:v?\d+\.\d+\.\d+(?:-[\w.-]+)?(?:\+[\w.-]+)?$/.test(release)) {
return {
release,
error: 'Checksum pinning requires a full version, for example tool:1.2.3'
};
}
return {release, checksum: `${algo}:${hash}`};
}
/**
* GitHub reference object from API response
*/
@@ -260,9 +314,18 @@ export async function filterList(tools_list: string[]): Promise<string[]> {
const regex_any = /^composer($|:.*)/;
const regex_valid =
/^composer:?($|preview$|snapshot$|v?\d+(\.\d+)?$|v?\d+\.\d+\.\d+[\w-]*$)/;
const matches: string[] = tools_list.filter(tool => regex_valid.test(tool));
const matches: string[] = tools_list.filter(tool => {
const parsed = extractChecksum(tool);
return (
regex_valid.test(parsed.release) ||
(regex_any.test(parsed.release) &&
(parsed.checksum !== undefined || parsed.error !== undefined))
);
});
let composer = 'composer';
tools_list = tools_list.filter(tool => !regex_any.test(tool));
tools_list = tools_list.filter(
tool => !regex_any.test(extractChecksum(tool).release)
);
switch (true) {
case matches[0] == undefined:
break;
@@ -335,7 +398,8 @@ export async function getPharUrl(data: ToolData): Promise<string> {
export async function addArchive(data: ToolData): Promise<string> {
return (
(await utils.getCommand(data.os, 'tool')) +
(await utils.joins(data.url, data.tool, data.version_parameter))
(await utils.joins(data.url, data.tool, data.version_parameter)) +
(data.checksum ? ' ' + data.checksum : '')
);
}
@@ -427,7 +491,7 @@ export async function addComposer(data: ToolData): Promise<string> {
case /^1$/.test(channel):
source_url = channel_source_url;
break;
case /^\d+\.\d+\.\d+(?:-[\w-]+)?$/.test(data.version):
case /^\d+\.\d+\.\d+(?:-[\w.-]+)?(?:\+[\w.-]+)?$/.test(data.version):
if (skipGitHubAuthForComposerVersion(data.version)) {
cleanComposerAuthJson();
skip_composer_github_auth = ' true';
@@ -612,6 +676,8 @@ export async function getData(
const json_file: string = fs.readFileSync(json_file_path, 'utf8');
const json_objects: Record<string, ToolConfig> = JSON.parse(json_file);
release = release.replace(/\s+/g, '');
const checksum_data = extractChecksum(release);
release = checksum_data.release;
const parts: string[] = release.split(':');
const tool = parts[0];
const version = parts[1];
@@ -663,7 +729,10 @@ export async function getData(
function: config.function,
alias: config.alias
};
data.checksum = checksum_data.checksum;
data.error = checksum_data.error;
data.release = await getRelease(release, data);
if (data.error !== undefined) return data;
data.version = version
? await getVersion(version, data)
: await getLatestVersion(data);
@@ -688,6 +757,25 @@ export const functionRecord: Record<
wp_cli: addWPCLI
};
/**
* Function to check if a tool supports checksum verification
*
* Only tools downloaded as archives via add_tool support it, so composer
* packages and tools set up using custom package scripts do not.
*
* @param data
*/
export async function supportsChecksum(data: ToolData): Promise<boolean> {
switch (data.type) {
case 'phar':
return true;
case 'custom-function':
return !['pecl', 'dev_tools'].includes(data.function ?? '');
default:
return false;
}
}
/**
* Setup tools
*
@@ -714,6 +802,14 @@ export async function addTools(
case data.error !== undefined:
script += await utils.addLog('$cross', data.tool, data.error, data.os);
break;
case data.checksum !== undefined && !(await supportsChecksum(data)):
script += await utils.addLog(
'$cross',
data.tool,
'Checksum verification is not supported for ' + data.tool,
data.os
);
break;
case 'phar' === data.type:
script += await addArchive(data);
break;
+41
View File
@@ -332,6 +332,47 @@ export async function suppressOutput(os: string): Promise<string> {
}
}
/**
* Prepare verbose runtime scripts without changing the original sources.
*/
export async function addVerbose(
run_path: string,
os: string
): Promise<string> {
const verbose = await readEnv('verbose');
process.env['SETUP_PHP_TRACE'] = /^v{2,3}$/.test(verbose)
? String(verbose.length - 1)
: '0';
if (!/^(true|v{1,3})$/.test(verbose) && process.env['RUNNER_DEBUG'] !== '1') {
return run_path;
}
const extension = await scriptExtension(os);
const src = path.dirname(path.dirname(run_path));
const dest = fs.mkdtempSync(src + '-verbose-');
await fs.promises.cp(src, dest, {recursive: true, dereference: true});
const scripts = path.join(dest, 'scripts');
const verbose_run = path.join(scripts, path.basename(run_path));
const pipe = />[ \t]*(?:\/dev\/null|\$null)[ \t]+2>&1/g;
for (const file of fs.readdirSync(scripts, {
recursive: true,
encoding: 'utf8'
})) {
if (!file.endsWith(extension)) continue;
const filename = path.join(scripts, file);
const original = fs.readFileSync(filename, 'utf8');
// PowerShell's success stream also carries function return values.
let script = original.replace(
pipe,
os === 'win32' ? '2>&1 | Out-Host' : ''
);
if (filename === verbose_run) {
script = script.replaceAll(src, dest);
}
if (script !== original) fs.writeFileSync(filename, script);
}
return verbose_run;
}
/**
* Function to get script to log unsupported extensions.
*
+8 -5
View File
@@ -3,17 +3,20 @@
"declaration": true,
"esModuleInterop": true,
"lib": [
"ES2024"
"ES2025"
],
"module": "commonjs",
"moduleResolution": "node",
"module": "Node20",
"moduleResolution": "Node16",
"noImplicitAny": true,
"outDir": "./lib",
"removeComments": true,
"rootDir": "./src",
"sourceMap": true,
"strict": true,
"target": "ES2024"
"target": "ES2025",
"types": [
"node"
]
},
"exclude": ["__tests__", "lib", "node_modules"]
}
}
+14
View File
@@ -0,0 +1,14 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"isolatedModules": true,
"noEmit": true,
"rootDir": ".",
"types": [
"jest",
"node"
]
},
"exclude": ["lib", "node_modules"],
"include": ["__tests__/**/*.ts", "src/**/*.ts"]
}