Mickaël Mottet
Posted on December 4, 2020
I had the opportunity to work on a PHP Symfony application with a new customer with Azure DevOps.
The problematic was to build the application with several commands to pass on the source code and afterwards to push the application to an Azure App Service web application.
I assume that you are familiar with Azure Pipelines and will only share the content of the pipeline itself and not the way to create it.
So, once the pipeline is created, we have several tasks to accomplish.
First, we need to select the correct version of PHP. In our case it will be PHP 7.4.
- script: |
sudo update-alternatives --set php /usr/bin/php$(phpVersion)
sudo update-alternatives --set phar /usr/bin/phar$(phpVersion)
sudo update-alternatives --set phpdbg /usr/bin/phpdbg$(phpVersion)
sudo update-alternatives --set php-cgi /usr/bin/php-cgi$(phpVersion)
sudo update-alternatives --set phar.phar /usr/bin/phar.phar$(phpVersion)
php -version
workingDirectory: $(rootFolder)
displayName: 'Use PHP version $(phpVersion)'
In our case, we'll have to execute database migrations with Doctrine. The customer has chosen Azure SQL Database as provider. The problem is that this driver is not embedded in the hosted agent image. We have to install it using PECL.
- script: |
sudo pecl config-set php_ini /etc/php/7.4/cli/php.ini
sudo pecl config-set ext_dir /usr/lib/php/20190902/
sudo pecl config-set bin_dir /usr/bin/
sudo pecl config-set php_bin /usr/bin/php7.4
sudo pecl config-set php_suffix 7.4
sudo pecl channel-update pecl.php.net
sudo pecl install sqlsrv-5.8.1
sudo pecl install pdo_sqlsrv-5.8.1
displayName: PECL install sqlsrv
Once installed, we have to tell to PHP where to find the installed modules.
- script: |
sudo bash -c "echo extension=sqlsrv.so > /etc/php/7.4/cli/conf.d/99-sqlsrv.ini"
sudo bash -c "echo extension=pdo_sqlsrv.so > /etc/php/7.4/cli/conf.d/99-sqlsrv.ini"
displayName: 'SQLSRV modify ini files'
A quick check that all is good using PHPinfo()
- script: php -i
workingDirectory: $(rootFolder)
displayName: 'PHPinfo()'
Now that all is good, we can add dependencies with Composer and "compile" the web application.
- script: |
curl -sS https://getcomposer.org/installer | php
php composer.phar install --no-dev --optimize-autoloader
php composer.phar dump-env %APP_ENV%
php bin/console cache:clear
workingDirectory: $(rootFolder)
displayName: 'Composer install'
Now we can update execute the database migrations using Doctrine
- script: php bin/console doctrine:migrations:migrate --no-interaction
workingDirectory: $(rootFolder)
displayName: 'Update database'
And finally, we can execute the "classic" steps, storing the build artifacts and deploying to Azure App Service.
- task: ArchiveFiles@2
displayName: 'Archive files'
inputs:
rootFolderOrFile: '$(rootFolder)'
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
replaceExistingArchive: true
- upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
displayName: 'Upload package'
artifact: drop
- stage: Deploy
displayName: 'Deploy Web App'
dependsOn: Build
condition: succeeded()
jobs:
- deployment: DeploymentJob
pool:
vmImage: $(vmImageName)
environment: $(environmentName)
strategy:
runOnce:
deploy:
steps:
- task: AzureWebApp@1
displayName: 'Deploy Azure Web App : $(webAppName)'
inputs:
azureSubscription: $(azureSubscription)
appName: $(webAppName)
appType: webAppLinux
package: $(Pipeline.Workspace)/drop/$(Build.BuildId).zip
And finally, our website is deployed! 👍🏻
Full script is below:
# PHP as Linux Web App on Azure
# Build, package and deploy your PHP project to Azure Linux Web App.
# Add steps that run tests and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/php
trigger:
- master
variables:
# Azure Resource Manager connection created during pipeline creation
azureSubscription: '##ID OF THE SERVICE CONNECTION##'
# Environment name
environmentName: '##NAME OF THE ENVIRONMENT##'
# Web app name
webAppName: '##NAME OF THE WEB APP##'
# Agent VM image name
vmImageName: 'Ubuntu-20.04'
# Root folder under which your |
rootFolder: $(System.DefaultWorkingDirectory)
stages:
- stage: Build
displayName: Build stage
variables:
phpVersion: '7.4'
jobs:
- job: BuildJob
pool:
vmImage: $(vmImageName)
steps:
- script: |
sudo update-alternatives --set php /usr/bin/php$(phpVersion)
sudo update-alternatives --set phar /usr/bin/phar$(phpVersion)
sudo update-alternatives --set phpdbg /usr/bin/phpdbg$(phpVersion)
sudo update-alternatives --set php-cgi /usr/bin/php-cgi$(phpVersion)
sudo update-alternatives --set phar.phar /usr/bin/phar.phar$(phpVersion)
php -version
workingDirectory: $(rootFolder)
displayName: 'Use PHP version $(phpVersion)'
- script: |
sudo pecl config-set php_ini /etc/php/7.4/cli/php.ini
sudo pecl config-set ext_dir /usr/lib/php/20190902/
sudo pecl config-set bin_dir /usr/bin/
sudo pecl config-set php_bin /usr/bin/php7.4
sudo pecl config-set php_suffix 7.4
sudo pecl channel-update pecl.php.net
sudo pecl install sqlsrv-5.8.1
sudo pecl install pdo_sqlsrv-5.8.1
displayName: PECL install sqlsrv
- script: |
sudo bash -c "echo extension=sqlsrv.so > /etc/php/7.4/cli/conf.d/99-sqlsrv.ini"
sudo bash -c "echo extension=pdo_sqlsrv.so > /etc/php/7.4/cli/conf.d/99-sqlsrv.ini"
displayName: 'SQLSRV modify ini files'
- script: php -i
workingDirectory: $(rootFolder)
displayName: 'PHPinfo()'
- script: |
curl -sS https://getcomposer.org/installer | php
php composer.phar install --no-dev --optimize-autoloader
php composer.phar dump-env %APP_ENV%
php bin/console cache:clear
workingDirectory: $(rootFolder)
displayName: 'Composer install'
- script: curl -sS https://get.symfony.com/cli/installer | bash
workingDirectory: $(rootFolder)
displayName: 'Install SymfonyCLI'
- script: /home/vsts/.symfony/bin/symfony check:requirements
workingDirectory: $(rootFolder)
displayName: 'Symfony check requirements'
- script: php bin/console doctrine:migrations:migrate --no-interaction
workingDirectory: $(rootFolder)
displayName: 'Update database'
- task: ArchiveFiles@2
displayName: 'Archive files'
inputs:
rootFolderOrFile: '$(rootFolder)'
includeRootFolder: false
archiveType: zip
archiveFile: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
replaceExistingArchive: true
- upload: $(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip
displayName: 'Upload package'
artifact: drop
- stage: Deploy
displayName: 'Deploy Web App'
dependsOn: Build
condition: succeeded()
jobs:
- deployment: DeploymentJob
pool:
vmImage: $(vmImageName)
environment: $(environmentName)
strategy:
runOnce:
deploy:
steps:
- task: AzureWebApp@1
displayName: 'Deploy Azure Web App : $(webAppName)'
inputs:
azureSubscription: $(azureSubscription)
appName: $(webAppName)
appType: webAppLinux
package: $(Pipeline.Workspace)/drop/$(Build.BuildId).zip
``
Posted on December 4, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.