Compare commits

..

No commits in common. "main" and "2.33.0" have entirely different histories.
main ... 2.33.0

90 changed files with 3310 additions and 5074 deletions

11
.github/SECURITY.md vendored
View File

@ -2,20 +2,23 @@
## Supported Versions
The latest patch version of `v2` release of this project is supported for security updates.
The latest patch versions of `v1` and `v2` releases of this project are supported for security updates.
## Supported PHP Versions
This security policy only applies to the latest patch releases of the following PHP versions.
This security policy only applies to the latest patches of the following PHP versions.
| Version | Supported |
|---------|--------------------|
| 8.1 | :white_check_mark: |
| 8.2 | :white_check_mark: |
| 8.3 | :white_check_mark: |
| 8.4 | :white_check_mark: |
## Reporting a Vulnerability
If you have found any issues that might have security implications in the versions supported, please send a report privately to [contact@setup-php.com](mailto:contact@setup-php.com).
If you have found any issues that might have security implications in the versions supported, please send a report privately to [contact@shivammathur.com](mailto:contact@shivammathur.com).
Do not report security reports publicly.
## Tidelift
If you use this GitHub Action through a Tidelift subscription, please refer to [https://tidelift.com/security](https://tidelift.com/security).

View File

@ -8,7 +8,6 @@ permissions:
jobs:
codeql:
if: github.event.repository.fork == false
permissions:
actions: read # for github/codeql-action/init to get workflow details
contents: read # for actions/checkout to fetch code
@ -16,18 +15,18 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
uses: github/codeql-action/init@v3
with:
config-file: ./.github/codeql/codeql-configuration.yml
languages: javascript
- name: Autobuild
uses: github/codeql-action/autobuild@v4
uses: github/codeql-action/autobuild@v3
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
uses: github/codeql-action/analyze@v3

View File

@ -8,7 +8,6 @@ permissions:
jobs:
create:
if: github.event.repository.fork == false
permissions:
contents: none
name: Create
@ -16,8 +15,8 @@ jobs:
strategy:
fail-fast: false
matrix:
operating-system: [ubuntu-24.04, ubuntu-22.04, windows-2022, macos-15-intel]
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']
operating-system: [ubuntu-24.04, ubuntu-22.04, windows-2022, macos-13]
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']
steps:
- name: Setup PHP
uses: shivammathur/setup-php@v2
@ -88,12 +87,11 @@ jobs:
Remove-Item "$env:file.all" -Force
Remove-Item "$env:file.builtin" -Force
- name: Upload artifacts
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v4
with:
name: lists-php${{ matrix.php-versions }}-${{ matrix.operating-system }}.md
path: php${{ matrix.php-versions }}-${{ matrix.operating-system }}.md
update:
if: github.event.repository.fork == false
permissions:
contents: write # for Git to git push
name: Update
@ -101,11 +99,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
repository: ${{ github.repository }}.wiki
- name: Download artifacts
uses: actions/download-artifact@v8
uses: actions/download-artifact@v4
with:
path: ${{ github.workspace }}/lists
pattern: lists-*
@ -116,11 +114,11 @@ jobs:
git config --local user.name "${{ github.repository_owner }}"
- name: Combine
run: |
for os in ubuntu-24.04 ubuntu-22.04 windows-2025 windows-2022 windows-2019 macos-13 macos-14 macos-15 macos-26; do
for os in ubuntu-24.04 ubuntu-22.04 windows-2022 windows-2019 macos-13 macos-14 macos-15; do
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
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; do
if [[ "${os%-*}" = "macos" ]]; then
cat lists/php"$version"-macos-15-intel.md >> Php-extensions-loaded-on-"$os".md
cat lists/php"$version"-macos-13.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

View File

@ -2,7 +2,7 @@ name: Node workflow
on:
pull_request:
branches:
- main
- master
- develop
- verbose
paths-ignore:
@ -10,7 +10,7 @@ on:
- 'examples/**'
push:
branches:
- main
- master
- develop
- verbose
paths-ignore:
@ -29,14 +29,14 @@ jobs:
operating-system: [ubuntu-latest, windows-latest, macos-latest]
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Setup Node.js 24.x
uses: actions/setup-node@v6
- name: Setup Node.js 20.x
uses: actions/setup-node@v4
with:
node-version: 24.x
node-version: 20.x
- name: Install dependencies
run: npm install

View File

@ -3,7 +3,7 @@ on:
workflow_dispatch:
pull_request:
branches:
- main
- master
- develop
- verbose
paths-ignore:
@ -11,7 +11,7 @@ on:
- 'examples/**'
push:
branches:
- main
- master
- develop
- verbose
paths-ignore:
@ -28,8 +28,8 @@ jobs:
strategy:
fail-fast: false
matrix:
operating-system: [ubuntu-24.04, ubuntu-22.04, windows-2022, macos-15-intel]
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']
operating-system: [ubuntu-24.04, ubuntu-22.04, windows-2022, macos-13]
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']
include:
- operating-system: ubuntu-24.04
php-versions: ''
@ -39,7 +39,7 @@ jobs:
key: cache-v5
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Setup cache environment
id: cache-env
@ -50,7 +50,7 @@ jobs:
key: ${{ env.key }}
- name: Cache extensions
uses: actions/cache@v5
uses: actions/cache@v4
with:
path: ${{ steps.cache-env.outputs.dir }}
key: ${{ steps.cache-env.outputs.key }}

View File

@ -19,16 +19,16 @@ jobs:
steps:
- name: Checkout release
if: github.event_name != 'workflow_dispatch'
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Checkout tag
uses: actions/checkout@v6
uses: actions/checkout@v4
if: github.event_name == 'workflow_dispatch'
with:
ref: ${{ github.event.inputs.tag }}
- name: Setup Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v4
with:
node-version: '20.x'
registry-url: https://registry.npmjs.org
@ -46,7 +46,7 @@ jobs:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Change to GitHub Packages registry
uses: actions/setup-node@v6
uses: actions/setup-node@v4
with:
registry-url: https://npm.pkg.github.com
scope: '@shivammathur'

2
.gitignore vendored
View File

@ -3,7 +3,7 @@ node_modules/
__tests__/runner/*
lib/
# Rest of the file pulled from https://github.com/github/gitignore/blob/main/Node.gitignore
# Rest of the file pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
# Logs
logs
*.log

276
README.md
View File

@ -10,7 +10,7 @@
<a href="https://github.com/shivammathur/setup-php" title="GitHub action to setup PHP"><img alt="GitHub Actions status" src="https://github.com/shivammathur/setup-php/workflows/Main%20workflow/badge.svg"></a>
<a href="https://codecov.io/gh/shivammathur/setup-php" title="Code coverage"><img alt="Codecov Code Coverage" src="https://img.shields.io/codecov/c/github/shivammathur/setup-php?logo=codecov"></a>
<a href="https://github.com/shivammathur/setup-php/blob/main/LICENSE" title="license"><img alt="LICENSE" src="https://img.shields.io/badge/license-MIT-428f7e.svg?logo=open%20source%20initiative&logoColor=white&labelColor=555555"></a>
<a href="#tada-php-support" title="PHP Versions Supported"><img alt="PHP Versions Supported" src="https://img.shields.io/badge/php-5.3%20to%208.6-777bb3.svg?logo=php&logoColor=white&labelColor=555555"></a>
<a href="#tada-php-support" title="PHP Versions Supported"><img alt="PHP Versions Supported" src="https://img.shields.io/badge/php-5.3%20to%208.5-777bb3.svg?logo=php&logoColor=white&labelColor=555555"></a>
</p>
<p align="center">
<a href="https://reddit.com/r/setup_php" title="setup-php reddit"><img alt="setup-php reddit" src="https://img.shields.io/badge/reddit-join-FF5700?logo=reddit&logoColor=FF5700&labelColor=555555"></a>
@ -68,19 +68,18 @@ Both `GitHub-hosted` and `self-hosted` runners are supported by `setup-php` on t
### GitHub-Hosted Runners
| Virtual environment | Arch | YAML workflow label | Pre-installed PHP |
|---------------------|---------|------------------------------------|-------------------|
| 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 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` |
| Windows Server 2022 | x64 | `windows-latest` or `windows-2022` | `PHP 8.5` |
| macOS Tahoe 26.x | arm64 | `macos-26` | - |
| macOS Sequoia 15.x | arm64 | `macos-latest` or `macos-15` | - |
| macOS Sonoma 14.x | arm64 | `macos-14` | - |
| macOS Tahoe 26.x | x86_64 | `macos-26-intel` | `PHP 8.5` |
| macOS Sequoia 15.x | x86_64 | `macos-15-intel` | `PHP 8.5` |
| Virtual environment | Arch | YAML workflow label | Pre-installed PHP |
|---------------------|---------|------------------------------------|------------------------|
| 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 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.3` |
| Windows Server 2022 | x64 | `windows-latest` or `windows-2022` | `PHP 8.3` |
| Windows Server 2019 | x64 | `windows-2019` | `PHP 8.3` |
| macOS Sequoia 15.x | arm64 | `macos-15` | - |
| macOS Sonoma 14.x | arm64 | `macos-latest` or `macos-14` | - |
| macOS Ventura 13.x | x86_64 | `macos-13` | `PHP 8.3` |
### Self-Hosted Runners
@ -88,14 +87,13 @@ Both `GitHub-hosted` and `self-hosted` runners are supported by `setup-php` on t
|----------------------------------|----------------------------|
| Ubuntu 24.04 | `self-hosted` or `Linux` |
| Ubuntu 22.04 | `self-hosted` or `Linux` |
| Debian 13 | `self-hosted` or `Linux` |
| Debian 12 | `self-hosted` or `Linux` |
| Debian 11 | `self-hosted` or `Linux` |
| Windows 7 and newer | `self-hosted` or `Windows` |
| Windows Server 2012 R2 and newer | `self-hosted` or `Windows` |
| macOS Tahoe 26.x x86_64/arm64 | `self-hosted` or `macOS` |
| macOS Sequoia 15.x x86_64/arm64 | `self-hosted` or `macOS` |
| macOS Sonoma 14.x x86_64/arm64 | `self-hosted` or `macOS` |
| macOS Ventura 13.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.
@ -103,11 +101,11 @@ Both `GitHub-hosted` and `self-hosted` runners are supported by `setup-php` on t
## :tada: PHP Support
On all supported OS/Platforms, the following PHP versions can be set up as per the runner.
On all supported OS/Platforms the following PHP versions can be set up as per the runner.
- PHP 5.3 to PHP 8.6 on GitHub-hosted runners, except for macOS ARM64 runners (macos-14).
- PHP 5.6 to PHP 8.6 on GitHub-hosted macOS ARM64 runners (macos-14).
- PHP 5.6 to PHP 8.6 on self-hosted runners.
- PHP 5.3 to PHP 8.5 on GitHub-hosted runners, except for macOS ARM64 runners (macos-14).
- PHP 5.6 to PHP 8.5 on GitHub-hosted macOS ARM64 runners (macos-14).
- PHP 5.6 to PHP 8.5 on self-hosted runners.
| PHP Version | Stability | Release Support | Runner Support |
|-------------|-----------|-----------------------|--------------------------------|
@ -121,16 +119,15 @@ On all supported OS/Platforms, the following PHP versions can be set up as per t
| `7.3` | `Stable` | `End of life` | `GitHub-hosted`, `self-hosted` |
| `7.4` | `Stable` | `End of life` | `GitHub-hosted`, `self-hosted` |
| `8.0` | `Stable` | `End of life` | `GitHub-hosted`, `self-hosted` |
| `8.1` | `Stable` | `End of life` | `GitHub-hosted`, `self-hosted` |
| `8.1` | `Stable` | `Security fixes only` | `GitHub-hosted`, `self-hosted` |
| `8.2` | `Stable` | `Security fixes only` | `GitHub-hosted`, `self-hosted` |
| `8.3` | `Stable` | `Security fixes only` | `GitHub-hosted`, `self-hosted` |
| `8.3` | `Stable` | `Active` | `GitHub-hosted`, `self-hosted` |
| `8.4` | `Stable` | `Active` | `GitHub-hosted`, `self-hosted` |
| `8.5` | `Stable` | `Active` | `GitHub-hosted`, `self-hosted` |
| `8.6` | `Nightly` | `In development` | `GitHub-hosted`, `self-hosted` |
| `8.5` | `Nightly` | `In development` | `GitHub-hosted`, `self-hosted` |
> [!Note]
> - Specifying `8.6` in `php-version` input installs a nightly build of `PHP 8.6.0-dev` from the master branch of PHP. See [nightly build setup](#nightly-build-setup) for more information.
> - Specifying `8.5` in `php-version` input installs a nightly build of `PHP 8.5.0-dev`. See [nightly build setup](#nightly-build-setup) for more information.
> - To use JIT on `PHP 8.0` and above, refer to the [JIT configuration](#jit-configuration) section.
## :heavy_plus_sign: PHP Extension Support
@ -143,8 +140,8 @@ PHP extensions can be set up using the `extensions` input. It accepts a `string`
- name: Setup PHP with PECL extension
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
extensions: imagick, redis
php-version: '8.4'
extensions: imagick, swoole
```
- On `Windows`, extensions available on `PECL` which have the `DLL` binary can be set up.
@ -171,7 +168,7 @@ PHP extensions can be set up using the `extensions` input. It accepts a `string`
- name: Setup PHP with pre-release PECL extension
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
extensions: xdebug-beta
```
@ -183,30 +180,30 @@ PHP extensions can be set up using the `extensions` input. It accepts a `string`
- name: Setup PHP and disable opcache
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
extensions: :mbstring
php-version: '8.4'
extensions: :opcache
```
- 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.
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.
This disables all core and third-party shared extensions and thus, can break some tools which 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.
```yaml
- name: Setup PHP without any shared extensions except mbstring
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
extensions: none, mbstring
```
- Extension `intl` can be set up with specific `ICU` version for `PHP 5.6` and above in `Ubuntu` workflows by suffixing `intl` with the `ICU` version. `ICU 50.2` and newer versions are supported for PHP 8.4 and lower, `ICU 57.2` and newer versions are supported for PHP 8.5 and above. Refer to [`ICU builds`](https://github.com/shivammathur/icu-intl#icu4c-builds) for the specific versions supported.
- Extension `intl` can be set up with specific `ICU` version for `PHP 5.6` and above in `Ubuntu` workflows by suffixing `intl` with the `ICU` version. `ICU 50.2` and newer versions are supported. Refer to [`ICU builds`](https://github.com/shivammathur/icu-intl#icu4c-builds) for the specific versions supported.
```yaml
- name: Setup PHP with intl
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
extensions: intl-77.1
php-version: '8.4'
extensions: intl-70.1
```
- Extensions loaded by default after `setup-php` runs can be found on the [wiki](https://github.com/shivammathur/setup-php/wiki).
@ -214,7 +211,7 @@ This disables all core and third-party shared extensions and thus, can break som
- These extensions have custom support:
- `cubrid` and `pdo_cubrid` on `Ubuntu`.
- `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.
- `blackfire`, `couchbase`, `ioncube`, `oci8`, `pdo_firebird`, `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`.
@ -222,7 +219,7 @@ This disables all core and third-party shared extensions and thus, can break som
- name: Setup PHP with fail-fast
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
extensions: oci8
env:
fail-fast: true
@ -232,13 +229,13 @@ 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`]
[`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`], [`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`], [`pint`], [`prestissimo`], [`protoc`], [`psalm`], [`rector`], [`symfony`] or [`symfony-cli`], [`vapor`] or [`vapor-cli`], [`wp`] or [`wp-cli`]
```yaml
- name: Setup PHP with tools
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
tools: php-cs-fixer, phpunit
```
@ -248,7 +245,7 @@ These tools can be set up globally using the `tools` input. It accepts a string
- name: Setup PHP with tools
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
tools: vimeo/psalm
```
@ -261,14 +258,27 @@ These tools can be set up globally using the `tools` input. It accepts a string
When you specify just the major version or the version in `major.minor` format, the latest patch version matching the input will be setup.
With the exception of major versions of `composer`, if you specify only the `major` version or the version in `major.minor` format for a tool you can get rate limited by GitHub's API. To avoid this, it is recommended to provide a [`GitHub` OAuth token](https://github.com/shivammathur/setup-php#composer-github-oauth "Composer GitHub OAuth").
You can do that by setting `GITHUB_TOKEN` environment variable. The `COMPOSER_TOKEN` environment variable has been deprecated in favor of `GITHUB_TOKEN` and will be removed in the next major version.
```yaml
- name: Setup PHP with tools
uses: shivammathur/setup-php@v2
with:
php-version: '8.4'
tools: php-cs-fixer:3.64, phpunit:11.4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
- 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.
```yaml
- name: Setup PHP with composer v2
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
tools: composer:v1
php-version: '8.4'
tools: composer:v2
```
- If you do not use composer in your workflow, you can specify `tools: none` to skip it.
@ -277,7 +287,7 @@ These tools can be set up globally using the `tools` input. It accepts a string
- name: Setup PHP without composer
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
tools: none
```
@ -293,23 +303,12 @@ These tools can be set up globally using the `tools` input. It accepts a string
- name: Setup PHP with fail-fast
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
tools: deployer
env:
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.
```yaml
- name: Setup PHP with fail-fast
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
env:
COMPOSER_ALLOW_PLUGINS: composer/installers, composer/satis
```
> [!NOTE]
> - Input `tools` is useful to set up tools which are only used in CI workflows, thus keeping your `composer.json` tidy.
> - If you do not want to use all your dev-dependencies in workflow, you can run composer with `--no-dev` and install required tools using `tools` input to speed up your workflow.
@ -321,7 +320,7 @@ These tools can be set up globally using the `tools` input. It accepts a string
- name: Setup PHP with composer and custom process timeout
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
env:
COMPOSER_PROCESS_TIMEOUT: 300
```
@ -337,7 +336,7 @@ Runs on all [PHP versions supported](#tada-php-support "List of PHP versions sup
- name: Setup PHP with Xdebug
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
coverage: xdebug
```
@ -366,12 +365,12 @@ Runs on PHP 7.1 and newer PHP versions.
- name: Setup PHP with PCOV
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
ini-values: pcov.directory=api #optional, see above for usage.
coverage: pcov
```
- PHPUnit 8.x and above support PCOV out of the box.
- PHPUnit 8.x and above supports 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.
```yaml
@ -396,7 +395,7 @@ Disable coverage for these reasons:
- name: Setup PHP with no coverage driver
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
coverage: none
```
@ -409,7 +408,7 @@ Disable coverage for these reasons:
#### `php-version` (optional)
- Specify the PHP version you want to set up.
- Accepts a `string`. For example `'8.5'`.
- Accepts a `string`. For example `'8.4'`.
- Accepts `lowest` to set up the lowest supported PHP version.
- Accepts `highest` or `latest` to set up the latest stable PHP version.
- Accepts `nightly` to set up a nightly build from the master branch of PHP.
@ -420,7 +419,7 @@ Disable coverage for these reasons:
- The `php-version-file` input if it exists
- A `composer.lock` file and the `platform-overrides.php` value
- A `composer.json` file and the `config.platform.php` value
- If the `composer.lock` or `composer.json` file is in a subdirectory in your repository, please specify the subdirectory path in `COMPOSER_PROJECT_DIR` env.
- If the `composer.lock` or `composer.json` file is in a sub-directory in your repository, please specify the subdirectory path in `COMPOSER_PROJECT_DIR` env.
#### `php-version-file` (optional)
@ -428,7 +427,7 @@ Disable coverage for these reasons:
- Accepts a `string`. For example `'.phpenv-version'`.
- See [PHP support](#tada-php-support) for the supported PHP versions.
- By default, `.php-version` file is used.
- The file needs to either have the PHP version as its content or follows the asdf `.tool-versions` format.
- The file either have the PHP version as its content, or follow the asdf `.tool-versions` format.
- If not specified and the default `.php-version` file is not found, the latest stable PHP version is set up.
#### `extensions` (optional)
@ -463,13 +462,6 @@ Disable coverage for these reasons:
- Accepts a `string` in csv-format. For example: `phpunit, phpcs`
- See [tools support](#wrench-tools-support) for tools supported.
#### `github-token` (optional)
- Specify the GitHub token to use for authentication.
- Accepts a `string`.
- By default, `GITHUB_TOKEN` secret provided by GitHub Actions is used.
- For GitHub Enterprise users, it is recommended to use a Personal Access Token (PAT).
### Outputs
#### `php-version`
@ -483,7 +475,7 @@ On GitHub Actions you can assign the `setup-php` step an `id`, you can use the s
id: setup-php
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
- name: Print PHP version
run: echo ${{ steps.setup-php.outputs.php-version }}
@ -525,7 +517,7 @@ steps:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
extensions: mbstring, intl
ini-values: post_max_size=256M, max_execution_time=180
coverage: xdebug
@ -543,7 +535,7 @@ jobs:
strategy:
matrix:
operating-system: ['ubuntu-latest', 'windows-latest', 'macos-latest']
php-versions: ['8.2', '8.3', '8.4', '8.5']
php-versions: ['8.2', '8.3', '8.4']
phpunit-versions: ['latest']
include:
- operating-system: 'ubuntu-latest'
@ -558,21 +550,23 @@ jobs:
ini-values: post_max_size=256M, max_execution_time=180
coverage: xdebug
tools: php-cs-fixer, phpunit:${{ matrix.phpunit-versions }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
### Nightly Build Setup
> Set up a nightly build of `PHP 8.6`.
> Set up a nightly build of `PHP 8.5`.
- These PHP versions are currently in active development and might contain bugs and breaking changes.
- Some user space extensions might not support these versions currently.
- Some user space extensions might not support this version currently.
```yaml
steps:
- name: Setup nightly PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.6'
php-version: '8.5'
extensions: mbstring
ini-values: post_max_size=256M, max_execution_time=180
coverage: xdebug
@ -596,7 +590,7 @@ steps:
- name: Setup PHP with debugging symbols
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
env:
debug: true # specify true or false
```
@ -616,7 +610,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
env:
phpts: ts # specify ts or nts
```
@ -633,7 +627,7 @@ jobs:
- name: Setup PHP with latest versions
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
env:
update: true # specify true or false
```
@ -648,35 +642,30 @@ To debug any issues, you can use the `verbose` tag instead of `v2`.
- name: Setup PHP with logs
uses: shivammathur/setup-php@verbose
with:
php-version: '8.5'
php-version: '8.4'
```
### Multi-Arch Setup
> Set up PHP on multiple architecture 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`.
- `PHP 5.6` to `PHP 8.4` are supported by `setup-php` on multiple architecture on `Ubuntu`.
- For this, you can use `shivammathur/node` images as containers. These have compatible `Nodejs` installed for `setup-php`.
- Currently, for `ARM` based setup, you will need [self-hosted runners](#self-hosted-setup).
```yaml
jobs:
run:
runs-on: ${{ matrix.os }}
container: shivammathur/node:php-${{ matrix.php-versions }}-24.04-${{ matrix.arch }}
runs-on: ubuntu-latest
container: shivammathur/node:latest-${{ matrix.arch }}
strategy:
matrix:
arch: ["amd64", "arm64v8"]
php-versions: [8.4, 8.5]
include:
- arch: "amd64"
os: "ubuntu-24.04"
- arch: "arm64v8"
os: "ubuntu-24.04-arm"
arch: ["amd64", "i386"]
steps:
- name: Install PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-versions }}
php-version: '8.4'
```
### Self Hosted Setup
@ -698,7 +687,7 @@ jobs:
runs-on: self-hosted
strategy:
matrix:
php-versions: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4', '8.5']
php-versions: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4']
name: PHP ${{ matrix.php-versions }}
steps:
- name: Setup PHP
@ -711,7 +700,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 self-hosted runners on the side of your development environment or your production server.
> - Do not set up self-hosted runners on the side on your development environment or your production server.
> - Avoid using the same labels for your `self-hosted` runners which are used by `GitHub-hosted` runners.
### Local Testing Setup
@ -726,22 +715,22 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
```
Run the workflow locally with `act` using [`shivammathur/node`](https://github.com/shivammathur/node-docker "Docker image to run setup-php") docker images.
Choose the image tag which matches the `runs-on` property in your workflow. For example, if you are using `ubuntu-22.04` in your workflow, run `act -P ubuntu-22.04=shivammathur/node:22.04`.
Choose the image tag which matches the `runs-on` property in your workflow. For example, if you are using `ubuntu-22.04` in your workflow, run `act -P ubuntu-22.04=shivammathur/node:2204`.
```bash
# For runs-on: ubuntu-latest
act -P ubuntu-latest=shivammathur/node:latest
# For runs-on: ubuntu-24.04
act -P ubuntu-24.04=shivammathur/node:24.04
act -P ubuntu-24.04=shivammathur/node:2404
# For runs-on: ubuntu-22.04
act -P ubuntu-22.04=shivammathur/node:22.04
act -P ubuntu-22.04=shivammathur/node:2204
```
### JIT Configuration
@ -750,7 +739,7 @@ act -P ubuntu-22.04=shivammathur/node:22.04
- To enable JIT, enable `opcache` in cli mode by setting `opcache.enable_cli=1`.
- JIT conflicts with `Xdebug`, `PCOV`, and other extensions which override `zend_execute_ex` function, so set `coverage: none` and disable any such extension if added.
- 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.
- By default, `opcache.jit=1235` and `opcache.jit_buffer_size=256M` 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`.
@ -759,7 +748,7 @@ For example to enable JIT in `tracing` mode with buffer size of `64 MB`.
- name: Setup PHP with JIT in tracing mode
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
coverage: none
ini-values: opcache.enable_cli=1, opcache.jit=tracing, opcache.jit_buffer_size=64M
```
@ -804,20 +793,19 @@ restore-keys: ${{ runner.os }}-composer-${{ matrix.prefer }}-
### GitHub Composer Authentication
By default, setup-php uses the `GITHUB_TOKEN` secret that is generated for each workflow run. In case you want to use a Personal Access Token (PAT) instead, you can set the `github-token` input.
If you have a number of workflows which set up multiple tools or have many composer dependencies, you might hit the GitHub's rate limit for composer. Also, if you specify only the major version or the version in `major.minor` format, you can hit the rate limit. To avoid this you can specify an `OAuth` token by setting `GITHUB_TOKEN` environment variable. You can use [`GITHUB_TOKEN`](https://help.github.com/en/actions/configuring-and-managing-workflows/authenticating-with-the-github_token "GITHUB_TOKEN documentation") secret for this purpose.
The `COMPOSER_TOKEN` environment variable has been deprecated in favor of `GITHUB_TOKEN` and will be removed in the next major version.
```yaml
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
github-token: ${{ secrets.YOUR_PAT_TOKEN }}
php-version: '8.4'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
The `COMPOSER_TOKEN` and `GITHUB_TOKEN` environment variables have been deprecated in favor of the `github-token` input and will be removed in the next major version.
For GitHub Enterprise users, the `github-token` input does not default to the `GITHUB_TOKEN` secret. Therefore, it's recommended to set the `github-token` input to a Personal Access Token (PAT).
### Private Packagist Authentication
If you use Private Packagist for your private composer dependencies, you can set the `PACKAGIST_TOKEN` environment variable to authenticate.
@ -826,7 +814,7 @@ If you use Private Packagist for your private composer dependencies, you can set
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
env:
PACKAGIST_TOKEN: ${{ secrets.PACKAGIST_TOKEN }}
```
@ -840,7 +828,7 @@ Please refer to the authentication section in [`composer documentation`](https:/
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
env:
COMPOSER_AUTH_JSON: |
{
@ -863,7 +851,7 @@ Put the code in the run property of a step and specify the shell as `php {0}`.
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
- name: Run PHP code
shell: php {0}
@ -903,7 +891,7 @@ PHPStan supports error reporting in GitHub Actions, so it does not require probl
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
tools: phpstan
- name: Run PHPStan
@ -918,7 +906,7 @@ Psalm supports error reporting in GitHub Actions with an output format `github`.
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
tools: psalm
- name: Run Psalm
@ -936,7 +924,7 @@ For examples refer to the [cs2pr documentation](https://github.com/staabm/annota
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.5'
php-version: '8.4'
tools: cs2pr, phpcs
- name: Run phpcs
@ -1006,45 +994,31 @@ Examples of using `setup-php` with various PHP frameworks and packages.
## :sparkling_heart: Support This Project
These companies generously provide setup-php their products and services to aid in the development of this project.
- Please star the project and share 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.
<p>
<a target="_blank" href="https://www.jetbrains.com/?from=setup-php#gh-light-mode-only">
<img src="https://setup-php.com/sponsors/jetbrains.svg" alt="JetBrains" width="140" height="100">
</a>
<a target="_blank" href="https://www.jetbrains.com/?from=setup-php#gh-dark-mode-only">
<img src="https://setup-php.com/sponsors/jetbrains-white.svg" alt="JetBrains" width="140" height="100">
</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a target="_blank" href="https://www.cloudflare.com/lp/project-alexandria/#gh-light-mode-only">
<img src="https://setup-php.com/sponsors/cloudflare.svg" alt="Cloudflare" width="240" height="80">
</a>
<a target="_blank" href="https://www.cloudflare.com/lp/project-alexandria/#gh-dark-mode-only">
<img src="https://setup-php.com/sponsors/cloudflare-white.svg" alt="Cloudflare" width="240" height="80">
</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a target="_blank" href="https://www.macstadium.com/company/opensource#gh-light-mode-only">
<img src="https://setup-php.com/sponsors/macstadium.png" alt="Mac Stadium" width="200" height="80">
</a>
<a target="_blank" href="https://www.macstadium.com/company/opensource#gh-dark-mode-only">
<img src="https://setup-php.com/sponsors/macstadium-white.png" alt="Mac Stadium" width="200" height="80">
</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a target="_blank" href="https://m.do.co/c/f1a8ee1277b0#gh-light-mode-only">
<img src="https://setup-php.com/sponsors/digitalocean.svg" alt="Digitalocean" width="100" height="100">
</a>
<a target="_blank" href="https://m.do.co/c/f1a8ee1277b0#gh-dark-mode-only">
<img src="https://setup-php.com/sponsors/digitalocean-white.svg" alt="Digitalocean" width="100" height="100">
</a>
</p>
Many users and organizations support setup-php via [GitHub Sponsors](https://github.com/sponsors/shivammathur).
Many users and organisations support setup-php via [GitHub Sponsors](https://github.com/sponsors/shivammathur).
<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 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.
These companies generously provide setup-php their products and services to aid in the development of this project.
<p>
<a href="https://www.jetbrains.com/?from=setup-php">
<img src="https://setup-php.com/sponsors/jetbrains.svg" alt="JetBrains" width="212" height="120">
</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="https://www.macstadium.com/opensource/members#gh-light-mode-only">
<img src="https://setup-php.com/sponsors/macstadium.png" alt="Mac Stadium" width="296" height="120">
</a>
<a href="https://www.macstadium.com/opensource/members#gh-dark-mode-only">
<img src="https://setup-php.com/sponsors/macstadium-white.png" alt="Mac Stadium" width="296" height="120">
</a>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<a href="https://tidelift.com/subscription/pkg/npm-setup-php">
<img src="https://setup-php.com/sponsors/tidelift.png" alt="Tidelift" width="140" height="120">
</a>
</p>
## :package: Dependencies
@ -1071,7 +1045,6 @@ Many users and organizations support setup-php via [GitHub Sponsors](https://git
<!-- Links to tools -->
[`backward-compatibility-check`]: https://github.com/Roave/BackwardCompatibilityCheck
[`behat`]: https://docs.behat.org/en/latest/
[`blackfire`]: https://blackfire.io/docs/php/index
[`blackfire-player`]: https://blackfire.io/docs/builds-cookbooks/player
@ -1088,11 +1061,9 @@ Many users and organizations support setup-php via [GitHub Sponsors](https://git
[`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
[`flex`]: https://flex.symfony.com/
[`grpc_php_plugin`]: https://grpc.io/
[`infection`]: https://infection.github.io/
[`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
[`pecl`]: https://pecl.php.net/
[`phan`]: https://github.com/phan/phan/wiki
@ -1115,7 +1086,6 @@ Many users and organizations support setup-php via [GitHub Sponsors](https://git
[`phpunit`]: https://phpunit.de/
[`phpunit-bridge`]: https://symfony.com/doc/current/components/phpunit_bridge.html
[`phpunit-polyfills`]: https://github.com/Yoast/PHPUnit-Polyfills
[`pie`]: https://github.com/php/pie
[`pint`]: https://github.com/laravel/pint
[`prestissimo`]: https://github.com/hirak/prestissimo
[`protoc`]: https://developers.google.com/protocol-buffers/

View File

@ -1,106 +0,0 @@
import * as core from '../src/core';
describe('Core tests', () => {
const originalEnv = process.env;
const originalExitCode = process.exitCode;
let stdoutOutput: string;
const originalWrite = process.stdout.write;
beforeEach(() => {
process.env = {...originalEnv};
process.exitCode = undefined;
stdoutOutput = '';
process.stdout.write = jest.fn((chunk: string | Uint8Array): boolean => {
stdoutOutput += chunk.toString();
return true;
}) as unknown as typeof process.stdout.write;
});
afterEach(() => {
process.env = originalEnv;
process.exitCode = originalExitCode;
process.stdout.write = originalWrite;
});
it('checking issueCommand with no properties', () => {
core.issueCommand('warning', {}, 'test message');
expect(stdoutOutput).toContain('::warning::test message');
});
it('checking issueCommand with properties', () => {
core.issueCommand('error', {file: 'test.ts', line: '10'}, 'error message');
expect(stdoutOutput).toContain(
'::error file=test.ts,line=10::error message'
);
});
it('checking issueCommand escapes special characters in message', () => {
core.issueCommand('warning', {}, 'line1\nline2\rline3%percent');
expect(stdoutOutput).toContain(
'::warning::line1%0Aline2%0Dline3%25percent'
);
});
it('checking issueCommand escapes special characters in properties', () => {
core.issueCommand('error', {file: 'path:to,file'}, 'message');
expect(stdoutOutput).toContain('::error file=path%3Ato%2Cfile::message');
});
it('checking issueCommand with Error object', () => {
const error = new Error('test error');
core.issueCommand('error', {}, error);
expect(stdoutOutput).toContain('::error::Error: test error');
});
it('checking issueCommand filters empty properties', () => {
core.issueCommand('warning', {file: 'test.ts', line: ''}, 'message');
expect(stdoutOutput).toContain('::warning file=test.ts::message');
});
it('checking error', () => {
core.error('error message');
expect(stdoutOutput).toContain('::error::error message');
});
it('checking error with Error object', () => {
core.error(new Error('error instance'));
expect(stdoutOutput).toContain('::error::Error: error instance');
});
it('checking setFailed', () => {
core.setFailed('failure message');
expect(process.exitCode).toBe(1);
expect(stdoutOutput).toContain('::error::failure message');
});
it('checking setFailed with Error object', () => {
core.setFailed(new Error('failure error'));
expect(process.exitCode).toBe(1);
expect(stdoutOutput).toContain('::error::Error: failure error');
});
it('checking getInput returns value', () => {
process.env['INPUT_TEST-INPUT'] = 'test value';
expect(core.getInput('test-input')).toBe('test value');
});
it('checking getInput trims value', () => {
process.env['INPUT_TEST-INPUT'] = ' trimmed ';
expect(core.getInput('test-input')).toBe('trimmed');
});
it('checking getInput returns empty string for missing input', () => {
expect(core.getInput('missing-input')).toBe('');
});
it('checking getInput throws for required missing input', () => {
expect(() => core.getInput('missing-input', true)).toThrow(
'Input required and not supplied: missing-input'
);
});
it('checking getInput handles spaces in name', () => {
process.env['INPUT_INPUT_WITH_SPACES'] = 'spaced value';
expect(core.getInput('input with spaces')).toBe('spaced value');
});
});

View File

@ -18,8 +18,6 @@ describe('Extension tests', () => {
${'oci8'} | ${'7.4'} | ${'Add-Oci oci8'}
${'pcov'} | ${'5.6'} | ${'Add-Log "$cross" "pcov" "pcov is not supported on PHP 5.6"'}
${'pdo_oci'} | ${'7.4'} | ${'Add-Oci pdo_oci'}
${'ibm_db2'} | ${'7.4'} | ${'Add-Ibm ibm_db2'}
${'pdo_ibm'} | ${'7.4'} | ${'Add-Ibm pdo_ibm'}
${'pecl_http'} | ${'7.4'} | ${'Add-Http'}
${'pdo_sqlsrv'} | ${'7.4'} | ${'Add-Sqlsrv pdo_sqlsrv'}
${'phalcon3'} | ${'7.2'} | ${'Add-Phalcon phalcon3'}
@ -58,13 +56,11 @@ describe('Extension tests', () => {
${'mongodb-mongodb/mongo-php-driver@master'} | ${'7.3'} | ${'add_extension_from_source mongodb https://github.com mongodb mongo-php-driver master extension'}
${'oci8'} | ${'7.3'} | ${'add_oci oci8'}
${'pcov'} | ${'5.6'} | ${'add_log "$cross" "pcov" "pcov is not supported on PHP 5.6'}
${'ibm_db2'} | ${'7.3'} | ${'add_ibm ibm_db2'}
${'pdo-odbc'} | ${'7.4'} | ${'add_pdo_extension odbc'}
${'pdo_cubrid'} | ${'7.0'} | ${'add_cubrid pdo_cubrid'}
${'pdo_cubrid'} | ${'7.4'} | ${'add_pdo_extension cubrid'}
${'pdo_mysql'} | ${'7.4'} | ${'add_pdo_extension mysql'}
${'pdo_oci'} | ${'7.3'} | ${'add_oci pdo_oci'}
${'pdo_ibm'} | ${'7.3'} | ${'add_ibm pdo_ibm'}
${'pdo_sqlsrv'} | ${'7.4'} | ${'add_sqlsrv pdo_sqlsrv'}
${'pecl_http'} | ${'7.3'} | ${'add_http'}
${'phalcon3'} | ${'7.3'} | ${'add_phalcon phalcon3'}
@ -131,11 +127,7 @@ describe('Extension tests', () => {
)
? `add_${ext_name}`
: `add_brew_extension ${formula} ${prefix}`;
return [
formula,
formula.match(/phalcon3|lua|propro/) ? '7.3' : '8.1',
output
];
return [formula, formula === 'phalcon3' ? '7.3' : '7.4', output];
});
it.each(data)(

View File

@ -19,9 +19,7 @@ it('checking fetch', async () => {
Location: host_url + '/pong'
})
.get('/pong')
.reply(200, 'pong')
.get('/error')
.replyWithError('Network failure');
.reply(200, 'pong');
let response: Record<string, string> = await fetch.fetch(manifest_url);
expect(response.error).toBe(undefined);
@ -38,8 +36,4 @@ it('checking fetch', async () => {
response = await fetch.fetch(manifest_url, 'invalid_token');
expect(response.error).not.toBe(undefined);
expect(response.data).toBe(undefined);
response = await fetch.fetch(host_url + '/error');
expect(response.error).toContain('Fetch error:');
expect(response.data).toBe(undefined);
});

View File

@ -1,33 +1,40 @@
import * as fs from 'fs';
import * as tools from '../src/tools';
import {ToolData, ToolInput} from '../src/tools';
function getData(data: Partial<ToolData>): ToolData {
const tool = data.tool || 'tool';
const version = data.version || '';
interface IData {
tool: string;
version?: string;
domain?: string;
extension?: string;
os?: string;
php_version?: string;
release?: string;
repository?: string;
scope?: string;
type?: string;
fetch_latest?: string;
version_parameter?: string;
version_prefix?: string;
}
function getData(data: IData): Record<string, string> {
return {
tool,
version,
url: data.url || '',
tool: data.tool,
version: data.version || '',
domain: data.domain || 'https://example.com',
extension: data.extension || '.phar',
os: data.os || 'linux',
php_version: data.php_version || '7.4',
release: data.release || [tool, version].join(':'),
release: data.release || [data.tool, data.version].join(':'),
repository: data.repository || '',
scope: data.scope || 'global',
type: data.type || 'phar',
fetch_latest: data.fetch_latest || 'false',
version_parameter: data.version_parameter || '-V',
version_prefix: data.version_prefix || '',
github: data.github || 'https://github.com',
prefix: data.prefix || 'releases',
verb: data.verb || 'download',
packagist: data.packagist || data.repository || '',
function: data.function,
alias: data.alias,
uri: data.uri,
error: data.error
github: 'https://github.com',
prefix: 'releases',
verb: 'download'
};
}
@ -54,23 +61,7 @@ jest.mock('../src/fetch', () => ({
} else if (!token || token === 'valid_token') {
return {data: `[{"ref": "refs/tags/1.2.3", "url": "${url}"}]`};
} else if (token === 'beta_token') {
return {data: `[{"ref": "refs/tags/1.2.3beta1", "url": "${url}"}]`};
} else if (token === 'rc_token') {
return {
data: `[{"ref":"refs/tags/3.0.0RC1"},{"ref":"refs/tags/3.0.0RC2"}]`
};
} else if (token === 'non_semver_tags') {
return {
data: `[{"ref":"refs/tags/release-2025-09-18"},{"ref":"refs/tags/release-2025-09-17"}]`
};
} else if (token === 'undefined_ref') {
return {
data: `[{"url":"${url}"},{"ref":"refs/tags/v1.2.4","url":"${url}"}]`
};
} else if (token === 'multi_refs') {
return {
data: `[{"ref":"refs/tags/v1.2.3","url":"${url}"},{"ref":"refs/tags/1.2.4","url":"${url}"}]`
};
return {data: `[{"ref": "refs/tags/1.2.3-beta1", "url": "${url}"}]`};
} else if (token === 'no_data') {
return {data: '[]'};
} else {
@ -98,14 +89,11 @@ jest.mock('../src/packagist', () => ({
describe('Tools tests', () => {
it.each`
token | version
${'invalid_token'} | ${'1.2'}
${'valid_token'} | ${'1.2.3'}
${'beta_token'} | ${'1.2.3beta1'}
${'undefined_ref'} | ${'1.2.4'}
${'multi_refs'} | ${'1.2.4'}
${'non_semver_tags'} | ${'release-2025-09-18'}
${''} | ${'1.2.3'}
token | version
${'invalid_token'} | ${'1.2'}
${'valid_token'} | ${'1.2.3'}
${'beta_token'} | ${'1.2.3-beta1'}
${''} | ${'1.2.3'}
`('checking getSemverVersion: $token', async ({token, version}) => {
process.env['GITHUB_TOKEN'] = token;
expect(
@ -113,26 +101,6 @@ describe('Tools tests', () => {
).toBe(version);
});
it('checking getSemverVersion triggers ?? fallback via Map#get mock', async () => {
process.env['GITHUB_TOKEN'] = 'rc_token';
const spy = jest
.spyOn(Map.prototype as Map<string, string>, 'get')
.mockImplementation(function (
this: Map<string, string>,
key: string
): string | undefined {
if (key === '3.0.0-RC2') {
return undefined;
}
return Map.prototype.get.call(this, key);
});
const result = await tools.getSemverVersion(
getData({tool: 'tool', version: '3.0.0'})
);
expect(result).toBe('3.0.0-RC2');
spy.mockRestore();
});
it.each`
tool | fetch_latest | version
${'tool'} | ${'true'} | ${'3.2.1'}
@ -154,18 +122,6 @@ describe('Tools tests', () => {
}
);
it('checking getLatestVersion with fetch_latest=true but no repository', async () => {
expect(
await tools.getLatestVersion(
getData({
tool: 'tool',
repository: '',
fetch_latest: 'true'
})
)
).toBe('latest');
});
it.each`
version | tool | type | expected
${'latest'} | ${'tool'} | ${'phar'} | ${'latest'}
@ -249,21 +205,6 @@ describe('Tools tests', () => {
}
);
it('checking getUrl handles undefined version without double slash', async () => {
const data: ToolInput = {
...getData({
tool: 'cs2pr',
repository: 'staabm/annotate-pull-request-from-checkstyle',
domain: 'https://github.com'
}),
version: undefined
};
data.extension = '';
expect(await tools.getUrl(data)).toBe(
'https://github.com/staabm/annotate-pull-request-from-checkstyle/releases/latest/download/cs2pr'
);
});
it.each`
version | version_prefix | url
${'latest'} | ${''} | ${'https://example.com/tool.phar'}
@ -291,9 +232,9 @@ describe('Tools tests', () => {
tool: 'tool',
version: 'latest',
version_parameter: JSON.stringify('-v'),
os: os,
url: 'https://example.com/tool.phar'
os: os
});
data['url'] = 'https://example.com/tool.phar';
expect(await tools.addArchive(data)).toContain(script);
});
@ -317,9 +258,8 @@ describe('Tools tests', () => {
it.each`
version | php_version | os | script
${'latest'} | ${'8.0'} | ${'linux'} | ${'add_tool https://github.com/phar-io/phive/releases/download/3.2.1/phive-3.2.1.phar phive'}
${'1.2.3'} | ${'8.0'} | ${'darwin'} | ${'add_tool https://github.com/phar-io/phive/releases/download/1.2.3/phive-1.2.3.phar phive'}
${'1.2.3'} | ${'7.4'} | ${'win32'} | ${'Add-Tool https://github.com/phar-io/phive/releases/download/0.15.3/phive-0.15.3.phar phive'}
${'latest'} | ${'7.4'} | ${'linux'} | ${'add_tool https://github.com/phar-io/phive/releases/download/3.2.1/phive-3.2.1.phar phive'}
${'1.2.3'} | ${'7.4'} | ${'darwin'} | ${'add_tool https://github.com/phar-io/phive/releases/download/1.2.3/phive-1.2.3.phar phive'}
${'1.2.3'} | ${'7.2'} | ${'win32'} | ${'Add-Tool https://github.com/phar-io/phive/releases/download/0.14.5/phive-0.14.5.phar phive'}
${'1.2.3'} | ${'7.1'} | ${'win32'} | ${'Add-Tool https://github.com/phar-io/phive/releases/download/0.13.5/phive-0.13.5.phar phive'}
${'latest'} | ${'5.6'} | ${'win32'} | ${'Add-Tool https://github.com/phar-io/phive/releases/download/0.12.1/phive-0.12.1.phar phive'}
@ -391,20 +331,14 @@ describe('Tools tests', () => {
${'preview'} | ${'7.4'} | ${'true'} | ${'https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-preview.phar'} | ${'https://getcomposer.org/composer-preview.phar'}
${'1'} | ${'7.4'} | ${'false'} | ${'https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-1.phar'} | ${'https://getcomposer.org/composer-1.phar'}
${'2'} | ${'7.4'} | ${'false'} | ${'https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-2.phar'} | ${'https://getcomposer.org/composer-2.phar'}
${'latest'} | ${'7.4'} | ${'true'} | ${'https://artifacts.setup-php.com/composer/composer-7.4-stable.phar'} | ${'https://getcomposer.org/composer-stable.phar'}
${'stable'} | ${'7.4'} | ${'true'} | ${'https://artifacts.setup-php.com/composer/composer-7.4-stable.phar'} | ${'https://getcomposer.org/composer-stable.phar'}
${'snapshot'} | ${'7.4'} | ${'true'} | ${'https://artifacts.setup-php.com/composer/composer-7.4-snapshot.phar'} | ${'https://getcomposer.org/composer.phar'}
${'preview'} | ${'7.4'} | ${'true'} | ${'https://artifacts.setup-php.com/composer/composer-7.4-preview.phar'} | ${'https://getcomposer.org/composer-preview.phar'}
${'1'} | ${'7.4'} | ${'false'} | ${'https://artifacts.setup-php.com/composer/composer-7.4-1.phar'} | ${'https://getcomposer.org/composer-1.phar'}
${'2'} | ${'7.4'} | ${'false'} | ${'https://artifacts.setup-php.com/composer/composer-7.4-2.phar'} | ${'https://getcomposer.org/composer-2.phar'}
${'latest'} | ${'7.1'} | ${'true'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.1-stable.phar'} | ${'https://getcomposer.org/download/latest-2.2.x/composer.phar'}
${'stable'} | ${'7.1'} | ${'true'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.1-stable.phar'} | ${'https://getcomposer.org/download/latest-2.2.x/composer.phar'}
${'snapshot'} | ${'7.1'} | ${'true'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.1-snapshot.phar'} | ${'https://getcomposer.org/download/latest-2.2.x/composer.phar'}
${'preview'} | ${'7.1'} | ${'true'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.1-preview.phar'} | ${'https://getcomposer.org/download/latest-2.2.x/composer.phar'}
${'1'} | ${'7.1'} | ${'false'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.1-1.phar'} | ${'https://getcomposer.org/composer-1.phar'}
${'2'} | ${'7.1'} | ${'false'} | ${'https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.1-2.phar'} | ${'https://getcomposer.org/download/latest-2.2.x/composer.phar'}
${'1.2.3'} | ${'7.4'} | ${'false'} | ${'https://github.com/composer/composer/releases/download/1.2.3/composer.phar'} | ${'https://getcomposer.org/download/1.2.3/composer.phar'}
${'1.2.3-RC1'} | ${'7.4'} | ${'false'} | ${'https://github.com/composer/composer/releases/download/1.2.3-RC1/composer.phar'} | ${'https://getcomposer.org/download/1.2.3-RC1/composer.phar'}
${'1.2.3'} | ${'7.4'} | ${'false'} | ${'https://github.com/composer/composer/releases/download/1.2.3/composer.phar'} | ${'https://getcomposer.org/composer-1.2.3.phar'}
${'1.2.3-RC1'} | ${'7.4'} | ${'false'} | ${'https://github.com/composer/composer/releases/download/1.2.3-RC1/composer.phar'} | ${'https://getcomposer.org/composer-1.2.3-RC1.phar'}
`(
'checking addComposer: $version, $php_version, $no_tool_cache',
async ({version, php_version, no_tool_cache, cache_url, source_url}) => {
@ -458,9 +392,9 @@ 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, cs2pr, flex, grpc_php_plugin, 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',
[
'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_tool https://github.com/shivammathur/composer-cache/releases/latest/download/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"',
@ -468,8 +402,6 @@ describe('Tools tests', () => {
'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',
'add_mago',
'add_composer_tool name-collision-detector name-collision-detector shipmonk/ scoped',
'add_tool https://github.com/php-parallel-lint/PHP-Parallel-Lint/releases/latest/download/parallel-lint.phar parallel-lint "--version"',
'add_tool https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/releases/download/v3.2.1/php-cs-fixer.phar php-cs-fixer "-V"',
'add_tool https://github.com/humbug/php-scoper/releases/latest/download/php-scoper.phar php-scoper "--version"',
@ -481,7 +413,7 @@ describe('Tools tests', () => {
'add_tool https://www.phing.info/get/phing-latest.phar phing "-v"',
'add_composer_tool phinx phinx robmorgan/ scoped',
'add_composer_tool phinx phinx:1.2.3 robmorgan/ scoped',
'add_tool https://github.com/phar-io/phive/releases/download/0.15.3/phive-0.15.3.phar phive "status"',
'add_tool https://github.com/phar-io/phive/releases/download/3.2.1/phive-3.2.1.phar phive "status"',
'add_composer_tool phpunit-bridge phpunit-bridge symfony/ global',
'add_composer_tool phpunit-polyfills phpunit-polyfills yoast/ global',
'add_tool https://github.com/laravel/pint/releases/latest/download/pint.phar pint "-V"',
@ -490,8 +422,7 @@ describe('Tools tests', () => {
'add_protoc latest',
'add_symfony latest',
'add_composer_tool vapor-cli vapor-cli laravel/ scoped',
'add_tool https://github.com/wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true wp-cli "--version"',
'add_tool https://github.com/php/pie/releases/latest/download/pie.phar pie "-V"'
'add_tool https://github.com/wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true wp-cli "--version"'
]
]
])('checking addTools on linux', async (tools_csv, scripts) => {
@ -503,9 +434,9 @@ 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',
'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, 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',
[
'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_tool https://github.com/shivammathur/composer-cache/releases/latest/download/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',
'add_blackfire',
'add_tool https://get.blackfire.io/blackfire-player-v1.22.0.phar blackfire-player "-V"',
@ -518,13 +449,11 @@ describe('Tools tests', () => {
'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_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"',
'add_tool https://github.com/phan/phan/releases/download/1.2.3/phan.phar phan "-v"',
'add_tool https://www.phing.info/get/phing-1.2.3.phar,https://github.com/phingofficial/phing/releases/download/1.2.3/phing-1.2.3.phar phing "-v"',
'add_composer_tool phinx phinx robmorgan/ scoped',
'add_tool https://github.com/phar-io/phive/releases/download/0.15.3/phive-0.15.3.phar phive',
'add_tool https://github.com/phar-io/phive/releases/download/1.2.3/phive-1.2.3.phar phive',
'add_devtools php-config',
'add_tool https://github.com/PHPCSStandards/PHP_CodeSniffer/releases/latest/download/phpcbf.phar phpcbf "--version"',
'add_tool https://phar.phpunit.de/phpcpd.phar phpcpd "--version"',
@ -538,12 +467,10 @@ describe('Tools tests', () => {
'add_protoc 1.2.3',
'add_tool https://github.com/vimeo/psalm/releases/latest/download/psalm.phar psalm "-v"',
'add_composer_tool rector rector rector/ scoped',
'add_composer_tool backward-compatibility-check backward-compatibility-check roave/ scoped',
'add_symfony latest',
'add_composer_tool vapor-cli vapor-cli laravel/ scoped',
'add_tool https://github.com/wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true wp-cli "--version"',
'add_composer_tool easy-coding-standard easy-coding-standard symplify/ scoped',
'add_tool https://github.com/php/pie/releases/latest/download/pie.phar pie "-V"'
'add_composer_tool easy-coding-standard easy-coding-standard symplify/ scoped'
]
]
])('checking addTools on darwin', async (tools_csv, scripts) => {
@ -555,9 +482,9 @@ describe('Tools tests', () => {
it.each([
[
'blackfire, blackfire-player:1.2.3, cs2pr, churn, deployer, does_not_exist, flex, mago, name-collision-detector, phinx, phive:0.13.2, php-config, phpize, phpmd, simple-phpunit, symfony, wp, pie',
'blackfire, blackfire-player:1.2.3, cs2pr, churn, deployer, does_not_exist, flex, phinx, phive:0.13.2, php-config, phpize, phpmd, simple-phpunit, symfony, wp',
[
'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-Tool https://github.com/shivammathur/composer-cache/releases/latest/download/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',
'blackfire-player is not a windows tool',
'Add-Tool https://github.com/staabm/annotate-pull-request-from-checkstyle/releases/latest/download/cs2pr cs2pr "-V"',
@ -565,17 +492,14 @@ describe('Tools tests', () => {
'Add-Tool https://deployer.org/deployer.phar deployer "-V"',
'Tool does_not_exist is not supported',
'Add-ComposerTool flex flex symfony/ global',
'Add-Mago',
'Add-ComposerTool name-collision-detector name-collision-detector shipmonk/ scoped',
'Add-ComposerTool phinx phinx robmorgan/ scoped',
'Add-Tool https://github.com/phar-io/phive/releases/download/0.15.3/phive-0.15.3.phar phive "status"',
'Add-Tool https://github.com/phar-io/phive/releases/download/0.13.2/phive-0.13.2.phar phive "status"',
'php-config is not a windows tool',
'phpize is not a windows tool',
'Add-Tool https://github.com/phpmd/phpmd/releases/latest/download/phpmd.phar phpmd "--version"',
'Add-ComposerTool phpunit-bridge phpunit-bridge symfony/ global',
'Add-Symfony',
'Add-Tool https://github.com/wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true wp-cli "--version"',
'Add-Tool https://github.com/php/pie/releases/latest/download/pie.phar pie "-V"'
'Add-Tool https://github.com/wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true wp-cli "--version"'
]
]
])('checking addTools on Windows', async (tools_csv, scripts) => {
@ -589,7 +513,7 @@ describe('Tools tests', () => {
[
'composer:v1, codeception/codeception, prestissimo, hirak/prestissimo, composer-prefetcher, narrowspark/automatic-composer-prefetcher, phinx: 1.2, robmorgan/phinx: ^1.2, user/tool:1.2.3, user/tool:~1.2',
[
'Add-Tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-1.phar,https://artifacts.setup-php.com/composer/composer-7.4-1.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-1.phar,https://getcomposer.org/composer-1.phar composer',
'Add-Tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-1.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-1.phar,https://getcomposer.org/composer-1.phar composer',
'Add-ComposerTool codeception codeception codeception/ global',
'Add-ComposerTool prestissimo prestissimo hirak/ global',
'Add-ComposerTool automatic-composer-prefetcher automatic-composer-prefetcher narrowspark/ global',
@ -638,10 +562,10 @@ describe('Tools tests', () => {
it.each`
tools_csv | script
${'none'} | ${''}
${'none, phpunit'} | ${'\nstep_log "Setup Tools"\nadd_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 latest\n\nadd_tool https://phar.phpunit.de/phpunit-7.4.0.phar,https://phar.phpunit.de/phpunit-7.phar phpunit "--version"'}
${'composer:preview'} | ${'add_tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-preview.phar,https://artifacts.setup-php.com/composer/composer-7.4-preview.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-preview.phar,https://getcomposer.org/composer-preview.phar composer preview'}
${'composer, composer:v1'} | ${'add_tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-1.phar,https://artifacts.setup-php.com/composer/composer-7.4-1.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-1.phar,https://getcomposer.org/composer-1.phar composer'}
${'composer:v1, composer:preview, composer:snapshot'} | ${'add_tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-snapshot.phar,https://artifacts.setup-php.com/composer/composer-7.4-snapshot.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-snapshot.phar,https://getcomposer.org/composer.phar composer snapshot'}
${'none, phpunit'} | ${'\nstep_log "Setup Tools"\nadd_tool https://github.com/shivammathur/composer-cache/releases/latest/download/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 latest\n\nadd_tool https://phar.phpunit.de/phpunit-7.4.0.phar,https://phar.phpunit.de/phpunit-7.phar phpunit "--version"'}
${'composer:preview'} | ${'add_tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-preview.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-preview.phar,https://getcomposer.org/composer-preview.phar composer preview'}
${'composer, composer:v1'} | ${'add_tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-1.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-1.phar,https://getcomposer.org/composer-1.phar composer'}
${'composer:v1, composer:preview, composer:snapshot'} | ${'add_tool https://github.com/shivammathur/composer-cache/releases/latest/download/composer-7.4-snapshot.phar,https://dl.cloudsmith.io/public/shivammathur/composer-cache/raw/files/composer-7.4-snapshot.phar,https://getcomposer.org/composer.phar composer snapshot'}
`('checking composer setup: $tools_csv', async ({tools_csv, script}) => {
expect(await tools.addTools(tools_csv, '7.4', 'linux')).toContain(script);
});
@ -656,43 +580,14 @@ describe('Tools tests', () => {
expect(await tools.addTools(tools_csv, '7.4', 'linux')).toContain(script);
});
it('checking error when custom-function tool is missing function field', async () => {
const brokenToolsJson = JSON.stringify({
composer: {
type: 'custom-function',
domain: 'https://getcomposer.org',
repository: 'composer/composer',
function: 'composer'
},
'broken-tool': {
type: 'custom-function'
}
});
let result: string = '';
await jest.isolateModulesAsync(async () => {
jest.doMock('fs', () => ({
...jest.requireActual('fs'),
readFileSync: (
filePath: fs.PathOrFileDescriptor,
options?: unknown
) => {
if (String(filePath).includes('tools.json')) {
return brokenToolsJson;
}
return (jest.requireActual('fs') as typeof fs).readFileSync(
filePath,
options as fs.ObjectEncodingOptions & {flag?: string}
);
}
}));
const isolatedTools = await import('../src/tools');
result = await isolatedTools.addTools('broken-tool', '7.4', 'linux');
});
expect(result).toContain(
'add_log "$cross" "broken-tool" "broken-tool has no function defined. Please report this issue."'
);
it.each`
tools_csv | token | script
${'cs2pr:1.2'} | ${'invalid_token'} | ${'add_log "$cross" "cs2pr" "Invalid token"'}
${'phpunit:1.2'} | ${'invalid_token'} | ${'add_log "$cross" "phpunit" "Invalid token"'}
${'phpunit:0.1'} | ${'no_data'} | ${'add_log "$cross" "phpunit" "No version found with prefix 0.1."'}
`('checking error: $tools_csv', async ({tools_csv, token, script}) => {
process.env['GITHUB_TOKEN'] = token;
expect(await tools.addTools(tools_csv, '7.4', 'linux')).toContain(script);
});
it.each`

View File

@ -1,7 +1,25 @@
import fs from 'fs';
import * as path from 'path';
import * as utils from '../src/utils';
import * as fetchModule from '../src/fetch';
/**
* Mock @actions/core
*/
jest.mock('@actions/core', () => ({
getInput: jest.fn().mockImplementation(key => {
return ['setup-php'].indexOf(key) !== -1 ? key : '';
}),
info: jest.fn()
}));
/**
* Mock fetch.ts
*/
jest.mock('../src/fetch', () => ({
fetch: jest.fn().mockImplementation(() => {
return {data: '{ "latest": "8.1", "5.x": "5.6" }'};
})
}));
describe('Utils tests', () => {
it('checking readEnv', async () => {
@ -16,38 +34,24 @@ describe('Utils tests', () => {
it('checking getInput', async () => {
process.env['test'] = 'setup-php';
process.env['INPUT_SETUP-PHP'] = 'setup-php';
expect(await utils.getInput('test', false)).toBe('setup-php');
expect(await utils.getInput('setup-php', false)).toBe('setup-php');
expect(await utils.getInput('DoesNotExist', false)).toBe('');
await expect(async () => {
await utils.getInput('DoesNotExist', true);
}).rejects.toThrow('Input required and not supplied: DoesNotExist');
delete process.env['INPUT_SETUP-PHP'];
});
it('checking getManifestURL', async () => {
for (const url of await utils.getManifestURLS()) {
expect(url).toContain('php-versions.json');
}
expect(await utils.getManifestURL()).toContain('php-versions.json');
});
it('checking parseVersion', async () => {
const fetchSpy = jest
.spyOn(fetchModule, 'fetch')
.mockResolvedValue({data: '{ "latest": "8.1", "5.x": "5.6" }'});
expect(await utils.parseVersion('latest')).toBe('8.1');
expect(await utils.parseVersion('7')).toBe('7.0');
expect(await utils.parseVersion('7.4')).toBe('7.4');
expect(await utils.parseVersion('5.x')).toBe('5.6');
expect(await utils.parseVersion('4.x')).toBe(undefined);
fetchSpy.mockReset();
fetchSpy.mockResolvedValueOnce({}).mockResolvedValueOnce({});
await expect(utils.parseVersion('latest')).rejects.toThrow(
'Could not fetch the PHP version manifest.'
);
expect(fetchSpy).toHaveBeenCalledTimes(2);
});
it('checking parseIniFile', async () => {

View File

@ -27,12 +27,9 @@ inputs:
tools:
description: 'Setup popular tools globally.'
required: false
github-token:
description: 'GitHub token to use for authentication.'
default: ${{ github.token }}
outputs:
php-version:
description: 'PHP version in semver format'
runs:
using: 'node24'
using: 'node20'
main: 'dist/index.js'

4
dist/index.js vendored

File diff suppressed because one or more lines are too long

View File

@ -1,22 +1,39 @@
import {fixupConfigRules, fixupPluginRules} from '@eslint/compat';
// eslint-disable-next-line import/no-unresolved
import typescriptEslint from '@typescript-eslint/eslint-plugin';
import importPlugin from 'eslint-plugin-import';
import jest from 'eslint-plugin-jest';
import prettierRecommended from 'eslint-plugin-prettier/recommended';
import eslintConfigPrettier from 'eslint-config-prettier';
import globals from 'globals';
// eslint-disable-next-line import/no-unresolved
import tsParser from '@typescript-eslint/parser';
import path from 'node:path';
import {fileURLToPath} from 'node:url';
import js from '@eslint/js';
import {FlatCompat} from '@eslint/eslintrc';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all
});
export default [
js.configs.recommended,
...typescriptEslint.configs['flat/recommended'],
importPlugin.flatConfigs.errors,
importPlugin.flatConfigs.warnings,
importPlugin.flatConfigs.typescript,
prettierRecommended,
eslintConfigPrettier,
...fixupConfigRules(
compat.extends(
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:import/typescript',
'plugin:prettier/recommended',
'prettier'
)
),
{
plugins: {
'@typescript-eslint': fixupPluginRules(typescriptEslint),
jest
},
@ -29,21 +46,6 @@ export default [
parser: tsParser,
ecmaVersion: 2021,
sourceType: 'module'
},
settings: {
'import/resolver': {
typescript: {
alwaysTryTypes: true,
project: './tsconfig.json'
},
node: {
extensions: ['.js', '.ts']
}
},
'import/parsers': {
'@typescript-eslint/parser': ['.ts']
}
}
}
];

View File

@ -11,7 +11,7 @@ jobs:
php-versions: ['7.4', '8.0', '8.1']
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -19,7 +19,7 @@ jobs:
# blackfire-player supports PHP >= 5.5
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -19,7 +19,7 @@ jobs:
# Blackfire supports PHP >= 5.3 on Ubuntu and macOS, and PHP >= 5.4 on Windows
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -28,7 +28,7 @@ jobs:
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP
@ -75,7 +75,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP
@ -108,7 +108,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -28,7 +28,7 @@ jobs:
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP
@ -75,7 +75,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP
@ -108,7 +108,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -11,7 +11,7 @@ jobs:
runs-on: ${{ matrix.operating-system }}
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP
@ -47,7 +47,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP
@ -79,7 +79,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -10,7 +10,7 @@ jobs:
runs-on: ${{ matrix.operating-system }}
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -10,7 +10,7 @@ jobs:
runs-on: ${{ matrix.operating-system }}
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -37,7 +37,7 @@ jobs:
php-versions: ['7.4', '8.0', '8.1']
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -39,7 +39,7 @@ jobs:
php-versions: ['7.4', '8.0', '8.1']
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -12,7 +12,7 @@ jobs:
php-versions: ['7.4', '8.0', '8.1']
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -37,7 +37,7 @@ jobs:
php-versions: ['7.4', '8.0', '8.1']
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -39,7 +39,7 @@ jobs:
php-versions: ['7.4', '8.0', '8.1']
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -12,7 +12,7 @@ jobs:
php-versions: ['7.4', '8.0', '8.1']
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -36,7 +36,7 @@ jobs:
# php-versions: ['7.0', '7.1', '7.2', '7.3']
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -37,7 +37,7 @@ jobs:
# php-versions: ['7.0', '7.1', '7.2', '7.3']
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -12,10 +12,10 @@ jobs:
node-versions: ['16']
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v5
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-versions }}

View File

@ -10,7 +10,7 @@ jobs:
runs-on: ${{ matrix.operating-system }}
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -23,7 +23,7 @@ jobs:
php-versions: ['7.4', '8.0', '8.1']
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -23,7 +23,7 @@ jobs:
php-versions: ['7.4', '8.0', '8.1']
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -12,7 +12,7 @@ jobs:
php-versions: ['7.4', '8.0', '8.1']
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# Docs: https://github.com/shivammathur/setup-php
- name: Setup PHP

View File

@ -29,10 +29,10 @@ jobs:
php-versions: ['7.4', '8.0']
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Set Node.js 10.x
uses: actions/setup-node@v5
uses: actions/setup-node@v1
with:
node-version: 10.x

View File

@ -29,10 +29,10 @@ jobs:
php-versions: ['7.4', '8.0']
steps:
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: Set Node.js 10.x
uses: actions/setup-node@v5
uses: actions/setup-node@v1
with:
node-version: 10.x

5220
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "setup-php",
"version": "2.36.0",
"version": "2.33.0",
"private": false,
"description": "Setup PHP for use with GitHub Actions",
"main": "lib/install.js",
@ -34,36 +34,32 @@
"author": "shivammathur",
"license": "MIT",
"dependencies": {
"@actions/exec": "^2.0.0",
"@actions/core": "^1.11.1",
"@actions/exec": "^1.1.1",
"@actions/io": "^1.1.3",
"compare-versions": "^6.1.1"
},
"devDependencies": {
"@eslint/compat": "^2.0.2",
"@eslint/js": "^9.39.1",
"@types/jest": "^30.0.0",
"@types/node": "^25.2.2",
"@typescript-eslint/eslint-plugin": "^8.54.0",
"@typescript-eslint/parser": "^8.54.0",
"@vercel/ncc": "^0.38.4",
"eslint": "^9.39.1",
"eslint-config-prettier": "^10.1.8",
"eslint-import-resolver-typescript": "^4.4.4",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jest": "^29.12.2",
"eslint-plugin-prettier": "^5.5.5",
"globals": "^17.3.0",
"jest": "^30.2.0",
"jest-circus": "^30.2.0",
"nock": "^14.0.10",
"prettier": "^3.8.1",
"simple-git-hooks": "^2.13.1",
"ts-jest": "^29.4.6",
"typescript": "^5.9.3"
},
"overrides": {
"test-exclude": "^7.0.1",
"glob": "^11.1.0",
"minimatch": "^10.2.1"
"@eslint/compat": "^1.2.8",
"@eslint/js": "9.24.0",
"@types/jest": "^29.5.14",
"@types/node": "^22.14.1",
"@typescript-eslint/eslint-plugin": "^8.29.1",
"@typescript-eslint/parser": "^8.29.1",
"@vercel/ncc": "^0.38.3",
"eslint": "9.24.0",
"eslint-config-prettier": "^10.1.2",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jest": "^28.11.0",
"eslint-plugin-prettier": "^5.2.6",
"globals": "^16.0.0",
"jest": "^29.7.0",
"jest-circus": "^29.7.0",
"nock": "^14.0.3",
"prettier": "^3.5.3",
"simple-git-hooks": "^2.12.1",
"ts-jest": "^29.3.1",
"typescript": "^5.8.3"
},
"bugs": {
"url": "https://github.com/shivammathur/setup-php/issues"

View File

@ -1,65 +1,45 @@
amqp=amqp
apcu=apcu
ast=ast
brotli=brotli
couchbase=couchbase
ds=ds
event=event
excimer=excimer
expect=expect
gearman=gearman
gmagick=gmagick
gnupg=gnupg
grpc=grpc
igbinary=igbinary
imagick=imagick
imap=imap
interbase=interbase
lua=lua
mailparse=mailparse
maxminddb=maxminddb
mcrypt=mcrypt
memcache=memcache
memcached=memcached
mongodb=mongodb
mongodb1=mongodb1
msgpack=msgpack
newrelic=newrelic
oauth=oauth
opentelemetry=opentelemetry
pcov=pcov
pdo_firebird=pdo_firebird
pdo_sqlsrv=pdo_sqlsrv
pecl_http=http
phalcon3=phalcon
phalcon4=phalcon
phalcon5=phalcon
pinba=pinba
propro=propro
protobuf=protobuf
psr=psr
raphf=raphf
rdkafka=rdkafka
phpredis=redis
redis=redis
seaslog=seaslog
scalar_objects=scalar_objects
snmp=snmp
sqlsrv=sqlsrv
spx=spx
ssh2=ssh2
swoole=swoole
swow=swow
uopz=uopz
uploadprogress=uploadprogress
uuid=uuid
v8js=v8js
vips=vips
vld=vld
xdebug=xdebug
xdebug2=xdebug
xhprof=xhprof
xlswriter=xlswriter
yaml=yaml
zmq=zmq
zstd=zstd

View File

@ -1,22 +0,0 @@
amqp=rabbitmq-c
decimal=mpdecimal
ev=libev
event=libevent
geoip=geoip
gmagick=graphicsmagick
gnupg=gpgme
grpc=grpc protobuf
imagick=imagemagick
memcached=libmemcached libevent
protobuf=protobuf
rdkafka=librdkafka
snappy=snappy
sodium=libsodium
ssh2=libssh2
uv=libuv
uuid=util-linux
vips=vips
yaz=yaz
yaml=libyaml
zstd=zstd
zmq=zeromq

View File

@ -1,3 +0,0 @@
opcache.enable=1
opcache.jit_buffer_size=128M
opcache.jit=1235

View File

@ -1,22 +0,0 @@
amqp=librabbitmq-dev
decimal=libmpdec-dev
ev=libev-dev
event=libevent-dev
geoip=libgeoip-dev
gmagick=graphicsmagick-libmagick-dev-compat
gnupg=libgpgme-dev
grpc=libgrpc-dev libprotobuf-dev protobuf-compiler
imagick=libmagickwand-dev libmagickcore-dev
memcached=libmemcached-dev libevent-dev
protobuf=libprotobuf-dev protobuf-compiler
rdkafka=librdkafka-dev
snappy=libsnappy-dev
sodium=libsodium-dev
ssh2=libssh2-1-dev
uv=libuv1-dev
uuid=uuid-dev
vips=libvips-dev
yaz=libyaz-dev
yaml=libyaml-dev
zstd=libzstd-dev
zmq=libzmq3-dev

View File

@ -20,5 +20,3 @@
23.04,lunar
23.10,mantic
24.04,noble
24.10,oracular
25.10,plucky

1 8 jessie
20 23.04 lunar
21 23.10 mantic
22 24.04 noble
24.10 oracular
25.10 plucky

View File

@ -1,10 +1,9 @@
{
"lowest": "8.1",
"highest": "8.5",
"latest": "8.5",
"nightly": "8.6",
"master": "8.6",
"highest": "8.4",
"latest": "8.4",
"nightly": "8.5",
"5.x": "5.6",
"7.x": "7.4",
"8.x": "8.5"
"8.x": "8.4"
}

View File

@ -1,9 +1,4 @@
{
"backward-compatibility-check": {
"type": "composer",
"repository": "roave/backward-compatibility-check",
"scope": "scoped"
},
"box": {
"type": "phar",
"repository": "box-project/box",
@ -50,12 +45,6 @@
"version_prefix": "",
"version_parameter": "-V"
},
"easy-coding-standard": {
"type": "composer",
"alias": "ecs",
"repository": "symplify/easy-coding-standard",
"scope": "scoped"
},
"infection": {
"type": "phar",
"repository": "infection/infection",
@ -64,11 +53,6 @@
"version_prefix": "",
"version_parameter": "-V"
},
"name-collision-detector": {
"type": "composer",
"repository": "shipmonk/name-collision-detector",
"scope": "scoped"
},
"phan": {
"type": "phar",
"repository": "phan/phan",
@ -152,14 +136,6 @@
"version_prefix": "",
"version_parameter": "-V"
},
"pie": {
"type": "phar",
"repository": "php/pie",
"extension": ".phar",
"domain": "https://github.com",
"version_prefix": "",
"version_parameter": "-V"
},
"pint": {
"type": "phar",
"repository": "laravel/pint",
@ -249,12 +225,6 @@
"domain": "https://github.com",
"version_prefix": "v"
},
"mago": {
"type": "custom-package",
"repository": "carthage-software/mago",
"domain": "https://github.com",
"version_prefix": ""
},
"protoc": {
"type": "custom-package",
"repository": "protocolbuffers/protobuf",
@ -266,8 +236,7 @@
"type": "custom-package",
"repository": "symfony-cli/symfony-cli",
"domain": "https://github.com",
"version_prefix": "v",
"version_parameter": "-V"
"version_prefix": "-V"
},
"blackfire-player": {
"type": "custom-function",
@ -354,5 +323,11 @@
"extension": ".phar",
"version_parameter": "--version",
"version_prefix": "v"
},
"easy-coding-standard": {
"type": "composer",
"alias": "ecs",
"repository": "symplify/easy-coding-standard",
"scope": "scoped"
}
}

View File

@ -1,112 +0,0 @@
import {EOL} from 'os';
/**
* Commands
*
* Command Format:
* ::name key=value,key=value::message
*
* @see https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions
*/
interface CommandProperties {
[key: string]: string;
}
/**
* Sanitizes the message for use in a workflow command.
* @param message
*/
function toCommandValue(message: string | Error): string {
if (message instanceof Error) {
return message.toString();
}
return message;
}
/**
* Escapes data for safe use in workflow command messages.
* @param s
*/
function escapeData(s: string | Error): string {
return toCommandValue(s)
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A');
}
/**
* Escapes property values for safe use in workflow command properties.
* @param s
*/
function escapeProperty(s: string): string {
return s
.replace(/%/g, '%25')
.replace(/\r/g, '%0D')
.replace(/\n/g, '%0A')
.replace(/:/g, '%3A')
.replace(/,/g, '%2C');
}
/**
* Issues a command to the GitHub Actions runner.
*
* @param command - The command name to issue
* @param properties - Additional properties for the command (key-value pairs)
* @param message - The message to include with the command
*/
export function issueCommand(
command: string,
properties: CommandProperties,
message: string | Error
): void {
let cmdStr = `::${command}`;
if (properties && Object.keys(properties).length > 0) {
cmdStr += ' ';
const props = Object.entries(properties)
.filter(([, val]) => val)
.map(([key, val]) => `${key}=${escapeProperty(val)}`)
.join(',');
cmdStr += props;
}
cmdStr += `::${escapeData(message)}`;
process.stdout.write(cmdStr + EOL);
}
/**
* Adds an error issue.
* @param message - error issue message
*/
export function error(message: string | Error): void {
issueCommand('error', {}, message);
}
/**
* Sets the action status to failed.
* When the action exits it will be with an exit code of 1.
* @param message - add error issue message
*/
export function setFailed(message: string | Error): void {
process.exitCode = 1;
error(message);
}
/**
* Gets the value of an input.
* The value is trimmed.
* Returns an empty string if the value is not defined.
*
* @param name - name of the input to get
* @param required - whether the input is required
* @returns string
*/
export function getInput(name: string, required = false): string {
const val: string =
process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] || '';
if (required && !val) {
throw new Error(`Input required and not supplied: ${name}`);
}
return val.trim();
}

View File

@ -32,19 +32,17 @@ export async function addExtensionDarwin(
add_script += await utils.parseExtensionSource(extension, ext_prefix);
return;
// match 7.4relay...8.5relay
// match 5.3blackfire...8.5blackfire
// match 5.3blackfire-(semver)...8.5blackfire-(semver)
// match couchbase, event, geos, ibm_db2, pdo_ibm, pdo_oci, oci8, http, pecl_http
// match 5.3blackfire...8.4blackfire
// match 5.3blackfire-(semver)...8.4blackfire-(semver)
// match couchbase, event, geos, pdo_oci, oci8, http, pecl_http
// match 5.3ioncube...8.4ioncube
// match 7.0phalcon3...7.3phalcon3, 7.2phalcon4...7.4phalcon4, and 7.4phalcon5...8.4phalcon5
// match 7.0zephir_parser...8.4zephir_parser
case /^(7\.4|8\.[0-5])relay(-v?\d+\.\d+\.\d+|-nightly)?$/.test(
case /^(7\.4|8\.[0-5])relay(-v?\d+\.\d+\.\d+)?$/.test(version_extension):
case /^(5\.[3-6]|7\.[0-4]|8\.[0-4])blackfire(-\d+\.\d+\.\d+)?$/.test(
version_extension
):
case /^(5\.[3-6]|7\.[0-4]|8\.[0-5])blackfire(-\d+\.\d+\.\d+)?$/.test(
version_extension
):
case /^couchbase|^event|^gearman$|^geos$|^ibm_db2$|^pdo_ibm$|^pdo_oci$|^oci8$|^(pecl_)?http|^pdo_firebird$/.test(
case /^couchbase|^event|^gearman$|^geos$|^pdo_oci$|^oci8$|^(pecl_)?http|^pdo_firebird$/.test(
extension
):
case /^(5\.[3-6]|7\.[0-4]|8\.[0-4])ioncube$/.test(version_extension):
@ -85,14 +83,13 @@ export async function addExtensionDarwin(
add_script += await utils.getUnsupportedLog('pcov', version, 'darwin');
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|expect|gnupg|grpc|igbinary|imagick|imap|mailparse|mcrypt|memcache|memcached|mongodb|msgpack|protobuf|psr|raphf|rdkafka|redis|snmp|ssh2|swoole|uuid|vld|xdebug|xdebug2|yaml|zmq)/.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\.[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):
add_script += await utils.joins(
'\nadd_brew_extension',
ext_name,
@ -137,19 +134,17 @@ export async function addExtensionWindows(
case /^none$/.test(ext_name):
add_script += '\nDisable-AllShared';
break;
// match 5.3blackfire...8.5blackfire
// match 5.3blackfire-(semver)...8.5blackfire-(semver)
// match ibm_db2, pdo_ibm, pdo_oci and oci8
// match 5.3blackfire...8.4blackfire
// match 5.3blackfire-(semver)...8.4blackfire-(semver)
// match pdo_oci and oci8
// match 5.3ioncube...8.4ioncube
// match 7.0phalcon3...7.3phalcon3, 7.2phalcon4...7.4phalcon4, and 7.4phalcon5...8.4phalcon5
// match 7.1pecl_http...8.1pecl_http and 7.1http...8.1http
// match 7.0zephir_parser...8.4zephir_parser
case /^(5\.[3-6]|7\.[0-4]|8\.[0-5])blackfire(-\d+\.\d+\.\d+)?$/.test(
case /^(5\.[3-6]|7\.[0-4]|8\.[0-4])blackfire(-\d+\.\d+\.\d+)?$/.test(
version_extension
):
case /^ibm_db2$|^pdo_ibm$|^pdo_oci$|^oci8$|^pdo_firebird$/.test(
extension
):
case /^pdo_oci$|^oci8$|^pdo_firebird$/.test(extension):
case /^(5\.[3-6]|7\.[0-4]|8\.[0-4])ioncube$/.test(version_extension):
case /^7\.[0-3]phalcon3$|^7\.[2-4]phalcon4$|^(7\.4|8\.[0-4])phalcon5?$/.test(
version_extension
@ -269,23 +264,21 @@ export async function addExtensionLinux(
add_script += await utils.parseExtensionSource(extension, ext_prefix);
return;
// match 7.4relay...8.5relay
// match 5.3blackfire...8.5blackfire
// match 5.3blackfire-(semver)...8.5blackfire-(semver)
// match 5.3blackfire...8.4blackfire
// match 5.3blackfire-(semver)...8.4blackfire-(semver)
// match 5.3pdo_cubrid...7.2php_cubrid, 5.3cubrid...7.4cubrid
// match couchbase, geos, ibm_db2, pdo_ibm, pdo_oci, oci8, http, pecl_http
// match couchbase, geos, pdo_oci, oci8, http, pecl_http
// match 5.3ioncube...8.4ioncube
// match 7.0phalcon3...7.3phalcon3, 7.2phalcon4...7.4phalcon4, 7.4phalcon5...8.4phalcon5
// match 7.0zephir_parser...8.4zephir_parser
case /^(7\.4|8\.[0-5])relay(-v?\d+\.\d+\.\d+|-nightly)?$/.test(
version_extension
):
case /^(5\.[3-6]|7\.[0-4]|8\.[0-5])blackfire(-\d+\.\d+\.\d+)?$/.test(
case /^(7\.4|8\.[0-5])relay(-v?\d+\.\d+\.\d+)?$/.test(version_extension):
case /^(5\.[3-6]|7\.[0-4]|8\.[0-4])blackfire(-\d+\.\d+\.\d+)?$/.test(
version_extension
):
case /^((5\.[3-6])|(7\.[0-2]))pdo_cubrid$|^((5\.[3-6])|(7\.[0-4]))cubrid$/.test(
version_extension
):
case /^couchbase|^event|^gearman$|^geos$|^ibm_db2$|^pdo_ibm$|^pdo_oci$|^oci8$|^(pecl_)?http|^pdo_firebird$/.test(
case /^couchbase|^event|^gearman$|^geos$|^pdo_oci$|^oci8$|^(pecl_)?http|^pdo_firebird$/.test(
extension
):
case /(?<!5\.[3-5])intl-\d+\.\d+$/.test(version_extension):

View File

@ -1,10 +1,9 @@
/**
* Redirect status codes set for O(1) lookup
*/
const REDIRECT_CODES = new Set([301, 302, 303, 307, 308]);
import {IncomingMessage, OutgoingHttpHeaders} from 'http';
import * as https from 'https';
import * as url from 'url';
/**
* Function to fetch a URL using native fetch API (Node 24+)
* Function to fetch a URL
*
* @param input_url
* @param auth_token
@ -15,28 +14,43 @@ export async function fetch(
auth_token?: string,
redirect_count = 5
): Promise<Record<string, string>> {
const headers: Record<string, string> = {
'User-Agent': `Mozilla/5.0 (${process.platform} ${process.arch}) setup-php`
};
if (auth_token) {
headers['Authorization'] = 'Bearer ' + auth_token;
}
try {
const response = await globalThis.fetch(input_url, {
headers,
redirect: redirect_count > 0 ? 'follow' : 'manual'
});
if (response.ok) {
const data = await response.text();
return {data};
} else if (REDIRECT_CODES.has(response.status) && redirect_count <= 0) {
return {error: `${response.status}: Redirect error`};
} else {
return {error: `${response.status}: ${response.statusText}`};
const fetch_promise: Promise<Record<string, string>> = new Promise(
resolve => {
const url_object: url.UrlObject = new url.URL(input_url);
const headers: OutgoingHttpHeaders = {
'User-Agent': `Mozilla/5.0 (${process.platform} ${process.arch}) setup-php`
};
if (auth_token) {
headers.authorization = 'Bearer ' + auth_token;
}
const options: https.RequestOptions = {
hostname: url_object.hostname,
path: url_object.pathname,
headers: headers,
agent: new https.Agent({keepAlive: false})
};
const req = https.get(options, (res: IncomingMessage) => {
if (res.statusCode === 200) {
let body = '';
res.setEncoding('utf8');
res.on('data', chunk => (body += chunk));
res.on('end', () => resolve({data: `${body}`}));
} else if (
[301, 302, 303, 307, 308].includes(res.statusCode as number)
) {
if (redirect_count > 0 && res.headers.location) {
fetch(res.headers.location, auth_token, redirect_count--).then(
resolve
);
} else {
resolve({error: `${res.statusCode}: Redirect error`});
}
} else {
resolve({error: `${res.statusCode}: ${res.statusMessage}`});
}
});
req.end();
}
} catch (error) {
return {error: `Fetch error: ${(error as Error).message}`};
}
);
return await fetch_promise;
}

View File

@ -1,8 +1,8 @@
import path from 'path';
import fs from 'fs';
import {exec} from '@actions/exec';
import * as core from '@actions/core';
import * as config from './config';
import * as core from './core';
import * as coverage from './coverage';
import * as extensions from './extensions';
import * as tools from './tools';
@ -18,6 +18,7 @@ export async function getScript(os: string): Promise<string> {
const filename = os + (await utils.scriptExtension(os));
const script_path = path.join(__dirname, '../src/scripts', filename);
const run_path = script_path.replace(os, 'run');
process.env['fail_fast'] = await utils.getInput('fail-fast', false);
const extension_csv: string = await utils.getInput('extensions', false);
const ini_values_csv: string = await utils.getInput('ini-values', false);
const coverage_driver: string = await utils.getInput('coverage', false);
@ -47,19 +48,10 @@ export async function getScript(os: string): Promise<string> {
return run_path;
}
/**
* Function to set environment variables based on inputs.
*/
export async function setEnv(): Promise<void> {
process.env['fail_fast'] = await utils.getInput('fail-fast', false);
process.env['GITHUB_TOKEN'] ??= await utils.getInput('github-token', false);
}
/**
* Run the script
*/
export async function run(): Promise<void> {
await setEnv();
const os: string = process.platform;
const tool = await utils.scriptTool(os);
const run_path = await getScript(os);

View File

@ -15,9 +15,7 @@ handle_dependency_extensions() {
brew_opts=(-sf)
patch_abstract_file >/dev/null 2>&1
for dependency_extension in "${dependency_extensions[@]}"; do
safe_brew install --skip-link "${brew_opts[@]}" "$ext_tap/$dependency_extension@$version" >/dev/null 2>&1 &&
brew link --overwrite --force "$dependency_extension@$version" >/dev/null 2>&1 &&
copy_brew_extensions "$dependency_extension"
brew install "${brew_opts[@]}" "$ext_tap/$dependency_extension@$version" >/dev/null 2>&1 && copy_brew_extensions "$dependency_extension"
done
fi
}
@ -41,21 +39,10 @@ get_extension_from_formula() {
local formula=$1
local extension
extension=$(grep -E "^$formula=" "$src"/configs/brew_extensions | cut -d '=' -f 2)
[[ -z "$extension" ]] && extension="$(echo "$formula" | sed -E "s/pecl_|php|[0-9]//g")"
[[ -z "$extension" ]] && extension="$(echo "$formula" | sed -E "s/pecl_|[0-9]//g")"
echo "$extension"
}
# Function to get renamed formula.
get_renamed_formula() {
local formula=$1
formula_renames_json="$tap_dir/$ext_tap/formula_renames.json"
if [ -e "$formula_renames_json" ] && grep -q "$formula@$version\":" "$formula_renames_json"; then
grep "$formula@$version\":" "$formula_renames_json" | cut -d ':' -f 2 | tr -d ' ",' | cut -d '@' -f 1
else
echo "$formula"
fi
}
# Function to copy extension binaries to the extension directory.
copy_brew_extensions() {
local formula=$1
@ -82,14 +69,10 @@ add_brew_extension() {
else
add_brew_tap "$php_tap"
add_brew_tap "$ext_tap"
formula="$(get_renamed_formula "$formula")"
sudo mv "$tap_dir"/"$ext_tap"/.github/deps/"$formula"/* "${core_repo:?}/Formula/" 2>/dev/null || true
update_dependencies >/dev/null 2>&1
handle_dependency_extensions "$formula" "$extension" >/dev/null 2>&1
(
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
(brew install "${brew_opts[@]}" "$ext_tap/$formula@$version" >/dev/null 2>&1 && copy_brew_extensions "$formula") || pecl_install "$extension" >/dev/null 2>&1
add_extension_log "$extension" "Installed and enabled"
fi
}
@ -152,10 +135,8 @@ patch_brew() {
update_dependencies() {
patch_brew
if ! [ -e /tmp/update_dependencies ]; then
for repo in "$brew_repo" "${core_repo:?}"; do
if [ -e "$repo" ]; then
git_retry -C "$repo" fetch origin main && git -C "$repo" reset --hard origin/main
fi
for repo in "$brew_repo" "$core_repo"; do
git_retry -C "$repo" fetch origin master && git -C "$repo" reset --hard origin/master
done
echo '' | sudo tee /tmp/update_dependencies >/dev/null 2>&1
fi
@ -166,9 +147,9 @@ get_brewed_php() {
cellar="$brew_prefix"/Cellar
php_cellar="$cellar"/php
if [ -d "$cellar" ] && ! [[ "$(find "$cellar" -maxdepth 1 -name "php@$version*" | wc -l 2>/dev/null)" -eq 0 ]]; then
php_semver
php_semver | cut -c 1-3
elif [ -d "$php_cellar" ] && ! [[ "$(find "$php_cellar" -maxdepth 1 -name "$version*" | wc -l 2>/dev/null)" -eq 0 ]]; then
php_semver
php_semver | cut -c 1-3
else
echo 'false';
fi
@ -178,25 +159,17 @@ get_brewed_php() {
add_php() {
action=$1
existing_version=$2
add_brew_tap "$php_tap"
update_dependencies
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
update_dependencies
add_brew_tap "$php_tap"
fi
php_formula="shivammathur/php/php@$version$suffix"
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"
else
brew unlink "$php_keg"
fi
([ "$action" = "upgrade" ] && brew upgrade -f --overwrite "$php_formula") || brew unlink "$php_formula"
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"
brew install -f --overwrite "$php_formula"
fi
brew link --force --overwrite "$php_keg" || (sudo chown -R "$(id -un)":"$(id -gn)" "$brew_prefix" && brew link --force --overwrite "$php_keg")
sudo chown -R "$(id -un)":"$(id -gn)" "$brew_prefix"
brew link --force --overwrite "$php_formula"
}
# Function to get formula suffix
@ -236,11 +209,6 @@ get_scan_dir() {
fi
}
# Function to handle self-hosted runner setup.
self_hosted_helper() {
sudo mkdir -p /opt/hostedtoolcache >/dev/null 2>&1 || true
}
# Function to Setup PHP.
setup_php() {
step_log "Setup PHP"
@ -248,18 +216,18 @@ setup_php() {
update=true
check_pre_installed
existing_version=$(get_brewed_php)
status="Found"
if [[ "$version" =~ ${old_versions:?} ]]; then
run_script "php5-darwin" "${version/./}" >/dev/null 2>&1
status="Installed"
elif [ "${existing_version:0:3}" != "$version" ]; then
elif [ "$existing_version" != "$version" ]; then
add_php "install" "$existing_version" >/dev/null 2>&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
elif [ "$existing_version" = "$version" ]; then
if [ "${update:?}" = "true" ]; then
add_php "upgrade" "$existing_version" >/dev/null 2>&1
status="Upgraded"
status="Updated to"
else
status="Found"
fi
fi
php_config="$(command -v php-config)"
@ -284,7 +252,7 @@ setup_php() {
}
# Variables
version=${1:-'8.5'}
version=${1:-'8.4'}
ini=${2:-'production'}
src=${0%/*}/..
php_formula=shivammathur/php/php@"$version"

View File

@ -1,10 +1,8 @@
# Function to log result of installing extension.
add_extension_log() {
if check_extension ${1%%-*}; then
add_log "${tick:?}" "$1" "$2"
else
add_log "${cross:?}" "$1" "${3:-Could not install $1 on PHP ${semver:?}}"
fi
(
check_extension "$(echo "$1" | cut -d '-' -f 1)" && add_log "${tick:?}" "$1" "$2"
) || add_log "${cross:?}" "$1" "Could not install $1 on PHP ${semver:?}"
}
# Function to test if extension is loaded.
@ -218,7 +216,7 @@ add_pecl_extension() {
add_log "${tick:?}" "$extension" "Enabled"
else
[ -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)
pecl_install "$extension$pecl_version" || add_extension "$extension" "$(get_extension_prefix "$extension")" >/dev/null 2>&1
extension_version="$(php -r "echo phpversion('$extension');")"
[ -n "$extension_version" ] && extension_version="-$extension_version"
add_extension_log "$extension$extension_version" "Installed and enabled"

View File

@ -7,6 +7,15 @@ add_license_log() {
echo "$END_GROUP"
}
# Function to setup gcc-7 and g++-7
setup_compiler() {
if ! command -v gcc-7 >/dev/null || ! command -v g++-7 >/dev/null; then
add_ppa ubuntu-toolchain-r/test
add_packages gcc-7 g++-7 -y
fi
printf "gcc g++" | xargs -d ' ' -I {} sudo update-alternatives --install /usr/bin/{} {} /usr/bin/{}-7 7
}
# Function to set cubrid repo for the extension.
set_cubrid_repo() {
case "${ext:?}" in

View File

@ -1,3 +1,17 @@
add_firebird_client_darwin() {
firebird_tag='v5.0.0'
arch_name='x64'
arch="$(uname -m)"
[[ "$arch" = "arm64" || "$arch" = "aarch64" ]] && arch_name='arm64'
pkg_name=$(get -s -n "" https://api.github.com/repos/FirebirdSQL/firebird/releases/tags/"$firebird_tag" | grep -Eo "Firebird-.*.-$arch_name.pkg" | head -n 1)
[ -z "$pkg_name" ] && pkg_name=$(get -s -n "" https://github.com/FirebirdSQL/firebird/releases/expanded_assets/"$firebird_tag" | grep -Eo "Firebird-.*.-$arch_name.pkg" | head -n 1)
get -q -e "/tmp/firebird.pkg" https://github.com/FirebirdSQL/firebird/releases/download/"$firebird_tag"/"$pkg_name"
sudo installer -pkg /tmp/firebird.pkg -target /
sudo mkdir -p /opt/firebird/include /opt/firebird/lib
sudo cp -a /Library/Frameworks/Firebird.framework/Headers/* /opt/firebird/include/
sudo find /Library/Frameworks/Firebird.framework -name '*.dylib' -exec cp "{}" /opt/firebird/lib \;
}
add_firebird_helper() {
firebird_dir=$1
tag="$(php_src_tag)"
@ -9,19 +23,22 @@ add_firebird_helper() {
}
add_firebird() {
if [ "$(uname -s )" = "Darwin" ]; then
add_firebird_client_darwin >/dev/null 2>&1
fi
enable_extension pdo_firebird extension
if check_extension pdo_firebird; then
add_log "${tick:?}" pdo_firebird Enabled
else
status="Enabled"
if ! check_extension pdo_firebird; then
status="Installed and enabled"
if [ "$(uname -s)" = "Linux" ]; then
if [[ "${version:?}" =~ 5.3|${php_builder_versions:?} ]]; then
if [[ "${version:?}" =~ 5.3|${nightly_versions:?} ]]; then
add_firebird_helper /usr >/dev/null 2>&1
else
add_pdo_extension firebird >/dev/null 2>&1
fi
else
add_brew_extension pdo_firebird extension >/dev/null 2>&1
add_firebird_helper /opt/firebird >/dev/null 2>&1
fi
add_extension_log pdo_firebird "Installed and enabled"
fi
add_extension_log pdo_firebird "$status"
}

View File

@ -1,13 +1,12 @@
# Helper function to add gearman extension.
add_gearman_helper() {
add_ppa ondrej/pkg-gearman
install_packages libgearman-dev
enable_extension gearman extension
if ! check_extension gearman; then
status="Installed and enabled"
if [[ "${version:?}" =~ 5.[3-6] ]]; then
if [[ "${version:?}" =~ 5.[3-5] ]]; then
pecl_install gearman-1.1.2
elif [[ "${version:?}" =~ 7.0 ]]; then
pecl_install gearman-2.1.3
else
install_packages php"${version:?}"-gearman || pecl_install gearman
fi

View File

@ -61,7 +61,7 @@ add_http_helper() {
export HTTP_CONFIGURE_OPTS="$http_configure_opts"
export HTTP_LINUX_LIBS="zlib1g libbrotli-dev libcurl4-openssl-dev libevent-dev libicu-dev libidn2-dev"
export HTTP_DARWIN_LIBS="brotli curl icu4c libevent libidn2"
if ! [[ ${version:?} =~ 5.[3-6]|7.[0-4] ]]; then
if [[ "${version:?}" =~ ${nightly_versions:?} ]]; then
add_extension_from_source http https://github.com m6w6 ext-http master extension
else
add_extension_from_source pecl_http https://pecl.php.net http http "${ext##*-}" extension pecl

View File

@ -1,56 +0,0 @@
# Function to log license information for ibm extensions.
Function Add-LicenseLog() {
printf "$env:GROUP\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" $extension "Click to read the $extension related license information"
printf "IBM Db2 ODBC and CLI Driver is required for %s extension.\n" $extension
printf "It is provided under the IBM International Program License Agreement.\n"
printf "Refer to: \033[35;1m%s \033[0m\n" "https://www.ibm.com/support/pages/db2-odbc-cli-driver-download-and-installation-information"
$licensePath = "$php_dir\clidriver\license\odbc_notices.rtf"
if (Test-Path $licensePath) {
Add-Type -AssemblyName System.Windows.Forms
$rtBox = New-Object System.Windows.Forms.RichTextBox
$rtBox.Rtf = [System.IO.File]::ReadAllText($licensePath);
Write-Host $rtBox.Text;
}
Write-Output "$env:END_GROUP"
}
# Function to install IBM Db2 CLI driver.
Function Add-IbmCli() {
$cliPath = "$php_dir\clidriver"
if (-not (Test-Path "$cliPath\bin")) {
$suffix = if ($arch -eq 'x86') { 'nt32' } else { 'ntx64' }
$archive = "$suffix`_odbc_cli.zip"
$destination = "$ENV:RUNNER_TOOL_CACHE\ibm_cli.zip"
Get-File -Url "https://public.dhe.ibm.com/ibmdl/export/pub/software/data/db2/drivers/odbc_cli/$archive" -OutFile $destination > $null 2>&1
Expand-Archive -Path $destination -DestinationPath $php_dir -Force > $null 2>&1
}
$env:IBM_DB_HOME = $cliPath
$env:LD_LIBRARY_PATH = "$cliPath\bin;$cliPath\lib;$env:LD_LIBRARY_PATH"
Add-Path "$cliPath\bin"
$env:PATH = "$cliPath\bin;$env:PATH"
}
# Function to install ibm_db2 and pdo_ibm.
Function Add-Ibm() {
Param (
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNull()]
[ValidateSet('ibm_db2', 'pdo_ibm')]
[string]
$extension
)
try {
$status = 'Enabled'
Add-IbmCli
if (Test-Path "$ext_dir\php_$extension.dll") {
Enable-PhpExtension -Extension $extension -Path $php_dir
} else {
Add-Extension $extension
$status = 'Installed and enabled'
}
Add-ExtensionLog $extension $status
Add-LicenseLog
} catch {
Add-Log $cross $extension "Could not install $extension on PHP $( $installed.FullVersion )"
}
}

View File

@ -1,106 +0,0 @@
# Function to log license details for ibm extensions.
add_license_log() {
printf "$GROUP\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "$ext" "Click to read the $ext related license information"
printf "IBM Db2 ODBC and CLI Driver is required for %s extension.\n" "$ext"
printf "Refer to: \033[35;1m%s \033[0m\n" "https://www.ibm.com/support/pages/db2-odbc-cli-driver-download-and-installation-information"
local license_file="$ibm_cli/license/odbc_notices.txt"
if [ -f "$license_file" ]; then
cat "$license_file"
fi
echo "$END_GROUP"
}
# Function to determine the driver archive for the current platform.
get_cli_archive() {
local os=$1
local arch=$2
case $os in
Linux)
case $arch in
x86_64|amd64) echo "linuxx64_odbc_cli.tar.gz";;
i?86) echo "linuxia32_odbc_cli.tar.gz";;
*) return 1;;
esac
;;
Darwin)
case $arch in
x86_64) echo "macos64_odbc_cli.tar.gz";;
arm64|aarch64) echo "macarm64_odbc_cli.tar.gz";;
*) return 1;;
esac
;;
*)
return 1
;;
esac
}
# Function to install IBM Db2 CLI driver.
add_cli_driver() {
local os arch archive url tmp libs
if [ -d "$ibm_cli" ]; then
return 0
fi
os=$(uname -s)
arch=$(uname -m)
archive=$(get_cli_archive "$os" "$arch") || return 1
url="https://public.dhe.ibm.com/ibmdl/export/pub/software/data/db2/drivers/odbc_cli/$archive"
tmp=/tmp/$archive
get -q -n "$tmp" "$url"
sudo mkdir -p "$ibm_home"
sudo tar -xzf "$tmp" -C "$ibm_home"
sudo rm -f "$tmp"
if [ ! -d "$ibm_cli" ]; then
local extracted
extracted=$(find "$ibm_home" -maxdepth 1 -type d -name 'clidriver*' | head -n 1)
[ -n "$extracted" ] && sudo mv "$extracted" "$ibm_cli"
fi
if [ "$os" = "Linux" ]; then
echo "$ibm_cli/lib" | sudo tee /etc/ld.so.conf.d/ibm_db2.conf >/dev/null
sudo ldconfig
else
libs='/usr/local/lib'
sudo mkdir -p "$libs"
sudo ln -sf "$ibm_cli"/lib/*.dylib "$libs" >/dev/null 2>&1 || true
fi
}
# Function to install ibm_db2 and pdo_ibm.
add_ibm_helper() {
if ! shared_extension "$ext"; then
status='Installed and enabled'
export IBM_DB_HOME="$ibm_cli"
export LD_LIBRARY_PATH="$IBM_DB_HOME/lib"
add_env DYLD_LIBRARY_PATH "$IBM_DB_HOME/lib"
local configure_flag
if [ "$ext" = 'ibm_db2' ]; then
configure_flag="--with-IBM_DB2=$IBM_DB_HOME"
else
configure_flag="--with-pdo-ibm=$IBM_DB_HOME"
fi
read -r "${ext}_CONFIGURE_OPTS" <<< "--with-php-config=$(command -v php-config) $configure_flag"
patch_phpize
add_extension_from_source "$ext" https://github.com php "pecl-database-$ext" master extension get
restore_phpize
else
enable_extension "$ext" extension
fi
}
# Function to add ibm_db2 and pdo_ibm.
add_ibm() {
ext=$1
status='Enabled'
ibm_home='/opt/ibm'
ibm_cli=$ibm_home/clidriver
if ! add_cli_driver >/dev/null 2>&1; then
add_log "${cross:?}" "$ext" "IBM Db2 CLI driver is not available on $(uname -s)/$(uname -m)"
return 1
fi
add_ibm_helper >/dev/null 2>&1
add_extension_log "$ext" "$status"
check_extension "$ext" && add_license_log
}
# shellcheck source=.
. "${scripts:?}"/extensions/patches/phpize.sh

View File

@ -11,14 +11,13 @@ install_icu() {
# Function to add ext-intl with the given version of ICU
add_intl() {
icu=$(echo "$1" | cut -d'-' -f 2)
supported_version=$(get -s -n "" https://api.github.com/repos/shivammathur/icu-intl/releases/tags/intl-"$icu" | grep -Po "php${version?}-intl-$icu" | head -n 1)
[ -z "$supported_version" ] && supported_version=$(get -s -n "" https://github.com/shivammathur/icu-intl/releases/expanded_assets/intl-"$icu" | grep -Po "php$version-intl-$icu" | head -n 1)
if [ "php$version-intl-$icu" != "$supported_version" ]; then
add_log "${cross:?}" "intl" "ICU $icu is not supported for PHP $version"
supported_version=$(get -s -n "" https://api.github.com/repos/shivammathur/icu-intl/releases | grep -Po "${icu//./\\.}" | head -n 1)
if [ "$icu" != "$supported_version" ]; then
add_log "${cross:?}" "intl" "ICU $icu is not supported"
else
[ "${ts:?}" = 'zts' ] && suffix='-zts'
install_icu "$icu" >/dev/null 2>&1
get -q -n "${ext_dir:?}/intl.so" "https://github.com/shivammathur/icu-intl/releases/download/intl-$icu/php${version:?}-intl-$icu$suffix$arch_suffix.so"
get -q -n "${ext_dir:?}/intl.so" "https://github.com/shivammathur/icu-intl/releases/download/intl/php${version:?}-intl-$icu$suffix$arch_suffix.so"
enable_extension intl extension
add_extension_log intl "Installed and enabled with ICU $icu"
fi

View File

@ -38,7 +38,7 @@ add_client() {
sudo mv "$icdir"/* "$oracle_client"/
done
sudo mkdir -p "$libs"
sudo ln -sf /opt/oracle/instantclient/*."$lib_ext"* "$libs"
sudo ln -sf /opt/oracle/instantclient/*.$lib_ext* $libs
if [ "$os" = "Linux" ]; then
[ -e "$libs/$arch"-linux-gnu/libaio.so.1 ] || sudo ln -sf "$libs/$arch"-linux-gnu/libaio.so.1t64 "$libs/$arch"-linux-gnu/libaio.so.1
fi
@ -49,7 +49,6 @@ add_client() {
add_oci_helper() {
if ! shared_extension "$ext"; then
status='Installed and enabled'
read -r "${ext}_CONFIGURE_PREFIX_OPTS" <<< "CFLAGS=-Wno-incompatible-function-pointer-types"
read -r "${ext}_LINUX_LIBS" <<< "libaio-dev"
read -r "${ext}_CONFIGURE_OPTS" <<< "--with-php-config=$(command -v php-config) --with-${ext/_/-}=instantclient,$oracle_client"
patch_phpize

View File

@ -1,5 +0,0 @@
patch_amqp() {
if [[ $(printf '%s\n%s\n' "${version:?}" "8.5" | sort -V | head -n1) == "8.5" ]]; then
get -q -n amqp_connection_resource.c https://raw.githubusercontent.com/remicollet/php-amqp/977449987412a3d5c59a036dbab8b6d67764bb3e/amqp_connection_resource.c
fi
}

View File

@ -1,35 +1,12 @@
patch_84() {
sed -i.bak \
-e '0,/#include.*\(php_lcg.h\|php_mt_rand.h\|php_rand.h\|standard\/php_random\.h\).*/s//#include <ext\/random\/php_random.h>/' \
-e '/#include.*\(php_lcg.h\|php_mt_rand.h\|php_rand.h\|standard\/php_random\.h\)/d' \
"$1" && rm -rf *.bak
process_file() {
local file=$1
sed -i'' -e '0,/#include.*\(php_lcg.h\|php_mt_rand.h\|php_rand.h\|standard\/php_random\.h\).*/s//\#include <ext\/random\/php_random.h>/' "$file"
sed -i'' -e '/#include.*\(php_lcg.h\|php_mt_rand.h\|php_rand.h\|standard\/php_random\.h\)/d' "$file"
}
patch_85() {
sed -i.bak \
-e 's#ext/standard/php_smart_string.h#Zend/zend_smart_string.h#g' \
-e 's#ext/standard/php_smart_string_public.h#Zend/zend_smart_string.h#g' \
-e 's#zend_exception_get_default(TSRMLS_C)#zend_ce_exception#g' \
-e 's#zend_exception_get_default()#zend_ce_exception#g' \
"$1" && rm -rf *.bak
}
export -f process_file
version_ge() {
ver=$1
min=$2
[[ $(printf '%s\n%s\n' "$ver" "$min" | sort -V | head -n1) == "$min" ]]
}
if version_ge "${version:?}" "8.4"; then
while IFS= read -r file; do
patch_84 "$file"
done < <(grep -rlE 'php_lcg\.h|php_mt_rand\.h|php_rand\.h|standard/php_random\.h' \
--include='*.c' --include='*.h' . || true)
fi
if version_ge "${version:?}" "8.5"; then
while IFS= read -r file; do
patch_85 "$file"
done < <(grep -rlE 'ext/standard/php_smart_string(_public)?\.h|zend_exception_get_default' \
--include='*.c' --include='*.h' . || true)
# Compare with 8.3 so it runs only on 8.4 and above
if [[ $(printf "%s\n%s" "${version:?}" "8.3" | sort -V | head -n1) != "$version" ]]; then
find . -type f \( -name "*.c" -o -name "*.h" \) -exec bash -c 'process_file "$0"' {} \;
fi

View File

@ -1,5 +1,5 @@
patch_geos() {
if [[ $(printf '%s\n%s\n' "${version:?}" "7.0" | sort -V | head -n1) == "7.0" ]]; then
if [ "$(php -r "echo PHP_VERSION_ID;")" -ge 70000 ]; 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

View File

@ -1,8 +1,5 @@
patch_pdo_oci() {
get -q -n config.m4 https://raw.githubusercontent.com/php/php-src/PHP-8.0/ext/pdo_oci/config.m4
if [[ $(printf '%s\n%s\n' "${version:?}" "8.5" | sort -V | head -n1) == "8.5" ]]; then
get -q -n pdo_oci.c https://raw.githubusercontent.com/shivammathur/pecl-database-pdo_oci/a9cf2c53b6de46f9e5f523bcd11fd344e3beeb85/pdo_oci.c
fi
if [[ ${version:?} =~ 5.[3-6] ]]; then
sudo sed -i '' "/PHP_CHECK_PDO_INCLUDES/d" config.m4 2>/dev/null || sudo sed -i "/PHP_CHECK_PDO_INCLUDES/d" config.m4
fi

View File

@ -1,5 +0,0 @@
if [[ $(printf '%s\n%s\n' "${version:?}" "8.5" | sort -V | head -n1) == "8.5" ]]; then
sed -i.bak -e 's/zval_ptr_dtor( &dbh->query_stmt_zval );/OBJ_RELEASE(dbh->query_stmt_obj);dbh->query_stmt_obj = NULL;/' php_pdo_sqlsrv_int.h
sed -i.bak -e 's/pdo_error_mode prev_err_mode/uint8_t prev_err_mode/g' pdo_dbh.cpp
rm -rf *.bak
fi

View File

@ -3,8 +3,7 @@ get_phpize() {
if [[ "${version:?}" =~ 5.[3-5] ]]; then
echo '/opt/local/bin/phpize'
else
[ -n "$brew_prefix" ] && phpize_dir="$brew_prefix" || phpize_dir="/usr/local/bin"
echo "${phpize_dir}/bin/$(readlink ${phpize_dir}/bin/phpize)"
echo "/usr/local/bin/$(readlink /usr/local/bin/phpize)"
fi
}

View File

@ -2,9 +2,11 @@
get_relay_version() {
local ext=$1
if [[ "$ext" =~ ^relay$ ]]; then
get -s -n "" "${relay_release:?}"
elif [[ $ext =~ ^relay-nightly$ ]]; then
echo "dev"
if [ "${version:?}" = "7.4" ]; then
echo 'v0.7.0'
else
get -s -n "" "${relay_releases:?}"/latest 2<&1 | grep -m 1 -Eo "tag/(v[0-9]+(\.[0-9]+)?(\.[0-9]+)?)" | head -n 1 | cut -d '/' -f 2
fi
else
relay_version="${ext##*-}"
echo "v${relay_version/v//}"
@ -36,10 +38,7 @@ get_openssl_suffix() {
change_library_paths() {
if [ "$os" = "Darwin" ]; then
otool -L "${ext_dir:?}"/relay.so | grep -q 'ssl.1' && openssl_version='1.1' || openssl_version='3'
[ -e "${brew_prefix:?}"/opt/openssl@"$openssl_version" ] || {
safe_brew install --skip-link openssl@"$openssl_version" &&
brew link --overwrite --force openssl@"$openssl_version"
}
[ -e "${brew_prefix:?}"/opt/openssl@"$openssl_version" ] || brew install openssl@"$openssl_version"
dylibs="$(otool -L "${ext_dir:?}"/relay.so | grep -Eo '.*\.dylib' | cut -f1 -d ' ')"
install_name_tool -change "$(echo "${dylibs}" | grep -E "libzstd.*dylib" | xargs)" "$brew_prefix"/opt/zstd/lib/libzstd.dylib "$ext_dir"/relay.so
install_name_tool -change "$(echo "${dylibs}" | grep -E "liblz4.*dylib" | xargs)" "$brew_prefix"/opt/lz4/lib/liblz4.dylib "$ext_dir"/relay.so
@ -49,6 +48,14 @@ change_library_paths() {
fi
}
# Link hiredis library
link_hiredis() {
lib_dir="${brew_prefix:?}"/opt/hiredis/lib
if [ -e "$lib_dir"/libhiredis_ssl.1.1.0.dylib ]; then
sudo ln -sf "$lib_dir"/libhiredis_ssl.1.1.0.dylib "$lib_dir"/libhiredis_ssl.dylib.1.1.0
fi
}
# Add relay dependencies
add_relay_dependencies() {
add_extension json
@ -57,7 +64,8 @@ add_relay_dependencies() {
if [ "$os" = "Darwin" ]; then
. "${0%/*}"/tools/brew.sh
configure_brew
safe_brew install lz4 hiredis zstd concurrencykit
brew install hiredis lz4 zstd concurrencykit
link_hiredis
fi
}
@ -111,7 +119,7 @@ configure_relay() {
# Helper function to add relay extension
add_relay_helper() {
local arch=$1
arch="$(uname -m | sed 's/_/-/')"
os_suffix="$(get_os_suffix)"
openssl_suffix="$(get_openssl_suffix)"
artifact_file_name="relay-$relay_version-php${version:?}-$os_suffix-$arch$openssl_suffix.tar.gz"
@ -135,24 +143,17 @@ add_relay() {
local ext=$1
local arch
local url
local message
local error
os=$(uname -s)
arch="$(uname -m | sed 's/_/-/')"
relay_release=https://builds.r2.relay.so/meta/latest
relay_releases=https://github.com/cachewerk/relay/releases
relay_trunk=https://builds.r2.relay.so
if [[ "$arch" = "x86-64" && "$os" = "Darwin" ]]; then
error="Relay extension is not available for macOS x86_64 architecture"
relay_version=$(get_relay_version "$ext")
add_relay_dependencies >/dev/null 2>&1
if shared_extension relay; then
message="Enabled"
else
relay_version=$(get_relay_version "$ext")
add_relay_dependencies >/dev/null 2>&1
if shared_extension relay; then
message="Enabled"
else
add_relay_helper "$arch" >/dev/null 2>&1
message="Installed and enabled ${relay_version}"
fi
configure_relay >/dev/null 2>&1
add_relay_helper >/dev/null 2>&1
message="Installed and enabled"
fi
add_extension_log relay "$message" "$error"
configure_relay >/dev/null 2>&1
add_extension_log relay "$message"
}

View File

@ -1,7 +1,3 @@
os="$(uname -s)"
os_lower=$(echo "$os" | tr '[:upper:]' '[:lower:]')
os_capital=$(echo "$os" | tr '[:lower:]' '[:upper:]')
# Function to parse extension environment variables
parse_args() {
local extension=${1%-*}
@ -40,7 +36,7 @@ add_lib_log() {
# Function to check if a library is installed
check_lib() {
local lib=$1
if [ "$os" = "Linux" ]; then
if [ "$(uname -s)" = "Linux" ]; then
[ "x$(dpkg -s "$lib" 2>/dev/null | grep Status)" != "x" ]
else
[ "x$(find "${brew_prefix:?}"/Cellar -maxdepth 1 -name "$lib")" != "x" ]
@ -60,11 +56,9 @@ add_linux_libs() {
add_darwin_libs() {
local lib=$1
if ! check_lib "$lib"; then
brew install "$lib" >/dev/null 2>&1 || true
if [[ "$lib" = *@* ]]; then
safe_brew install --skip-link "$lib" >/dev/null 2>&1 || true
brew link --overwrite --force "$lib" >/dev/null 2>&1 || true
else
safe_brew install "$lib" >/dev/null 2>&1 || true
fi
fi
add_lib_log "$lib"
@ -74,7 +68,7 @@ add_darwin_libs() {
add_libs() {
local all_libs=("$@")
for lib in "${all_libs[@]}"; do
if [ "$os" = "Linux" ]; then
if [ "$(uname -s)" = "Linux" ]; then
add_linux_libs "$lib"
else
add_darwin_libs "$lib"
@ -82,19 +76,6 @@ add_libs() {
done
}
# Function to get required libraries for an extension
get_libraries() {
local extension=$1
{
parse_args "$extension" LIBS
parse_args "$extension" "$os_capital"_LIBS
[ -r "${src:?}/configs/${os_lower}_libs" ] && \
grep -E "^[[:space:]]*${extension}[[:space:]]*=" "${src:?}/configs/${os_lower}_libs" | \
head -n1 | \
sed -E "s/^[[:space:]]*${extension}[[:space:]]*=[[:space:]]*//"
} | xargs -n 1 2>/dev/null | sort -u | xargs 2>/dev/null
}
# Function to run command in a group
run_group() {
local command=$1
@ -102,10 +83,8 @@ run_group() {
echo "$command" | sudo tee ./run_group.sh >/dev/null 2>&1
echo "$GROUP$log"
. ./run_group.sh
local status=$?
rm ./run_group.sh
echo "$END_GROUP"
return $status
}
patch_extension() {
@ -138,10 +117,9 @@ fetch_extension() {
elif [ "$fetch" = "pecl" ]; then
source="pecl"
pecl_name=${extension/http/pecl_http}
capital_pecl_name=$(echo "$pecl_name" | tr '[:lower:]' '[:upper:]')
get -q -n /tmp/"$pecl_name".tgz https://pecl.php.net/get/"$pecl_name"-"$release".tgz https://pecl.php.net/get/"$capital_pecl_name"-"$release".tgz
get -q -n /tmp/"$pecl_name".tgz https://pecl.php.net/get/"$pecl_name"-"$release".tgz
tar -xzf /tmp/"$pecl_name".tgz -C /tmp
cd /tmp/"$pecl_name"-"$release" 2>/dev/null || cd /tmp/"$capital_pecl_name"-"$release" 2>/dev/null || exit
cd /tmp/"$pecl_name"-"$release" || exit
fi
}
@ -156,7 +134,7 @@ add_extension_from_source() {
local fetch=${7:-clone}
slug="$extension-$release"
source="$url/$org/$repo"
libraries="$(get_libraries "$extension")"
libraries="$(parse_args "$extension" LIBS) $(parse_args "$extension" "$(uname -s)"_LIBS)"
opts="$(parse_args "$extension" CONFIGURE_OPTS)"
prefix_opts="$(parse_args "$extension" CONFIGURE_PREFIX_OPTS)"
suffix_opts="$(parse_args "$extension" CONFIGURE_SUFFIX_OPTS)"
@ -172,10 +150,10 @@ add_extension_from_source() {
[[ -n "${libraries// }" ]] && run_group "add_libs $libraries" "add libraries"
[ "${debug:?}" = "debug" ] && suffix_opts="$suffix_opts --enable-debug"
patch_extension "$extension" >/dev/null 2>&1
run_group "phpize" "phpize" && \
run_group "sudo $prefix_opts ./configure $suffix_opts $opts" "configure" && \
run_group "sudo $prefix_opts make -j$(nproc 2>/dev/null || sysctl -n hw.ncpu)" "make" && \
run_group "sudo make install" "make install" && \
run_group "phpize" "phpize"
run_group "sudo $prefix_opts ./configure $suffix_opts $opts" "configure"
run_group "sudo $prefix_opts make -j$(nproc 2>/dev/null || sysctl -n hw.ncpu)" "make"
run_group "sudo make install" "make install"
enable_extension "$extension" "$prefix"
fi
)

View File

@ -9,8 +9,6 @@ Function Get-SqlsrvReleaseVersion() {
return '5.10.1'
} elseif ($version -eq '8.0') {
return '5.11.1'
} elseif ($version -match '8.[1-2]') {
return '5.12.0'
} else {
return 'latest'
}

View File

@ -6,8 +6,6 @@ get_sqlsrv_version() {
echo '5.10.1'
elif [[ "${version:?}" =~ 8.0 ]]; then
echo '5.11.1'
elif [[ "${version:?}" =~ 8.[1-2] ]]; then
echo '5.12.0'
else
# Return an empty string so that pecl will install the latest version.
echo ''

View File

@ -20,7 +20,6 @@ self_hosted_helper() {
sudo ln -sf /usr/bin/apt-get /usr/bin/apt-fast
trap "sudo rm -f /usr/bin/apt-fast 2>/dev/null" exit
fi
sudo mkdir -p /opt/hostedtoolcache >/dev/null 2>&1 || true
install_packages apt-transport-https ca-certificates curl file make jq unzip autoconf automake gcc g++ gnupg
}
@ -187,7 +186,7 @@ update_php() {
# Function to install PHP.
add_php() {
if [ "${runner:?}" = "self-hosted" ] || [ "${use_package_cache:-true}" = "false" ]; then
if [[ "$version" =~ ${php_builder_versions:?} || "$ts" = "zts" ]]; then
if [[ "$version" =~ ${nightly_versions:?} || "$ts" = "zts" ]]; then
setup_php_builder
else
add_packaged_php
@ -291,7 +290,7 @@ setup_php() {
}
# Variables
version=${1:-'8.5'}
version=${1:-'8.4'}
ini=${2:-'production'}
src=${0%/*}/..
debconf_fix="DEBIAN_FRONTEND=noninteractive"

View File

@ -28,52 +28,6 @@ Function Edit-ComposerConfig() {
Set-ComposerAuth
}
# Function to update auth.json.
Function Update-AuthJson {
[CmdletBinding()]
param(
[Parameter(Mandatory)][string[]] $ComposerAuth
)
if (Test-Path $composer_home\auth.json) {
try {
$existing = Get-Content $composer_home\auth.json -Raw | ConvertFrom-Json
} catch {
$existing = [PSCustomObject]@{}
}
} else {
$existing = [PSCustomObject]@{}
}
foreach ($fragment in $ComposerAuth) {
$piece = ('{' + $fragment + '}') | ConvertFrom-Json
foreach ($prop in $piece.PSObject.Properties) {
if ($prop.Name -eq 'http-basic') {
if (-not $existing.'http-basic') {
$existing | Add-Member -MemberType NoteProperty -Name 'http-basic' -Value ([PSCustomObject]@{}) -Force
}
foreach ($domainProp in $prop.Value.PSObject.Properties) {
$existing.'http-basic' | Add-Member -MemberType NoteProperty -Name $domainProp.Name -Value $domainProp.Value -Force
}
} else {
$existing | Add-Member -MemberType NoteProperty -Name $prop.Name -Value $prop.Value -Force
}
}
}
Set-Content -Path $composer_home\auth.json -Value ($existing | ConvertTo-Json -Depth 5)
}
function Test-GitHubPublicAccess {
param(
[Parameter(Mandatory=$true)]
[string]$Token
)
try {
Invoke-RestMethod -Uri 'https://api.github.com/' -Headers @{ Authorization = "token $Token" } -ErrorAction Stop | Out-Null
return $true
} catch {
return $false
}
}
# Function to setup authentication in composer.
Function Set-ComposerAuth() {
if(Test-Path env:COMPOSER_AUTH_JSON) {
@ -87,18 +41,14 @@ Function Set-ComposerAuth() {
if(Test-Path env:PACKAGIST_TOKEN) {
$composer_auth += '"http-basic": {"repo.packagist.com": { "username": "token", "password": "' + $env:PACKAGIST_TOKEN + '"}}'
}
$write_token = $true
$token = if ($env:COMPOSER_TOKEN) { $env:COMPOSER_TOKEN } else { $env:GITHUB_TOKEN }
if ($token) {
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(-not(Test-Path env:GITHUB_TOKEN) -and (Test-Path env:COMPOSER_TOKEN)) {
$env:GITHUB_TOKEN = $env:COMPOSER_TOKEN
}
if (Test-Path env:GITHUB_TOKEN) {
$composer_auth += '"github-oauth": {"github.com": "' + $env:GITHUB_TOKEN + '"}'
}
if($composer_auth.length) {
Update-AuthJson $composer_auth
Add-Env COMPOSER_AUTH ('{' + ($composer_auth -join ',') + '}')
}
}
@ -108,11 +58,6 @@ Function Set-ComposerEnv() {
(Get-Content $src\configs\composer.env -Raw) -replace '(?m)^COMPOSER_PROCESS_TIMEOUT=.*$', "COMPOSER_PROCESS_TIMEOUT=$env:COMPOSER_PROCESS_TIMEOUT" | Set-Content $src\configs\composer.env
}
Add-EnvPATH $src\configs\composer.env
if($env:COMPOSER_ALLOW_PLUGINS) {
$env:COMPOSER_ALLOW_PLUGINS -split '\s*,\s*' | Where-Object { $_ } | ForEach-Object {
& composer global config --no-plugins "allow-plugins.$_" true > $null 2>&1
}
}
}
# Function to extract tool version.
@ -158,7 +103,12 @@ Function Add-ToolsHelper() {
} elseif($tool -eq "cs2pr") {
(Get-Content $bin_dir/cs2pr).replace('exit(9)', 'exit(0)') | Set-Content $bin_dir/cs2pr
} elseif($tool -eq "deployer") {
Copy-Item $bin_dir\deployer.bat -Destination $bin_dir\dep.bat
if(Test-Path $composer_bin\deployer.phar.bat) {
Copy-Item $composer_bin\deployer.phar.bat -Destination $composer_bin\dep.bat
}
if(Test-Path $composer_bin\dep.bat) {
Copy-Item $composer_bin\dep.bat -Destination $composer_bin\deployer.bat
}
} elseif($tool -eq "phan") {
$extensions += @('fileinfo', 'ast')
} elseif($tool -eq "phinx") {
@ -200,48 +150,30 @@ Function Add-Tool() {
[Parameter(Position = 2, Mandatory = $false)]
$ver_param
)
$urls = $urls -split ','
if (Test-Path $bin_dir\$tool) {
Copy-Item $bin_dir\$tool -Destination $bin_dir\$tool.old -Force
}
$tool_path = "$bin_dir\$tool"
$is_exe = ((($urls[0] | Split-Path -Extension).ToLowerInvariant()) -eq '.exe')
if ($is_exe) { $tool_path = "$tool_path.exe" }
$tool_ext = if ($is_exe) { '.exe' } else { '' }
$url_stream = [System.IO.MemoryStream]::New([System.Text.Encoding]::UTF8.GetBytes($urls[0]))
$cache_key = (Get-FileHash -InputStream $url_stream -Algorithm SHA256).Hash.Substring(0, 16)
$cache_path = "$env:TEMP\$tool-$cache_key$tool_ext"
$status_code = 200
if (Test-Path $cache_path -PathType Leaf) {
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 }
foreach ($url in $urls){
try {
$status_code = (Invoke-WebRequest -Passthru -Uri $url -OutFile $tool_path).StatusCode
} catch {
if($url -match '.*github.com.*releases.*latest.*') {
try {
$url = $url.replace("releases/latest/download", "releases/download/" + ([regex]::match((Get-File -Url ($url.split('/release')[0] + "/releases")).Content, "([0-9]+\.[0-9]+\.[0-9]+)/" + ($url.Substring($url.LastIndexOf("/") + 1))).Groups[0].Value).split('/')[0])
$status_code = (Invoke-WebRequest -Passthru -Uri $url -OutFile $tool_path).StatusCode
} catch {
$status_code = 0
}
} else {
$status_code = 0
}
}
if($status_code -eq 200 -and (Test-Path $tool_path)) {
Copy-Item $tool_path -Destination $cache_path -Force
break
foreach ($url in $urls){
if (($url | Split-Path -Extension) -eq ".exe") {
$tool_path = "$tool_path.exe"
}
try {
$status_code = (Invoke-WebRequest -Passthru -Uri $url -OutFile $tool_path).StatusCode
} catch {
if($url -match '.*github.com.*releases.*latest.*') {
try {
$url = $url.replace("releases/latest/download", "releases/download/" + ([regex]::match((Get-File -Url ($url.split('/release')[0] + "/releases")).Content, "([0-9]+\.[0-9]+\.[0-9]+)/" + ($url.Substring($url.LastIndexOf("/") + 1))).Groups[0].Value).split('/')[0])
$status_code = (Invoke-WebRequest -Passthru -Uri $url -OutFile $tool_path).StatusCode
} catch { }
}
}
if ($status_code -ne 200 -and (Test-Path $backup_path)) {
Copy-Item $backup_path -Destination $tool_path -Force
if($status_code -eq 200 -and (Test-Path $tool_path)) {
break
}
Remove-Item $backup_path -Force -ErrorAction SilentlyContinue
}
$escaped_tool = [regex]::Escape($tool)
if (((Get-ChildItem -Path $bin_dir/* | Where-Object Name -Match "^$escaped_tool(\.exe|\.phar)?$").Count -gt 0)) {
if (((Get-ChildItem -Path $bin_dir/* | Where-Object Name -Match "^$tool(.exe|.phar)*$").Count -gt 0)) {
$bat_content = @()
$bat_content += "@ECHO off"
$bat_content += "setlocal DISABLEDELAYEDEXPANSION"
@ -255,6 +187,8 @@ Function Add-Tool() {
} else {
if($tool -eq "composer") {
$env:fail_fast = 'true'
} elseif (Test-Path $bin_dir\$tool.old) {
Copy-Item $bin_dir\$tool.old -Destination $bin_dir\$tool -Force
}
Add-Log $cross $tool "Could not add $tool"
}

View File

@ -11,7 +11,7 @@ get_tool_version() {
alp="[a-zA-Z0-9\.]"
version_regex="[0-9]+((\.{1}$alp+)+)(\.{0})(-$alp+){0,1}"
if [ "$tool" = "composer" ]; then
composer_alias_version="$(grep -Ea "const\sBRANCH_ALIAS_VERSION" "${tool_path_dir:?}/composer" | grep -Eo "$version_regex")"
composer_alias_version="$(grep -Ea "const\sBRANCH_ALIAS_VERSION" "$tool_path_dir/composer" | grep -Eo "$version_regex")"
if [[ -n "$composer_alias_version" ]]; then
composer_version="$composer_alias_version+$(grep -Ea "const\sVERSION" "$tool_path_dir/composer" | grep -Eo "$alp+" | tail -n 1)"
else
@ -46,30 +46,6 @@ configure_composer() {
set_composer_auth
}
# Function to merge auth.json fragments.
update_auth_json() {
local auth_file="$composer_home/auth.json"
local merged
[[ -f "$auth_file" ]] && merged=$(<"$auth_file") || merged='{}'
for frag in "$@"; do
local obj="{$frag}"
merged=$(jq -n --argjson b "$merged" --argjson n "$obj" '
if $n|has("http-basic") then
(($b["http-basic"]//{}) + $n["http-basic"]) as $hb
| ($b + $n) | .["http-basic"] = $hb
else
$b + $n
end
')
done
printf '%s' "$merged" > "$composer_home/auth.json"
}
# Function to check if public GitHub token authentication is possible.
can_access_public_github() {
curl --fail -s -H "Authorization: token $1" 'https://api.github.com/' >/dev/null 2>&1
}
# Function to setup authentication in composer.
set_composer_auth() {
if [ -n "$COMPOSER_AUTH_JSON" ]; then
@ -83,18 +59,11 @@ set_composer_auth() {
if [ -n "$PACKAGIST_TOKEN" ]; then
composer_auth+=( '"http-basic": {"repo.packagist.com": { "username": "token", "password": "'"$PACKAGIST_TOKEN"'"}}' )
fi
token="${COMPOSER_TOKEN:-$GITHUB_TOKEN}"
if [ -n "$token" ]; then
write_token=true
if [ "$GITHUB_SERVER_URL" != "https://github.com" ]; then
can_access_public_github "$token" || write_token=false
fi
if [ "$write_token" = 'true' ]; then
composer_auth+=( '"github-oauth": {"github.com": "'"$token"'"}' )
fi
if [ -n "${GITHUB_TOKEN:-$COMPOSER_TOKEN}" ]; then
composer_auth+=( '"github-oauth": {"github.com": "'"${GITHUB_TOKEN:-$COMPOSER_TOKEN}"'"}' )
fi
if ((${#composer_auth[@]})); then
update_auth_json "${composer_auth[@]}"
add_env COMPOSER_AUTH "{$(IFS=$','; echo "${composer_auth[*]}")}"
fi
}
@ -106,11 +75,6 @@ set_composer_env() {
sed -i "$sed_arg" "$composer_env" 2>/dev/null || sed -i '' "$sed_arg" "$composer_env"
fi
add_env_path "$composer_env"
if [ -n "$COMPOSER_ALLOW_PLUGINS" ]; then
echo "$COMPOSER_ALLOW_PLUGINS" | tr ',' '\n' | sed 's/^[[:space:]]*//;s/[[:space:]]*$//' | grep -v '^$' | while IFS= read -r plugin; do
composer global config --no-plugins "allow-plugins.$plugin" true >/dev/null 2>&1
done
fi
}
# Helper function to configure tools.
@ -123,15 +87,19 @@ add_tools_helper() {
extensions+=(iconv mbstring phar sodium)
elif [ "$tool" = "codeception" ]; then
extensions+=(json mbstring)
sudo ln -s "$scoped_dir"/vendor/bin/codecept "$scoped_dir"/vendor/bin/codeception 2>/dev/null || true
sudo ln -s "$scoped_dir"/vendor/bin/codecept "$scoped_dir"/vendor/bin/codeception
elif [ "$tool" = "composer" ]; then
configure_composer "$tool_path"
elif [ "$tool" = "cs2pr" ]; then
sudo sed -i 's/\r$//; s/exit(9)/exit(0)/' "$tool_path" 2>/dev/null ||
sudo sed -i '' 's/\r$//; s/exit(9)/exit(0)/' "$tool_path"
elif [ "$tool" = "deployer" ]; then
sudo ln -s "$tool_path" "$tool_path_dir"/deployer 2>/dev/null || true
sudo ln -s "$tool_path" "$tool_path_dir"/dep 2>/dev/null || true
if [ -e "$composer_bin"/deployer.phar ]; then
sudo ln -s "$composer_bin"/deployer.phar "$composer_bin"/dep
fi
if [ -e "$composer_bin"/dep ]; then
sudo ln -s "$composer_bin"/dep "$composer_bin"/deployer
fi
elif [ "$tool" = "phan" ]; then
extensions+=(fileinfo ast)
elif [ "$tool" = "phinx" ]; then
@ -147,7 +115,7 @@ add_tools_helper() {
elif [ "$tool" = "phpDocumentor" ]; then
extensions+=(ctype hash json fileinfo iconv mbstring simplexml xml)
sudo ln -s "$tool_path" "$tool_path_dir"/phpdocumentor 2>/dev/null || true
sudo ln -s "$tool_path" "$tool_path_dir"/phpdoc 2>/dev/null || true
sudo ln -s "$tool_path" "$tool_path_dir"/phpdoc
elif [ "$tool" = "phpunit" ]; then
extensions+=(dom json libxml mbstring xml xmlwriter)
elif [ "$tool" = "phpunit-bridge" ]; then
@ -158,9 +126,9 @@ add_tools_helper() {
fi
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
sudo ln -s "$scoped_dir"/vendor/bin/vapor "$scoped_dir"/vendor/bin/vapor-cli
elif [ "$tool" = wp-cli ]; then
sudo ln -s "$tool_path" "$tool_path_dir"/"${tool%-*}" 2>/dev/null || true
sudo ln -s "$tool_path" "$tool_path_dir"/"${tool%-*}"
fi
for extension in "${extensions[@]}"; do
add_extension "$extension" extension >/dev/null 2>&1
@ -176,45 +144,27 @@ add_tool() {
if ! [ -d "$tool_path_dir" ]; then
sudo mkdir -p "$tool_path_dir"
fi
if ! [ -d "$tool_cache_path_dir" ]; then
sudo mkdir -p "$tool_cache_path_dir"
add_path "$tool_path_dir"
if [ -e "$tool_path" ]; then
sudo cp -aL "$tool_path" /tmp/"$tool"
fi
add_path "$tool_path_dir" verify
add_path "$tool_cache_path_dir"
IFS="," read -r -a url <<<"$url"
cache_key=$(get_sha256 "${url[0]}" | head -c 16)
cache_path="$tool_cache_path_dir/${tool}-${cache_key}"
status_code="200"
if [ -f "$cache_path" ]; then
sudo cp -a "$cache_path" "$tool_path"
else
[ -f "$tool_path" ] && sudo cp -a "$tool_path" "$tool_path.bak"
status_code=$(get -v -e "$tool_path" "${url[@]}")
if [ "$status_code" != "200" ] && [[ "${url[0]}" =~ .*github.com.*releases.*latest.* ]]; then
url[0]="${url[0]//releases\/latest\/download/releases/download/$(get -s -n "" "$(echo "${url[0]}" | cut -d '/' -f '1-5')/releases" | grep -Eo -m 1 "([0-9]+\.[0-9]+\.[0-9]+)/$(echo "${url[0]}" | sed -e "s/.*\///")" | cut -d '/' -f 1)}"
status_code=$(get -v -e "$tool_path" "${url[0]}")
fi
if [ "$status_code" = "200" ]; then
sudo cp -a "$tool_path" "$cache_path"
elif [ -f "$tool_path.bak" ]; then
sudo mv "$tool_path.bak" "$tool_path"
fi
sudo rm -f "$tool_path.bak"
status_code=$(get -v -e "$tool_path" "${url[@]}")
if [ "$status_code" != "200" ] && [[ "${url[0]}" =~ .*github.com.*releases.*latest.* ]]; then
url[0]="${url[0]//releases\/latest\/download/releases/download/$(get -s -n "" "$(echo "${url[0]}" | cut -d '/' -f '1-5')/releases" | grep -Eo -m 1 "([0-9]+\.[0-9]+\.[0-9]+)/$(echo "${url[0]}" | sed -e "s/.*\///")" | cut -d '/' -f 1)}"
status_code=$(get -v -e "$tool_path" "${url[0]}")
fi
if [ "$status_code" = "200" ]; then
add_tools_helper "$tool"
[ -L "$tool_cache_path_dir/$tool" ] || sudo ln -s "$tool_path" "$tool_cache_path_dir/$tool" 2>/dev/null || true
tool_version=$(get_tool_version "$tool" "$ver_param")
add_log "${tick:?}" "$tool" "Added $tool $tool_version"
else
if [ "$tool" = "composer" ]; then
export fail_fast=true
elif [ -e /tmp/"$tool" ]; then
sudo cp -a /tmp/"$tool" "$tool_path"
fi
if [ "$status_code" = "404" ]; then
add_log "$cross" "$tool" "Failed to download $tool from ${url[*]}"
else
add_log "$cross" "$tool" "Could not setup $tool"
fi
add_log "$cross" "$tool" "Could not setup $tool"
fi
}

View File

@ -8,7 +8,7 @@ add_blackfire_linux() {
add_blackfire_darwin() {
sudo mkdir -p /usr/local/var/run
add_brew_tap blackfireio/homebrew-blackfire
safe_brew install blackfire
brew install blackfire
}
blackfire_config() {

View File

@ -44,141 +44,12 @@ add_brew_bins_to_path() {
add_path "$brew_prefix"/sbin
}
# Function to get file modification time.
get_file_mtime() {
local file=$1
if [ "$(uname -s)" = "Darwin" ]; then
stat -f "%m" "$file" 2>/dev/null || echo 0
else
stat -c "%Y" "$file" 2>/dev/null || echo 0
fi
}
# Function to terminate a process and its direct children.
terminate_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"
done
sleep 2
kill -KILL "$pid" >/dev/null 2>&1 || true
for child in $children; do
terminate_process_tree "$child"
done
}
# Function to run a command with an inactivity watchdog.
run_with_inactivity_watchdog() {
local timeout_secs="${SETUP_PHP_BREW_INACTIVITY_TIMEOUT:-180}"
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
tmp_dir="$(mktemp -d "${TMPDIR:-/tmp}/setup-php-brew.XXXXXX")" || return 1
stdout_fifo="$tmp_dir/stdout.fifo"
stderr_fifo="$tmp_dir/stderr.fifo"
stdout_log="$tmp_dir/stdout.log"
stderr_log="$tmp_dir/stderr.log"
timeout_file="$tmp_dir/timed_out"
mkfifo "$stdout_fifo" "$stderr_fifo" || {
rm -rf "$tmp_dir"
return 1
}
: >"$stdout_log"
: >"$stderr_log"
("$@" >"$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"
) &
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"
) &
stderr_reader_pid=$!
(
local last_activity current_activity current_err_activity now
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"
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
: >"$timeout_file"
terminate_process_tree "$command_pid"
break
fi
done
) &
monitor_pid=$!
wait "$command_pid"
exit_code=$?
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"
return 124
fi
rm -rf "$tmp_dir"
return "$exit_code"
}
# Function to run brew with retries and an inactivity watchdog.
safe_brew() {
local max_attempts="${SETUP_PHP_BREW_RETRY_ATTEMPTS:-3}"
local attempt=1
local exit_code=0
if [ "${SETUP_PHP_BREW_WATCHDOG:-true}" = "false" ]; then
brew "$@"
return $?
fi
while [ "$attempt" -le "$max_attempts" ]; do
run_with_inactivity_watchdog brew "$@" && return 0
exit_code=$?
if [ "$attempt" -ge "$max_attempts" ]; then
return "$exit_code"
fi
printf "setup-php: retrying brew command (attempt %s/%s, exit %s)\n" "$((attempt + 1))" "$max_attempts" "$exit_code" >&2
sleep "$((attempt * 5))"
attempt=$((attempt + 1))
done
return "$exit_code"
}
# Function to add brew.
add_brew() {
brew_prefix="$(get_brew_prefix)"
if ! [ -d "$brew_prefix"/bin ]; then
step_log "Setup Brew"
get -s "" "/tmp/install.sh" "https://raw.githubusercontent.com/Homebrew/install/main/install.sh" | bash -s >/dev/null 2>&1
get -s "" "/tmp/install.sh" "https://raw.githubusercontent.com/Homebrew/install/master/install.sh" | bash -s >/dev/null 2>&1
add_log "${tick:?}" "Brew" "Installed Homebrew"
fi
add_brew_bins_to_path "$brew_prefix"
@ -203,7 +74,6 @@ configure_brew() {
export HOMEBREW_NO_ENV_HINTS=1
export HOMEBREW_NO_INSTALL_CLEANUP=1
export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1
export HOMEBREW_DOWNLOAD_CONCURRENCY="${HOMEBREW_DOWNLOAD_CONCURRENCY:-6}"
export brew_opts
export brew_path
export brew_path_dir

View File

@ -4,7 +4,7 @@ add_bazel() {
add_list bazel/apt https://storage.googleapis.com/bazel-apt https://bazel.build/bazel-release.pub.gpg stable jdk1.8
install_packages bazel
else
safe_brew install bazel
brew install bazel
fi
fi
}
@ -25,7 +25,7 @@ add_grpc_php_plugin_brew() {
. "${0%/*}"/tools/brew.sh
configure_brew
[ -e /usr/local/bin/protoc ] && sudo mv /usr/local/bin/protoc /tmp/protoc && sudo mv /usr/local/include/google /tmp
safe_brew install grpc
brew install grpc
brew link --force --overwrite grpc >/dev/null 2>&1
[ -e /tmp/protoc ] && sudo mv /tmp/protoc /usr/local/bin/protoc && sudo mv /tmp/google /usr/local/include/
grpc_tag="v$(brew info grpc | grep "grpc:" | grep -Eo "[0-9]+\.[0-9]+\.[0-9]+")"

View File

@ -1,36 +0,0 @@
Function Get-MagoTag() {
$releases = 'https://github.com/carthage-software/mago/releases'
if("$mago_tag" -eq "latest") {
$mago_tag = (Get-File -Url $releases/latest).BaseResponse.RequestMessage.RequestUri.Segments[-1]
} else {
try {
[net.httpWebRequest] $request = [net.webRequest]::create("$releases/tag/$mago_tag")
$request.Method = "HEAD"
[net.httpWebResponse] $response = $request.getResponse()
$response.Close()
$mago_tag = "$mago_tag"
} catch {
$mago_tag = (Get-File -Url $releases/latest).BaseResponse.RequestMessage.RequestUri.Segments[-1]
}
}
return $mago_tag
}
Function Add-Mago() {
param(
[Parameter(Mandatory = $true, Position = 0, HelpMessage = 'The mago version to be installed')]
[ValidatePattern('^latest$|^\d+\.\d+\.\d+$')]
[string] $mago_tag
)
$mago_tag = Get-MagoTag
$arch_name = 'x86_64'
if(-not([Environment]::Is64BitOperatingSystem)) {
$arch_name = 'i686'
}
$url = "https://github.com/carthage-software/mago/releases/download/$mago_tag/mago-$mago_tag-$arch_name-pc-windows-msvc.zip"
Get-File -Url $url -OutFile $bin_dir\mago.zip >$null 2>&1
Expand-Archive -Path $bin_dir\mago.zip -DestinationPath $bin_dir\mago -Force >$null 2>&1
Move-Item -Path $bin_dir\mago\mago-$mago_tag-$arch_name-pc-windows-msvc\mago.exe -Destination $bin_dir\mago.exe -Force
Add-ToProfile $current_profile 'mago' "New-Alias mago $bin_dir\mago.exe"
Add-Log $tick "mago" "Added mago $mago_tag"
}

View File

@ -1,29 +0,0 @@
get_mago_tag() {
if [ "$mago_tag" = "latest" ]; then
mago_tag=$(get -s -n "" https://github.com/carthage-software/mago/releases/latest 2<&1 | grep -m 1 -Eo "tag/([0-9]+(\.[0-9]+)?(\.[0-9]+)?)" | head -n 1 | cut -d '/' -f 2)
else
status_code=$(get -v -n /tmp/mago.tmp "https://github.com/carthage-software/mago/releases/tag/$mago_tag")
if [ "$status_code" = "200" ]; then
mago_tag="$mago_tag"
else
mago_tag=$(get -s -n "" https://github.com/carthage-software/mago/releases/latest 2<&1 | grep -m 1 -Eo "tag/([0-9]+(\.[0-9]+)?(\.[0-9]+)?)" | head -n 1 | cut -d '/' -f 2)
fi
fi
}
add_mago() {
mago_tag=$1
get_mago_tag
(
platform='unknown-linux-gnu'
[ "$(uname -s)" = "Darwin" ] && platform='apple-darwin'
arch="$(uname -m)"
[[ "$arch" = 'arm64' || "$arch" = 'aarch64' ]] && arch='aarch64'
[[ "$arch" = 'x86_64' || "$arch" = 'amd64' ]] && arch='x86_64'
get -q -n /tmp/mago.tar.gz "https://github.com/carthage-software/mago/releases/download/$mago_tag/mago-$mago_tag-$arch-$platform.tar.gz"
sudo tar -xzf /tmp/mago.tar.gz -C /tmp/
sudo mv /tmp/mago-$mago_tag-$arch-$platform/mago /usr/local/bin/mago
sudo chmod +x /usr/local/bin/mago
) >/dev/null 2>&1
add_log "${tick:?}" "mago" "Added mago $mago_tag"
}

View File

@ -50,23 +50,12 @@ update_lists_helper() {
update_lists() {
local ppa=${1:-}
local ppa_search=${2:-}
local status_token=${3:-$ppa_search}
local list=
local status_file=/tmp/os_lists
local hash_cmd
status_file=/tmp/os_lists
if [[ -n "$ppa" && -n "$ppa_search" ]]; then
if [ -f "$ppa_search" ]; then
list="$ppa_search"
else
list="$(grep -Elr "$ppa_search" "$list_dir" 2>/dev/null | head -n 1)"
fi
hash_cmd="$(command -v sha256sum || command -v shasum)"
if [ -n "$status_token" ] && [ -n "$hash_cmd" ]; then
status_file=/tmp/os_lists_"$(echo -n "$status_token" | $hash_cmd | awk '{print $1}')"
elif [ -n "$status_token" ]; then
status_file=/tmp/os_lists_$(date +%s)
fi
elif [ -e "$list_file" ] && grep -Eq '^deb |^Types: *deb' "$list_file"; then
list="$list_dir"/"$(basename "$(grep -lr "$ppa_search" "$list_dir")")"
status_file=/tmp/"$(echo -n "$ppa_search" | shasum -a 256 | cut -d ' ' -f 1)"
elif [ -e "$list_file" ] && grep -Eq '^deb |^Types deb' "$list_file"; then
list="$list_file"
fi
if [ ! -e "$status_file" ]; then
@ -75,91 +64,12 @@ update_lists() {
fi
}
# Determine whether deb822 sources are the default on this system.
get_sources_format() {
if [ -n "$sources_format" ]; then
echo "$sources_format"
return
fi
sources_format=deb
if [ -e "$list_dir"/ubuntu.sources ] || [ -e "$list_dir"/debian.sources ]; then
sources_format="deb822"
elif ! [[ "$ID" =~ ubuntu|debian ]]; then
find "$list_dir" -type f -name '*.sources' | grep -q . && sources_format="deb822"
fi
echo "$sources_format"
}
# Function to get sources file extension.
get_sources_extension() {
[ "$1" = "deb822" ] && echo "sources" || echo "list"
}
# Function to escape regex special characters.
escape_regex() {
printf '%s' "$1" | sed -e 's/[][\.^$*+?{}()|\/]/\\&/g'
}
# Function to merge two components strings.
merge_components() {
local out=() t
for t in $1 $2; do [[ $t && " ${out[*]} " != *" $t "* ]] && out+=("$t"); done
printf '%s\n' "${out[*]}"
}
# Function to merge components from a file.
merge_components_from_file() {
local path=$1
local incoming=$2
local current=
if [ -n "$path" ] && [ -e "$path" ]; then
if grep -Eq '^Components:' "$path"; then
current="$(grep -E '^Components:' "$path" | head -n 1 | cut -d ':' -f 2 | xargs)"
else
current="$(sed -E -n 's/^deb[[:space:]]+(\[[^]]*\][[:space:]]+)?[^[:space:]]+[[:space:]]+[^[:space:]]+[[:space:]]+//p' "$path" | head -n 1 | xargs)"
fi
fi
local merged
merged="$(merge_components "$current" "$incoming")"
if [ -z "$merged" ] || [ "$merged" = "$current" ]; then
return 1
fi
printf '%s\n' "$merged"
}
# Function to get repo patterns based on format.
get_repo_patterns() {
local list_format=$1
local ppa_url=$2
local package_dist=$3
local branches=$4
local escaped_url
local escaped_dist
local escaped_branches
escaped_url="$(escape_regex "$ppa_url")"
escaped_dist="$(escape_regex "$package_dist")"
escaped_branches="$(escape_regex "$branches")"
local deb_primary="^deb[[:space:]]+(\\[[^]]*\\][[:space:]]+)?${escaped_url}[[:space:]]+${escaped_dist}[[:space:]]"
local deb_secondary="^deb[[:space:]]+(\\[[^]]*\\][[:space:]]+)?${escaped_url}[[:space:]]+${escaped_dist}[[:space:]]+.*${escaped_branches}([[:space:]]|$)"
local deb822_primary="^URIs: ${escaped_url}$"
local deb822_secondary="^Suites: ${escaped_dist}$"
if [ "$list_format" = "deb822" ]; then
printf '%s|%s\n' "$deb822_primary" "$deb822_secondary"
else
printf '%s|%s\n' "$deb_primary" "$deb_secondary"
fi
}
# Function to get fingerprint from an Ubuntu PPA.
ubuntu_fingerprint() {
ppa="$1"
ppa_uri="~${ppa%/*}/+archive/ubuntu/${ppa##*/}"
get -s -n "" "${lp_api[0]}/$ppa_uri" | jq -er '.signing_key_fingerprint' 2>/dev/null \
|| get -s -n "" "${lp_api[1]}/$ppa_uri" | jq -er '.signing_key_fingerprint' 2>/dev/null \
|| get -s -n "" "$ppa_sp/keys/$ppa.fingerprint"
ppa=$1
get -s -n "" "${lp_api[@]/%//~${ppa%/*}/+archive/${ppa##*/}}" | jq -r '.signing_key_fingerprint'
}
# Function to get fingerprint from a Debian PPA.
debian_fingerprint() {
ppa=$1
@ -183,85 +93,25 @@ add_key() {
sks_params="op=get&options=mr&exact=on&search=0x$fingerprint"
key_urls=("${sks[@]/%/\/pks\/lookup\?"$sks_params"}")
fi
key_urls+=("$ppa_sp/keys/$ppa.gpg")
[ ! -e "$key_source" ] && get -q -n "$key_file" "${key_urls[@]}"
if [[ "$(file "$key_file")" =~ .*('Public-Key (old)'|'Secret-Key') ]]; then
sudo gpg --batch --yes --dearmor "$key_file" >/dev/null 2>&1 && sudo mv "$key_file".gpg "$key_file"
fi
}
# Function to handle existing list files.
handle_existing_list() {
local ppa=$1
local list_format=$2
local branches=$3
local merged_components
if [ -z "$check_lists_file" ]; then
echo "Repository $ppa ($branches) already exists" && return 1
fi
if merged_components="$(merge_components_from_file "$check_lists_file" "$branches")"; then
sudo rm -f "$check_lists_file" && printf '%s\n' "$merged_components" && return 0
fi
if [[ "$list_format" = "deb822" && "$check_lists_file" = *.list ]]; then
sudo rm -f "$check_lists_file" && printf '%s\n' "$branches" && return 0
fi
echo "Repository $ppa ($branches) already exists" && return 1
}
# Function to write a list file.
write_list() {
local type=$1
local ppa=$2
local url=$3
local suite=$4
local components=$5
local key_file=$6
local list_basename="${ppa%%/*}"-"$ID"-"${ppa#*/}"-"$suite"
local arch
arch="$(dpkg --print-architecture)"
sudo rm -f "$list_dir"/"${ppa/\//-}".list "$list_dir"/"${ppa/\//-}".sources "$list_dir"/"$list_basename".list "$list_dir"/"$list_basename".sources || true
if [ "$type" = "deb822" ]; then
cat <<EOF | sudo tee "$list_dir"/"$list_basename".sources >/dev/null
Types: deb
URIs: $url
Suites: $suite
Components: $components
Architectures: $arch
Signed-By: $key_file
EOF
else
echo "deb [arch=$arch signed-by=$key_file] $url $suite $components" | sudo tee "$list_dir"/"$list_basename".list >/dev/null 2>&1
fi
}
# Function to check if a PPA and its lists exist
check_lists() {
local ppa=$1
local primary=${2:-}
local secondary=${3:-}
local status_token=${4:-$primary}
local match_file=
check_lists_file=
if [ -n "$primary" ]; then
match_file=$(grep -Elr "$primary" "$list_dir" 2>/dev/null | head -n 1)
fi
if [ -z "$match_file" ] && [ -n "$secondary" ]; then
local candidate
candidate=$(grep -Elr "$secondary" "$list_dir" 2>/dev/null | head -n 1)
if [ -n "$candidate" ] && { [ -z "$primary" ] || grep -Eq "$primary" "$candidate"; }; then
match_file="$candidate"
fi
fi
if [ -n "$match_file" ]; then
local list_count
ppa=$1
ppa_search=$2
if grep -Eqr "$ppa_search" "$list_dir"; then
list_count="$(sudo find /var/lib/apt/lists -type f -name "*${ppa/\//_}*" | wc -l)"
if [ "$list_count" = "0" ]; then
update_lists "$ppa" "$match_file" "$status_token"
update_lists "$ppa" "$ppa_search"
fi
check_lists_file="$match_file"
return 0
return 0;
else
return 1;
fi
return 1
}
# Function to add a sources list.
@ -271,32 +121,18 @@ add_list() {
key_source=${3:-"$ppa_url"}
package_dist=${4:-"$VERSION_CODENAME"}
branches=${5:-main}
local list_format
local list_extension
local status_token
local resolved_branches
local list_path=
list_format="$(get_sources_format)"
list_extension="$(get_sources_extension "$list_format")"
status_token="${ppa_url}|${package_dist}|${branches}"
IFS='|' read -r primary_pattern secondary_pattern <<< "$(get_repo_patterns "$list_format" "$ppa_url" "$package_dist" "$branches")"
if check_lists "$ppa" "$primary_pattern" "$secondary_pattern" "$status_token"; then
list_path="$check_lists_file"
if resolved_branches="$(handle_existing_list "$ppa" "$list_format" "$branches")"; then
branches="$resolved_branches"
else
[ -n "$resolved_branches" ] && echo "$resolved_branches" && return 1
fi
check_lists_file=
IFS='|' read -r primary_pattern secondary_pattern <<< "$(get_repo_patterns "$list_format" "$ppa_url" "$package_dist" "$branches")"
status_token="${ppa_url}|${package_dist}|${branches}"
ppa_search="deb .*$ppa_url $package_dist .*$branches$"
if check_lists "$ppa" "$ppa_search"; then
echo "Repository $ppa already exists";
return 1;
else
arch=$(dpkg --print-architecture)
[ -e "$key_source" ] && key_file=$key_source || key_file="$key_dir"/"${ppa/\//-}"-keyring.gpg
add_key "$ppa" "$ppa_url" "$package_dist" "$key_source" "$key_file"
echo "deb [arch=$arch signed-by=$key_file] $ppa_url $package_dist $branches" | sudo tee -a "$list_dir"/"${ppa/\//-}".list >/dev/null 2>&1
update_lists "$ppa" "$ppa_search"
. /etc/os-release
fi
[ -e "$key_source" ] && key_file=$key_source || key_file="$key_dir"/"${ppa/\//-}"-keyring.gpg
add_key "$ppa" "$ppa_url" "$package_dist" "$key_source" "$key_file"
write_list "$list_format" "$ppa" "$ppa_url" "$package_dist" "$branches" "$key_file"
list_path="$list_dir"/"${ppa%%/*}"-"$ID"-"${ppa#*/}"-"$package_dist"."$list_extension"
update_lists "$ppa" "$list_path" "$status_token"
. /etc/os-release
return 0;
}
@ -306,12 +142,8 @@ check_ppa() {
ppa_url=${2:-"$lpc_ppa/$ppa/ubuntu"}
package_dist=${3:-"$VERSION_CODENAME"}
branches=${4:-main}
local list_format
list_format="$(get_sources_format)"
IFS='|' read -r primary_pattern secondary_pattern <<< "$(get_repo_patterns "$list_format" "$ppa_url" "$package_dist" "$branches")"
local status_token
status_token="${ppa_url}|${package_dist}|${branches}"
if check_lists "$ppa" "$primary_pattern" "$secondary_pattern" "$status_token"; then
ppa_search="deb .*$ppa_url $package_dist .*$branches$"
if check_lists "$ppa" "$ppa_search"; then
return 0;
else
return 1;
@ -325,13 +157,13 @@ remove_list() {
for ppa_url in "${ppa_urls[@]}"; do
grep -lr "$ppa_url" "$list_dir" | xargs -n1 sudo rm -f
done
sudo rm -f "$key_dir"/"${ppa/\//-}"-keyring /tmp/os_lists* || true
sudo rm -f "$key_dir"/"${ppa/\//-}"-keyring || true
}
# Function to check if ubuntu ppa is up
is_ubuntu_ppa_up() {
ppa=${1:-ondrej/php}
curl -s --connect-timeout 10 --max-time 10 --head --fail "$lpc_ppa/$ppa/ubuntu/dists/$VERSION_CODENAME/Release" > /dev/null
curl -s --connect-timeout 5 --max-time 5 --head --fail "$lpc_ppa/$ppa/ubuntu/dists/$VERSION_CODENAME/Release" > /dev/null
}
# Function to add the PPA mirror.
@ -339,8 +171,8 @@ add_ppa_sp_mirror() {
ppa=$1
ppa_name="$(basename "$ppa")"
remove_list "$ppa" || true
[ "${debug:?}" = "debug" ] && add_list sp/"$ppa_name" "$ppa_sp/$ppa/ubuntu" "$ppa_sp/$ppa/ubuntu/key.gpg" "$VERSION_CODENAME" "main/debug"
add_list sp/"$ppa_name" "$ppa_sp/$ppa/ubuntu" "$ppa_sp/$ppa/ubuntu/key.gpg"
[ "${debug:?}" = "debug" ] && add_list sp/"$ppa_name" "$sp/$ppa/ubuntu" "$sp/$ppa/ubuntu/key.gpg" "$VERSION_CODENAME" "main/debug"
add_list sp/"$ppa_name" "$sp/$ppa/ubuntu" "$sp/$ppa/ubuntu/key.gpg"
}
# Function to add a PPA.
@ -349,13 +181,10 @@ add_ppa() {
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"
else
add_log "${cross:?}" "$ppa" "PPA $ppa is not available"
add_ppa_sp_mirror "$ppa"
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"
@ -375,23 +204,12 @@ update_ppa() {
ppa_url=${2:-"$lpc_ppa/$ppa/ubuntu"}
package_dist=${4:-"$VERSION_CODENAME"}
branches=${5:-main}
local list_format
list_format="$(get_sources_format)"
IFS='|' read -r primary_pattern secondary_pattern <<< "$(get_repo_patterns "$list_format" "$ppa_url" "$package_dist" "$branches")"
local list_path
list_path="$(grep -Elr "$primary_pattern" "$list_dir" 2>/dev/null | head -n 1)"
if [ -z "$list_path" ] && [ -n "$secondary_pattern" ]; then
list_path="$(grep -Elr "$secondary_pattern" "$list_dir" 2>/dev/null | head -n 1)"
fi
local status_token
status_token="${ppa_url}|${package_dist}|${branches}"
update_lists "$ppa" "${list_path:-$primary_pattern}" "$status_token"
ppa_search="deb .*$ppa_url $package_dist .*$branches"
update_lists "$ppa" "$ppa_search"
. /etc/os-release
}
# Variables
sources_format=
check_lists_file=
list_dir='/etc/apt/sources.list.d'
list_file="/etc/apt/sources.list.d/$ID.sources"
[ -e "$list_file" ] || list_file='/etc/apt/sources.list'
@ -405,7 +223,6 @@ lpc_ppa='https://ppa.launchpadcontent.net'
key_dir='/usr/share/keyrings'
dist_info_dir='/usr/share/distro-info'
sury='https://packages.sury.org'
ppa_sp='https://ppa.setup-php.com'
sp='https://setup-php.com'
sks=(
'https://keyserver.ubuntu.com'

View File

@ -35,6 +35,6 @@ Function Add-Protoc() {
Add-ToProfile $current_profile 'protoc' "New-Alias protoc $bin_dir\protoc.exe"
Add-Log $tick "protoc" "Added protoc $($protobuf_tag -replace 'v', '')"
printf "$env:GROUP\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "protoc" "Click to read the protoc related license information"
Write-Output (Invoke-WebRequest https://raw.githubusercontent.com/protocolbuffers/protobuf/main/LICENSE).Content
Write-Output (Invoke-WebRequest https://raw.githubusercontent.com/protocolbuffers/protobuf/master/LICENSE).Content
Write-Output "$env:END_GROUP"
}

View File

@ -25,6 +25,6 @@ add_protoc() {
) >/dev/null 2>&1
add_log "${tick:?}" "protoc" "Added protoc ${protobuf_tag:1}"
printf "$GROUP\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "protoc" "Click to read the protoc related license information"
curl "${curl_opts[@]:?}" https://raw.githubusercontent.com/protocolbuffers/protobuf/main/LICENSE
curl "${curl_opts[@]:?}" https://raw.githubusercontent.com/protocolbuffers/protobuf/master/LICENSE
echo "$END_GROUP"
}

View File

@ -1,32 +1,18 @@
Function Add-Symfony() {
param(
[Parameter(Mandatory = $true, Position = 0, HelpMessage = 'Symfony version to be installed')]
[string] $protobuf_tag
)
$protobuf_tag = $protobuf_tag.replace('v', '')
if($protobuf_tag -ne 'latest' -and $protobuf_tag -notmatch '^\d+(\.\d+)*$') {
Add-Log $cross "symfony-cli" "Invalid symfony version: $protobuf_tag"
$arch_name ='amd64'
if(-not([Environment]::Is64BitOperatingSystem) -or $version -lt '7.0') {
$arch_name = '386'
}
$url = "https://github.com/symfony-cli/symfony-cli/releases/latest/download/symfony-cli_windows_${arch_name}.zip"
Get-File -Url $url -OutFile $bin_dir\symfony.zip >$null 2>&1
Expand-Archive -Path $bin_dir\symfony.zip -DestinationPath $bin_dir -Force >$null 2>&1
if(Test-Path $bin_dir\symfony.exe) {
Copy-Item -Path $bin_dir\symfony.exe -Destination $bin_dir\symfony-cli.exe > $null 2>&1
Add-ToProfile $current_profile 'symfony' "New-Alias symfony $bin_dir\symfony.exe"
Add-ToProfile $current_profile 'symfony_cli' "New-Alias symfony-cli $bin_dir\symfony-cli.exe"
$tool_version = Get-ToolVersion symfony "-V"
Add-Log $tick "symfony-cli" "Added symfony-cli $tool_version"
} else {
$arch_name = 'amd64'
if (-not ([Environment]::Is64BitOperatingSystem) -or $version -lt '7.0') {
$arch_name = '386'
}
$symfony_releases = "https://github.com/symfony-cli/symfony-cli/releases"
if ($protobuf_tag -eq 'latest') {
$url = "$symfony_releases/latest/download/symfony-cli_windows_${arch_name}.zip"
} else {
$url = "$symfony_releases/download/v$protobuf_tag/symfony-cli_windows_${arch_name}.zip"
}
Get-File -Url $url -OutFile $bin_dir\symfony.zip > $null 2>&1
Expand-Archive -Path $bin_dir\symfony.zip -DestinationPath $bin_dir -Force > $null 2>&1
if (Test-Path $bin_dir\symfony.exe) {
Copy-Item -Path $bin_dir\symfony.exe -Destination $bin_dir\symfony-cli.exe > $null 2>&1
Add-ToProfile $current_profile 'symfony' "New-Alias symfony $bin_dir\symfony.exe"
Add-ToProfile $current_profile 'symfony_cli' "New-Alias symfony-cli $bin_dir\symfony-cli.exe"
$tool_version = Get-ToolVersion symfony "-V"
Add-Log $tick "symfony-cli" "Added symfony-cli $tool_version"
} else {
Add-Log $cross "symfony-cli" "Could not setup symfony-cli"
}
Add-Log $cross "symfony-cli" "Could not setup symfony-cli"
}
}

View File

@ -1,44 +1,41 @@
add_symfony_with_brew() {
add_brew_tap symfony-cli/homebrew-tap
brew install symfony-cli/tap/symfony-cli
}
get_symfony_artifact_url() {
local symfony_tag=$1
local os
local arch
os="$(uname -s | tr '[:upper:]' '[:lower:]')"
arch="$(uname -m)"
case "$arch" in
arm|armv6*|armv7*) arch="armv6" ;;
aarch64*|armv8*|arm64) arch="arm64" ;;
i[36]86) arch="386" ;;
x86_64|amd64) arch="amd64" ;;
esac
[ "$os" = "darwin" ] && arch="all"
symfony_releases="https://github.com/symfony-cli/symfony-cli/releases"
if [ "$symfony_tag" = "latest" ]; then
echo "$symfony_releases/latest/download/symfony-cli_${os}_${arch}.tar.gz"
else
echo "$symfony_releases/download/v$symfony_tag/symfony-cli_${os}_${arch}.tar.gz"
fi
arch=$(dpkg --print-architecture)
url=$(get -s -n "" https://raw.githubusercontent.com/symfony-cli/homebrew-tap/main/Formula/symfony-cli.rb 2<&1 | grep -m 1 "url.*linux.*${arch}" | cut -d\" -f 2)
if [ -z "$url" ]; then
url=$(get -s -n "" https://api.github.com/repos/symfony-cli/symfony-cli/releases 2<&1 | grep -m 1 "url.*linux.*${arch}.*gz\"" | cut -d\" -f 4)
fi
echo "$url"
}
add_symfony_helper() {
local install_dir=/usr/local/bin
[ "$(uname -s)" = "Darwin" ] && install_dir=${brew_prefix:?}/bin
get -s -n "" "$(get_symfony_artifact_url "$symfony_tag")" | sudo tar -xz -C "$install_dir" 2>/dev/null
sudo chmod a+x "$install_dir"/symfony
if [ "$(uname -s)" = "Linux" ]; then
url="$(get_symfony_artifact_url)"
if [ -z "$url" ]; then
. "${0%/*}"/tools/brew.sh
configure_brew
add_symfony_with_brew
else
get -s -n "" "$url" | sudo tar -xz -C "${tool_path_dir:?}" 2>/dev/null
sudo chmod a+x /usr/local/bin/symfony
fi
elif [ "$(uname -s)" = "Darwin" ]; then
add_symfony_with_brew
fi
}
add_symfony() {
local symfony_tag="${1/v/}"
if ! [[ "$symfony_tag" =~ ^[0-9]+(\.[0-9]+)*$ || "$symfony_tag" == 'latest' ]]; then
add_log "${cross:?}" "symfony-cli" "Version '$symfony_tag' is not valid for symfony-cli"
add_symfony_helper >/dev/null 2>&1
symfony_path="$(command -v symfony)"
if [[ -n "$symfony_path" ]]; then
sudo ln -s "$symfony_path" "${tool_path_dir:?}"/symfony-cli
tool_version=$(get_tool_version "symfony" "-V")
add_log "${tick:?}" "symfony-cli" "Added symfony-cli $tool_version"
else
add_symfony_helper "$symfony_tag" >/dev/null 2>&1
symfony_path="$(command -v symfony)"
if [[ -n "$symfony_path" ]]; then
sudo ln -s "$symfony_path" "${tool_path_dir:?}"/symfony-cli
tool_version=$(get_tool_version "symfony" "-V")
add_log "${tick:?}" "symfony-cli" "Added symfony-cli $tool_version"
else
add_log "${cross:?}" "symfony-cli" "Could not setup symfony-cli"
fi
add_log "${cross:?}" "symfony-cli" "Could not setup symfony-cli"
fi
}

View File

@ -4,7 +4,7 @@ export cross="✗"
export curl_opts=(-sL)
export old_versions="5.[3-5]"
export jit_versions="8.[0-9]"
export php_builder_versions="8.[3-9]"
export nightly_versions="8.[3-9]"
export xdebug3_versions="7.[2-4]|8.[0-9]"
export latest="releases/latest/download"
export github="https://github.com/shivammathur"
@ -53,12 +53,9 @@ read_env() {
[ "${debug:-${DEBUG:-false}}" = "true" ] && debug=debug && update=true || debug=release
[[ "${phpts:-${PHPTS:-nts}}" = "ts" || "${phpts:-${PHPTS:-nts}}" = "zts" ]] && ts=zts && update=true || ts=nts
fail_fast="${fail_fast:-${FAIL_FAST:-false}}"
[[ ( -z "$ImageOS" && -z "$ImageVersion" ) ||
( -n "$RUNNER_ENVIRONMENT" && "$RUNNER_ENVIRONMENT" = "self-hosted" ) ||
-n "$ACT" || -n "$CONTAINER" ]] && _runner=self-hosted || _runner=github
[[ -z "${ImageOS}" && -z "${ImageVersion}" || -n ${ACT} ]] && _runner=self-hosted || _runner=github
runner="${runner:-${RUNNER:-$_runner}}"
tool_path_dir="${setup_php_tools_dir:-${SETUP_PHP_TOOLS_DIR:-/usr/local/bin}}"
tool_cache_path_dir="${setup_php_tool_cache_dir:-${SETUP_PHP_TOOL_CACHE_DIR:-${RUNNER_TOOL_CACHE:-/opt/hostedtoolcache}/setup-php/tools}}"
tool_path_dir="${tools_dir:-${TOOLS_DIR:-/usr/local/bin}}"
if [[ "$runner" = "github" && $_runner = "self-hosted" ]]; then
fail_fast=true
@ -79,8 +76,7 @@ read_env() {
export runner
export update
export ts
export tool_path_dir
export tool_cache_path_dir
export tools_dir_path
}
# Function to create a lock.
@ -109,18 +105,6 @@ release_lock() {
sudo rm -rf "$lock_path"
}
# Function to get the SHA256 hash of a string.
get_sha256() {
local input=$1
if command -v sha256sum >/dev/null; then
printf '%s' "$input" | sha256sum | cut -d' ' -f1
elif command -v shasum >/dev/null; then
printf '%s' "$input" | shasum -a 256 | cut -d' ' -f1
elif command -v openssl >/dev/null; then
printf '%s' "$input" | openssl dgst -sha256 | cut -d' ' -f2
fi
}
# 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
@ -134,7 +118,7 @@ get() {
sudo curl "${curl_opts[@]}" "${links[0]}"
else
if [ "$runner" = "self-hosted" ]; then
lock_path="/tmp/sp-lck-$(get_sha256 "$file_path")"
lock_path="$file_path.lock"
acquire_lock "$lock_path"
if [ "$execute" = "-e" ]; then
until [ -z "$(fuser "$file_path" 2>/dev/null)" ]; do
@ -147,7 +131,7 @@ get() {
status_code=$(sudo curl -w "%{http_code}" -o "$file_path" "${curl_opts[@]}" "$link")
[ "$status_code" = "200" ] && break
done
[[ "$execute" = "-e" && -e "$file_path" ]] && sudo chmod a+x "$file_path"
[ "$execute" = "-e" ] && sudo chmod a+x "$file_path"
[ "$mode" = "-v" ] && echo "$status_code"
[ "$runner" = "self-hosted" ] && release_lock "$lock_path"
fi
@ -171,15 +155,14 @@ get_shell_profile() {
# Function to add a path to the PATH variable.
add_path() {
path_to_add=$1
action=$2
[[ "$action" == "verify" && ":$PATH:" == *":$path_to_add:"* ]] && return
[[ ":$PATH:" == *":$path_to_add:"* ]] && return
if [[ -n "$GITHUB_PATH" ]]; then
printf '%s\n%s' "$path_to_add" "$(grep -v "^${path_to_add}$" "$GITHUB_PATH" 2>/dev/null)" > "$GITHUB_PATH"
echo "$path_to_add" | tee -a "$GITHUB_PATH" >/dev/null 2>&1
else
profile=$(get_shell_profile)
([ -e "$profile" ] && grep -q ":$path_to_add\"" "$profile" 2>/dev/null) || echo "export PATH=\"\${PATH:+\${PATH}:}\"$path_to_add" | sudo tee -a "$profile" >/dev/null 2>&1
fi
[[ ":$PATH:" == *":$path_to_add:"* ]] || export PATH="${PATH:+${PATH}:}$path_to_add"
export PATH="${PATH:+${PATH}:}$path_to_add"
}
# Function to add environment variables using a PATH.
@ -224,7 +207,7 @@ self_hosted_setup() {
exit 1
else
self_hosted_helper >/dev/null 2>&1
add_env RUNNER_TOOL_CACHE /opt/hostedtoolcache
add_env RUNNER_TOOL_CACHE /tmp
fi
fi
}
@ -247,9 +230,7 @@ configure_php() {
add_php_config
ini_config_dir="${src:?}"/configs/ini
ini_config_files=("$ini_config_dir"/php.ini)
arch="$(uname -m)"
[[ "$arch" = "arm64" || "$arch" = "aarch64" ]] && jit_ini="$ini_config_dir"/jit_aarch64.ini || jit_ini="$ini_config_dir"/jit.ini
jit_config_files=("$jit_ini")
jit_config_files=("$ini_config_dir"/jit.ini)
[[ "$version" =~ $xdebug3_versions ]] && ini_config_files+=("$ini_config_dir"/xdebug.ini)
cat "${ini_config_files[@]}" | sudo tee -a "${ini_file[@]:?}" >/dev/null 2>&1
[[ "$version" =~ $jit_versions ]] && cat "${jit_config_files[@]}" | sudo tee -a "${pecl_file:-${ini_file[@]}}" >/dev/null 2>&1

View File

@ -81,10 +81,9 @@ Function Get-PathFromRegistry {
# Function to add a location to PATH.
Function Add-Path {
param(
[string]$PathItem,
[switch]$Force
[string]$PathItem
)
if(-not($Force) -and "$env:PATH;".contains("$PathItem;")) {
if("$env:PATH;".contains("$PathItem;")) {
return
}
if ($env:GITHUB_PATH) {
@ -324,7 +323,7 @@ $php_builder = "$github/shivammathur/php-builder-windows"
$current_profile = "$env:TEMP\setup-php.ps1"
$ProgressPreference = 'SilentlyContinue'
$jit_versions = '8.[0-9]'
$nightly_versions = '8.[6-9]'
$nightly_versions = '8.[2-9]'
$xdebug3_versions = "7.[2-4]|8.[0-9]"
$enable_extensions = ('openssl', 'curl', 'mbstring')
@ -376,7 +375,6 @@ if(-not($env:ImageOS) -and -not($env:ImageVersion)) {
if(-not(Test-Path -LiteralPath $current_profile)) {
New-Item -Path $current_profile -ItemType "file" -Force >$null 2>&1
}
Add-Path -PathItem $bin_dir -Force
}
$src = Join-Path -Path $PSScriptRoot -ChildPath \..
@ -446,13 +444,10 @@ if($installed.MajorMinorVersion -ne $version) {
}
if($version -lt "5.5") {
('libeay32.dll', 'ssleay32.dll') | ForEach-Object -Parallel { Invoke-WebRequest -Uri "$using:php_builder/releases/download/openssl-1.0.2u/$_" -OutFile $using:php_dir\$_ >$null 2>&1 }
} elseif($version -lt "8.5") {
} else {
$enable_extensions += ('opcache')
}
if($version -ge "8.5" -and (Test-Path $ext_dir\php_opcache.dll)) {
Remove-Item $ext_dir\php_opcache.dll -Force
}
Enable-PhpExtension -Extension ($enable_extensions | Where-Object { Test-Path $ext_dir\php_$_.dll }) -Path $php_dir
Enable-PhpExtension -Extension $enable_extensions -Path $php_dir
Add-PhpCAInfo
Add-OpenSSLConf
Copy-Item -Path $src\configs\pm\*.json -Destination $env:RUNNER_TOOL_CACHE

View File

@ -1,98 +1,17 @@
import path from 'path';
import fs from 'fs';
import * as cv from 'compare-versions';
import * as fetch from './fetch';
import * as packagist from './packagist';
import * as utils from './utils';
/**
* Valid function names for custom tool handlers
*/
type ToolFunction =
| 'castor'
| 'composer'
| 'deployer'
| 'dev_tools'
| 'phive'
| 'blackfire_player'
| 'pecl'
| 'phing'
| 'phpunit'
| 'phpcpd'
| 'wp_cli';
type RS = Record<string, string>;
type RSRS = Record<string, RS>;
/**
* Tool data interface containing all properties for tool installation
*/
export interface ToolData {
tool: string;
version: string;
os: string;
php_version: string;
github: string;
domain: string;
extension: string;
repository: string;
prefix: string;
verb: string;
fetch_latest: 'true' | 'false';
scope: string;
version_parameter: string;
version_prefix: string;
release: string;
packagist: string;
type?: string;
function?: ToolFunction;
alias?: string;
url: string;
uri?: string;
error?: string;
}
/**
* Input type for functions that may receive partial/unresolved tool data
* Used by getUrl, getLatestVersion etc. before version is fully resolved
*/
export type ToolInput = Omit<ToolData, 'version' | 'url'> & {version?: string};
/**
* Partial tool data from tools.json configuration
*/
interface ToolConfig {
tool?: string;
repository?: string;
type?: string;
function?: ToolFunction;
alias?: string;
domain?: string;
extension?: string;
fetch_latest?: 'true' | 'false';
scope?: string;
version_parameter?: string;
version_prefix?: string;
packagist?: string;
}
/**
* GitHub reference object from API response
*/
interface GitHubRef {
interface IRef {
ref: string;
node_id: string;
url: string;
object: {
sha: string;
type: string;
url: string;
};
}
/**
* Deployer manifest entry
*/
interface DeployerManifestEntry {
version: string;
url: string;
object: RS;
}
/**
@ -100,42 +19,21 @@ interface DeployerManifestEntry {
*
* @param data
*/
export async function getSemverVersion(data: ToolData): Promise<string> {
const fixSemver = (t: string): string => {
if (/^\d+\.\d+\.\d+(-|$)/.test(t)) return t;
const m = t.match(/^(\d+\.\d+\.\d+)([A-Za-z]+[0-9A-Za-z.]+)$/);
return m ? `${m[1]}-${m[2]}` : t;
};
export async function getSemverVersion(data: RS): Promise<string> {
const search: string = data['version_prefix'] + data['version'];
const url = `https://api.github.com/repos/${data['repository']}/git/matching-refs/tags%2F${search}.`;
const github_token: string =
(await utils.readEnv('GITHUB_TOKEN')) ||
(await utils.readEnv('COMPOSER_TOKEN'));
const response = await fetch.fetch(url, github_token);
const response: RS = await fetch.fetch(url, github_token);
if (response.error || response.data === '[]') {
data.error = response.error ?? `No version found with prefix ${search}.`;
return data.version;
data['error'] = response.error ?? `No version found with prefix ${search}.`;
return data['version'];
} else {
const refs: GitHubRef[] = JSON.parse(response.data);
const tags = refs
.map((i: GitHubRef) =>
(i.ref?.split('/').pop() ?? '').replace(/^v(?=\d)/, '')
)
.filter((t: string) => t.length > 0);
const fixedToOriginal = new Map<string, string>();
const fixed = tags.map(t => {
const f = fixSemver(t);
fixedToOriginal.set(f, t);
return f;
});
const sorted = fixed.toSorted((a, b) => {
try {
return cv.compareVersions(b, a);
} catch {
return b.localeCompare(a, 'en', {numeric: true, sensitivity: 'base'});
}
});
return fixedToOriginal.get(sorted[0]) ?? sorted[0];
const refs = JSON.parse(response['data']).reverse();
const ref = refs.find((i: IRef) => /.*\d+.\d+.\d+$/.test(i['ref']));
const tag: string = (ref || refs[0])['ref'].split('/').pop();
return tag.replace(/^v(\d)/, '$1');
}
}
@ -144,25 +42,25 @@ export async function getSemverVersion(data: ToolData): Promise<string> {
*
* @param data
*/
export async function getLatestVersion(data: ToolInput): Promise<string> {
if (!data.version && data.fetch_latest === 'false') {
export async function getLatestVersion(data: RS): Promise<string> {
if (!data['version'] && data['fetch_latest'] === 'false') {
return 'latest';
}
if (data.fetch_latest === 'true' && !data.repository) {
return 'latest';
}
const resp = await fetch.fetch(
`${data.github}/${data.repository}/releases.atom`
const resp: Record<string, string> = await fetch.fetch(
`${data['github']}/${data['repository']}/releases.atom`
);
if (resp.data) {
if (resp['data']) {
const releases: string[] = [
...resp.data.matchAll(/releases\/tag\/([a-zA-Z]*)?(\d+\.\d+\.\d+)"/g)
...resp['data'].matchAll(/releases\/tag\/([a-zA-Z]*)?(\d+.\d+.\d+)"/g)
].map(match => match[2]);
const sorted = releases.toSorted((a: string, b: string) =>
a.localeCompare(b, undefined, {numeric: true})
return (
releases
.sort((a: string, b: string) =>
a.localeCompare(b, undefined, {numeric: true})
)
.pop() || 'latest'
);
return sorted.at(-1) || 'latest';
}
return 'latest';
}
@ -173,29 +71,26 @@ export async function getLatestVersion(data: ToolInput): Promise<string> {
* @param version
* @param data
*/
export async function getVersion(
version: string,
data: ToolData
): Promise<string> {
export async function getVersion(version: string, data: RS): Promise<string> {
// semver_regex - https://semver.org/
const semver_regex =
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
const composer_regex = /^composer:(stable|preview|snapshot|[12])$/;
const composer_regex = /^composer:(stable|preview|snapshot|[1|2])$/;
const constraint_regex = /[><=^~]+.*/;
const major_minor_regex = /^\d+(\.\d+)?$/;
data.version = version.replace(/v?(\d)/, '$1').replace(/\.x/, '');
data['version'] = version.replace(/v?(\d)/, '$1').replace(/\.x/, '');
switch (true) {
case composer_regex.test(data.release):
case semver_regex.test(data.version):
case constraint_regex.test(data.version) && data.type === 'composer':
return data.version;
case major_minor_regex.test(data.version) && data.type === 'composer':
data.release = `${data.tool}:${data.version}.*`;
return `${data.version}.*`;
case !!data.repository && major_minor_regex.test(data.version):
case composer_regex.test(data['release']):
case semver_regex.test(data['version']):
case constraint_regex.test(data['version']) && data['type'] === 'composer':
return data['version'];
case major_minor_regex.test(data['version']) && data['type'] === 'composer':
data['release'] = `${data['tool']}:${data['version']}.*`;
return `${data['version']}.*`;
case data['repository'] && major_minor_regex.test(data['version']):
return await getSemverVersion(data);
default:
return data.version.replace(/[><=^~]*/, '');
return data['version'].replace(/[><=^~]*/, '');
}
}
@ -205,14 +100,11 @@ export async function getVersion(
* @param release
* @param data
*/
export async function getRelease(
release: string,
data: ToolData
): Promise<string> {
export async function getRelease(release: string, data: RS): Promise<string> {
release = release.includes('/') ? release.split('/')[1] : release;
return release.includes(':')
? [data.tool, release.split(':')[1]].join(':')
: data.tool;
? [data['tool'], release.split(':')[1]].join(':')
: data['tool'];
}
/**
@ -231,7 +123,7 @@ export async function filterList(tools_list: string[]): Promise<string[]> {
case matches[0] == undefined:
break;
default:
composer = matches.at(-1)!.replace(/v(\d\S*)/, '$1');
composer = matches[matches.length - 1].replace(/v(\d\S*)/, '$1');
break;
}
tools_list.unshift(composer);
@ -243,27 +135,26 @@ export async function filterList(tools_list: string[]): Promise<string[]> {
*
* @param data
*/
export async function getUrl(data: ToolInput): Promise<string> {
const version = data.version ?? 'latest';
if (version === 'latest' || version === '') {
export async function getUrl(data: RS): Promise<string> {
if (data['version'] === 'latest') {
return [
data.domain,
data.repository,
data.prefix,
'latest',
data.verb,
data.tool + data.extension
data['domain'],
data['repository'],
data['prefix'],
data['version'],
data['verb'],
data['tool'] + data['extension']
]
.filter(Boolean)
.join('/');
} else {
return [
data.domain,
data.repository,
data.prefix,
data.verb,
data.version_prefix + data.version,
data.tool + data.extension
data['domain'],
data['repository'],
data['prefix'],
data['verb'],
data['version_prefix'] + data['version'],
data['tool'] + data['extension']
]
.filter(Boolean)
.join('/');
@ -275,17 +166,17 @@ export async function getUrl(data: ToolInput): Promise<string> {
*
* @param data
*/
export async function getPharUrl(data: ToolData): Promise<string> {
if (data.version === 'latest') {
return data.domain + '/' + data.tool + '.phar';
export async function getPharUrl(data: RS): Promise<string> {
if (data['version'] === 'latest') {
return data['domain'] + '/' + data['tool'] + '.phar';
} else {
return (
data.domain +
data['domain'] +
'/' +
data.tool +
data['tool'] +
'-' +
data.version_prefix +
data.version +
data['version_prefix'] +
data['version'] +
'.phar'
);
}
@ -296,10 +187,10 @@ export async function getPharUrl(data: ToolData): Promise<string> {
*
* @param data
*/
export async function addArchive(data: ToolData): Promise<string> {
export async function addArchive(data: RS): Promise<string> {
return (
(await utils.getCommand(data.os, 'tool')) +
(await utils.joins(data.url, data.tool, data.version_parameter))
(await utils.getCommand(data['os'], 'tool')) +
(await utils.joins(data['url'], data['tool'], data['version_parameter']))
);
}
@ -308,14 +199,14 @@ export async function addArchive(data: ToolData): Promise<string> {
*
* @param data
*/
export async function addPackage(data: ToolData): Promise<string> {
const command = await utils.getCommand(data.os, 'composer_tool');
const parts: string[] = data.repository.split('/');
export async function addPackage(data: RS): Promise<string> {
const command = await utils.getCommand(data['os'], 'composer_tool');
const parts: string[] = data['repository'].split('/');
const args: string = await utils.joins(
parts[1],
data.release,
data['release'],
parts[0] + '/',
data.scope
data['scope']
);
return command + args;
}
@ -325,24 +216,24 @@ export async function addPackage(data: ToolData): Promise<string> {
*
* @param data
*/
export async function addBlackfirePlayer(data: ToolData): Promise<string> {
switch (data.os) {
export async function addBlackfirePlayer(data: RS): Promise<string> {
switch (data['os']) {
case 'win32':
return await utils.addLog(
'$cross',
data.tool,
data.tool + ' is not a windows tool',
data['tool'],
data['tool'] + ' is not a windows tool',
'win32'
);
default:
if (data.version == 'latest') {
if (/5\.[5-6]|7\.0/.test(data.php_version)) {
data.version = '1.9.3';
} else if (/7\.[1-4]|8\.0/.test(data.php_version)) {
data.version = '1.22.0';
if (data['version'] == 'latest') {
if (/5\.[5-6]|7\.0/.test(data['php_version'])) {
data['version'] = '1.9.3';
} else if (/7\.[1-4]|8\.0/.test(data['php_version'])) {
data['version'] = '1.22.0';
}
}
data.url = await getPharUrl(data);
data['url'] = await getPharUrl(data);
return addArchive(data);
}
}
@ -352,12 +243,12 @@ export async function addBlackfirePlayer(data: ToolData): Promise<string> {
*
* @param data
*/
export async function addCastor(data: ToolData): Promise<string> {
data.tool = 'castor.' + data.os.replace('win32', 'windows') + '-amd64';
data.url = await getUrl(data);
data.tool = 'castor';
data.version_parameter = fs.existsSync('castor.php')
? data.version_parameter
export async function addCastor(data: RS): Promise<string> {
data['tool'] = 'castor.' + data['os'].replace('win32', 'windows') + '-amd64';
data['url'] = await getUrl(data);
data['tool'] = 'castor';
data['version_parameter'] = fs.existsSync('castor.php')
? data['version_parameter']
: '';
return await addArchive(data);
}
@ -367,42 +258,39 @@ export async function addCastor(data: ToolData): Promise<string> {
*
* @param data
*/
export async function addComposer(data: ToolData): Promise<string> {
const channel = data.version.replace('latest', 'stable');
const github = data.github;
const getcomposer = data.domain;
export async function addComposer(data: RS): Promise<string> {
const channel = data['version'].replace('latest', 'stable');
const github = data['github'];
const getcomposer = data['domain'];
const cds = 'https://dl.cloudsmith.io';
const spc = 'https://artifacts.setup-php.com';
const filename = `composer-${data.php_version}-${channel}.phar`;
const filename = `composer-${data['php_version']}-${channel}.phar`;
const releases_url = `${github}/shivammathur/composer-cache/releases/latest/download/${filename}`;
const cds_url = `${cds}/public/shivammathur/composer-cache/raw/files/${filename}`;
const spc_url = `${spc}/composer/${filename}`;
const lts_url = `${getcomposer}/download/latest-2.2.x/composer.phar`;
const is_lts = /^5\.[3-6]$|^7\.[0-1]$/.test(data.php_version);
const channel_source_url = `${getcomposer}/composer-${channel}.phar`;
const version_source_url = `${getcomposer}/download/${channel}/composer.phar`;
let cache_url = `${releases_url},${spc_url},${cds_url}`;
const is_lts = /^5\.[3-6]$|^7\.[0-1]$/.test(data['php_version']);
const version_source_url = `${getcomposer}/composer-${channel}.phar`;
let cache_url = `${releases_url},${cds_url}`;
let source_url = `${getcomposer}/composer.phar`;
switch (true) {
case /^snapshot$/.test(channel):
source_url = is_lts ? lts_url : source_url;
break;
case /^preview$|^2$/.test(channel):
source_url = is_lts ? lts_url : channel_source_url;
source_url = is_lts ? lts_url : version_source_url;
break;
case /^1$/.test(channel):
source_url = channel_source_url;
source_url = version_source_url;
break;
case /^\d+\.\d+\.\d+[\w-]*$/.test(data.version):
cache_url = `${github}/${data.repository}/releases/download/${data.version}/composer.phar`;
case /^\d+\.\d+\.\d+[\w-]*$/.test(data['version']):
cache_url = `${github}/${data['repository']}/releases/download/${data['version']}/composer.phar`;
source_url = version_source_url;
break;
default:
source_url = is_lts ? lts_url : channel_source_url;
source_url = is_lts ? lts_url : version_source_url;
}
const use_cache: boolean = (await utils.readEnv('NO_TOOLS_CACHE')) !== 'true';
data.url = use_cache ? `${cache_url},${source_url}` : source_url;
data.version_parameter = data.version;
data['url'] = use_cache ? `${cache_url},${source_url}` : source_url;
data['version_parameter'] = data['version'];
return await addArchive(data);
}
@ -411,27 +299,27 @@ export async function addComposer(data: ToolData): Promise<string> {
*
* @param data
*/
export async function addDeployer(data: ToolData): Promise<string> {
if (data.version === 'latest') {
data.url = data.domain + '/deployer.phar';
export async function addDeployer(data: RS): Promise<string> {
if (data['version'] === 'latest') {
data['url'] = data['domain'] + '/deployer.phar';
} else {
const manifest = await fetch.fetch('https://deployer.org/manifest.json');
const version_data: Record<string, DeployerManifestEntry> = JSON.parse(
manifest.data
const manifest: RS = await fetch.fetch(
'https://deployer.org/manifest.json'
);
const version_data: RSRS = JSON.parse(manifest.data);
const version_key: string | undefined = Object.keys(version_data).find(
(key: string) => {
return version_data[key].version === data.version;
return version_data[key]['version'] === data['version'];
}
);
if (version_key) {
data.url = version_data[version_key].url;
data['url'] = version_data[version_key]['url'];
} else {
return await utils.addLog(
'$cross',
'deployer',
'Version missing in deployer manifest',
data.os
data['os']
);
}
}
@ -443,22 +331,22 @@ export async function addDeployer(data: ToolData): Promise<string> {
*
* @param data
*/
export async function addDevTools(data: ToolData): Promise<string> {
switch (data.os) {
export async function addDevTools(data: RS): Promise<string> {
switch (data['os']) {
case 'linux':
case 'darwin':
return 'add_devtools ' + data.tool;
return 'add_devtools ' + data['tool'];
case 'win32':
return await utils.addLog(
'$tick',
data.tool,
data.tool + ' is not a windows tool',
data['tool'],
data['tool'] + ' is not a windows tool',
'win32'
);
default:
return await utils.log(
'Platform ' + data.os + ' is not supported',
data.os,
'Platform ' + data['os'] + ' is not supported',
data['os'],
'error'
);
}
@ -469,8 +357,8 @@ export async function addDevTools(data: ToolData): Promise<string> {
*
* @param data
*/
export async function addPECL(data: ToolData): Promise<string> {
return await utils.getCommand(data.os, 'pecl');
export async function addPECL(data: RS): Promise<string> {
return await utils.getCommand(data['os'], 'pecl');
}
/**
@ -478,13 +366,14 @@ export async function addPECL(data: ToolData): Promise<string> {
*
* @param data
*/
export async function addPhing(data: ToolData): Promise<string> {
data.url = data.domain + '/get/phing-' + data.version + data.extension;
if (data.version != 'latest') {
[data.prefix, data.verb] = ['releases', 'download'];
data.domain = data.github;
data.extension = '-' + data.version + data.extension;
data.url += ',' + (await getUrl(data));
export async function addPhing(data: RS): Promise<string> {
data['url'] =
data['domain'] + '/get/phing-' + data['version'] + data['extension'];
if (data['version'] != 'latest') {
[data['prefix'], data['verb']] = ['releases', 'download'];
data['domain'] = data['github'];
data['extension'] = '-' + data['version'] + data['extension'];
data['url'] += ',' + (await getUrl(data));
}
return await addArchive(data);
}
@ -494,33 +383,30 @@ export async function addPhing(data: ToolData): Promise<string> {
*
* @param data
*/
export async function addPhive(data: ToolData): Promise<string> {
export async function addPhive(data: RS): Promise<string> {
switch (true) {
case /5\.[3-5]/.test(data.php_version):
case /5\.[3-5]/.test(data['php_version']):
return await utils.addLog(
'$cross',
'phive',
'Phive is not supported on PHP ' + data.php_version,
data.os
'Phive is not supported on PHP ' + data['php_version'],
data['os']
);
case /5\.6|7\.0/.test(data.php_version):
data.version = '0.12.1';
case /5\.6|7\.0/.test(data['php_version']):
data['version'] = '0.12.1';
break;
case /7\.1/.test(data.php_version):
data.version = '0.13.5';
case /7\.1/.test(data['php_version']):
data['version'] = '0.13.5';
break;
case /7\.2/.test(data.php_version):
data.version = '0.14.5';
case /7\.2/.test(data['php_version']):
data['version'] = '0.14.5';
break;
case /7\.3|7\.4/.test(data.php_version):
data.version = '0.15.3';
break;
case /^latest$/.test(data.version):
data.version = await getLatestVersion(data);
case /^latest$/.test(data['version']):
data['version'] = await getLatestVersion(data);
break;
}
data.extension = '-' + data.version + data.extension;
data.url = await getUrl(data);
data['extension'] = '-' + data['version'] + data['extension'];
data['url'] = await getUrl(data);
return await addArchive(data);
}
@ -529,15 +415,15 @@ export async function addPhive(data: ToolData): Promise<string> {
*
* @param data
*/
export async function addPHPUnitTools(data: ToolData): Promise<string> {
/* istanbul ignore next */
if (data.version === 'latest') {
data.version =
(await packagist.search(data.packagist, data.php_version)) ?? 'latest';
export async function addPHPUnitTools(data: RS): Promise<string> {
if (data['version'] === 'latest') {
data['version'] =
(await packagist.search(data['packagist'], data['php_version'])) ??
'latest';
}
data.url = await getPharUrl(data);
if (data.url.match(/-\d+/)) {
data.url += ',' + data.url.replace(/-(\d+)\.\d+\.\d+/, '-$1');
data['url'] = await getPharUrl(data);
if (data['url'].match(/-\d+/)) {
data['url'] += ',' + data['url'].replace(/-(\d+)\.\d+\.\d+/, '-$1');
}
return await addArchive(data);
}
@ -547,13 +433,13 @@ export async function addPHPUnitTools(data: ToolData): Promise<string> {
*
* @param data
*/
export async function addWPCLI(data: ToolData): Promise<string> {
if (data.version === 'latest') {
data.uri = 'wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true';
data.url = [data.domain, data.uri].join('/');
export async function addWPCLI(data: RS): Promise<string> {
if (data['version'] === 'latest') {
data['uri'] = 'wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true';
data['url'] = [data['domain'], data['uri']].join('/');
} else {
data.extension = '-' + data.version + data.extension;
data.url = await getUrl(data);
data['extension'] = '-' + data['version'] + data['extension'];
data['url'] = await getUrl(data);
}
return await addArchive(data);
}
@ -569,74 +455,56 @@ export async function getData(
release: string,
php_version: string,
os: string
): Promise<ToolData> {
): Promise<RS> {
const json_file_path = path.join(__dirname, '../src/configs/tools.json');
const json_file: string = fs.readFileSync(json_file_path, 'utf8');
const json_objects: Record<string, ToolConfig> = JSON.parse(json_file);
const json_objects: RSRS = JSON.parse(json_file);
release = release.replace(/\s+/g, '');
const parts: string[] = release.split(':');
const tool = parts[0];
const version = parts[1];
let config: ToolConfig & {tool: string};
if (Object.hasOwn(json_objects, tool)) {
config = {...json_objects[tool], tool};
let data: RS;
if (Object.keys(json_objects).includes(tool)) {
data = json_objects[tool];
data['tool'] = tool;
} else {
const key: string | undefined = Object.keys(json_objects).find(
(key: string) => {
return json_objects[key].alias == tool;
return json_objects[key]['alias'] == tool;
}
);
if (key) {
config = {...json_objects[key], tool: key};
} else if (tool.includes('/')) {
config = {
data = json_objects[key];
data['tool'] = key;
} else {
data = {
tool: tool.split('/')[1],
repository: tool,
type: 'composer'
};
} else {
config = {tool};
data = !tool.includes('/') ? {tool: tool} : data;
}
}
const github = 'https://github.com';
const domain = config.domain ?? github;
const data: ToolData = {
tool: config.tool,
version: '',
url: '',
os,
php_version,
github,
domain,
extension: config.extension ?? '.phar',
repository: config.repository ?? '',
prefix: domain === github ? 'releases' : '',
verb: domain === github ? 'download' : '',
fetch_latest: config.fetch_latest ?? 'false',
scope: config.scope ?? 'global',
version_parameter:
config.version_parameter != null
? JSON.stringify(config.version_parameter)
: '',
version_prefix: config.version_prefix ?? '',
release: '',
packagist: config.packagist ?? config.repository ?? '',
type: config.type,
function: config.function,
alias: config.alias
};
data.release = await getRelease(release, data);
data.version = version
data['github'] = 'https://github.com';
data['domain'] ??= data['github'];
data['extension'] ??= '.phar';
data['os'] = os;
data['php_version'] = php_version;
data['packagist'] ??= data['repository'];
data['prefix'] = data['github'] === data['domain'] ? 'releases' : '';
data['verb'] = data['github'] === data['domain'] ? 'download' : '';
data['fetch_latest'] ??= 'false';
data['scope'] ??= 'global';
data['version_parameter'] = JSON.stringify(data['version_parameter']) || '';
data['version_prefix'] ??= '';
data['release'] = await getRelease(release, data);
data['version'] = version
? await getVersion(version, data)
: await getLatestVersion(data);
data.url = await getUrl(data);
return data;
}
export const functionRecord: Record<
ToolFunction,
(data: ToolData) => Promise<string>
> = {
export const functionRecord: Record<string, (data: RS) => Promise<string>> = {
castor: addCastor,
composer: addComposer,
deployer: addDeployer,
@ -670,46 +538,43 @@ export async function addTools(
}
const tools_list = await filterList(await utils.CSVArray(tools_csv));
await utils.asyncForEach(tools_list, async function (release: string) {
const data: ToolData = await getData(release, php_version, os);
const data: RS = await getData(release, php_version, os);
script += '\n';
switch (true) {
case data.error !== undefined:
script += await utils.addLog('$cross', data.tool, data.error, data.os);
break;
case 'phar' === data.type:
script += await addArchive(data);
break;
case 'composer' === data.type:
script += await addPackage(data);
break;
case 'custom-package' === data.type:
script += await utils.customPackage(
data.tool.split('-')[0],
'tools',
data.version,
data.os
case data['error'] !== undefined:
script += await utils.addLog(
'$cross',
data['tool'],
data['error'],
data['os']
);
break;
case 'custom-function' === data.type:
if (!data.function) {
script += await utils.addLog(
'$cross',
data.tool,
data.tool + ' has no function defined. Please report this issue.',
data.os
);
} else {
script += await functionRecord[data.function](data);
}
case 'phar' === data['type']:
data['url'] = await getUrl(data);
script += await addArchive(data);
break;
case /^none$/.test(data.tool):
case 'composer' === data['type']:
script += await addPackage(data);
break;
case 'custom-package' === data['type']:
script += await utils.customPackage(
data['tool'].split('-')[0],
'tools',
data['version'],
data['os']
);
break;
case 'custom-function' === data['type']:
script += await functionRecord[data['function']](data);
break;
case /^none$/.test(data['tool']):
break;
default:
script += await utils.addLog(
'$cross',
data.tool,
'Tool ' + data.tool + ' is not supported',
data.os
data['tool'],
'Tool ' + data['tool'] + ' is not supported',
data['os']
);
break;
}

View File

@ -1,6 +1,6 @@
import fs from 'fs';
import * as path from 'path';
import * as core from './core';
import * as core from '@actions/core';
import * as fetch from './fetch';
/**
@ -48,11 +48,8 @@ export async function getInput(
/**
* Function to get manifest URL
*/
export async function getManifestURLS(): Promise<string[]> {
return [
'https://raw.githubusercontent.com/shivammathur/setup-php/develop/src/configs/php-versions.json',
'https://setup-php.com/php-versions.json'
];
export async function getManifestURL(): Promise<string> {
return 'https://raw.githubusercontent.com/shivammathur/setup-php/develop/src/configs/php-versions.json';
}
/**
@ -62,14 +59,10 @@ export async function getManifestURLS(): Promise<string[]> {
*/
export async function parseVersion(version: string): Promise<string> {
switch (true) {
case /^(latest|lowest|highest|nightly|master|\d+\.x)$/.test(version):
for (const manifestURL of await getManifestURLS()) {
const fetchResult = await fetch.fetch(manifestURL);
if (fetchResult['data'] ?? false) {
return JSON.parse(fetchResult['data'])[version];
}
}
throw new Error(`Could not fetch the PHP version manifest.`);
case /^(latest|lowest|highest|nightly|\d+\.x)$/.test(version):
return JSON.parse((await fetch.fetch(await getManifestURL()))['data'])[
version
];
default:
switch (true) {
case version.length > 1:
@ -97,8 +90,9 @@ export async function parseIniFile(ini_file: string): Promise<string> {
}
/**
* Async foreach loop using modern for...of pattern
* Async foreach loop
*
* @author https://github.com/Atinux
* @param array
* @param callback
*/
@ -110,8 +104,8 @@ export async function asyncForEach(
array: Array<string>
) => Promise<void>
): Promise<void> {
for (const [index, element] of array.entries()) {
await callback(element, index, array);
for (let index = 0; index < array.length; index++) {
await callback(array[index], index, array);
}
}
@ -399,7 +393,7 @@ export async function customPackage(
version: string,
os: string
): Promise<string> {
const pkg_name: string = pkg.replace(/\d+|(pdo|pecl)[_-]|[_-]db2/, '');
const pkg_name: string = pkg.replace(/\d+|(pdo|pecl)[_-]/, '');
const script_extension: string = await scriptExtension(os);
const script: string = path.join(
__dirname,
@ -455,7 +449,6 @@ export async function readPHPVersion(): Promise<string> {
const composerLock = path.join(composerProjectDir, 'composer.lock');
if (fs.existsSync(composerLock)) {
const lockFileContents = JSON.parse(fs.readFileSync(composerLock, 'utf8'));
/* istanbul ignore next */
if (
lockFileContents['platform-overrides'] &&
lockFileContents['platform-overrides']['php']
@ -469,7 +462,6 @@ export async function readPHPVersion(): Promise<string> {
const composerFileContents = JSON.parse(
fs.readFileSync(composerJson, 'utf8')
);
/* istanbul ignore next */
if (
composerFileContents['config'] &&
composerFileContents['config']['platform'] &&

View File

@ -3,7 +3,7 @@
"declaration": true,
"esModuleInterop": true,
"lib": [
"ES2024"
"ES2021"
],
"module": "commonjs",
"moduleResolution": "node",
@ -13,7 +13,7 @@
"rootDir": "./src",
"sourceMap": true,
"strict": true,
"target": "ES2024"
"target": "ES2021"
},
"exclude": ["__tests__", "lib", "node_modules"]
}