Semaphore Blog

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

Improved Project Collaboration Management

Get future posts like this one in your inbox.

Follow us on

We are glad to announce a more flexible solution for managing project collaborators. So far, project collaborators were directly mapped from repository collaborators on GitHub. In order to have access to a Semaphore project, user had to have a GitHub account and be a collaborator on the corresponding repository on GitHub. This was a great solution back in the early days since it enabled a fast onramp process, but since then our users and ourselves have grown and a need for something different has emerged.

In the past, if the user wanted to leave the project, she would have to leave or be removed from the collaborators list on GitHub. After this, the project owner on Semaphore still had to trigger a sync of collaborators with GitHub in order to remove the user from project on Semaphore. Same thing goes with joining project. Overall there was not much flexibility in the processes that take place after a project was set up on Semaphore.

From now on, project’s collaborators on Semaphore will not be bound to those on GitHub. You can manage your collaborators on Semaphore without making any changes on GitHub.

The project owner on Semaphore can invite anyone to collaborate via email, including people who are not collaborators on GitHub, for example the QA team.

If the user with that specific email already exists, she will automatically be added to project’s collaborators. Otherwise, an invitation email will be sent. Once the user follows the link in the invitation email and signs up, she will gain access to the project. Also, every user can now leave a project with a single click.

We hope that you find our new project collaborators approach useful and that it will improve your workflow.

TDD Antipatterns: Local Hero

hidden under clouds

This is the second blog post in a series inspired by a Stack Overflow thread. You can read the first post here.

A local hero is defined as:

A test case that is dependent on something specific to the development environment it was written on in order to run. The result is the test passes on development boxes, but fails when someone attempts to run it elsewhere.

Leaving database state aside, this typically arises due to differences in configuration between a developer’s machine and somebody else’s or CI system.

Machines used for CI for web apps usually run in headless mode, which means that they lack a hardware display. Instead, the OS renders the screen as a bitmap in memory. On Linux the most frequently used implementation is Xfvb, which is also used on Semaphore.

In earlier versions of Semaphore’s build platform, the virtual resolution was set to be 1280x800. Eventually we learned that this resolution is not large enough for all users. Some developers that use Selenium to run tests in a real browser were getting mysterious failures due to an expected element not being present on the screen. For example, the navigation bar was implemented as a responsive element, hiding certain links in smaller browser windows. Nowadays the default resolution on Semaphore is 1900x1200.

In case above, the tests were implicitly depending on screen resolution, a rather unexpected component. But sometimes a local hero arises when the application simply was not configured completely. For example, Semaphore’s front-end application tests depend on the existence of a file config/config.yml, which is not stored in version control (because it contains sensitive credentials) but should be copied or created manually during project setup. To make it work, it was necessary to create an encrypted custom configuration file on Semaphore with just enough content to make the tests pass.

A related case is…

The hidden dependency

a unit test that requires some existing data to have been populated somewhere before the test runs. If that data wasn’t populated, the test will fail and leave little indication to the developer what it wanted, or why… forcing them to dig through acres of code to find out where the data it was using was supposed to come from.

Management of database state in tests is best to be to completely automated by your tools. If your tests require you to manually clear the database before each run, look for a tool to do that for you. For example, Ruby developers often use database_cleaner, whose purpose is to maintain a clean state during tests. There’s a similar package for Node.js.

The problem occurs because test runners — or your own code — often wrap tests in a transaction, so other processes, such as the web server, may not be able to access test data which was previously set.

Having established this practice, you also insulate your test suite from the bad practice of requiring some special data to be manually inserted before the tests run.

See also Incidental database state in Rails Testing Antipatterns: Models.

Upcoming Platform Update on July 7th

The upcoming platform update is scheduled for Monday, July 7, 2014.

Elasticsearch is updated to version 1.2.1.

NodeJS gets two updates with 0.8.27 and 0.10.29. These releases of NodeJS address the current OpenSSL vulnerability and introduce a breaking UTF-8 change. Read more about it here.

JRuby is updated to version 1.7.13.

Firefox is bumped up to version 30, requiring bundle update selenium-webdriver for most projects that use that gem. Issues with selenium-webdriver and the latest Firefox can be reported here.

Two PHP version updates are inluded too, namely 5.4.30 and 5.5.14.

Bundler is now updated to version 1.6.3.

As an addition, AWS CLI is now included in our platform.

A full list of changes is available in the platform changelog

TDD Antipatterns: The Free Ride

