diff --git a/README.md b/README.md index d39fc121..9d8c64a7 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,8 @@ with: extensions: xdebug-beta ``` +- Blackfire PHP extension is available for install. + - Extensions which cannot be installed gracefully leave an error message in the logs, the action is not interrupted. ## :wrench: Tools Support @@ -489,6 +491,7 @@ Examples for setting up this GitHub Action with different PHP Frameworks/Package |Yii2 Starter Kit with `MySQL`|`ubuntu`|[yii2-mysql.yml](./examples/yii2-mysql.yml "GitHub Action for Yii2 Starter Kit with MySQL")| |Yii2 Starter Kit with `PostgreSQL`|`ubuntu`|[yii2-postgres.yml](./examples/yii2-postgres.yml "GitHub Action for Yii2 Starter Kit with PostgreSQL")| |Zend Framework|`macOS`, `ubuntu` and `windows`|[zend-framework.yml](./examples/zend-framework.yml "GitHub Action for Zend Framework")| +|Blackfire|`macOS`, `ubuntu` and `windows`|[blackfire.yml](./examples/blackfire.yml "GitHub Action using blackfire")| ## :scroll: License diff --git a/__tests__/extensions.test.ts b/__tests__/extensions.test.ts index cd09d800..9f69fac9 100644 --- a/__tests__/extensions.test.ts +++ b/__tests__/extensions.test.ts @@ -25,6 +25,12 @@ describe('Extension tests', () => { win32 = await extensions.addExtension('xdebug', '7.2', 'fedora'); expect(win32).toContain('Platform fedora is not supported'); + + win32 = await extensions.addExtension('blackfire', '7.3', 'win32'); + expect(win32).toContain('blackfire.ps1 73'); + + win32 = await extensions.addExtension('blackfire-1.31.0', '7.3', 'win32'); + expect(win32).toContain('blackfire.ps1 73 1.31.0'); }); it('checking addExtensionOnLinux', async () => { @@ -63,6 +69,12 @@ describe('Extension tests', () => { linux = await extensions.addExtension('phalcon3, phalcon4', '7.3', 'linux'); expect(linux).toContain('phalcon.sh phalcon3 7.3'); expect(linux).toContain('phalcon.sh phalcon4 7.3'); + + linux = await extensions.addExtension('blackfire', '7.3', 'linux'); + expect(linux).toContain('blackfire.sh 7.3 73'); + + linux = await extensions.addExtension('blackfire-1.31.0', '7.3', 'linux'); + expect(linux).toContain('blackfire.sh 7.3 73 1.31.0'); }); it('checking addExtensionOnDarwin', async () => { @@ -120,6 +132,12 @@ describe('Extension tests', () => { expect(darwin).toContain('brew install pkg-config imagemagick'); expect(darwin).toContain('sudo pecl install -f imagick'); + darwin = await extensions.addExtension('blackfire', '7.3', 'darwin'); + expect(darwin).toContain('blackfire_darwin.sh 7.3 73'); + + darwin = await extensions.addExtension('blackfire-1.31.0', '7.3', 'darwin'); + expect(darwin).toContain('blackfire_darwin.sh 7.3 73 1.31.0'); + darwin = await extensions.addExtension( 'does_not_exist', '7.2', diff --git a/__tests__/utils.test.ts b/__tests__/utils.test.ts index 59dcb80e..79e58023 100644 --- a/__tests__/utils.test.ts +++ b/__tests__/utils.test.ts @@ -161,4 +161,11 @@ describe('Utils tests', () => { 'Platform fedora is not supported' ); }); + + it('checking getMinorVersion', async () => { + expect(await utils.getMinorVersion('7.14.0')).toEqual('7.14'); + expect(await utils.getMinorVersion('7.4')).toEqual('7.4'); + expect(await utils.getMinorVersion('7.4.1')).toEqual('7.4'); + expect(await utils.getMinorVersion('7.aa')).toEqual('7.aa'); + }); }); diff --git a/dist/index.js b/dist/index.js index 95e81ace..e7a2e0a1 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1247,6 +1247,17 @@ function suppressOutput(os_version) { }); } exports.suppressOutput = suppressOutput; +function getMinorVersion(version) { + return __awaiter(this, void 0, void 0, function* () { + const regex = /^\d+\.\d+/; + const match = version.match(regex); + if (match === null) { + return version; + } + return match[0]; + }); +} +exports.getMinorVersion = getMinorVersion; /***/ }), @@ -2706,6 +2717,18 @@ function addExtensionDarwin(extension_csv, version, pipe) { const prefix = yield utils.getExtensionPrefix(ext_name); let install_command = ''; switch (true) { + case /^blackfire(-\d+\.\d+\.\d+)?$/.test(extension): + script += + '\nsh ' + + path.join(__dirname, '../src/scripts/ext/blackfire_darwin.sh') + + ' ' + + version + + ' ' + + (yield utils.getMinorVersion(version)).replace('.', ''); + if (ext_version) { + script += ' ' + ext_version; + } + return; // match pre-release versions case /.*-(beta|alpha|devel|snapshot)/.test(version_extension): script += @@ -2787,6 +2810,17 @@ function addExtensionWindows(extension_csv, version, pipe) { const version_extension = version + extension; let matches; switch (true) { + // match blackfire...blackfire-1.31.0 + case /^blackfire(-\d+\.\d+\.\d+)?$/.test(extension): + script += + '\n& ' + + path.join(__dirname, '../src/scripts/ext/blackfire.ps1') + + ' ' + + (yield utils.getMinorVersion(version)).replace('.', ''); + if (ext_version) { + script += ' ' + ext_version; + } + return; // match pre-release versions case /.*-(beta|alpha|devel|snapshot)/.test(version_extension): script += '\nAdd-Extension ' + ext_name + ' ' + ext_version; @@ -2840,6 +2874,19 @@ function addExtensionLinux(extension_csv, version, pipe) { const prefix = yield utils.getExtensionPrefix(ext_name); let install_command = ''; switch (true) { + // match blackfire... blackfire-1.31.0 + case /^blackfire(-\d+\.\d+\.\d+)?$/.test(extension): + script += + '\nsh ' + + path.join(__dirname, '../src/scripts/ext/blackfire.sh') + + ' ' + + version + + ' ' + + (yield utils.getMinorVersion(version)).replace('.', ''); + if (ext_version) { + script += ' ' + ext_version; + } + return; // match pre-release versions case /.*-(beta|alpha|devel|snapshot)/.test(version_extension): script += diff --git a/examples/blackfire.yml b/examples/blackfire.yml new file mode 100644 index 00000000..af0ecac5 --- /dev/null +++ b/examples/blackfire.yml @@ -0,0 +1,32 @@ +# GitHub Action for blackfire +name: Profiling with blackfire +on: [push, pull_request] +jobs: + bedrock: + name: Blackfire (PHP ${{ matrix.php-versions }}) + runs-on: ${{ matrix.operating-system }} + services: + blackfire: + image: blackfire/blackfire + ports: + - 8707:8707 + env: + BLACKFIRE_SERVER_ID: "" + BLACKFIRE_SERVER_TOKEN: "" + strategy: + fail-fast: false + matrix: + operating-system: [ubuntu-latest, windows-latest, macos-latest] + php-versions: ['7.1', '7.2', '7.3', '7.4'] + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php + with: + php-version: ${{ matrix.php-versions }} + extensions: blackfire-1.30.0 + ini-values: blackfire.agent_socket=tcp://localhost:8707 + - name: Profile + # Note that blackfire agent is not installed. So an implementation with the sdk is required! + run: php your-blackfire-sdk-script.php diff --git a/src/extensions.ts b/src/extensions.ts index ed55c820..2322e3fa 100644 --- a/src/extensions.ts +++ b/src/extensions.ts @@ -22,6 +22,19 @@ export async function addExtensionDarwin( const prefix = await utils.getExtensionPrefix(ext_name); let install_command = ''; switch (true) { + case /^blackfire(-\d+\.\d+\.\d+)?$/.test(extension): + script += + '\nsh ' + + path.join(__dirname, '../src/scripts/ext/blackfire_darwin.sh') + + ' ' + + version + + ' ' + + (await utils.getMinorVersion(version)).replace('.', ''); + + if (ext_version) { + script += ' ' + ext_version; + } + return; // match pre-release versions case /.*-(beta|alpha|devel|snapshot)/.test(version_extension): script += @@ -103,6 +116,18 @@ export async function addExtensionWindows( const version_extension: string = version + extension; let matches: RegExpExecArray; switch (true) { + // match blackfire...blackfire-1.31.0 + case /^blackfire(-\d+\.\d+\.\d+)?$/.test(extension): + script += + '\n& ' + + path.join(__dirname, '../src/scripts/ext/blackfire.ps1') + + ' ' + + (await utils.getMinorVersion(version)).replace('.', ''); + + if (ext_version) { + script += ' ' + ext_version; + } + return; // match pre-release versions case /.*-(beta|alpha|devel|snapshot)/.test(version_extension): script += '\nAdd-Extension ' + ext_name + ' ' + ext_version; @@ -160,6 +185,20 @@ export async function addExtensionLinux( const prefix = await utils.getExtensionPrefix(ext_name); let install_command = ''; switch (true) { + // match blackfire... blackfire-1.31.0 + case /^blackfire(-\d+\.\d+\.\d+)?$/.test(extension): + script += + '\nsh ' + + path.join(__dirname, '../src/scripts/ext/blackfire.sh') + + ' ' + + version + + ' ' + + (await utils.getMinorVersion(version)).replace('.', ''); + + if (ext_version) { + script += ' ' + ext_version; + } + return; // match pre-release versions case /.*-(beta|alpha|devel|snapshot)/.test(version_extension): script += diff --git a/src/scripts/ext/blackfire.ps1 b/src/scripts/ext/blackfire.ps1 new file mode 100644 index 00000000..f7955b49 --- /dev/null +++ b/src/scripts/ext/blackfire.ps1 @@ -0,0 +1,27 @@ +Param ( + [Parameter(Position = 0, Mandatory = $true)] + [ValidateNotNull()] + [string] + $phpversion, + [Parameter(Position = 1, Mandatory = $true)] + [ValidateNotNull()] + [ValidateLength(1, [int]::MaxValue)] + [string] + $version = '1.31.0' +) + +Function Install-Blackfire() { + $installed = Get-Php -Path $php_dir + $nts = if (!$installed.ThreadSafe) { "_nts" } else { "" } + Invoke-WebRequest -UseBasicParsing -Uri "https://packages.blackfire.io/binaries/blackfire-php/${version}/blackfire-php-windows_x64-php-${phpversion}${nts}.dll" -OutFile $ENV:RUNNER_TOOL_CACHE\blackfire.dll > $null 2>&1 + Copy-Item -Path "$ENV:RUNNER_TOOL_CACHE\blackfire.dll" -Destination "$ext_dir\blackfire.dll" + Enable-PhpExtension -Extension blackfire -Path $php_dir + printf "\033[%s;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s \033[0m\n" "32" $tick "Blackfire" "Installed and enabled" +} + +$tick = ([char]8730) +$php_dir = 'C:\tools\php' +$ext_dir = $php_dir + '\ext' + +Install-Blackfire + diff --git a/src/scripts/ext/blackfire.sh b/src/scripts/ext/blackfire.sh new file mode 100644 index 00000000..1dfd35ff --- /dev/null +++ b/src/scripts/ext/blackfire.sh @@ -0,0 +1,23 @@ +add_log() { + mark=$1 + subject=$2 + message=$3 + if [ "$mark" = "$tick" ]; then + printf "\033[32;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s\033[0m\n" "$mark" "$subject" "$message" + else + printf "\033[31;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s\033[0m\n" "$mark" "$subject" "$message" + fi +} + +phpversion=$2 +blackfireVersion=${3:-1.31.0} +ini_file="/etc/php/$1/cli/conf.d/50-blackfire.ini" +tick="✓" +cross="✗" + +(curl -A "Github action" -o /tmp/blackfire.so -L -s https://packages.blackfire.io/binaries/blackfire-php/$blackfireVersion/blackfire-php-linux_amd64-php-$phpversion.so >/dev/null 2>&1 && \ +sudo mv /tmp/blackfire.so $(php -r "echo ini_get ('extension_dir');")/blackfire.so >/dev/null 2>&1 && \ +echo "extension=blackfire.so" | sudo tee -a "$ini_file" >/dev/null 2>&1 && \ +add_log "$tick" "blackfire" "Installed and enabled") || \ +add_log "$cross" "blackfire" "Could not install blackfire" + diff --git a/src/scripts/ext/blackfire_darwin.sh b/src/scripts/ext/blackfire_darwin.sh new file mode 100644 index 00000000..f6b137cf --- /dev/null +++ b/src/scripts/ext/blackfire_darwin.sh @@ -0,0 +1,23 @@ +# Function to log result of a operation +add_log() { + mark=$1 + subject=$2 + message=$3 + if [ "$mark" = "$tick" ]; then + printf "\033[32;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s\033[0m\n" "$mark" "$subject" "$message" + else + printf "\033[31;1m%s \033[0m\033[34;1m%s \033[0m\033[90;1m%s\033[0m\n" "$mark" "$subject" "$message" + fi +} + +tick="✓" +cross="✗" +phpversion=$2 +blackfireVersion=${3:-1.31.0} +ini_file=$(php -d "date.timezone=UTC" --ini | grep "Loaded Configuration" | sed -e "s|.*:s*||" | sed "s/ //g") + +(curl -A "Github action" -o /tmp/blackfire.so -L -s https://packages.blackfire.io/binaries/blackfire-php/$blackfireVersion/blackfire-php-darwin_amd64-php-$phpversion.so && \ +sudo mv /tmp/blackfire.so $(php -r "echo ini_get ('extension_dir');")/blackfire.so && \ +echo "extension=blackfire.so" >>"$ini_file" && \ +add_log "$tick" "blackfire" "Installed and enabled") || \ +add_log "$cross" "blackfire" "Could not install blackfire" diff --git a/src/utils.ts b/src/utils.ts index af305504..88cc4805 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -261,3 +261,14 @@ export async function suppressOutput(os_version: string): Promise { ); } } + +export async function getMinorVersion(version: string): Promise { + const regex = /^\d+\.\d+/; + const match = version.match(regex); + + if (match === null) { + return version; + } + + return match[0]; +}