Workarounds for not being able to put environment variables in build.ignore

Hello :wave:

I want to setup a single git repository that would work to build three different sites in Netlify. The code that powers each site would be the same (with a bit of configuration differences) but the content for each site would vary (the content being a bunch of markdown files). I thought perhaps I could setup the following structure

sites/
  site_a/
    post1.md
    post2.md
    etc...
  site_b/
    post1.md
    post2.md
    etc...
  site_c/
    post1.md
    post2.md
    etc...
src/
  index.html
  otherFilesAndTemplates.html
  etc..
netlify.toml
package.json

With the above structure, I figured I could configure my build command via the Netlify UI to pass in the site I want to build as a query param so my build script would know which sites/ folder to grab content from, i.e.

// build command for site a in netlify UI
npm run build -- --site=a

// build command for site b in netlify UI
npm run build -- --site=b

// build command for site c in netlify UI
npm run build -- --site=c

Awesome, that gets me 95% of the way there. The one problem is CI. Because this is one git repository, but three different sites in Netlify, I don’t want to build all three sites every single time I make a change to the repo. I want each site to be able to check and say “if anything in src/ or anything in this site’s folder changed, rebuild and deploy”. I thought I would be able to do this with build.ignore, i.e. set an environment variable via the Netlify UI for each site and then do something like:

[build]
  ignore = "git diff --quiet HEAD~ HEAD src/ site/$SITE_ID"

But then I found this one little problem:

Using environment variables directly as values ( $VARIABLENAME ) in your netlify.toml file is not supported.

So my question is: is it possible to get a setup like what I described above? It’s kind of like a monorepo, but I don’t have a package.json for every unique site. As mentioned, the code is the same for each site, it’s the content that changes. Is there a way to configure Netlify’s CI so that each site that links to the same git repo can check “hey, did anything in src/ or my folder (be it a, b, or c) change? if so, then run a build and deploy. Otherwise, don’t do anything.”

Thanks!

HI there, those are some good questions.

Did you see this guide already?

I’m setting the environment variable correctly, I think perhaps I’m just not understanding the syntax correctly.

If I set build.ignore to a git diff command, the variable doesn’t seem to work. For example, I even just tried setting an env variable WATCH_FILE to README.md via Netlify UI and then have this in my netlify.toml:

[build]
  ignore = "echo $WATCH_FILE"

Which results in this output:

1:50:19 PM: Detected ignore command in Netlify configuration file. Proceeding with the specified command: 'echo $WATCH_FILE'
1:50:19 PM: $WATCH_FILE

It’s like variable interpolation in the build.ignore command doesn’t work? I’ve tried echo $VAR, echo ${VAR}, echo "$VAR", none work.

But if I execute a shell script as my build.ignore command, then I can access WATCH_FILE, i.e.

[build]
  ignore = "./script.sh"

Inside script.sh:

#!/bin/bash
echo "$WATCH_FILE"

That results in Netlify’s build logging:

1:34:31 PM: Detected ignore command in Netlify configuration file. Proceeding with the specified command: './script.sh'
1:34:31 PM: README.md

So I can access that variable, I guess I just have to do it via a shell script?


EDIT ON THE BELOW Netlify docs do say that build.ignore “allows you to specify a unix shell command” so I assume that’s why I can’t run node.

Tangentially related: I thought “ok this can work, but I’d prefer to write my script as a node script” so changing my build.ignore to something like this:

[build]
  ignore = "node ./script.js"

And then in ./script.js

if (process.env.WATCH_FILE === 'somevalue') {
  process.exit(0);
} else {
  process.exit(1);
}

But that doesn’t seem to work at all. Can you run a node script as your build.ignore command like that?

FWIW I was able to get this working by using the shell script workaround.

This doesn’t work

[build]
  ignore = "git diff --quiet HEAD^ HEAD $MY_VAR"

This does work

Tell netlify.toml to run a shell script:

[build]
  ignore = "./ignore.sh"

And put that same command in the shell script:

#!/bin/bash
git diff --quiet HEAD^ HEAD $MY_VAR
1 Like

Yup, that’s expected behavior, good move to use a script instead!

@fool It looks like our ignore bash script doesn’t actually run when the build is triggered using the build hook (eg: https://api.netlify.com/build_hooks/XXX).

The log does says it’s running the script, but it then just keeps going with the build without outputting anything from the script:

If the build is triggered from a PR merged into the repo, then it actually runs the ignore script properly:

Any ideas why?

@fool Ok, so according to @marcus 's post, the “hooks will never be ignored/cancelled”.

We use the hooks to automatically trigger builds on our site (periodically), but we have a condition for the build to go ahead, which I was hoping to check with the ignore bash script. If the hooks bypass this ignore script, how could I achieve this?

I have also created a build plugin onPreBuild to cancel the deploy then (utils.build.cancelBuild()). However, it takes 2 and half minutes to get to this, as it installs all the yarn dependencies first. Would this 2 and half minutes be deducted from our account? Is there a way to cache/skip the node_modules of these yarn packages?

Thanks guys.

Hey @website-devs,
Can you say which env variables are needed for the build (just the keys, not the values, please!)? We’re wondering if there are some that are missing with the hook-triggered command.