If you’re a PHP developer whose cloud provider of choice is AWS, chances are you’ve suffered through a bit of serverless FOMO due to AWS Lambda’s lack of support for PHP. But thanks to the AWS Serverless Application Model (AWS SAM) and Bref — both open source projects available on GitHub — it’s now possible to deploy your PHP applications to Lambda without having to fiddle with Node.js shims. And with the help of Travis CI, running automated tests and deployments is essentially a cinch. There are, however, a few gotchas.
Bref provides the tools and documentation to easily deploy and run serverless PHP applications.
You should take a look at the Bref documentation before you move on to familiarize yourself with the goals of the project, walk through the “Getting Started” steps, and read the recommendations concerning the project’s use (for example, don’t expect to use Bref to deploy your legacy application without experiencing the sort of difficulty you’d normally associate with deploying a legacy application).
The work detailed in this post rests comfortably on the shoulders of unselfish giants; I would be remiss if I didn’t point you to this post explaining what’s needed to deploy Python applications to AWS Lambda using AWS SAM and Travis CI. You’ll find that a lot of what is covered there was put to use here, and the author (Mike Vanbuskirk) does a great job covering the pertinent prerequisites. In fact, I consider that series to be a prerequisite to this post, and suggest you read it before continuing, unless you’re impatient and just want to get to the goodies.
Alright. Into the fray. I’ve set up a sample application at https://github.com/guillermoandrae/bref-hello-world, and will be using its .travis.yml file to explain this process:
language: generic dist: xenial before\_install: - phpenv global 7.2 install: - pip install --user awscli - pip install --user aws-sam-cli script: - composer install --optimize-autoloader - composer test - composer package deploy: provider: script script: composer deploy skip\_cleanup: true on: repo: guillermoandrae/bref-hello-world env: global: - AWS\_DEFAULT\_REGION=us-east-1 - secure: <obfuscated AWS Access Key ID> - secure: <obfuscated AWS Secret Key>
Let’s start at the tippy top:
language: generic dist: xenial
A cursory look at the configuration file reveals two points:
- I’m using phpenv, which is a PHP version manager.
- I’m using pip, which is the standard package manager for Python.
The build environment needs to have both PHP and Python installed in order for all of the necessary tasks to be successfully executed. If you’ve used Travis CI for your PHP projects before, you’ve probably specified the language at the top of the YAML file with a line like language: php, which would prompt Travis CI to use a PHP build environment. I needed to use a lesser known language designation that supported my use case.
Travis CI provides two build environments that are not language-specific: the minimal environment and the generic environment. The former is, as the name implies, pretty bare. Aside from gcc, curl, and a few other tools, minimal is not outfitted with much besides Docker and Python. The generic environment, on the other hand, includes everything included in the minimal environment as well as some additional runtimes such as Go, Ruby, and PHP.
If you’re not familiar with it, the dist parameter of a Travis CI configuration file is used to denote the specific distribution of the build environment that you’d like to use. With Ubuntu images, you’ve got three options — trusty (the default, used when no distribution is specified), precise, and xenial —and they all contain specific configuration settings. In the case of the minimal and generic build environments, however, only precise and xenial are available. I’m using the xenial environment, as it’s the one that contains a suitable version of PHP.
By default, the xenial environment uses the lowest of the three versions of PHP that are installed: 5.6. To change that, I used phpenv to specify the version that meets our needs. phpenv is installed on all Travis CI images that run PHP:
before\_install: - phpenv global 7.2
In Mike’s series, the installation of the AWS CLI and AWS SAM CLI tools seemed pretty straight forward, and I had no problem installing them on my laptop. I, however, found myself running into this error using Travis CI:
InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.io/en/latest/security.html#insecureplatformwarning.
I tried using the python parameter, then the TRAVIS_PYTHON_VERSION environment variable to specify a newer Python version, but neither brought me joy. So, after some focussed Googling, I was led to a solution that involved adding the --user flag to the installation commands. So I ended up with:
install: - pip install --user awscli - pip install --user aws-sam-cli
I really, really, really, really, really like Composer scripts. In the past, I used Phing as a task runner without realizing that I could leverage the scripts feature of Composer to do almost exactly the same thing. I’ve since seen the proverbial light and haven’t turned back:
script: - composer install --optimize-autoloader - composer test - composer package
A look at an excerpt of the project’s composer.json file will shed some light on exactly what is going on:
The test script includes calls to Squizlabs’ code beautifier and code sniffer as well as a call to run the tests and generate coverage reports in both text format and Clover format (the Clover format is especially useful if you plan to integrate Travis CI with a tool/service that can create code coverage visualizations or store a project’s code coverage history). The package script calls sam package to build the stack configuration file.
I’m using Travis CI’s script deployment option to call my deployment script and associate the appropriate GitHub repository. The details behind the composer deploy call below are uncovered in the aforementioned composer.json excerpt:
deploy: provider: script script: composer deploy skip\_cleanup: true on: repo: guillermoandrae/bref-hello-world
We’re done. PHP on AWS Lambda with a proper CI/CD pipeline. No fuss. Life is good. If you have any questions or comments, don’t be shy about sharing them.