Compare commits

..

3 Commits

Author SHA1 Message Date
Shivam Mathur 2adfe5537a Use private SASL plugins with the MongoDB extension archive 2026-09-24 16:02:19 +05:30
Shivam Mathur 8a84b8ac93 Remove optional extension staging files after an unavailable installer 2026-09-24 15:52:52 +05:30
Shivam Mathur 6ad98ef8cf Prefetch optional macOS extension caches alongside PHP installation 2026-09-24 15:39:10 +05:30
4 changed files with 6 additions and 118 deletions
+2 -90
View File
@@ -1,71 +1,6 @@
import {extensionPacks} from '../src/extensions'; import {extensionPacks} from '../src/extensions';
import {execFileSync} from 'node:child_process';
import * as fs from 'node:fs';
import * as os from 'node:os';
import * as path from 'node:path';
describe('Optional macOS extension archives', () => { describe('Optional macOS extension archives', () => {
it('installs packs concurrently and preserves successful packs when another fails', () => {
const directory = fs.mkdtempSync(
path.join(os.tmpdir(), 'setup-php-packs-')
);
const cache = path.join(directory, 'cache');
fs.mkdirSync(cache);
try {
for (const name of ['imagick', 'mongodb', 'memcached']) {
fs.writeFileSync(path.join(cache, name + '.json'), '{}');
}
fs.writeFileSync(
path.join(cache, 'install-extensions.cjs'),
`const fs=require('node:fs'), path=require('node:path');
const [,directory,name]=process.argv.slice(2);
fs.writeFileSync(path.join(directory,name+'.started'),'yes');
setTimeout(()=>process.exit(2),1500);
setInterval(()=>{
if (fs.readdirSync(directory).filter(file=>file.endsWith('.started')).length!==3) return;
fs.writeFileSync(path.join(directory,name+'.env'),'SASL_PATH=/cache/'+name+'\\n');
console.log('completed '+name);
process.exit(name==='mongodb'?1:0);
},10);
`
);
const output = execFileSync(
'bash',
[
'-c',
'. "$CACHE_SCRIPT"; add_env() { printf "env %s %s\\n" "$1" "$2"; }; enable_extensions() { printf "enable batch %s\\n" "$*"; }; enable_extension() { printf "enable module %s\\n" "$1"; }; php() { echo refreshed; }; (exit 0) & extension_cache_pid=$!; finish_extension_cache_downloads; test "$extension_cache_memcached_dependencies" = "igbinary msgpack"; test "$(cat /tmp/php${version}_extensions)" = refreshed; rm /tmp/php${version}_extensions'
],
{
encoding: 'utf8',
env: {
...process.env,
CACHE_SCRIPT: path.resolve(
'src/scripts/extensions/darwin_cache.sh'
),
SETUP_PHP_NODE: process.execPath,
SETUP_PHP_EXTENSION_PACKS: 'imagick mongodb memcached',
extension_cache_dir: cache,
version: 'cache-test-' + path.basename(directory),
verbose: ''
}
}
);
expect(output).toContain('completed imagick');
expect(output).toContain('completed memcached');
expect(output).toContain('mongodb cache unavailable');
expect(output).toContain('env SASL_PATH /cache/imagick');
expect(output).not.toContain('env SASL_PATH /cache/mongodb');
expect(output).toContain('enable batch imagick igbinary msgpack');
expect(output).toContain('enable module memcached');
expect(output).not.toContain('enable batch mongodb');
expect(output.indexOf('enable batch')).toBeLessThan(
output.indexOf('enable module memcached')
);
expect(fs.existsSync(cache)).toBe(false);
} finally {
fs.rmSync(directory, {recursive: true, force: true});
}
});
it('selects each requested pack once', async () => { it('selects each requested pack once', async () => {
expect( expect(
await extensionPacks( await extensionPacks(
@@ -90,31 +25,8 @@ setInterval(()=>{
} }
); );
it('selects optional packs for PHP 5.6 through 8.7', async () => { it('keeps legacy PHP and other platforms on their existing paths', async () => {
for (const version of [ for (const version of ['5.4', '7.4', '8.1', '8.6']) {
'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',
'8.7'
]) {
expect(
await extensionPacks('imagick, mongodb, memcached', version, 'darwin')
).toEqual(['imagick', 'mongodb', 'memcached']);
}
});
it('keeps unsupported PHP and other platforms on their existing paths', async () => {
for (const version of ['5.4', '5.5', '7.5', '8.8', '9.0']) {
expect(await extensionPacks('imagick', version, 'darwin')).toEqual([]); expect(await extensionPacks('imagick', version, 'darwin')).toEqual([]);
} }
for (const os of ['linux', 'win32']) { for (const os of ['linux', 'win32']) {
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -6,7 +6,7 @@ export async function extensionPacks(
version: string, version: string,
os: string os: string
): Promise<string[]> { ): Promise<string[]> {
if (os !== 'darwin' || !/^(5\.6|7\.[0-4]|8\.[0-7])$/.test(version)) return []; if (os !== 'darwin' || !/^8\.[2-5]$/.test(version)) return [];
const requested = await utils.extensionArray(extension_csv); const requested = await utils.extensionArray(extension_csv);
return ['imagick', 'mongodb', 'memcached'].filter( return ['imagick', 'mongodb', 'memcached'].filter(
name => requested.includes(name) && !requested.includes(':' + name) name => requested.includes(name) && !requested.includes(':' + name)
+2 -26
View File
@@ -29,21 +29,10 @@ finish_extension_cache_downloads() {
extension_cache_dir= extension_cache_dir=
return 0 return 0
fi fi
local extension variable value index local extension variable value
local cache_install_names=() cache_install_pids=() cache_enable_names=()
for extension in $SETUP_PHP_EXTENSION_PACKS; do for extension in $SETUP_PHP_EXTENSION_PACKS; do
[ -s "$extension_cache_dir/$extension.json" ] || continue [ -s "$extension_cache_dir/$extension.json" ] || continue
# Packs own separate directories and module names. Extract and validate them if "$SETUP_PHP_NODE" "$extension_cache_dir/install-extensions.cjs" install "$extension_cache_dir" "$extension"; then
# concurrently, then import their environments only after each one succeeds.
"$SETUP_PHP_NODE" "$extension_cache_dir/install-extensions.cjs" install "$extension_cache_dir" "$extension" \
> "$extension_cache_dir/$extension.install.log" 2>&1 &
cache_install_names+=("$extension")
cache_install_pids+=("$!")
done
for index in "${!cache_install_pids[@]}"; do
extension=${cache_install_names[$index]}
if wait "${cache_install_pids[$index]}"; then
cat "$extension_cache_dir/$extension.install.log"
while IFS='=' read -r variable value; do while IFS='=' read -r variable value; do
case "$variable" in case "$variable" in
MAGICK_CONFIGURE_PATH|MAGICK_CODER_MODULE_PATH|MAGICK_FILTER_MODULE_PATH|SASL_PATH) MAGICK_CONFIGURE_PATH|MAGICK_CODER_MODULE_PATH|MAGICK_FILTER_MODULE_PATH|SASL_PATH)
@@ -55,26 +44,13 @@ finish_extension_cache_downloads() {
# can be removed before the action enables its requested extensions. # can be removed before the action enables its requested extensions.
if [ "$extension" = memcached ]; then if [ "$extension" = memcached ]; then
extension_cache_memcached_dependencies='igbinary msgpack' extension_cache_memcached_dependencies='igbinary msgpack'
cache_enable_names+=(igbinary msgpack)
else
cache_enable_names+=("$extension")
fi fi
else else
cat "$extension_cache_dir/$extension.install.log"
printf 'setup-php: %s cache unavailable for this PHP; using the existing installer\n' "$extension" printf 'setup-php: %s cache unavailable for this PHP; using the existing installer\n' "$extension"
fi fi
done done
rm -rf "$extension_cache_dir" rm -rf "$extension_cache_dir"
extension_cache_dir= extension_cache_dir=
# Use the normal enabling rules, but overlap independent modules and refresh
# the loaded-module list once so later extension checks do not repeat php -m.
if [ "${#cache_enable_names[@]}" -gt 0 ]; then
enable_extensions "${cache_enable_names[@]}"
if [ -n "${extension_cache_memcached_dependencies:-}" ]; then
enable_extension memcached extension
fi
php -m > "/tmp/php${version}_extensions"
fi
} }
enable_extension_cache_dependencies() { enable_extension_cache_dependencies() {