Suggestions how to have a permanent "staging"

We love the Preview Environments and have enabled it in our blueprint:

previewsEnabled: true
previewsExpireAfterDays: 3

But we also would like to have a permanent “staging” server that is separate from our permanent “Live” services.

How can we do this but also keep our Preview Environments?

Hi Michael,

This is a pretty common question that we’re getting and right now we don’t have a perfect answer but we do have some workarounds. Let me try and break it down.

Let’s start with talking about the staging environment.

The first question here, is what branch do you want deploying to your staging environment, I think the majority of folks would want it to be the master/main branch, ie the code that’s going to be deployed to production.

Master/Main Branch → Staging environment :white_check_mark:

Ok, so keeping our attention on the staging environment and our development cycle, it follows that work would be done in Pull requests and made against the master/main branch so that preview environments are created.

previewEnabled: true :white_check_mark:

And once those PRs are merged, we want the staging environment to autodeploy.

autoDeploy: true :white_check_mark:

To demonstrate this, I’ve created a very simple example at GitHub - johnbeynonorg/render-devcycle-example with the render.yaml looking like:

    previewsEnabled: true
    services: 
      - type: web 
        name: my-amazing-app
        plan: free 
        env: ruby 
        autoDeploy: true # this is the default but included for explicitness 
        buildCommand: ./render-build.sh 
        startCommand: ./render-start.sh

A behaviour I’m using here which we’ll come back to later is described in Blueprint Specification | Render - I’m not specifying a branch or repo attribute - which means that when we create the blueprint we would use the repo that the render.yaml is located in and the branch the PR is for s deployed.

Continuining on and deploying this to us as a new Blueprint,


and here’s the results of this https://my-amazing-app.onrender.com/

So that’s our staging environment setup.

A quick PR against the repo Some new work by johnbeynon · Pull Request #1 · johnbeynonorg/render-devcycle-example · GitHub

and here’s the results of that in a preview environment, https://my-amazing-app-pr-1.onrender.com/

So at this point, we’ve now got:

  • A separate staging environment that autodeploys master
  • Preview environments

But what about production?

If we had our production service set to auto deploy master, then at this point we may have deployed master to production - which isn’t what you want.

Bear with me. It’s not a great story right now but it’s something we’re blissfully aware of and have plans to address this.

Create a new repo to house just a render.yaml file (no other files required) like GitHub - johnbeynonorg/render-devcycle-example-prod - the render.yaml here looks very similar to the previous one:

    services: 
       - type: web 
         name: my-amazing-app-production 
         repo: https://github.com/johnbeynonorg/render-devcycle-example 
         plan: free 
         env: ruby
         autoDeploy: false
         buildCommand: ./render-build.sh 
         startCommand: ./render-start.sh

except notice that here that I’ve given the app a new name to clearly identify it as production, I’m actually explicitly setting the repo to the original repo path, disabled previewEnvironments and disabling auto deployments.

Here’s the example repo:

https://github.com/johnbeynonorg/render-devcycle-example-prod

So now, I create a new blueprint pointing at this repo


and here’s the result - https://my-amazing-app-production.onrender.com

Notice, that’s deploying the master branch - because again, that’s the branch the render.yaml is on (even though it’s a different repo). With autodeploy set to false that means to put anything into production you either need to:

So that’s our environments setup, what does our flow look like?

  • Developer checks out code and creates a branch
  • Code, code, code
  • Developer submits a PR
  • Preview environment is created
  • PR to closed and merged
  • Preview environment is deleted
  • staging autodeploys master
  • Production is manually deployed using method above

Whilst the additional repo is a tad clunky right now, it does have some added advantages in that you can have render.yaml in both repo’s - the different environments can have different environment variables different plans etc

Could you do all of this without a separate repo?

Yes you could. It definitely gets a little tricky as you have to be careful about merging changes made to the render.yaml between branches. You’d also have to have a separate branch for ‘production’ so the flow would be:

GitHub repo with develop and master branch - names are up to you. You can change the github default branch to ‘develop’ as well if that helps.

PRs are made against the develop branch - when closed the ‘develop’ branch is auto deployed to the staging environment. Then, when develop is merged into master then the master branch could be autodeployed (as it’s a separate branch now) or manually deployed as detailed above.

Whilt the separate repo for production is a little odd, it keeps things a little bit simpler and actually the method I prefer for my own flow as it means I’m in control when code is deployed to production. Obviously, if you want to run a fully automated deploy process then you’d have to go with this second flow but be aware of the limitations right now.

I hope that helps,

Regards,

John B

Wow John, thanks for such a detailed and helpful reply! I massively appreciate it.

Yes I have been considering a “multi-repo” approach but was hoping for an alternative.

Fantastic to hear you guys are working on it however.

Keep up the great work,

Mike