auto-detect required extension

This commit is contained in:
Indra Gunawan 2024-10-07 15:23:30 +08:00
parent 9f51892bda
commit 4d06eb8c86
No known key found for this signature in database
4 changed files with 122 additions and 3 deletions

View File

@ -87,6 +87,18 @@ describe('Utils tests', () => {
await utils.extensionArray('a, :b, php_c, none, php-d, Zend e, :Zend f') await utils.extensionArray('a, :b, php_c, none, php-d, Zend e, :Zend f')
).toEqual(['none', 'a', ':b', 'c', 'd', 'e', ':f']); ).toEqual(['none', 'a', ':b', 'c', 'd', 'e', ':f']);
expect(await utils.extensionArray('a, none, a')).toEqual(['none', 'a']);
expect(await utils.extensionArray('a, none, a-1.1.0')).toEqual([
'none',
'a-1.1.0'
]);
expect(await utils.extensionArray('a-1.1.0, none, :a, a')).toEqual([
'none',
':a'
]);
expect(await utils.extensionArray('')).toEqual([]); expect(await utils.extensionArray('')).toEqual([]);
expect(await utils.extensionArray(' ')).toEqual([]); expect(await utils.extensionArray(' ')).toEqual([]);
}); });
@ -304,6 +316,31 @@ describe('Utils tests', () => {
readFileSync.mockClear(); readFileSync.mockClear();
}); });
it('checking getRequiredExtension', async () => {
const existsSync = jest.spyOn(fs, 'existsSync').mockImplementation();
const readFileSync = jest.spyOn(fs, 'readFileSync').mockImplementation();
existsSync.mockReturnValueOnce(true);
readFileSync.mockReturnValue(
'{ "packages": [ { "require": { "ext-hash": "*", "ext-json": "*", "php": "^8.0", "psr/cache": "^3.0", "psr/log": "^3.0" } } ], "packages-dev": [ { "require": { "ext-dom": "*", "ext-pcre": "*", "php": "^8.0", "symfony/console": "^7.0.0", "symfony/process": "^7.0.0" } } ], "platform": { "php": ">=8.3.6", "ext-ctype": "*", "ext-redis": "*" }, "platform-dev": { "ext-gmp": "*" } }'
);
expect(await utils.getRequiredExtension()).toBe(
'hash,json,dom,pcre,ctype,redis,gmp'
);
existsSync.mockReturnValueOnce(false).mockReturnValueOnce(true);
readFileSync.mockReturnValue(
'{ "require": { "php": ">=8.3.6", "ext-ctype": "*", "ext-redis": "*" }, "require-dev": { "ext-gmp": "*" } }'
);
expect(await utils.getRequiredExtension()).toBe('ctype,redis,gmp');
existsSync.mockReturnValueOnce(false).mockReturnValueOnce(false);
expect(await utils.getRequiredExtension()).toBe('');
existsSync.mockClear();
readFileSync.mockClear();
});
it('checking setVariable', async () => { it('checking setVariable', async () => {
let script: string = await utils.setVariable('var', 'command', 'linux'); let script: string = await utils.setVariable('var', 'command', 'linux');
expect(script).toEqual('\nvar="$(command)"\n'); expect(script).toEqual('\nvar="$(command)"\n');

2
dist/index.js vendored

File diff suppressed because one or more lines are too long

View File

@ -30,8 +30,13 @@ export async function getScript(os: string): Promise<string> {
await utils.getInput('ini-file', false) await utils.getInput('ini-file', false)
); );
let script = await utils.joins('.', script_path, version, ini_file); let script = await utils.joins('.', script_path, version, ini_file);
if (extension_csv) { const required_extensions = await utils.getRequiredExtension();
script += await extensions.addExtension(extension_csv, version, os); if (extension_csv || required_extensions) {
script += await extensions.addExtension(
`${extension_csv},${required_extensions}`,
version,
os
);
} }
script += await tools.addTools(tools_csv, version, os); script += await tools.addTools(tools_csv, version, os);
if (coverage_driver) { if (coverage_driver) {

View File

@ -226,6 +226,38 @@ export async function extensionArray(
.toLowerCase() .toLowerCase()
.replace(/^(:)?(php[-_]|none|zend )|(-[^-]*)-/, '$1$3'); .replace(/^(:)?(php[-_]|none|zend )|(-[^-]*)-/, '$1$3');
}) })
.filter(function (value, index, array) {
if (array.indexOf(value) !== index) {
return false;
}
/**
* there are several actions to install extension
* action selected base on this priority
* 1. Disable an extension
* 2. Install specific extension version
* 3. Install extension latest version
*/
if (value.startsWith(':')) {
return true;
}
if (value.includes('-')) {
return !array.some(item =>
item.startsWith(`:${value.split('-')[0]}`)
);
}
if (
array.indexOf(`:${value}`) !== -1 ||
array.some(item => item.startsWith(`${value}-`))
) {
return false;
}
return true;
})
].filter(Boolean); ].filter(Boolean);
} }
} }
@ -491,3 +523,48 @@ export async function setVariable(
return '\n' + variable + '="$(' + command + ')"\n'; return '\n' + variable + '="$(' + command + ')"\n';
} }
} }
/**
* Get required extension from composer.lock or composer.json file
*/
export async function getRequiredExtension(): Promise<string> {
const composerLock = 'composer.lock';
if (fs.existsSync(composerLock)) {
const lockFileContents = JSON.parse(fs.readFileSync(composerLock, 'utf8'));
const requireExts = [
...lockFileContents['packages'],
...lockFileContents['packages-dev']
].flatMap(pkg =>
Object.keys(pkg['require'] || {})
.filter(key => key.startsWith('ext-'))
.map(item => item.replace(/^ext-/, ''))
);
const platformExts = Object.keys({
...lockFileContents['platform'],
...lockFileContents['platform-dev']
})
.filter(key => key.startsWith('ext-'))
.map(item => item.replace(/^ext-/, ''));
return [...requireExts, ...platformExts].join(',');
}
const composerJson = 'composer.json';
if (fs.existsSync(composerJson)) {
const composerFileContents = JSON.parse(
fs.readFileSync(composerJson, 'utf8')
);
const platformExts = Object.keys({
...composerFileContents['require'],
...composerFileContents['require-dev']
})
.filter(key => key.startsWith('ext-'))
.map(item => item.replace(/^ext-/, ''));
return platformExts.join(',');
}
return '';
}