Netlify-cms: Different configs for different branches / environments

Created on 10 Nov 2020  路  7Comments  路  Source: netlify/netlify-cms

I would like to be able to have different configs for each of our environments (one-to-one with branches). The situation I keep running into:

  • Locally, the config needs to point to a local proxy server for authentication and won't go through the whole pull request flow. This means that every time I want to make changes locally, I update the config, then revert the connection information before I push it to origin.
  • On a feature branch, I need the config to point to that feature branch, so that the author may change content related to the new feature. Then, before it's merged to develop, I need to update the branch to develop.
  • On develop, I need the config to point to develop so that the author changes content related to the feature set on our develop branch (i.e. our staging site). But before a release, I need to update develop to point to master.
  • On master (i.e. our live site), I need the config to point to master so that the author changes content related to the feature set on master.

I would like a way for that connection information to either be configurable based on the branch the user is on, or be broken out into another file so that I can update it once and then not override it every time I do a merge.

feature

Most helpful comment

If you're using Gatsby then you're probably using gatsby-plugin-netlify-cms. To be able to provide different configs conditionally you have to initialize cms manually. In order to do that you have to provide certain options to gatsby-plugin-netlify-cms. This is how it's done in my gatsby-config.js

{
  resolve: `gatsby-plugin-netlify-cms`,
  options: {
    modulePath: `${__dirname}/src/cms/cms.ts`,
    manualInit: true,
  },
}

and then in cms.ts (or cms.js if you're not using TypeScript)

import CMS from 'netlify-cms-app'

const config =
  process.env.NODE_ENV === 'development'
    ? { local_backend: { url: 'http://localhost:8000/api/v1' } }
    : {
        backend: {
          name: 'git-gateway',
          branch: process.env.GATSBY_BRANCH || 'master',
        },
      }

CMS.init({ config })

if you want to use local backend in development, then in gatsby-node.js

const { registerLocalFs } = require('netlify-cms-proxy-server/dist/middlewares')

exports.onCreateDevServer = async ({ app }) => {
  await registerLocalFs(app)
}

Also, as I'm using netlify for hosting I need to assign current branch name to GATSBY_BRANCH env variable. I'm doing it also in gatsby-config.js like this

// process.env.HEAD comes from Netlify
process.env.GATSBY_BRANCH = process.env.HEAD

All 7 comments

Hi @acarnwath, do the solutions provided in https://github.com/netlify/netlify-cms/issues/3790 cover your use case?

It sounds very similar but I don't think I'm fully connecting the dots. I'm using Gatsby.js + Federalist and I'm not sure where to find cms.js or how to override/add to it in order to set up the conditional config.

Giving this a bump @erezrokah or maybe @smashercosmo can answer my question since they were talking about it in the other issue...?

If you're using Gatsby then you're probably using gatsby-plugin-netlify-cms. To be able to provide different configs conditionally you have to initialize cms manually. In order to do that you have to provide certain options to gatsby-plugin-netlify-cms. This is how it's done in my gatsby-config.js

{
  resolve: `gatsby-plugin-netlify-cms`,
  options: {
    modulePath: `${__dirname}/src/cms/cms.ts`,
    manualInit: true,
  },
}

and then in cms.ts (or cms.js if you're not using TypeScript)

import CMS from 'netlify-cms-app'

const config =
  process.env.NODE_ENV === 'development'
    ? { local_backend: { url: 'http://localhost:8000/api/v1' } }
    : {
        backend: {
          name: 'git-gateway',
          branch: process.env.GATSBY_BRANCH || 'master',
        },
      }

CMS.init({ config })

if you want to use local backend in development, then in gatsby-node.js

const { registerLocalFs } = require('netlify-cms-proxy-server/dist/middlewares')

exports.onCreateDevServer = async ({ app }) => {
  await registerLocalFs(app)
}

Also, as I'm using netlify for hosting I need to assign current branch name to GATSBY_BRANCH env variable. I'm doing it also in gatsby-config.js like this

// process.env.HEAD comes from Netlify
process.env.GATSBY_BRANCH = process.env.HEAD

This is great @smashercosmo - I think our docs don't clarify it but the local backend only runs if you're on localhost so I think you can drop that condition:
https://github.com/netlify/netlify-cms/blob/92a3bfa4855de0db503cc5909b5f750fc0b862ae/packages/netlify-cms-core/src/actions/config.js#L365

Thanks @smashercosmo - I was missing the connection in gatsby-config, this works!
For those that find this looking for Federalist, it is process.env.BRANCH and process.env.NODE_ENV is the same as above.

Just a little more context - process.env.BRANCH is not available on the client-side which is where this cms.js is processed, so there is another step here to expose it. Theoretically, based on Gatsby's documentation and @smashercosmo 's example above, you should be able to set a property on process.env that starts with GATSBY_ and it will expose it on the client side (when referenced specifically, just process.env results in an empty object). However, I got an error trying to set it that way.
The way I got it to work was to install the gatsby-plugin-env-variables plugin and expose it that way.

This is my gatsby-config.js file:

//...
{
  resolve: `gatsby-plugin-env-variables`,
  options: {
    allowList: ["BRANCH"]
  },
},
{
  resolve: `gatsby-plugin-netlify-cms`,
  options: {
    modulePath: `${__dirname}/src/cms-config/cms.js`,
    manualInit: true,
    htmlTitle: 'Content Management | REACH to Prevent Suicide'
  },
}
//...

cms.js

import CMS from 'netlify-cms-app'

let config = {};

let backend = {};
if( process.env.NODE_ENV === 'development' ) {
  backend.name = 'git-gateway';
  config.local_backend = true;
} else {
  //...
  backend.branch = process.env.BRANCH || 'master';
}
config.backend = backend;
//...

// Make the config object available on the global scope for processing by subsequent scripts.
window.CMS_CONFIGURATION = config;

CMS.init({ config })
Was this page helpful?
0 / 5 - 0 ratings