myt/myvc-run.js

162 lines
4.7 KiB
JavaScript
Raw Normal View History

2020-12-02 07:35:26 +00:00
2020-12-04 16:30:26 +00:00
const MyVC = require('./myvc');
2020-12-02 07:35:26 +00:00
const docker = require('./docker');
2020-12-04 16:30:26 +00:00
const Container = require('./docker').Container;
2020-12-02 07:35:26 +00:00
const fs = require('fs-extra');
2020-12-04 09:15:29 +00:00
const path = require('path');
2020-12-02 07:35:26 +00:00
const Server = require('./server/server');
/**
* Builds the database image and runs a container. It only rebuilds the
* image when fixtures have been modified or when the day on which the
* image was built is different to today. Some workarounds have been used
* to avoid a bug with OverlayFS driver on MacOS.
*/
class Run {
get usage() {
return {
description: 'Build and start local database server container',
params: {
ci: 'Workaround for continuous integration system',
random: 'Whether to use a random container name or port'
}
};
}
get localOpts() {
2020-12-02 07:35:26 +00:00
return {
alias: {
2020-12-02 07:35:26 +00:00
ci: 'c',
random: 'r'
},
boolean: [
'ci',
'random'
]
2020-12-02 07:35:26 +00:00
};
}
async run(myvc, opts) {
const dumpDir = `${opts.myvcDir}/dump`;
2022-06-09 16:07:58 +00:00
const serverDir = path.join(__dirname, 'server');
// Fetch dump information
2020-12-05 21:50:45 +00:00
if (!await fs.pathExists(`${dumpDir}/.dump.sql`))
throw new Error('To run local database you have to create a dump first');
2020-12-02 07:35:26 +00:00
const dumpInfo = `${dumpDir}/.dump.json`;
if (await fs.pathExists(dumpInfo)) {
2020-12-04 09:15:29 +00:00
const cache = await myvc.cachedChanges();
2020-12-02 07:35:26 +00:00
const version = JSON.parse(
await fs.readFileSync(dumpInfo, 'utf8')
);
const changes = await myvc.changedRoutines(version.gitCommit);
2020-12-04 09:15:29 +00:00
let isEqual = false;
2020-12-04 16:30:26 +00:00
if (cache && changes && cache.length == changes.length)
2020-12-04 09:15:29 +00:00
for (let i = 0; i < changes.length; i++) {
isEqual = cache[i].path == changes[i].path
&& cache[i].mark == changes[i].mark;
if (!isEqual) break;
}
if (!isEqual) {
const fd = await fs.open(`${dumpDir}/.changes`, 'w+');
for (const change of changes)
fs.write(fd, change.mark + change.path + '\n');
await fs.close(fd);
}
2020-12-02 07:35:26 +00:00
}
2022-06-09 16:07:58 +00:00
// Build base server image
let serverDockerfile = path.join(dumpDir, 'Dockerfile');
if (!await fs.pathExists(serverDockerfile))
serverDockerfile = path.join(serverDir, 'Dockerfile.server');
2022-06-09 16:07:58 +00:00
await docker.build(__dirname, {
tag: 'myvc/server-base',
file: serverDockerfile
2022-06-09 16:07:58 +00:00
}, opts.debug);
// Build myvc server image
2022-06-09 16:07:58 +00:00
2020-12-02 07:35:26 +00:00
await docker.build(__dirname, {
tag: 'myvc/server',
file: path.join(serverDir, 'Dockerfile')
2020-12-04 09:15:29 +00:00
}, opts.debug);
2020-12-02 07:35:26 +00:00
2022-06-09 16:07:58 +00:00
// Build dump image
2020-12-02 07:35:26 +00:00
const today = new Date();
const pad = v => v < 10 ? '0' + v : v;
const year = today.getFullYear();
const month = pad(today.getMonth() + 1);
const day = pad(today.getDate());
const stamp = `${year}-${month}-${day}`;
await docker.build(opts.myvcDir, {
2020-12-04 09:15:29 +00:00
tag: opts.code,
2022-06-09 16:07:58 +00:00
file: path.join(serverDir, 'Dockerfile.dump'),
2020-12-02 07:35:26 +00:00
buildArg: `STAMP=${stamp}`
2020-12-04 09:15:29 +00:00
}, opts.debug);
2022-06-09 16:07:58 +00:00
// Run container
2020-12-04 09:15:29 +00:00
const isRandom = opts.random;
const dbConfig = Object.assign({}, opts.dbConfig);
2020-12-02 07:35:26 +00:00
let runOptions;
2020-12-04 09:15:29 +00:00
if (isRandom)
2020-12-02 07:35:26 +00:00
runOptions = {publish: '3306'};
else {
runOptions = {
2020-12-04 09:15:29 +00:00
name: opts.code,
publish: `3306:${dbConfig.port}`
2020-12-02 07:35:26 +00:00
};
try {
2020-12-04 16:30:26 +00:00
const server = new Server(new Container(opts.code));
await server.rm();
2020-12-02 07:35:26 +00:00
} catch (e) {}
}
const runChown = process.platform != 'linux';
Object.assign(runOptions, null, {
env: `RUN_CHOWN=${runChown}`,
detach: true
});
2020-12-04 09:15:29 +00:00
const ct = await docker.run(opts.code, null, runOptions);
const server = new Server(ct, dbConfig);
2020-12-02 07:35:26 +00:00
try {
2020-12-04 09:15:29 +00:00
if (isRandom) {
2020-12-02 07:35:26 +00:00
const netSettings = await ct.inspect({
2020-12-04 09:15:29 +00:00
format: '{{json .NetworkSettings}}'
2020-12-02 07:35:26 +00:00
});
if (opts.ci)
2020-12-04 09:15:29 +00:00
dbConfig.host = netSettings.Gateway;
2020-12-02 07:35:26 +00:00
2020-12-04 09:15:29 +00:00
dbConfig.port = netSettings.Ports['3306/tcp'][0].HostPort;
2020-12-02 07:35:26 +00:00
}
} catch (err) {
2020-12-04 09:15:29 +00:00
if (isRandom)
await server.rm();
2020-12-02 07:35:26 +00:00
throw err;
}
2020-12-04 09:15:29 +00:00
await server.wait();
return server;
2020-12-02 07:35:26 +00:00
}
}
module.exports = Run;
if (require.main === module)
new MyVC().run(Run);