Staging Servers on SymfonyCloud

Video not working?

It looks like your browser may not support the H264 codec. If you're using Linux, try a different browser or try installing the gstreamer0.10-ffmpeg gstreamer0.10-plugins-good packages.

Thanks! This saves us from needing to use Flash or encode videos in multiple formats. And that let's us get back to making more videos :). But as always, please feel free to message us.

For your site, you hopefully have a staging environment - or maybe multiple staging environments where you can deploy new features and test them. What about those machines? Should we also run Blackfire builds on them?

Why Profile Staging Servers?

At first, that might not seem important. After all, if a staging machine is a bit slow, who cares? But thanks to the assertions we've been writing, if we executed our Blackfire scenarios on a staging machine, we could identify performance failures before deploying them to production. And if you have a really cool setup, you can even have build results posted automatically to your pull request. OooOOoo.

Separating Staging from Production on Blackfire

Getting Blackfire set up on a staging server seems simple enough: just repeat the Blackfire installation process... on a different server! But stop! I don't want you to quite do that.

Why? I want your Blackfire production environment to only contains builds from your actual production servers. I want this to be a perfect history and representation of production only. If we suddenly start adding builds from a staging server - which maybe has different hardware specs... or is running a buggy new feature - some of those builds will fail... and we'll get extra noise in our notifications.

Instead, I like to create a second Blackfire environment and send profiles to it. If I have multiple staging servers, I make them all use this same new environment.

SymfonyCloud Environments

But... before we create that second Blackfire environment... I need you to - once again - pretend like Blackfire doesn't exist at all... for a few minutes.

Because before we talk about how we profile a staging server, we need to create a staging server and deploy to it. SymfonyCloud has an incredible way to do this. Unfortunately, the feature in Symfony cloud that does this is called... environments. And it has absolutely nothing to do with Blackfire environments.

Here's how it works: in addition to your master branch, which is your production server, SymfonyCloud allows you to deploy different git branches. Each deploy will get its own unique URL. Each branch deployment is called an "environment". If you run:

symfony envs

Yep! We currently have one environment: master. It's the "current" environment because we're checked out to the master git branch locally.

Ok, pretend that we're working on a new feature. And so, we want to create a new local branch for it. Instead of doing that manually, run:

symfony env:create some_feature

This does two things. First, it created a new local branch called some_feature. That's no big deal: we could have done that by hand. Second, it deploys that branch! It does this by creating a "clone" of the master environment: - even creating a copy of the production database!

I'll fast-forward through the deploy. When it finishes, it gives us a URL to the deploy. This is a different URL than on production: it's a totally separate, isolated deployment. Let's open this the lazy way:

symfony open:remote

Say hello to our staging server for the some_feature branch, which you can see contains a copy of the production database! How cool is that?

Configuring Blackfire on the Environments

Back on Blackfire, refresh to see the builds for the production environment. When we deployed to that environment, it did not create a new build. We expected that. When we added the integration to SymfonyCloud - we told it to trigger a build on this Blackfire environment whenever we deploy the master branch only. We did that because we don't want these staging servers to create builds here.

Next, let's create a second environment and configure our staging servers to use it.

Leave a comment!

This tutorial can be used to learn how to profile any app - including Symfony 5.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.1.3",
        "ext-ctype": "*",
        "ext-iconv": "*",
        "blackfire/php-sdk": "^1.20", // v1.20.0
        "sensio/framework-extra-bundle": "^5.4", // v5.5.1
        "symfony/console": "4.3.*", // v4.3.10
        "symfony/dotenv": "4.3.*", // v4.3.10
        "symfony/flex": "^1.3.1", // v1.6.0
        "symfony/form": "4.3.*", // v4.3.10
        "symfony/framework-bundle": "4.3.*", // v4.3.9
        "symfony/http-client": "4.3.*", // v4.3.10
        "symfony/orm-pack": "^1.0", // v1.0.7
        "symfony/security-bundle": "4.3.*", // v4.3.10
        "symfony/serializer-pack": "^1.0", // v1.0.2
        "symfony/twig-bundle": "4.3.*", // v4.3.10
        "symfony/validator": "4.3.*", // v4.3.10
        "symfony/webpack-encore-bundle": "^1.6", // v1.7.2
        "symfony/yaml": "4.3.*", // v4.3.10
        "twig/extensions": "^1.5" // v1.5.4
    },
    "require-dev": {
        "doctrine/doctrine-fixtures-bundle": "^3.2", // 3.2.2
        "fzaninotto/faker": "^1.8", // v1.8.0
        "symfony/debug-pack": "^1.0", // v1.0.7
        "symfony/maker-bundle": "^1.13", // v1.14.3
        "symfony/test-pack": "^1.0" // v1.0.6
    }
}