How a marketing guy quickly built a Python microservice chatbot app for Drift on Platform.sh

12 Dec 2018
Chris Yates
VP Marketing
Thumbnail

A few weeks ago, it was snowing. Actually, snow isn’t quite the right descriptor. It was a chilly mixture of snow, rain, and sleet, with a helping of wind for good measure. (Lovely weather outside my Boston-area home office.) Instead of going outdoors (and who would), I sat down at my desk and decided to scratch an itch our marketing automation pipeline had been giving me.

The view from my window … in November

At Platform.sh, we use Drift, a conversational marketing platform built by smart folks here in Boston. Through Drift, Platform.sh customers and prospects can have direct 1:1 conversations with our team to find out more about how they can use our product. What makes Drift really great? It has a robust API.

This got me to thinking: Platform.sh, like Drift, has a really robust API. In fact, it’s so robust we’ve built our web UI and Platform Shell Command Line Interface (CLI) on it. What if I could connect Drift to Platform.sh, so our team would know what projects a user might be working on, enabling us to better support them? Now, that would be the makings of an afternoon coding project—a project that went from an idea to cloud deployment in just a few of hours.

Let me set the stage by sharing that most of the time I spent on this project was invested in re-learning how to write Python code, something I hadn’t done since my NASA days, eight years ago! In fact, I couldn’t remember the last time I wrote any code, mostly because getting development workflows and environments ready—the stuff you have to do before getting real features written—had become such a hassle.

Platform.sh turned out to be the easiest part of the journey—getting my little service up and running, from development through to production.

The Drift team has provided not only a well-documented, full-featured API, but has also provided SDKs in several languages, including Python. Platform.sh supports most modern languages including Golang, Node.js, Ruby, PHP, and Java*, but I chose Python based on my familiarity (however rusty), and the batteries-included philosophy that the community shares with Platform.sh (incidentally, much of our product is also Python-based!).

Creating a project: somewhere for my code to run

Creating a new project on Platform.sh is simple. You can even start a trial for free, no credit card required. With Platform.sh, I don’t need to worry about managing servers, virtual machines, or even containers—I just choose the amount of resources I think I’ll need for my app, which I can always change later.

Platform.sh checkout screen

You can also create and manage your projects from the Platform Shell CLI or the API.

Once my project was created, I did a couple of things. Platform.sh is based around Git, which makes it a powerful tool for teams—and even individual devs—to manage their workflows. Because apps aren’t just the code you write, we use Git to manage the configuration of infrastructure, continuous integration, and deployment, too.

First, in the Platform.sh web UI, I created a new branch called ‘dev,’ where I could work on my new idea. We use the master branch for production, so you’ll want to create other branches for your work in progress.

Branching from master

Then, you’ll want to check out your project; you can do this via Git directly, or with the Platform.sh CLI, like so:

checking out code

Building a simple app, no specific architecture required

My app is about as simple as you can get. It listens for a webhook from Drift, triggered when Drift identifies a user. When that happens, my little Python app sends a query to the Platform.sh users API.

As I mentioned earlier, everything that can be done through the Platform.sh web UI can be done through the API. So while here, I’m just returning information about the user, their projects (if any), and a few other things. I could also use the Platform.sh API as part of a white-label service, much like our friends at Symfony have done.

Finally, I used the Drift conversation API to return a message to Drift, so that anyone interacting with a user can have context about how they’re using Platform.sh.

UML showing how Drift, my app, and the Platform.sh API interact

Soon, I’ll get this code posted on Github for those that want to see for themselves. But the most important point I want to make is this: to get an app running on Platform.sh required no adaptations. By using features like inheritable variables, I was able to keep any application- specific configuration (like API tokens, for example) out of my code, and manageable across multiple environments—say, if I wanted to have my development or staging branches use credentials for a Drift sandbox, instead of production.

Tokens for Drift

I don’t even need to know how these variables work on Platform.sh; I can just access them with my language’s standards, in this case, Python’s os.getenv().

Telling Platform.sh about what my app needs to run

Adapting the code I want to run to whatever environment it’s running on is often challenging, and frankly, as a rusty and lazy developer, it’s where I often throw up my hands in frustration. Ensuring that your code is going to build and run when you send it to the cloud is often the last step in the process, or even something that other teams [like ops] do. But it shouldn’t be. Getting my app running on Platform.sh requires only a few simple steps:

  1. Add a .platform.app.yaml file to my app’s directory. This file describes how to build, deploy, and run my app, which dependencies need to be included, and what the app should be called. For this simple app, I’ve got only one service (the Python script), and my .platform.app.yaml looks like this:

.platform.app.yaml example

  1. Add a .platform directory, and in it, a routes.yaml, and services.yaml file. As you might expect, the routes.yaml file defines how your services communicate with the outside world, and the services.yaml file enumerates any additional services that your app needs. You might need a SQL database, like MySQL or Postgres, a queue, like Redis or RabbitMQ, or a document database, like Mongo. Listing these services in  your services.yaml and creating relationships in your .platform.app.yaml are all you need to do.

Once you commit and push your code, Platform.sh takes care of running any build and deploy processes you’ve specified in your .platform.app.yaml file, then containerizes and deploys each service.

Pushing the code, and running it

Pushing my app to platform.sh

That stream of text actually shows a lot: I now have a microservice running on Platform.sh, deployed directly from Git. In this case, I’ve made a simple change, and Platform.sh has deployed my app. For more complex microservices apps, we only deploy things that have changed. Updating a front-end React component? No need to rebuild everything. Platform.sh just deploys the changes to that specific component. In our new UI, you can see how our Drifty app has been deployed to its own container, separate from the router (admittedly, it’s just about the simplest application ever, with no stateful services needed).

Running on platform.sh

Unlike a purely functional Platform-as-a-Service (fPaaS, e.g., AWS Lambda, Azure Functions), Platform.sh has also taken care of automatically deploying an SSL certificate for any branch I’ve created, so I can go directly to my application, share it with colleagues, test it, and so forth. Using the platform ssh command, I can also SSH directly to my app container to view logs, interact live, and more.

Speaking of sharing, we know that real-life development is a team sport. For every project, and every branch you create within that project, you can delegate access as a developer (contributor), reader, or admin. With the Platform.sh API, you can also integrate these rules within your broader workflow.

Summing it up

I’ve just scratched the surface of what’s possible with Platform.sh, and hopefully I’ve given you some insights into how it can help teams focus on developing features to solve business problems—rather than building a toolchain and managing servers, VMs, or containers.

If the marketing guy can deliver a real service to production with minimal effort and no worry, just about anyone can.

P.S. Special thanks to the Drift API team, specifically Chris Buonocore, for being super responsive on Slack and adding new functionality on the fly to make this work.