lecture 15 of 170 completed

Environment variables and keeping secrets out of Git

The same suite has to run against local, staging and production-like systems, with credentials that must never reach your repository.

A tester on a project I joined had committed the staging password to the repository, inside a spec file. It sat in the Git history for eight months. Nobody had been careless; nobody had shown her where else to put it.

This lecture is where else to put it.

The problem. Your suite has to run in more than one place. On your laptop the app is at localhost:3000. On the build server it is at a staging address. The login credentials differ too. Writing them into the test means editing tests to change environment, and it means secrets live in your repository forever.

Environment variables are values you supply from outside the code.

Cypress reads them from several places. The two you need at the start are the config file and the command line.

For values that are not secret, the config file is fine:

const { defineConfig } = require('cypress');

module.exports = defineConfig({
  e2e: {
    baseUrl: 'http://localhost:3000',
    env: {
      apiUrl: 'http://localhost:4000',
    },
  },
});

Read it in a test with Cypress.env:

cy.request(`${Cypress.env('apiUrl')}/contacts`);

For anything secret, pass it in when you run, so it never appears in a file:

npx cypress run --env password=$STAGING_PASSWORD

The $STAGING_PASSWORD part reads a value from your shell or from the build server's secret storage. Every CI system has a place to store these, and that is where credentials belong.

To point the whole suite at a different environment, override baseUrl:

npx cypress run --config baseUrl=https://staging.example.com

Same tests, different target, no file edited.

Three rules I would put on a wall.

Never commit a real credential. If it reaches Git, treat it as public and rotate it, even in a private repository. The history keeps it after you delete the line.

Add cypress.env.json to .gitignore. Cypress reads this file automatically, which makes it convenient for local secrets and dangerous if it is tracked.

Do not put an environment name in your tests. A test containing if (env === 'staging') will drift until it only passes in one place. Tests should not know where they are running. Configuration decides that.

Remember this: addresses in config, secrets on the command line, and nothing sensitive in Git.

Reference: Environment Variables.