NEW Run your Ruby tests in a few minutes and ship faster with Boosters, one-click auto parallelization · Learn more…

Semaphore Blog

News and updates from your friendly continuous integration and deployment service.

Continuous Integration and Deployment of PHP applications from GitHub to Heroku with Semaphore

Get future posts like this one in your inbox.

Follow us on

The practice of continuous delivery is steadily gaining ground in the PHP community. It is no wonder: continuous integration keeps your development risk-free by automatically testing every new version of the code, while continuous deployment helps you ship working code faster by automatically deploying working versions of your application to your users. All together, these practices allow you to focus on the code and deliver your product safely without hassle.

With PHP support being recently launched on both Semaphore and Heroku, you can set up a continuous delivery pipeline for your web application in a matter of minutes.

In this post I will show you how to set up continuous integration and deployment for a simple Laravel web application through Semaphore. You can find the application’s source code on GitHub.

Creating the application on Heroku

You can create a new application on Heroku either on their web interface or from the command line. If you need custom software in the Heroku instance, go with the latter.

For deploying a Laravel project to Heroku, I prefer creating the Heroku app from the command line with a custom build pack.

heroku create php-cogs --buildpack

This installs all the needed dependecies which are needed to properly run a Laravel application.

Either way, the new application will appear in your “Apps” screen on Heroku.

While you’re here, copy your Heroku API key from the Account settings. Semaphore will need this key to deploy your application.

Setting up continuous integration from GitHub to Semaphore

Sign up for a Semaphore account and connect with GitHub.

In my example I am working with an open source project, so I will select “Build Public Project”.

After receiving access to your public information on GitHub, Semaphore will present you a list of available projects to choose from.

If you don’t have a repository ready, feel free to fork my example application and refresh this screen. After you select a project, Semaphore will analyze it and suggest some common build commands.

At this point, we are ready to launch the first build.

Great! Now we have a fully set up continuous integration for our project. Every time you or other people push new code to GitHub, Semaphore will run a build to test it.

Setting up continuous deployment to Heroku

Say you’ve worked on your app for a while and have come to a point where you’d like to deploy it to your users. Instead of doing this manually every time, we can use Semaphore to do it for us automatically every time a build passes.

Opening the deployment section of project settings allows you to add a server to which we’re going to deploy.

Choose Heroku from our supported deployment methods.

The deployment can be automatic or manual. In the spirit of continuous delivery, we’ll go with automatic deployment.

After pasting your Heroku API key on Semaphore, choose the previously created Heroku app, name the server and you’re ready to go.

Clicking the Get Started button will finish the deployment setup. Semaphore now has all the information it needs to automatically deploy your application.

Now every time you push a new commit to Github and all tests pass, Semaphore will deploy the new version of your application to Heroku.

Of course, you or any of your collaborators can always trigger the deployment manually on the build page of a branch. This is especially useful when you need to deploy a feature branch to a staging server.

One thing to note is that by default many projects include the composer.lock file in .gitignore but that way deploying to Heroku will not work, so it’s a good idea to remove it from there.

That’s it. Make something awesome and rest assured that your application will automagically reach its audience. Happy building!

Introducing Continuous Integration For PHP Projects On Semaphore

Today we’re really happy to announce our next step in platform expansion with full support for PHP projects on Semaphore. Developers working with all languages are embracing automated tools to develop web applications that meet requirements in a process that is both faster and safer comparing to old days of manual deployment and no tests. Now you can take advantage of Semaphore’s continuous integration and deployment features, already trusted by thousands of developers across the globe, in your PHP projects too.

Sample test results of a PHP application.

PHP is, without doubt, one of the most popular programming languages on the web. It is powering more than 240 million web pages (according to Wikipedia) and this number is still steadily growing. The famous LAMP stack, made of Linux, Apache, MySQL and PHP, was a driving force of open source web development that paved the way for many innovations both for developers and ordinary users across the globe. Lately, the rise of modern tools and frameworks such as Composer and Laravel is making development of robust PHP applications easier than ever.

Setting up a PHP project on Semaphore

To add your PHP project on Semaphore, first you’ll need to create an account. After that you will be able to add a new project from GitHub, right from your dashboard.

After you’ve selected a branch to build and a brief repository analysis, Semaphore will automatically configure your project for testing. For example, if your project contains a composer.json file in its root directory, Semaphore will assume that it’s written in PHP and propose commands to install dependencies and run your tests.

Semaphore can automatically configure your PHP project for continuous integration.

At this point you can simply launch your first build or you can define your custom commands.

The PHP stack

Semaphore includes PHP versions 5.3, 5.4 and 5.5 out of the box. Internally, versions are managed with phpbrew. Choosing a PHP version in the interface corresponds to a command phpbrew switch <version>. Exact current versions are documented here.

Installing PHP extensions and packages

PHP extensions can be installed with either PECL or PEAR. As an alternative, you can use

phpbrew ext install <extension>

which downloads, installs, creates a config file and enables the extension. Packages can be installed with Composer and cached for reuse across builds.


PHPUnit is one of the most popular testing frameworks for PHP to date with a big community behind it and it’s installed by default in our platform. If you are using other tools which you’d like to be part of the platform, please let us know.


Heroku has recently launched PHP support and Semaphore users can easily set up deployment of their PHP applications to its cloud platform. A generic deployment option via SSH key is also available. Either strategy enables you to ship new features, track releases and gain feedback faster than ever.

PHP support on Semaphore is new to us as well so we may hit a few bumps along the way. We encourage you to contact us with your suggestions and feedback. Happy building!

Upcoming Platform Update on May 28th

The upcoming platform update is scheduled for Wednesday, May 28, 2014.

