Environment variables inside of NodeJs and Github actions CI/CD pipeline with Playwright test

M Ferreira
M Ferreira

This guide will show you how to inject environment variables into the Github actions pipeline. the context of this guide is to have our tests run in the pipeline in the same way as they run on our localhost.

We will write a simple test to ensure that the project has a .env file with values present.

In the project you may or may not have .env file holding all variables required throughout your 12 Factor app. If not create them now.

1. create .env files

In root of project:

touch .env
touch .env.example

2. Add variables to file

.env

API_BASE_URL="https://api.website.com/v1/" API_KEY="adbcefg"

.env.example (empty values for the example file) It's a good idea to have an example .env file so the next engineer knows what variables are required.

API_BASE_URL= API_KEY=

3. Create the test file and test

In project root:

mkdir tests
touch tests/env.spec.ts

All code below should be written in the same file.

Import dependencies, playright, dotenv and path:

import { test, expect } from "@playwright/test"; import dotenv from "dotenv"; import path from "path"; dotenv.config();
  • Read a specific .env file depending on whether it's run on localhost or the CI pipeline.
  • We want the pipeline to run against the .env.example which is commited to git.
  • The .env is not and should never be commited to git.
dotenv.config({ path: path.resolve(__dirname, "..", process.env.CI ? ".env.example" : ".env") });
  • Grab the variables using destructuring
const { API_BASE_URL, API_KEY } = process.env;
  • create a user freiendly messsage to output in the console later on should the test fail.
let environmentVarWarning = "❗ No environment variable found, use the .env.example file to create your own .env file with required properties and values.";
  • Create a describe so multple tests can be grouped, plan to run 2 tests
test.describe('Environment variables present and configured', async () => { ... });
test.describe("Environment variables present and configured", async () => { // 1 test("API_BASE_URL is present", async () => { expect(API_BASE_URL, environmentVarWarning).toBeDefined(); }); // 2 test("API_KEY is present", async () => { expect(API_KEY, environmentVarWarning).toBeDefined(); }); });

The final look fo the test:

import { test, expect } from "@playwright/test"; import dotenv from "dotenv"; import path from "path"; dotenv.config(); dotenv.config({ path: path.resolve(__dirname, "..", process.env.CI ? ".env.example" : ".env") }); const { API_BASE_URL, API_KEY } = process.env; let environmentVarWarning = "❗ No environment variable found, use the .env.example file to create your own .env file with required properties and values."; test.describe("Environment variables present and configured", async () => { test("API_BASE_URL is present", async () => { expect(API_BASE_URL, environmentVarWarning).toBeDefined(); }); test("API_KEY is present", async () => { expect(API_KEY, environmentVarWarning).toBeDefined(); }); });

4. Create the pipeline file

Guthub actions allows you execute bash commands and allows you to run runtime variables in your pipeline by using the run: command.

Write your variable creator command right before you need, in this context I need them before my tests execute.

Zoom into the steps section to see "Creates environment variables" heading and configurations.

name: Playwright Tests on: push: branches: [main, master] pull_request: branches: [main, master] jobs: test: timeout-minutes: 60 runs-on: ubuntu-latest steps: - name: Creates environment variables run: | echo "API_BASE_URL: https://ws.audioscrobbler.com/2.0/" echo "API_KEY: abcdefghijklmnopqrstuvxyz" ...
  • The pipeline triggers are set to run this action on push and on pull request.
  • creates jobs called test
  • creates steps
    • uses actions checkout
    • users actions setup node, specifies version of 16
    • uses action pnpm, specifies version 7.14.1
    • Installs dependencies with pnpm
    • creates environment variables

Here is the completed file:

name: Playwright Tests on: push: branches: [main, master] pull_request: branches: [main, master] jobs: test: timeout-minutes: 60 runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: node-version: 16 - uses: pnpm/action-setup@v2 with: version: 7.14.1 - name: Install dependencies run: pnpm install - name: Install Playwright Browsers run: npx playwright install --with-deps - name: Creates environment variables run: | echo "API_BASE_URL: https://ws.audioscrobbler.com/2.0/" echo "API_KEY: abcdefghijklmnopqrstuvxyz" - name: Run Playwright tests run: pnpm dlx playwright test - uses: actions/upload-artifact@v3 if: always() with: name: playwright-report path: playwright-report/ retention-days: 30

And here is how the pipeline looks:

pipeline

Click here to see it live in Github.

I hope you enjoyed this whirlwind tour, concider sharing with your colleagues and friends.

Stay up to date

Consider keeping up to date with software development and design by signing up to my newsletter.

I will only email you when I make a new post.