Can I use Build Environment Variables in Netlify with Create-React-App? - environment-variables

How do I use Build Environment Variables in Netlify with Create-React-App?

You CAN use environment variables in your create-react-app on Netlify, but all the build constraints of the Create React App will still apply.
By default you will have NODE_ENV defined for you
Any other environment variables starting with REACT_APP_ will be available
Any other variables except NODE_ENV will be ignored
Changing any environment variables will require you to trigger a new build/deploy
IMPORTANT NOTE: No environment variables can be accessed from a create-react-app dynamically from the browser hosted on Netlify! They must be accessed at build time to be used in the static site.
From an example create-react-app repo hosted on Netlify:
App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
class App extends Component {
render() {
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">Environment Variables in a Create React App on Netlify</h1>
</header>
<p className="App-intro">
To get started, edit <code>src/App.js</code> and commit to your repo.
</p>
<p>NODE_ENV value is "{process.env.NODE_ENV}"</p>
<p>CUSTOM_ENV_VAR value is "{process.env.CUSTOM_ENV_VAR}"</p>
<p>REACT_APP_CUSTOM_ENV_VAR value is "{process.env.REACT_APP_CUSTOM_ENV_VAR}"</p>
<p>TOML_ENV_VAR value is "{process.env.TOML_ENV_VAR}"</p>
<p>REACT_APP_TOML_ENV_VAR value is "{process.env.REACT_APP_TOML_ENV_VAR}"</p>
</div>
);
}
}
export default App;
Produces the following at https://netlify-cra-env-vars.netlify.com/:
Setting Environment Variables in site settings on Netlify.com
In app.netlify.com, CUSTOM_ENV_VAR and REACT_APP_CUSTOM_ENV_VAR were set as follows:
Setting Environment Variables in netlify.toml
The netlify.toml environment variables were set as:
[build]
command = "yarn build"
publish = "build"
[context.production.environment]
TOML_ENV_VAR = "From netlify.toml"
REACT_APP_TOML_ENV_VAR = "From netlify.toml (REACT_APP_)"
[Extra] Setting environment variables in .env
You could set environment variables in a .env file at the root of your project and commit to your repository. The following is available with react-scripts#1.1.0 and higher which takes your version value of your package.json file.
.env
REACT_APP_VERSION=$npm_package_version
Note: the version (and many other npm exposed environment variables) can be accessed.
Do not put secret keys into your repository.

While there are many ways to accomplish this, the simplest way I found to get Netlify Environment variables into my React app was to create an .env file at the root of the project with the following content:
# React Environment Variables
# https://facebook.github.io/create-react-app/docs/adding-custom-environment-variables#expanding-environment-variables-in-env
# Netlify Environment Variables
# https://www.netlify.com/docs/continuous-deployment/#environment-variables
REACT_APP_VERSION=$npm_package_version
REACT_APP_REPOSITORY_URL=$REPOSITORY_URL
REACT_APP_BRANCH=$BRANCH
REACT_APP_PULL_REQUEST=$PULL_REQUEST
REACT_APP_HEAD=$HEAD
REACT_APP_COMMIT_REF=$COMMIT_REF
REACT_APP_CONTEXT=$CONTEXT
REACT_APP_REVIEW_ID=$REVIEW_ID
REACT_APP_INCOMING_HOOK_TITLE=$INCOMING_HOOK_TITLE
REACT_APP_INCOMING_HOOK_URL=$INCOMING_HOOK_URL
REACT_APP_INCOMING_HOOK_BODY=$INCOMING_HOOK_BODY
REACT_APP_URL=$URL
REACT_APP_DEPLOY_URL=$DEPLOY_URL
REACT_APP_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
Display all these env variables by placing this in a visible components:
<pre>{JSON.stringify(process.env, undefined, 2)}</pre>
Important! You will need to re-start (or re-build) the app in order to set these environment variables anytime they change.

The fastest way to test/accomplish this in create-react-app is
package.json
{
...
"scripts": {
"build": "export REACT_APP_COMMIT_REF=\"$COMMIT_REF\" && react-scripts build",
}
...
}
config.ts
if (!process.env.REACT_APP_COMMIT_REF) {
throw new Error("`REACT_APP_COMMIT_REF` not set")
}
console.log("REACT_APP_COMMIT_REF is", process.env.REACT_APP_COMMIT_REF)
export const config = {
GIT_SHA: process.env.REACT_APP_COMMIT_REF,
}
Thanks to Netlify's automatic deploy preview, you can verify commit SHA is shown in the application console.

This is how I added my environment variables from React to Netlify:
On Netlify's website go to your app's page.
Click on Site settings.
Go to Build & deploy.
Scroll down to Environment variables and add all variables you have in your .env file in React.
Redeploy your app.

Related

Playwright - Test against different environments and different variables

