sequelize / cli

The Sequelize CLI
MIT License
2.53k stars 525 forks source link

sequelize-cli db:migrate always using development environment #835

Open sujeet-agrahari opened 5 years ago

sujeet-agrahari commented 5 years ago

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.

savokiss commented 5 years ago

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

savokiss commented 5 years ago

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

JefferyHus commented 4 years ago

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

sujeet-agrahari commented 4 years ago

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;
braj011 commented 4 years ago

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!

JefferyHus commented 4 years ago

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.

actlikewill commented 4 years ago

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.

sujeet-agrahari commented 4 years ago

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"
  },
karlmacz-08 commented 3 years ago

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.

bitvilag commented 2 years ago

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

Paskid commented 1 year ago

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).