mirror of
https://github.com/crazywhalecc/static-php-cli.git
synced 2026-07-20 07:15:35 +08:00
Compare commits
32 Commits
48a7d814f8
...
2.7.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa10142f13 | ||
|
|
c342741670 | ||
|
|
64d49003e0 | ||
|
|
b0c93c7418 | ||
|
|
085abd635e | ||
|
|
3789c7c335 | ||
|
|
4fb4e42896 | ||
|
|
81e7a0c554 | ||
|
|
4cbe4ea82d | ||
|
|
ea4905cd0d | ||
|
|
3c09ba59d7 | ||
|
|
430f436b79 | ||
|
|
93001dce88 | ||
|
|
2d6d25cadf | ||
|
|
b644da8210 | ||
|
|
f1a9a28ed7 | ||
|
|
643926886c | ||
|
|
9a5a59d876 | ||
|
|
e7fe91faef | ||
|
|
e6cf05ddff | ||
|
|
c3e9a2816b | ||
|
|
0bb8e83d68 | ||
|
|
d0053534ab | ||
|
|
38725c2bb4 | ||
|
|
b8fe70e5ee | ||
|
|
3960a21e05 | ||
|
|
e14301d991 | ||
|
|
65f74044d8 | ||
|
|
f6eba32be5 | ||
|
|
af62e55da8 | ||
|
|
22a8191b97 | ||
|
|
17ff5f63bf |
45
.github/workflows/release-build.yml
vendored
45
.github/workflows/release-build.yml
vendored
@@ -3,6 +3,10 @@ name: Build SPC Binary
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
paths:
|
||||
- '.github/workflows/release-build.yml'
|
||||
release:
|
||||
types:
|
||||
- published
|
||||
@@ -10,7 +14,7 @@ on:
|
||||
|
||||
env:
|
||||
PHP_VERSION: 8.4
|
||||
MICRO_VERSION: 8.4.10
|
||||
MICRO_VERSION: 8.4.11
|
||||
|
||||
jobs:
|
||||
build-release-artifacts:
|
||||
@@ -117,7 +121,8 @@ jobs:
|
||||
files: dist/${{ matrix.operating-system.filename }}
|
||||
|
||||
- name: "Deploy to self-hosted OSS"
|
||||
if: github.repository == 'crazywhalecc/static-php-cli'
|
||||
# only run this step if the repository is static-php-cli and the branch is main
|
||||
if: github.repository == 'crazywhalecc/static-php-cli' && github.ref == 'refs/heads/main'
|
||||
uses: static-php/upload-s3-action@v1.0.0
|
||||
with:
|
||||
aws_key_id: ${{ secrets.AWS_KEY_ID }}
|
||||
@@ -132,3 +137,39 @@ jobs:
|
||||
with:
|
||||
path: spc${{ env.SUFFIX }}
|
||||
name: spc-${{ matrix.operating-system.name }}${{ env.SUFFIX }}
|
||||
test-spc:
|
||||
name: "Test SPC Binary for ${{ matrix.operating-system.name }}"
|
||||
runs-on: ${{ matrix.operating-system.os }}
|
||||
needs: [build-release-artifacts]
|
||||
strategy:
|
||||
matrix:
|
||||
operating-system:
|
||||
- name: "linux-x86_64"
|
||||
os: "ubuntu-latest"
|
||||
- name: "macos-x86_64"
|
||||
os: "macos-13"
|
||||
- name: "linux-aarch64"
|
||||
os: "ubuntu-24.04-arm"
|
||||
- name: "macos-aarch64"
|
||||
os: "macos-latest"
|
||||
- name: "windows-x64"
|
||||
os: "windows-latest"
|
||||
steps:
|
||||
- name: "Checkout"
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: "Download Artifact"
|
||||
uses: actions/download-artifact@v4
|
||||
env:
|
||||
SUFFIX: ${{ matrix.operating-system.name == 'windows-x64' && '.exe' || '' }}
|
||||
with:
|
||||
name: spc-${{ matrix.operating-system.name }}${{ env.SUFFIX }}
|
||||
|
||||
- name: "Chmod"
|
||||
if: matrix.operating-system.name != 'windows-x64'
|
||||
run: chmod +x spc
|
||||
|
||||
- name: "Run SPC Tests"
|
||||
env:
|
||||
SUFFIX: ${{ matrix.operating-system.name == 'windows-x64' && '.exe' || '' }}
|
||||
run: ./spc${{ env.SUFFIX }} dev:extensions
|
||||
|
||||
4
.github/workflows/tests.yml
vendored
4
.github/workflows/tests.yml
vendored
@@ -145,6 +145,10 @@ jobs:
|
||||
os: ${{ fromJSON(needs.define-matrix.outputs.os) }}
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: "Update runner packages"
|
||||
if: ${{ startsWith(matrix.os, 'ubuntu-') }}
|
||||
run: sudo apt-get update && sudo apt-get install -y ca-certificates
|
||||
|
||||
- name: "Checkout"
|
||||
uses: actions/checkout@v4
|
||||
|
||||
|
||||
@@ -488,6 +488,7 @@
|
||||
"opcache": {
|
||||
"type": "builtin",
|
||||
"arg-type-unix": "custom",
|
||||
"arg-type-windows": "enable",
|
||||
"zend-extension": true
|
||||
},
|
||||
"openssl": {
|
||||
@@ -530,9 +531,10 @@
|
||||
},
|
||||
"notes": true,
|
||||
"type": "builtin",
|
||||
"arg-type": "with-path",
|
||||
"arg-type": "custom",
|
||||
"lib-depends": [
|
||||
"libargon2"
|
||||
"libargon2",
|
||||
"openssl"
|
||||
]
|
||||
},
|
||||
"pcntl": {
|
||||
|
||||
@@ -1012,6 +1012,7 @@
|
||||
"path": "php-src/ext/swoole",
|
||||
"type": "ghtar",
|
||||
"repo": "swoole/swoole-src",
|
||||
"match": "v6\\.+",
|
||||
"prefer-stable": true,
|
||||
"license": {
|
||||
"type": "file",
|
||||
|
||||
@@ -34,7 +34,7 @@ use Symfony\Component\Console\Application;
|
||||
*/
|
||||
final class ConsoleApplication extends Application
|
||||
{
|
||||
public const VERSION = '2.7.0';
|
||||
public const VERSION = '2.7.1';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
@@ -51,13 +51,7 @@ class opcache extends Extension
|
||||
|
||||
public function getUnixConfigureArg(bool $shared = false): string
|
||||
{
|
||||
$version = $this->builder->getPHPVersion();
|
||||
$opcache_jit = !$this->builder->getOption('disable-opcache-jit', false);
|
||||
$opcache_jit = $opcache_jit ? '--enable-opcache-jit' : '--disable-opcache-jit';
|
||||
if (version_compare($version, '8.5.0-dev', '<')) {
|
||||
return "--enable-opcache {$opcache_jit}";
|
||||
}
|
||||
return $opcache_jit;
|
||||
return '--enable-opcache';
|
||||
}
|
||||
|
||||
public function getDistName(): string
|
||||
|
||||
@@ -5,23 +5,11 @@ declare(strict_types=1);
|
||||
namespace SPC\builder\extension;
|
||||
|
||||
use SPC\builder\Extension;
|
||||
use SPC\store\FileSystem;
|
||||
use SPC\util\CustomExt;
|
||||
|
||||
#[CustomExt('openssl')]
|
||||
class openssl extends Extension
|
||||
{
|
||||
public function patchBeforeBuildconf(): bool
|
||||
{
|
||||
// Fix php 8.5 alpha1~4 zts openssl build bug
|
||||
FileSystem::replaceFileStr(
|
||||
SOURCE_PATH . '/php-src/ext/openssl/config.w32',
|
||||
'WARNING("OpenSSL argon2 hashing not supported in ZTS mode for now");',
|
||||
'AC_DEFINE("HAVE_OPENSSL_ARGON2", 1, "Define to 1 to enable OpenSSL argon2 password hashing.");'
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
public function patchBeforeMake(): bool
|
||||
{
|
||||
$patched = parent::patchBeforeMake();
|
||||
@@ -40,7 +28,7 @@ class openssl extends Extension
|
||||
{
|
||||
$openssl_dir = $this->builder->getPHPVersionID() >= 80400 ? '' : ' --with-openssl-dir=' . BUILD_ROOT_PATH;
|
||||
$args = '--with-openssl=' . ($shared ? 'shared,' : '') . BUILD_ROOT_PATH . $openssl_dir;
|
||||
if ($this->builder->getPHPVersionID() >= 80500) {
|
||||
if ($this->builder->getPHPVersionID() >= 80500 || ($this->builder->getPHPVersionID() >= 80400 && !$this->builder->getOption('enable-zts'))) {
|
||||
$args .= ' --with-openssl-argon2 OPENSSL_LIBS="-lz"';
|
||||
}
|
||||
return $args;
|
||||
@@ -49,7 +37,7 @@ class openssl extends Extension
|
||||
public function getWindowsConfigureArg(bool $shared = false): string
|
||||
{
|
||||
$args = '--with-openssl';
|
||||
if ($this->builder->getPHPVersionID() >= 80500) {
|
||||
if ($this->builder->getPHPVersionID() >= 80500 || ($this->builder->getPHPVersionID() >= 80400 && !$this->builder->getOption('enable-zts'))) {
|
||||
$args .= ' --with-openssl-argon2';
|
||||
}
|
||||
return $args;
|
||||
|
||||
@@ -42,4 +42,14 @@ class password_argon2 extends Extension
|
||||
}
|
||||
return $patched;
|
||||
}
|
||||
|
||||
public function getConfigureArg(bool $shared = false): string
|
||||
{
|
||||
if ($this->builder->getLib('openssl') !== null) {
|
||||
if ($this->builder->getPHPVersionID() >= 80500 || ($this->builder->getPHPVersionID() >= 80400 && !$this->builder->getOption('enable-zts'))) {
|
||||
return '--without-password-argon2'; // use --with-openssl-argon2 in openssl extension instead
|
||||
}
|
||||
}
|
||||
return '--with-password-argon2';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,17 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
$phpVersionID = $this->getPHPVersionID();
|
||||
$json_74 = $phpVersionID < 80000 ? '--enable-json ' : '';
|
||||
|
||||
$opcache_jit = !$this->getOption('disable-opcache-jit', false);
|
||||
if ($opcache_jit && ($phpVersionID >= 80500 || $this->getExt('opcache'))) {
|
||||
// php 8.5 contains opcache extension by default,
|
||||
// if opcache_jit is enabled for 8.5 or opcache enabled,
|
||||
// we need to disable undefined behavior sanitizer.
|
||||
f_putenv('SPC_COMPILER_EXTRA=-fno-sanitize=undefined');
|
||||
} elseif ($opcache_jit) {
|
||||
$opcache_jit = false;
|
||||
}
|
||||
$opcache_jit_arg = $opcache_jit ? '--enable-opcache-jit ' : '--disable-opcache-jit ';
|
||||
|
||||
if ($this->getOption('enable-zts', false)) {
|
||||
$maxExecutionTimers = $phpVersionID >= 80100 ? '--enable-zend-max-execution-timers ' : '';
|
||||
$zts = '--enable-zts --disable-zend-signals ';
|
||||
@@ -73,10 +84,7 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
$maxExecutionTimers = '';
|
||||
$zts = '';
|
||||
}
|
||||
$disable_jit = $this->getOption('disable-opcache-jit', false) ? '--disable-opcache-jit ' : '';
|
||||
if (!$disable_jit && $this->getExt('opcache')) {
|
||||
f_putenv('SPC_COMPILER_EXTRA=-fno-sanitize=undefined');
|
||||
}
|
||||
|
||||
$config_file_path = $this->getOption('with-config-file-path', false) ?
|
||||
('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : '';
|
||||
$config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ?
|
||||
@@ -89,9 +97,10 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
$enableFrankenphp = ($build_target & BUILD_TARGET_FRANKENPHP) === BUILD_TARGET_FRANKENPHP;
|
||||
|
||||
// prepare build php envs
|
||||
// $musl_flag = SPCTarget::getLibc() === 'musl' ? ' -D__MUSL__' : ' -U__MUSL__';
|
||||
$php_configure_env = SystemUtil::makeEnvVarString([
|
||||
'CFLAGS' => getenv('SPC_CMD_VAR_PHP_CONFIGURE_CFLAGS'),
|
||||
'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH,
|
||||
'CPPFLAGS' => '-I' . BUILD_INCLUDE_PATH, // . ' -Dsomethinghere', // . $musl_flag,
|
||||
'LDFLAGS' => '-L' . BUILD_LIB_PATH,
|
||||
// 'LIBS' => SPCTarget::getRuntimeLibs(), // do not pass static libraries here yet, they may contain polyfills for libc functions!
|
||||
]);
|
||||
@@ -114,7 +123,7 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
($enableMicro ? '--enable-micro=all-static ' : '--disable-micro ') .
|
||||
$config_file_path .
|
||||
$config_file_scan_dir .
|
||||
$disable_jit .
|
||||
$opcache_jit_arg .
|
||||
$json_74 .
|
||||
$zts .
|
||||
$maxExecutionTimers .
|
||||
@@ -335,6 +344,15 @@ class LinuxBuilder extends UnixBuilderBase
|
||||
$this->patchPhpScripts();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return extra variables for php make command.
|
||||
*
|
||||
* @throws FileSystemException
|
||||
* @throws RuntimeException
|
||||
* @throws WrongUsageException
|
||||
* @throws \ReflectionException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function getMakeExtraVars(): array
|
||||
{
|
||||
$config = (new SPCConfigUtil($this, ['libs_only_deps' => true, 'absolute_libs' => true]))->config($this->ext_list, $this->lib_list, $this->getOption('with-suggested-exts'), $this->getOption('with-suggested-libs'));
|
||||
|
||||
@@ -102,6 +102,13 @@ class MacOSBuilder extends UnixBuilderBase
|
||||
$json_74 = $phpVersionID < 80000 ? '--enable-json ' : '';
|
||||
$zts = $this->getOption('enable-zts', false) ? '--enable-zts --disable-zend-signals ' : '';
|
||||
|
||||
$opcache_jit = !$this->getOption('disable-opcache-jit', false);
|
||||
// disable opcache jit for PHP < 8.5.0 when opcache is not enabled
|
||||
if ($opcache_jit && $phpVersionID < 80500 && !$this->getExt('opcache')) {
|
||||
$opcache_jit = false;
|
||||
}
|
||||
$opcache_jit_arg = $opcache_jit ? '--enable-opcache-jit ' : '--disable-opcache-jit ';
|
||||
|
||||
$config_file_path = $this->getOption('with-config-file-path', false) ?
|
||||
('--with-config-file-path=' . $this->getOption('with-config-file-path') . ' ') : '';
|
||||
$config_file_scan_dir = $this->getOption('with-config-file-scan-dir', false) ?
|
||||
@@ -136,6 +143,7 @@ class MacOSBuilder extends UnixBuilderBase
|
||||
($enableFpm ? '--enable-fpm ' : '--disable-fpm ') .
|
||||
($enableEmbed ? "--enable-embed={$embed_type} " : '--disable-embed ') .
|
||||
($enableMicro ? '--enable-micro ' : '--disable-micro ') .
|
||||
$opcache_jit_arg .
|
||||
$config_file_path .
|
||||
$config_file_scan_dir .
|
||||
$json_74 .
|
||||
|
||||
@@ -89,6 +89,9 @@ class WindowsBuilder extends BuilderBase
|
||||
}
|
||||
}
|
||||
|
||||
$opcache_jit = !$this->getOption('disable-opcache-jit', false);
|
||||
$opcache_jit_arg = $opcache_jit ? '--enable-opcache-jit=yes ' : '--enable-opcache-jit=no ';
|
||||
|
||||
if (($logo = $this->getOption('with-micro-logo')) !== null) {
|
||||
// realpath
|
||||
// $logo = realpath($logo);
|
||||
@@ -115,6 +118,7 @@ class WindowsBuilder extends BuilderBase
|
||||
($enableMicro ? ('--enable-micro=yes ' . $micro_logo . $micro_w32) : '--enable-micro=no ') .
|
||||
($enableEmbed ? '--enable-embed=yes ' : '--enable-embed=no ') .
|
||||
$config_file_scan_dir .
|
||||
$opcache_jit_arg .
|
||||
"{$this->makeStaticExtensionArgs()} " .
|
||||
$zts .
|
||||
'"'
|
||||
|
||||
@@ -69,6 +69,35 @@ class SourcePatcher
|
||||
);
|
||||
}
|
||||
|
||||
// Fix PHP VS version
|
||||
if ($builder instanceof WindowsBuilder) {
|
||||
// get vs version
|
||||
$vc = \SPC\builder\windows\SystemUtil::findVisualStudio();
|
||||
$vc_matches = match ($vc['version']) {
|
||||
'vs17' => ['VS17', 'Visual C++ 2022'],
|
||||
'vs16' => ['VS16', 'Visual C++ 2019'],
|
||||
default => ['unknown', 'unknown'],
|
||||
};
|
||||
// patch php-src/win32/build/confutils.js
|
||||
FileSystem::replaceFileStr(
|
||||
SOURCE_PATH . '\php-src\win32\build\confutils.js',
|
||||
'var name = "unknown";',
|
||||
"var name = short ? \"{$vc_matches[0]}\" : \"{$vc_matches[1]}\";return name;"
|
||||
);
|
||||
}
|
||||
|
||||
// patch configure.ac
|
||||
$musl = SPCTarget::getLibc() === 'musl';
|
||||
FileSystem::backupFile(SOURCE_PATH . '/php-src/configure.ac');
|
||||
FileSystem::replaceFileStr(
|
||||
SOURCE_PATH . '/php-src/configure.ac',
|
||||
'if command -v ldd >/dev/null && ldd --version 2>&1 | grep ^musl >/dev/null 2>&1',
|
||||
'if ' . ($musl ? 'true' : 'false')
|
||||
);
|
||||
if (getenv('SPC_LIBC') === false && ($libc = SPCTarget::getLibc()) !== null) {
|
||||
putenv("SPC_LIBC={$libc}");
|
||||
}
|
||||
|
||||
// patch php-src/build/php.m4 PKG_CHECK_MODULES -> PKG_CHECK_MODULES_STATIC
|
||||
FileSystem::replaceFileStr(SOURCE_PATH . '/php-src/build/php.m4', 'PKG_CHECK_MODULES(', 'PKG_CHECK_MODULES_STATIC(');
|
||||
|
||||
@@ -102,6 +131,11 @@ class SourcePatcher
|
||||
if (is_unix()) {
|
||||
FileSystem::replaceFileRegex(SOURCE_PATH . '/php-src/configure', '/have_capstone="yes"/', 'have_capstone="no"');
|
||||
}
|
||||
|
||||
if (file_exists(SOURCE_PATH . '/php-src/configure.ac.bak')) {
|
||||
// restore configure.ac
|
||||
FileSystem::restoreBackupFile(SOURCE_PATH . '/php-src/configure.ac');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,13 +6,27 @@ assert(function_exists('curl_init'));
|
||||
assert(function_exists('curl_setopt'));
|
||||
assert(function_exists('curl_exec'));
|
||||
assert(function_exists('curl_close'));
|
||||
assert(function_exists('curl_version'));
|
||||
$curl_version = curl_version();
|
||||
if (stripos($curl_version['ssl_version'], 'schannel') !== false) {
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, 'https://captive.apple.com/');
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||||
$data = curl_exec($curl);
|
||||
curl_close($curl);
|
||||
assert($data !== false);
|
||||
$domain_list = [
|
||||
'https://captive.apple.com/',
|
||||
'https://detectportal.firefox.com/',
|
||||
'https://static-php.dev/',
|
||||
'https://www.example.com/',
|
||||
];
|
||||
$valid = false;
|
||||
foreach ($domain_list as $domain) {
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, $domain);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curl, CURLOPT_HEADER, 0);
|
||||
$data = curl_exec($curl);
|
||||
curl_close($curl);
|
||||
if ($data !== false) {
|
||||
$valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert($valid);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,31 @@ declare(strict_types=1);
|
||||
assert(function_exists('openssl_digest'));
|
||||
assert(openssl_digest('123456', 'md5') === 'e10adc3949ba59abbe56e057f20f883e');
|
||||
if (file_exists('/etc/ssl/openssl.cnf')) {
|
||||
assert(file_get_contents('https://captive.apple.com/') !== false);
|
||||
$domain_list = [
|
||||
'captive.apple.com',
|
||||
'detectportal.firefox.com',
|
||||
'static-php.dev',
|
||||
'www.example.com',
|
||||
];
|
||||
$valid = false;
|
||||
foreach ($domain_list as $domain) {
|
||||
$ssloptions = [
|
||||
'capture_peer_cert' => true,
|
||||
'capture_peer_cert_chain' => true,
|
||||
'allow_self_signed' => false,
|
||||
'CN_match' => $domain,
|
||||
'verify_peer' => true,
|
||||
'SNI_enabled' => true,
|
||||
'SNI_server_name' => $domain,
|
||||
];
|
||||
$context = stream_context_create(['ssl' => $ssloptions]);
|
||||
$result = stream_socket_client("ssl://{$domain}:443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $context);
|
||||
if ($result !== false) {
|
||||
$valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert($valid);
|
||||
}
|
||||
if (PHP_VERSION_ID >= 80500 && defined('OPENSSL_VERSION_NUMBER') && OPENSSL_VERSION_NUMBER >= 0x30200000) {
|
||||
assert(function_exists('openssl_password_hash'));
|
||||
|
||||
@@ -13,11 +13,11 @@ declare(strict_types=1);
|
||||
|
||||
// test php version (8.1 ~ 8.4 available, multiple for matrix)
|
||||
$test_php_version = [
|
||||
'8.1',
|
||||
'8.2',
|
||||
'8.3',
|
||||
// '8.1',
|
||||
// '8.2',
|
||||
// '8.3',
|
||||
'8.4',
|
||||
'8.5',
|
||||
// '8.5',
|
||||
'git',
|
||||
];
|
||||
|
||||
@@ -26,10 +26,10 @@ $test_os = [
|
||||
// 'macos-13', // bin/spc for x86_64
|
||||
// 'macos-14', // bin/spc for arm64
|
||||
// 'macos-15', // bin/spc for arm64
|
||||
// 'ubuntu-latest', // bin/spc-alpine-docker for x86_64
|
||||
'ubuntu-latest', // bin/spc-alpine-docker for x86_64
|
||||
// 'ubuntu-22.04', // bin/spc-gnu-docker for x86_64
|
||||
// 'ubuntu-24.04', // bin/spc for x86_64
|
||||
// 'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64
|
||||
'ubuntu-24.04', // bin/spc for x86_64
|
||||
'ubuntu-22.04-arm', // bin/spc-gnu-docker for arm64
|
||||
'ubuntu-24.04-arm', // bin/spc for arm64
|
||||
// 'windows-latest', // .\bin\spc.ps1
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user