Deploy To Platform.sh From Your GitLab CI Pipeline

Tags: Platform.sh, CI



Platform.sh is a popular platform-as-a-service (PaaS) platform (yes, I said “platform” thrice in that sentence 😁) for several PHP applications (and other languages as well, which you can read about on their website). One of the attractions of Platform.sh is how it provides a containerized deployment environment which developers can interact with just by using Git. Developers may just create branches to create new environments and push to deploy.

Note: This article assumes you already have an application set up on Platform.sh. It only covers integrating the application with GitLab CI. If you need help setting up your application, please refer to the platform.sh documentation.

Of course, teams would still use Git hosting (like GitHub or GitLab) to manage their work and primarily push there. As a tech lead on this team, you would be responsible for integrating GitHub or GitLab with the Platform.sh repository. Fortunately, Platform.sh natively provides these integrations and it’s a one-time setup.

Why isn’t this integration enough?

While these integrations are helpful, they may not be very useful if you want to follow the typical continuous integration (CI) setup of “Build → Test → Deploy”. The integration would mirror the Git repository to Platform.sh as soon as there is a git push. This means that even if the code fails style checks or tests, the environments on Platform.sh are updated. In most cases, this may not be desirable.

The solution is to then push to Platform.sh only when the tests pass. This article explores just how to do that.

How did we do this until now?

We have been using GitLab and Platform.sh for a while and we have previously written about how to integrate them. This involved a custom Docker image we wrote which worked well, even if not following the best practices. When I looked at it again, I wanted to simplify the process and use an officially supported solution, if available.

Research

Some quick Google-based research didn’t lead to any results, except for leading me back to our own article. I had two broad approaches in my mind.

  1. Emulate the native GitLab integration behavior using the webhook it creates.
  2. Find an officially supported Docker image for the Platform.sh CLI tool.

I was leaning towards the first approach initially, mainly because of its simplicity. My concern was how to construct the webhook data which will drive the integration. The GitLab push event webhook is quite elaborate and difficult to construct. I would need to find out what minimum data is required to use it.

I asked this on the Platform.sh official support chat and was pointed to answers for both. For the first approach, there is no need to send any data. Just sending a POST request with an empty object ({}) is enough.

While this is easy to do, I didn’t go with this approach. If an empty object is enough, it is likely the way the integration works is by mirroring all the branches, not just the branch being tested in the CI pipeline. This defeats the purpose of everything we are doing here.

The only option left is to use the CLI to push the code (we can do it with Git as well and we’ll discuss that later). We didn’t want to keep maintaining a Docker image for this, and so we found a community maintained one (maintained by pjcdawkins from the Platform.sh team). This is not an officially supported one, but it is as close as we can get.

Using the Docker image

While using the image is straightforward, there are a few prerequisites. If you’re not sure how to use Docker images in the GitLab CI pipeline, it is covered in their documentation.

For the Platform.sh CLI to be able to push the code, we need these things to be available.

  • Platform.sh project ID
  • Platform.sh CLI token
  • SSH keys registered with Platform.sh

Additionally, the environment should have known hosts checking disabled or the host for git.us.platform.sh (which is the git remote for Platform.sh projects) should be recognized. Let’s look at the relevant part of the .gitlab-ci.yml file to see how all this can be done.

We use the before_script section to set up the SSH environment. Specifically, we add our SSH private keys and known_hosts file so that we can push to the Platform.sh repository. Here, the Docker image happens to have ssh-agent installed and all the steps aren’t strictly necessary, but GitLab documentation covers it and we have left it there.

The actual execution section (script section) of the deployment steps does two simple things. The first command sets the project ID and the second command executes the push.

All the relevant and sensitive data is made available to the commands using environment variables. The GitLab documentation covers this well and we won’t repeat all the steps here. These are the variables you need:

  • PLATFORM_PROJECT_ID - The project ID from Platform.sh.
  • PLATFORMSH_CLI_TOKEN - The API token that lets the CLI client authenticate your account. The Platform.sh documentation covers how to create an API token.
  • SSH_KNOWN_HOSTS - You can get this value by running ssh-keyscan git.us.platform.sh. More information is available in the GitLab documentation.
  • SSH_PRIVATE_KEY - This is your private key for which the corresponding public key is added to your Platform.sh account. Be careful with this key and storing it in your GitLab configuration. It is NOT a good idea to use your personal keypair here. Create a new pair specific to the project and add the public key to Platform.sh and the private key to GitLab.

What’s next?

Another option to using the CLI is to just run a git push. I am not entirely convinced about that approach yet. The benefit of deploying with Git is that we don’t need an API token. If you use Git to deploy from your CI pipeline, do let us know about your experience in the comments section below.

Some of the steps above can be simplified further. An easy win I see is to have the known hosts file part of the Docker image itself. This makes sense as this image is specifically for Platform.sh. We will update the post here if we get around to doing that either in the community repository or our own.

Hussain Abbas, Engineering Manager
Posted by

Hussain Abbas, Engineering Manager

Hussain is a calm ambivert who'll surprise you with his sense of humor (and sublime cooking skills). Our resident sci-fi and fantasy fanatic.