cli icon indicating copy to clipboard operation
cli copied to clipboard

sequelize-cli db:migrate always using development environment

Open sujeet-agrahari opened this issue 4 years ago • 11 comments

I am using dotenv package. I reuire the package on top. I also tried changing "development" to "test" or "production", but still It's always using "development".

'use strict';
require('dotenv').config({path:'../../.env'})
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development'; // I tried changing 'development' to 'production' and 'test'
const config = require(__dirname + '/../config/config.json')[env];
const db = {};
let sequelize;
console.log(env)
if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
  console.log(config)
  sequelize = new Sequelize(config.database, config.username, config.password, config);
}

fs
  .readdirSync(__dirname)
  .filter(file => {
    return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
  })
  .forEach(file => {
    const model = sequelize['import'](path.join(__dirname, file));
    db[model.name] = model;
  });

Object.keys(db).forEach(modelName => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

Here is my .env file

//set environment for different configurations 
NODE_ENV=test

//define port
PORT=4000

NODE_CONFIG_DIR =./src/config

When I run the server, then It uses test environment.

sujeet-agrahari avatar Oct 09 '19 04:10 sujeet-agrahari

Same as u, I was wonder how to migrate db to testing server

savokiss avatar Oct 21 '19 10:10 savokiss

Oops, I just use this npx sequelize db:migrate --env testing

savokiss avatar Oct 21 '19 10:10 savokiss

You can just do this all time --env production, but I don't like it this way. It would make sense to just let things works as it should and use my .env file instead

JefferyHus avatar Dec 12 '19 18:12 JefferyHus

Yes, exactly. I don't want passing the parameter all the time, instead, It should pick the appropriate configurations as defined in .env file. NODE_ENV = test In below file, as you can see it is checking for if NODE_ENV is set, if not use development. Even I am getting this error.

WARNING: NODE_ENV value of 'test' did not match any deployment config file names.

Below is the configurations

  "test": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql",
    "operatorsAliases": false
  },

But why it is using development always, developer of this package should answer

'use strict';

const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require(__dirname + '/../config/config.json')[env];
const db = {};

let sequelize;
if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
  config.define = {
    "createdAt":"created_on",
    "updatedAt":"updated_on"
  }
  sequelize = new Sequelize(config.database, config.username, config.password, config);
}

fs
  .readdirSync(__dirname)
  .filter(file => {
    return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
  })
  .forEach(file => {
    const model = sequelize['import'](path.join(__dirname, file));
    db[model.name] = model;
  });

Object.keys(db).forEach(modelName => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

sujeet-agrahari avatar Feb 17 '20 05:02 sujeet-agrahari

Yep, I have the same problem too.

I am running 'sequelize db:migrate --env test' to get my test database up-to-date - it'll be a fairly infrequent action, so it's not terrible, but definitely not the best way to go about this.

Did anyone figure this out? Thanks!

braj011 avatar Apr 23 '20 19:04 braj011

The workaround that I found working is, I run a JS file to initiate my NODE_ENV and then I run the sequelize cli migration and it works. Having that said, if your server is running and you init your ENV variables, then surely sequelize will pick the correct value.

Also try to use JS configuration file instead of JSON, there you can load your .env and have it working as you like.

JefferyHus avatar Apr 23 '20 22:04 JefferyHus

Phew! I have found the solution. You have to set the environment variables in the current shell.

Run

export DATABASE_URL=path_to_your_database

to export your variables one at a time. I am using bash with linux. Better still, you can have another .env file and name it .env.local or .env.test and add the variables with the export keyword for example:

export DATABASE_URL=path_to_your_database
export NODE_ENV=development_or_test
export ANOTHER_VARIABLE=another variable

With that you can run

source .env.local

in the terminal and all the variables will be set. You can now run your migrations.

actlikewill avatar May 05 '20 14:05 actlikewill

I have to do something like this in my package.json file.

 "scripts": {
    "test": "env NODE_ENV=test nyc mocha --recursive --exit --timeout 100000",
    "start": "env NODE_ENV=development nodemon -L server.js"
  },

sujeet-agrahari avatar May 18 '20 06:05 sujeet-agrahari

For those who doesn't want to touch NODE_ENV and/or always use .env file, the approach I used for this issue is create a JS file that contains functions that will execute commands for me.

migration.js

require('dotenv').config();

const { exec } = require('child_process');

module.exports = {
  migrate: () => {
    exec(`npx sequelize db:migrate --env ${process.env.APP_ENV}`, (err, stdout, stderr) => {
      if (err) {
        console.error(`${stdout}`);
      }
    
      console.log(`${stdout}`);
      console.warn(`${stderr}`);
    });
  },
  migrateRollback: () => {
    exec(`npx sequelize db:migrate:undo --env ${process.env.APP_ENV}`, (err, stdout, stderr) => {
      if (err) {
        console.error(`${stdout}`);
      }
    
      console.log(`${stdout}`);
      console.warn(`${stderr}`);
    });
  },
  migrateReset: () => {
    exec(`npx sequelize db:migrate:undo:all --env ${process.env.APP_ENV}`, (err, stdout, stderr) => {
      if (err) {
        console.error(`${stdout}`);
      }
    
      console.log(`${stdout}`);
      console.warn(`${stderr}`);
    });
  }
};

then add scripts in package.json

{
  ...
  
  "scripts": {
    "migrate": "node -e \"require('./migration').migrate()\"",
    "migrate:rollback": "node -e \"require('./migration').migrateRollback()\"",
    "migrate:reset": "node -e \"require('./migration').migrateReset()\""
  }
  
  ...
}

Although it's quite a setup, this approach works well for me because now I only need to update the APP_ENV variable in my .env file.

karl-macz-08 avatar Jul 17 '21 15:07 karl-macz-08

I have same issue, I expect NODE_ENV to work, but sequelize ignores it. Any update when this will be fixed?

bitvilag avatar Dec 24 '21 00:12 bitvilag

I had the same issue and managed to make sequelize use my environment variables by using this config:

import dotenv from 'dotenv';
dotenv.config();

export default {
  "development": {
    "use_env_variable": "DATABASE_URL",
    "dialect": "postgresql"
  },
  "test": {
    "use_env_variable": "DATABASE_URL",
    "dialect": "postgresql",
    "logging": false
  },
  "production": {
    "use_env_variable": "DATABASE_URL",
    "dialect": "postgresql",
    "logging": false
  }
};

It seems sequelize doesn't read the environment variables itself so I had to make him do it.

I can confirm it reads the values fine from my .env file when running sequelize db:migrate.

Now the only problem I have is that using an URL still tries to connect to a local DB even if the URL points to an AWS bucket. (but that's a whole other issue).

Paskid avatar Feb 24 '23 14:02 Paskid