Im looking to use Playwright to test against a web page.
The system im working on has 4 different environments that we need to deploy against,
for example the test urls may be
www.test1.com
www.test2.com
www.test3.com
www.test4.com
The first question is how do I target the different Environment? In my playwright config I had a baseUrl but I need to override that.
In addition each environment has different login credentials, how can I create and override these as parameters per environment?
Since Playwright v1.13.0, there is a baseURL option available. You can utilise that in this way probably
In your config.js file, you can have this
import { PlaywrightTestConfig } from '#playwright/test';
const config: PlaywrightTestConfig = {
use: {
baseURL: process.env.URL,
},
};
export default config;
Now in the package.json file, you can have the environment variables set in the test commands for various env in the scripts , like this
...
"scripts": {
"start": "node app.js",
"test1": "URL=www.test1.com mocha --reporter spec",
"test2": "URL=www.test2.com mocha --reporter spec",
.
.
},
...
Similarly you can set the environment variables for the login credentials also and then pass them in the script in the same way the URL is passed.
Another approach to this is to use a Bash script. I use something like the following to run tests across environments, to ensure that my Playwright tests will work in all environments they're run in -
#!/bin/bash
echo "Running tests against env 1";
ENV_URL=https://www.env1.com SOMESERVICE_ENV_URL=http://www.env1.com/scholarship npx playwright test $1;
echo "Running tests against env 2"
ENV_URL=https://env2.com SOMESERVICE_ENV_URL=http://env2.com:4008 npx playwright test $1;
echo "Running tests against env 3";
ENV_URL=http://localhost:3000 SOMESERVICE_ENV_URL=http://localhost:4008 npx playwright test $1;
And then run with ./myScript.sh myTest.test.ts
(In a Bash script, the first argument passed in is available via $1.)

how to output a variable that is updated dynamically inside a step in jenkins console. config file ( environment file ) that I passed for a job

