Current section: Persisting Data and Automatic Deployment 5 exercises

Add a Staging Environment

As of now, every commit that goes into main is going to go to production.

However, it's nice to be able to play around in a staging environment based on a dev branch.

The first step is to add an entry for the dev branch inside of deploy.yml


Loading lesson


Instructor: 0:00 Every commit that goes into main is going to go to production. What if I wanted to have an environment that's a special, really close-to-production-like environment, that I can test changes out to before going to production?

0:11 This is common for teams, and it's normally called a staging environment. Often they'll just make a dev branch and everything that goes to the dev branch goes into the staging environment where you can play around with and test things out.

0:23 We're going to make that work now. As soon as I created this dev config on our branches, I'm automatically sending things to the production environment because of the way that things are configured down here. I don't want to do that, so we'll make sure to handle that but before we do, we need to create that staging environment.

0:41 Let's say, fly apps create. The staging environment, I want to have the same name as my app just with a -staging at the end. We'll say fly apps create, that app-staging. Then we also need a persistent volume for our staging environment for the SQL-like database.

0:58 We'll say fly vol create data with the app as our staging environment, and the size as 1. Then we'll choose the region that's closest to me. You choose the region that's closest to you or whatever region you prefer. Now we're ready to deploy to this environment.

1:18 We'll come back here and we'll add a bit of config to this Deploy Production to make sure that we only deploy the main branch to production. We'll say, if the github.ref is refs/heads/main.

1:34 Now, this step will only execute if our ref is refs/heads/main, which is the main branch. Now, we can copy this and make a staging version of this. If the refs/heads is dev, now this one will run.

1:51 Now it's a little bit tricky here because this deploy command is going to look up our app name inside of the fly.toml. We don't want it to use that one. That's the production one, so we're going to add an app flag here with our staging app name.

2:04 Now, right here, I get a little bit concerned because I don't like having the configuration duplicated between two different places. Like those two strings are really important and close, and they're supposed to be that way. I'd rather have that be encoded in the way that things are written.

2:23 Instead of hard-coding this, I'm going to use another action step that will read the app name, from our fly.toml. This is the SebRollen/toml-action, which has an ID of app_name that I specify.

2:35 Then we say we want them to read the fly.toml and get us the field app and it will expose that to us. Instead of hard-coding this we can use this as a variable, and the variable name is going to be steps.app_name -- that's referencing that ID there -- .outputs.value. That's going to get the value of the app property in the fly.toml.

3:01 Now I don't have to duplicate that app name and I can use this in other apps that I deploy on Fly as well, which is quite nice. With all of that set up, we can now say git commit add staging environment. We'll push that, and again, we're pushing to main.

3:19 This is going to actually deploy to our production environment, but we can look at that action as it comes in and ensure that indeed only the production step is the one that gets run here and the staging step gets skipped.

3:35 We'll just let that run, and here we can see the deploy staging step got skipped, but the deploy production step is running just as we would expect.

3:44 Now, let's just test this out really quick. We'll say Demo App staging, in parentheses, and then we'll make a branch called dev. We'll git commit staging and push that dev branch to GitHub. We'll look at our actions again, and we see that staging commit in dev has kicked off a new workflow run.

4:08 This one, hopefully, will just run the staging and will not run the production step so that we deploy to staging instead of production. Indeed it is running the staging step.

4:20 Now it's releasing our v2. We can look at our logs here, pop that open on our brand-new staging environment, which is currently setting up the volume data. It's executed our migrations because it just barely created this new database. Now we're all set. It's already starting to give us logs for those health checks, so we can go to overview and look at this.

4:50 Hostname, open that up. Our staging environment is looking exactly the way it should. It has our changes, and our production app does not have those changes, so we can safely experiment in the staging environment without worrying about the production environment getting affected.

5:05 Inner view, what we did to make this work is we ran the fly apps create command to create our staging environment. Then we ran fly vol create to create the persistent volume for our staging environment.

5:18 Then we updated our deploy.yml so that we would only deploy to production if we're on the main branch and we added a staging step that deploys if we're on the dev branch, and then we also read the app name from the fly.toml so we could use that as part of the deploy command of our staging step.

5:37 Then we pushed our changes, made some changes specifically for our dev branch, and pushed the dev branch. That's how you get a staging environment automatically deployed with Fly.