There is an excellent thread on Stack Overflow TDD Anti-patterns catalogue which contains short descriptions of some common traps we can fall into when writing test-driven code. In the upcoming series of short blog posts, I will illustrate some of them with snippets of Ruby code.

The Free Ride a.k.a Piggyback: rather than write a new test case method to test another/distinct feature/functionality, a new assertion rides along in an existing test case.

In the following spec we are verifying that an event contains a feedback form whenever a user posts some content that indicates that she was present at the event. It comes from a real code base, just a little bit adapted for readability.

describe Event do
  describe "feedback form presence" do

    before do
      @user = create(:user)
      @event = create(:event)
    end

    it "is displayed when user generates an activity" do
      comment = @event.create_comment(:user => @user)
      expect(@event).to include_feedback_form(@user)

      comment.destroy
      expect(@event).not_to include_feedback_form(@user)

      photo = @user.post_photo(@event)
      expect(@event).to include_feedback_form(@user)

      photo.destroy
      expect(@event).not_to include_feedback_form(@user)

      like = @user.like(@event)
      expect(@event).to include_feedback_form(@user)

      like.destroy
      expect(@event).not_to include_feedback_form(@user)
    end
  end
end

What’s the problem here? Aside from unnecessary repetition of expectations that an event without any associated data does not include the feedback form, the description of the test does not match the things it tests. It is vague (“is displayed when user generates an activity”), which naturally comes from the fact that the test contains multiple different expectations. Once we let ourselves go down this path though, it is easy to end up with further complications. This example is actually rather simple; sometimes the expectations may not even appear to be connected when you look at them with fresh eyes, because of a lacking description.

A failure in any of these expectations would then not point to the exact cause of the test failure, which breaks down one of the main benefits of tests — a short feedback loop about our programming decisions. In a moment when more than one expectation would be broken, eg during a refactoring session, you would not be able to get that information because the test runner stops at the first failed expectation.

If we consider this OK, then the logical conclusion would be to make the whole suite a single test with numerous expectations. But the opposite is rather easy to achieve:

describe Event do
  describe "feedback form" do

    before do
      @user = create(:user)
      @event = create(:event)
    end

    context "before all activity" do
      it "is not displayed" do
        expect(@event).not_to include_feedback_form(@user)
      end
    end

    context "user posts a comment" do

      before { @event.create_comment(:user => @user) }

      it "is displayed" do
        expect(@event).to include_feedback_form(@user)
      end
    end

    context "user removes a comment" do

      before do
        comment = @event.create_comment(:user => @user)
        comment.destroy
      end

      it "is not displayed" do
        expect(@event).not_to include_feedback_form(@user)
      end
    end

    context "user posts a photo" do

      before { @user.post_photo(@event) }

      it "is displayed" do
        expect(@event).to include_feedback_form(@user)
      end
    end

    context "user likes it" do

      before { @user.like(@event) }

      it "is displayed" do
        expect(@event).to include_feedback_form(@user)
      end
    end
  end
end

Using different test values in a single test case

A related case, perhaps more a matter of readability, is to avoid grouping different test values in a single test case. For example:

describe City do

  it "generates slug based on name" do
    city = create(:city, :name => "San Sebastián")
    expect(city.slug).to eq("sansebastian")

    city = create(:city, :name => "Maceió")
    expect(city.slug).to eq("maceio")
  end
end

Instead we can follow the approach which would produce the most informative form of test output and feedback during development:

describe City do

  describe "slug, generated from name" do

    context "name is 'San Sebastián'" do
      subject { create(:city, :name => "San Sebastián") }
      its(:slug) { is_expected.to eq("sansebastian") }
    end

    context "name is 'Maceió'" do
      subject { create(:city, :name => "Maceió") }
      its(:slug) { is_expected.to eq("maceio") }
    end
  end
end

Update Jun 25: The examples above could be improved by explicitly stating what they are testing:

describe City do

  describe "slug, generated from name" do

    context "name is 'San Domingo'" do
      subject { create(:city, :name => "San Domingo") }

      it "strips the whitespace and converts to lowercase" do
        expect(subject.slug).to eq("sandomingo") }
      end
    end

    context "name is 'Maceió'" do
      subject { create(:city, :name => "Maceió") }

      it "strips replaces accented character" do
        expect(subject.slug).to eq("maceio") }
      end
    end
  end
end

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

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 https://github.com/winglian/heroku-buildpack-php

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.

Testing

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.

Deployment

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 RubyGems.org. 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 rubygems.org 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.

Get future posts like this one in your inbox.

Follow us on