Node.js gets two version updates, namely 11.13 and 10.28.

The star of this update is PHP. We’re expanding our platform to support testing and deployment of PHP projects. As the first step, three versions will be available on the platform out of the box: 5.3.28, 5.4.28 and 5.5.12. We are looking forward to sharing more news regarding PHP with you soon.

A full list of changes is available in the platform changelog.

New Navigation Design

I am excited to share with you a new navigation experience in Semaphore, a piece of design that we’ve been thinking about and working on in the past two months.

Easier on the eyes

We were and still are very proud of the first version of Semaphore’s application design, but if there’s one thing we’ve grown tired of, it’s the black navigation stripe. It is replaced with a transparent row that lets you do the same things but feels much less intrusive. To go to your dashboard, click on the Semaphore cogs. The new Help menu lists in more detail all the ways you can learn more about Semaphore and get support.

Consistency to hold on to

When you are using Semaphore, outside account management, the permanent scope you are in is the scope of a project. So now when you are in it, the project’s owner and linked name, along with a link to project settings, will be visible above all other elements. This has allowed us to streamline the actions and information about specific entities being displayed.

The build page is a good example. The build and branch information are grouped into a logical unit, which enabled a clear position for actions such as “Rebuild” and “Deploy manually” on the right hand side.

Less copy, more content

We have always tried to make the content be the sufficient UI, and this time we also removed some unnecessary words from the project page.

We believe that these changes are also a solid foundation for things we want to do in the future (which might even be obvious from the way UI is laid out now ;).

Hope you all enjoy!

Introducing RubyGems Mirror

Like pretty much everything in the Ruby world, Semaphore would not exist without Bundler and So first of all I would like to say big thanks to the guys and gals for providing and maintaining such great tools for all of us. <3

As in every good story, there is a “but”. In the past few months, there were days when many of our users experienced network related issues, causing gem installs to be slow or fail completely. Our investigations have shown that when this happens, it is due to packet losses between a network in Germany that is outside our provider and Amazon’s servers.

Our permanent goal is to keep providing an enjoyable experience to our users. The dependency installation stage is a critical part of the continuous integration process, and we’re excited to announce some big improvements we’ve made in that area while isolating our platform from issues which we cannot control.

Improved repository caching

Our first step was to increase the capacity for caching gems and other dependencies for each project. In case of a cache miss, dependency installation, via commands such as bundle install, needs to run from scratch.

RubyGems mirror

The second step was to create a private RubyGems mirror, which I am happy to announce as launching today. The mirror is now used by all projects on Semaphore without any custom settings or configuration needed.

What that actually means for everyday usage? In beta period we noticed that bundle install and gem install commands run twice as fast using the mirror comparing to regular downloads. We’ll be more than happy to hear your observations about this.

You can control the use of Semaphore’s RubyGems mirror in project settings, just below build commands. So if you have any issues using our mirror, you can easily disable it (by default it’s on for all projects). As this is a fresh part of our platform, all feedback is more than welcome.

Also I would like to thank all our beta testers who greatly helped in testing and evaluating our work on the mirror. The positive reactions we got were overwhelming. It’s a pleasure to see that our efforts have an effect to so many people. :)

A note to all beta testers: we have removed your commands for setting up the mirror during beta period, because Semaphore now handles them globally.

Happy building!

Easier Way To Manage Environment Variables

Thus far the only way you could add an environment variable to you project was to include an export SECRET_TOKEN=abcd123 command in your build configuration. But from now on you can use our project settings interface to manage your project’s environment variables.

Apart from being easier to use, the new interface gives you the ability to encrypt values of your variables. We strongly recommend that you select this option if you are storing some sensitive data in your variables.

Note that you can also keep your export SECRET_TOKEN=abcd123 build commands if you prefer.

MySQL Strict Mode And You

We’ve recently upgraded MySQL 5.5 to 5.6 in our platform. Along with many performance and stability improvements, the new version also has strict mode turned on by default, which means it has stricter syntax and data validation checking. This, of course, is a good thing from your data’s standpoint but it may also cause some unexpected errors in your builds.

To turn off MySQL’s strict mode, you’ll have to add the following command to your build commands in project settings.

mysql -u root -psemaphoredb -e "SET @@global.sql_mode= '';"

For more information about MySQL modes, you can check out the official documentation here.

Trigger a Deploy Over API And More Updates

As our API evolves, a need for an action that allows user to trigger a deploy via API appeared.

This feature is now available. From now on you will be able to trigger deploys through our API, easy as:

curl -d "auth_token=XXX" -v

The API documentation has been updated accordingly with these latest additions.

Also, we would like to announce that there are a few additions to our server API response structures. You can find the latest specifications in the documentation.

Upcoming Platform Update on May 5th

The upcoming platform update is scheduled for Monday, May 5, 2014.

Bundler is updated to version 1.6.2 featuring a lot of goodies, including 10x faster Gemfile resolving.

Firefox goes up to version 29, requiring bundle update selenium-webdriver for most projects that use that gem.

ElasticSearch has been also updated and it’s now on version 1.1.1.

MySQL is upgraded to version 5.6 with lots of performance and stability improvements. To avoid an error which pops up when the cached mysql gem tries to use the new library, we will remove the caches for all projects which use this gem. If a few projects slip through our fingers, please contact us.

rake aborted!
Incorrect MySQL client library version! This gem was compiled for 5.5.35 but
the client library is 5.6.17.

A quick remedy for this would be to include rm -rf .bundle or rm -rf vendor/bundle to your build commands in project settings.

A full list of changes is available in the platform changelog.

Update 2014-05-07: Firefox 29 was added to the release.

Get future posts like this one in your inbox.

Follow us on