mirror of
https://github.com/shivammathur/setup-php.git
synced 2026-09-17 10:21:29 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e3f88f3ca7 | ||
|
|
870fe79ecc | ||
|
|
25618cc48e | ||
|
|
5eaed2e30b | ||
|
|
85dc78fbb0 | ||
|
|
83c9e52793 | ||
|
|
9af3b52286 | ||
|
|
0e80ac5270 | ||
|
|
ea331059db | ||
|
|
3ad6232c89 | ||
|
|
2ec764e0ab | ||
|
|
e6ee35895b | ||
|
|
0c6410c670 | ||
|
|
250924180e | ||
|
|
63b8b6feda | ||
|
|
de306754b1 | ||
|
|
1e29d2af9f | ||
|
|
52fea29a50 | ||
|
|
1d62418c5a | ||
|
|
e4c0f64cb6 | ||
|
|
4de6f6f4a5 | ||
|
|
c482204203 | ||
|
|
02e8f2dc92 | ||
|
|
14d457bbef | ||
|
|
9fe8278c96 | ||
|
|
b8123f29e1 | ||
|
|
3cd644eeae | ||
|
|
047d693cbc | ||
|
|
084a79c9b8 | ||
|
|
159772ba0f | ||
|
|
c9e91c1e82 | ||
|
|
12cc6a507b | ||
|
|
33139dbaea | ||
|
|
1adbee900f | ||
|
|
7d04f5ee7e | ||
|
|
19bc37cbe5 | ||
|
|
b52e51b078 | ||
|
|
a6c520081f | ||
|
|
ced9161b13 | ||
|
|
858ddd7182 | ||
|
|
2608ba9a1a | ||
|
|
7d83587834 | ||
|
|
a75416c329 | ||
|
|
0c0c27b4cb | ||
|
|
5a9d09b8e0 | ||
|
|
8e6e5267e7 | ||
|
|
8ca9579834 | ||
|
|
b9ef68088b | ||
|
|
fffd6b1db6 | ||
|
|
d64d1a1275 | ||
|
|
add91f08e1 | ||
|
|
93f351c169 | ||
|
|
529ee057c4 | ||
|
|
3fa88f2494 | ||
|
|
0c10338998 | ||
|
|
805dfa40c1 | ||
|
|
1b1cce8c66 | ||
|
|
95edd72557 |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 }}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'}
|
||||
|
||||
@@ -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
@@ -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');
|
||||
});
|
||||
|
||||
|
||||
@@ -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`
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -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
|
||||
|
||||
Generated
+1510
-822
File diff suppressed because it is too large
Load Diff
+24
-15
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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 )"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = @()
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"]
|
||||
}
|
||||
Reference in New Issue
Block a user