I have a config file that has some environment variable including a variable called MONGO_UUID and I pass this variable to a test step via a configFileProvider plugin and save it to .env file as in step below:
stage('Build ') {
steps {
configFileProvider([configFile(fileId: 'jenkins_config_filename', variable: "CONFIG_FILE")]) {
sh '''
cp -f $CONFIG_FILE ./.env
npm run test // this step dynamically updates MONGO_UUID
echo "$MONGO_UUID" // trying to output newly updated value here
'''
jenkins_config_filename has following format:
MONGO_HOST=123.123.123.1
MONGO_DB=dbname
MONGO_US=user
MONGO_UUID=null
What I am trying to do is to output variable MONGO_UUID which was passed to the test step via config file and the value of MONGO_UUID get updated in the process. I can see that the MONGO_UUID got updated because I can see new record in mongodb but I am wondering how to echo that value in jenkins console.
add this line (with proper changes based on your MongoDB configuration) after npm run test:
MONGO_UUID=`mongo db.collection.find("whatever you query is")`
and then you can echo the variable to Jenkins output.
If you want to update the file, you can use sed like below :
sed -i "s/MONGO_UUID=.*/MONGO_UUID=${MONGO_UUID}/" .env

Active choice plugin Groovy script - Read environment variable

I want to use environment variable "WORKSPACE" in the active choice plugin groovy script.
I tried to retrieve it like this but it didnt work. WORKSPACE is not recognised.
${WORKSPACE}
Can anyone help me here?
Snippet:
def sout = new StringBuffer(), serr = new StringBuffer()
def proc ='/test/script.sh'.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println sout
Here instead of /test/script.sh i need to access the script as following:
def process='$workspace path/test/script.sh
It's not possible to get that "environment" variable. A better name would be "property". Those are dynamically generated by Jenkins when the build starts, not when the parameters are set.
You can get some environment variables with EnvVars when you're setting the parameters, but they are very few. This can be tested on the Jenkins Script Console with the following code:
import hudson.EnvVars
for (envVarName in EnvVars.masterEnvVars.keySet()) {
def envVarValue = EnvVars.masterEnvVars[envVarName]
println("${envVarName}=${envVarValue}")
}
Result:
_=/etc/alternatives/java
HOME=/home/jenkins
LANG=en_US.UTF-8
LOGNAME=jenkins
NLSPATH=/usr/dt/lib/nls/msg/%L/%N.cat
PATH=/sbin:/usr/sbin:/bin:/usr/bin
PWD=/
SHELL=/bin/bash
SHLVL=2
TERM=xterm-256color
USER=jenkins
XFILESEARCHPATH=/usr/dt/app-defaults/%L/Dt
WORKSPACE property has more to it. The directory may not exist when you launch the build, specially if it's the first time you are doing it. My recommendation, if it makes sense to you, is to place the script in userContent directory and work out the rest based on that.

Set environment variables from external file in serverless.yml

I'm using serverless and serverless-local for local development.
I've got an external file which holds references to environment variables which I retrieve from node.env in my app.
From what I understand, I should be able to set my environment variables such as
dev:
AWS_KEY: 'key',
SECRET: 'secret
test:
AWS_KEY: 'test-key',
SECRET: 'test-secret',
etc:
...
and have those environment variables included in my app through the following line in my serverless.yml
provider:
name: aws
runtime: nodejs4.3
stage: ${opt:stage, self:custom.default_stage}
deploymentBucket: serverless-deploy-packages/${opt:stage, self:custom.default_stage}
environment:
${file(./serverless-env.yml):${opt:stage, self:custom.default_stage}}
then in the commandline, I call
serverless offline --stage dev --port 9000
I thought this would include the correct vars in my app, but it isn't working. Is this not how it is supposed to work? Am I doing something wrong here?
From docs:
You can set the contents of an external file into a variable:
file: ${file(./serverless-env.yml)}
And later you can use this new variable to access the file variables.
secret: file.dev.SECRET
Or you can use the file directly:
secret: ${file(./serverless-env.yml):dev.SECRET}
You can also now use remote async values with the serverless framework. See https://serverless.com/blog/serverless-v1.13.0/
This means you can call values from s3 or remote databases etc.
Example:
serverless.yml
service: serverless-async-vars
provider:
name: aws
runtime: nodejs6.10
custom:
secret: ${file(./vars.js):fetchSecret} # JS file running async / promised
vars.js
module.exports.fetchSecret = () => {
// async code
return Promise.resolve('SomeSecretKey');
}
This is how you can separate your environments by different stages:
serverless.yml:
custom:
test:
project: xxx
prod:
project: yyy
provider:
...
stage: ${opt:stage, 'test'}
project: ${self:custom.${opt:stage, 'test'}.project}
environment:
${file(.env.${opt:stage, 'test'}.yml):}
package:
exclude:
- .env.*
.env.test.yml:
VARIABLE1: value1
VARIABLE2: value2
During deploy, pass --stage=prod or skip and test project will be deployed. Then in your JS code you can access ENV variables with process.env.VARIABLE1.
Set Lambda environment variables from JSON file ( using AWS CLI)
aws lambda update-function-configuration --profile mfa --function-name test-api --cli-input-json file://dev.json
I had this correct, but I was referencing the file incorrectly.
I don't see this in the docs, but passing a file to environment will include the files yaml file, and the above structure does work.

find env variables for a all builds for a job on jenkins

I need to monitor what are the changes going with a job on jenkins(update the changes to a file). Need to list the env variables of a job. JOB_NAME,BUILD_NUMBER,BUILD_STATUS,GIT_URL for that build(all the builds of a job). I didn't find out a good example with the groovy. What is the best way to fetch all the info?
build.getEnvironment(listener) should get you what you need
Depending on what you would like to achieve there are at least several approaches to retrieve and save environment variables for:
current build
all past builds
Get environments variables for current build (from slave)
Execute Groovy script
// Get current environment variables and save as
// a file in $WORKSPACE.
new File(".",'env.txt').withWriter('utf-8') { writer ->
System.getenv().each { key, value ->
writer.writeLine("${key}:${value}")
}
}
Using Groovy Plug-in.
Get environment variables for current build (from master)
Execute system Groovy script
// Get current environment variables and save as
// a file in $WORKSPACE.
import hudson.FilePath
def path = "env-sys.txt"
def file = null
if (build.workspace.isRemote()) {
file = new FilePath(build.workspace.channel, build.workspace.toString() + "/" + path)
} else {
file = new FilePath(build.workspace.toString() + "/" + path)
}
def output = ""
build.getEnvironment(listener).each { key, value ->
output += "${key}:${value}\n"
}
file.write() << output
Using Groovy Plug-in.
Environment variables returned by Groovy scripts are kept in map. If you don't need all of them, you can access individual values using standard operators/methods.
Get environment variables for all past builds (from master)
This approach expecst that you have installed EnvInject Plug-in and have access to $JENKINS_HOME folder:
$ find . ${JENKINS_HOME}/jobs/[path-to-your-job] -name injectedEnvVars.txt
...
ps. I suspect that one could analyze EnvInject Plug-in API and find a way to extract this information directly from Java/Groovy code.
Using EnvInject Plug-in.
To look for only specific variables you can utilize find, grep and xargs tools .
You can use below script to get the Environment Variables
def thread = Thread.currentThread()
def build = thread.executable
// Get build parameters
def buildVariablesMap = build.buildVariables
// Get all environment variables for the build
def buildEnvVarsMap = build.envVars
String jobName = buildEnvVarsMap?.JOB_NAME // This is for JOB Name env variable.
Hope it helps!

Resources