Running scripts in Production

sibelius

Sibelius Seraphini

Posted on January 18, 2024

Running scripts in Production

Introduction

When operating software in production, you need to run some on-off scripts or migrations to consult or perform some manual tasks until they are automated somehow.
To make this possible and safe we made some improvements in our codebase.

.env.stg

When we need to run a script in staging, we have a special environment variable ENV_FILE, that let us customize what .env file to load:

ENV_FILE='.env.stg' yarn w path/to/script.ts
Enter fullscreen mode Exit fullscreen mode

yarn w is how we run our scripts, it uses webpack to bundle the script and run it using node.

Here is the implementation of ENV_FILE

import dotenvSafe from 'dotenv-safe';
import path from 'path';

import pkg from '../package.json';

const cwd = process.cwd();

const root = path.join.bind(cwd);

const getEnvFile = () => {
  if (process.env.ENV_FILE !== undefined) {
    return process.env.ENV_FILE;
  }

  return '.env';
};

const envFile = getEnvFile();

dotenvSafe.config({
  path: root(envFile),
  sample: root('.env.example'),
});

if (process.env.NODE_ENV === 'development') {
  // eslint-disable-next-line
  console.log('.env: ', path.join(cwd, envFile));
}
Enter fullscreen mode Exit fullscreen mode

It will also console.log what .env file it was loaded

Script Run Confirmation

Before running the script, we show some environment variables and ask to confirm

let rl: Interface | null = null;

export const ask = (question: string): Promise<string> => {
  if (!rl) {
    rl = readline.createInterface({ input, output });
  }

  return new Promise((resolve) => {
    rl.question(question, (answer) => resolve(answer));
  });
};


export const prompt = async () => {
  // eslint-disable-next-line
  console.log({
    MONGO_URI: config.MONGO_URI,
    REDIS_HOST: config.REDIS_HOST,
    APP_ENV: config.APP_ENV,
  });

  if (process.env.CONFIRM_PROMPT !== 'true') {
    return;
  }

  const answer = await ask('Run ? (y/n)');

  if (answer?.toLowerCase() !== 'y') {
    throw new Error('Aborted');
  }
};

Enter fullscreen mode Exit fullscreen mode

Confirmation

onlyLocalhost

We also have a function onlyLocalhost that we use in some scripts like seed or drop database that should never being run against staging or production environment.

export const onlyLocalhost = () => {
  if (
    config.MONGO_URI !== 'mongodb://localhost/woovi' &&
    config.MONGO_URI !==
      'mongodb://mongo1:27017,mongo2:27017/woovi?replicaSet=rs0'
  ) {
    throw new Error(`MONGO_URI is not localhost: ${config.MONGO_URI}`);
  }
}
Enter fullscreen mode Exit fullscreen mode

If we try to run a script with onlyLocalhost() against staging or production it will break the script from running.

In Short

Sometimes you can't avoid running a script in production to provide a quick fix for some unexpected behavior.
If you need to make this, try to add this tooling to make it fast, and avoid running DROP DATABASE in production.


Woovi
Woovi is a Startup that enables shoppers to pay as they like. To make this possible, Woovi provides instant payment solutions for merchants to accept orders.

If you want to work with us, we are hiring!


Image By vecstock

πŸ’– πŸ’ͺ πŸ™… 🚩
sibelius
Sibelius Seraphini

Posted on January 18, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related