148 строки
4.2 KiB
JavaScript
148 строки
4.2 KiB
JavaScript
const fs = require("fs");
|
|
const { execSync } = require(`child_process`);
|
|
|
|
const deleteDatabase = process.argv.includes(`--delete`);
|
|
const silent = { stdio: [`ignore`, `ignore`, `ignore`] };
|
|
const PROD_APP = `foundation-mozilla-org`;
|
|
const STAGE_APP = `foundation-mofostaging-net`;
|
|
const APP = process.argv.includes(`--prod`) ? PROD_APP : STAGE_APP;
|
|
|
|
if (APP === STAGE_APP) {
|
|
console.log(
|
|
`Running db copy for staging, run with --prod to run for production`
|
|
);
|
|
}
|
|
|
|
if (!isLoggedInToHeroku()) {
|
|
console.log(
|
|
"You are not logged into Heroku. Make sure you have the Heroku CLI installed. Run `heroku login` and try again."
|
|
);
|
|
process.exit(1);
|
|
}
|
|
|
|
const HEROKU_OUTPUT = run(`heroku config:get DATABASE_URL -a ${APP}`);
|
|
const HEROKU_TEXT = HEROKU_OUTPUT.toString().replaceAll(`\n`, ` `);
|
|
const URL_START = HEROKU_TEXT.indexOf(`postgres://`);
|
|
const DATABASE_URL = HEROKU_TEXT.substring(URL_START).trim();
|
|
const ROLE = DATABASE_URL.match(/postgres:\/\/([^:]+):/)[1];
|
|
const DUMP_FILE = `${ROLE}.db.archive`;
|
|
const DB_FLAGS = `-hpostgres -Ufoundation`;
|
|
|
|
/**
|
|
* Exec a command and return its output as plain string
|
|
*/
|
|
function run(cmd, ignoreThrows = false, opts = {}) {
|
|
try {
|
|
return execSync(cmd, opts).toString();
|
|
} catch (e) {
|
|
if (ignoreThrows) return e.toString();
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Run a command in the postgres docker container
|
|
*/
|
|
function postgres(cmd, ignoreThrows = false) {
|
|
cmd = `docker exec ${IMAGE_NAMES.POSTGRES} ${cmd}`;
|
|
return run(cmd, ignoreThrows);
|
|
}
|
|
|
|
function getContainerNames() {
|
|
return run(`docker ps`)
|
|
.split(`\n`)
|
|
.map((v) => v.match(/\s(\S+)$/g))
|
|
.filter(Boolean)
|
|
.map((v) => v[0].trim())
|
|
.reduce((a, v) => {
|
|
if (!v) return a;
|
|
if (v.includes(`backend`)) a.BACKEND = v;
|
|
if (v.includes(`postgres`)) a.POSTGRES = v;
|
|
return a;
|
|
}, {});
|
|
}
|
|
|
|
function stopContainers() {
|
|
const IMAGE_NAMES = getContainerNames();
|
|
|
|
const backend = IMAGE_NAMES.BACKEND;
|
|
if (backend) {
|
|
console.log(`Stopping ${backend}`);
|
|
run(`docker stop ${backend}`, true, silent);
|
|
}
|
|
|
|
const postgres = IMAGE_NAMES.POSTGRES;
|
|
if (postgres) {
|
|
console.log(`Stopping ${postgres}`);
|
|
run(`docker stop ${postgres}`, true, silent);
|
|
}
|
|
}
|
|
|
|
function isLoggedInToHeroku() {
|
|
try {
|
|
execSync("heroku whoami");
|
|
return true;
|
|
} catch (error) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// ======================== //
|
|
// Our script starts here //
|
|
// ======================== //
|
|
|
|
console.log(`Making sure no docker containers are running...`);
|
|
stopContainers();
|
|
|
|
console.log(`Starting postgres docker image...`);
|
|
run(`docker-compose up -d postgres`, true, silent);
|
|
|
|
console.log(`Starting backend docker image...`);
|
|
run(`docker-compose up -d backend`, true, silent);
|
|
|
|
console.log(`Getting running image names...`);
|
|
const IMAGE_NAMES = getContainerNames();
|
|
|
|
if (!fs.existsSync(DUMP_FILE)) {
|
|
console.log(`Downloading ${APP} database (this may take a while)...`);
|
|
postgres(`pg_dump -F c ${DATABASE_URL} > ${DUMP_FILE}`);
|
|
} else {
|
|
console.log(`Found local ${APP} database file, skipping download...`);
|
|
}
|
|
|
|
console.log(`Resetting db...`);
|
|
postgres(`dropdb ${DB_FLAGS} --if-exists wagtail --force`);
|
|
postgres(`createdb ${DB_FLAGS} wagtail`);
|
|
|
|
console.log(`Building user roles...`);
|
|
[ROLE, `datastudio`, `datagrip-cade`].forEach((role) =>
|
|
postgres(`createuser ${DB_FLAGS} -s ${role}`, true)
|
|
);
|
|
|
|
console.log(`Importing database snapshot...`);
|
|
run(`docker cp ${DUMP_FILE} ${IMAGE_NAMES.POSTGRES}:/`);
|
|
// Based on the Heroku docs for restoring to local database:
|
|
// https://devcenter.heroku.com/articles/heroku-postgres-import-export#restore-to-local-database
|
|
postgres(`pg_restore ${DB_FLAGS} -dwagtail --no-acl --no-owner ${DUMP_FILE}`);
|
|
|
|
console.log(`Updating site bindings...`);
|
|
run(`inv manage fix_local_site_bindings`, true, silent);
|
|
|
|
console.log(`Creating admin:admin superuser account...`);
|
|
run(`inv createsuperuser`, true, silent);
|
|
|
|
console.log(`Migrating database to match current branch migrations...`);
|
|
run(
|
|
`docker exec ${IMAGE_NAMES.BACKEND} ./dockerpythonvenv/bin/python network-api/manage.py migrate`
|
|
);
|
|
|
|
console.log(`Stopping docker images...`);
|
|
run(`docker-compose down`, true, silent);
|
|
|
|
if (deleteDatabase) {
|
|
console.log(`Running cleanup`);
|
|
fs.unlinkSync(DUMP_FILE);
|
|
}
|
|
|
|
console.log(`All done.`);
|