cli/src/build/repository/build.ts

152 lines
4.2 KiB
TypeScript

import { PluginMetaLoader } from '@squeebot/core/lib/plugin';
import { takeChecksum } from '@squeebot/core/lib/util';
import fs from 'fs-extra';
import path from 'path';
import tar from 'tar';
import { defaultEnvironment } from '../default/environment.default';
import { execute } from '../execute';
import { REPOSITORY_SCHEMA } from './constants';
import { deploy } from './deploy';
/**
* Build repository ready for deployment
* @param location Repository location
* @param out Create output files for deployment (false - only compile tsc in-place)
* @param doDeploy Deployment name
* @param onlyDeploy Deploy only without building
*/
export async function buildRepository(
location?: string,
out = true,
doDeploy?: string,
onlyDeploy = false
): Promise<void> {
if (!location) {
location = process.cwd();
}
location = path.resolve(process.cwd(), location);
const outDir = path.join(location, '.out');
// Check for repository metadata
const buildMetaFile = path.join(location, 'squeebot.repo.json');
if (!await fs.pathExists(buildMetaFile)) {
throw new Error(`${location} is not a valid squeebot repository development environment!`);
}
// Read repository metadata
const meta = await fs.readJson(buildMetaFile);
const env = defaultEnvironment(location);
env.pluginsPath = location;
if (!meta.name) {
throw new Error(`${location} is not a valid squeebot repository development environment!`);
}
console.log('Detected repository "%s"!', meta.name);
if (onlyDeploy) {
if (!await fs.pathExists(outDir)) {
throw new Error('You need to build before deploying!');
} else {
return deploy(meta.name, location, outDir, doDeploy as string);
}
}
// Run typescript build
if (meta.typescript) {
console.log('Running build task..');
await execute(['npm', 'run', 'build'], location);
}
console.log('Detecting plugins in this environment..');
const loader = new PluginMetaLoader(env);
const plugins = await loader.loadAll(false);
console.log('Found the following plugins:', plugins.map((plugin) => {
return `${plugin.name}@${plugin.version}`;
}).join(', '));
const savedList = plugins.map((plugin) => ({
name: plugin.name,
version: plugin.version,
}));
meta.plugins = savedList;
await fs.writeJson(buildMetaFile, meta, { spaces: 2 });
if (!out) {
console.log('Done!');
return;
}
await fs.remove(outDir);
await fs.ensureDir(outDir);
console.log('Copying plugins');
for (const plugin of plugins) {
const src = path.join(location, plugin.name);
const dst = path.join(outDir, plugin.name);
await fs.copy(src, dst);
}
if (meta.typescript) {
console.log('Stripping TypeScript source files');
for (const plugin of plugins) {
const plOut = path.join(outDir, plugin.name);
const listAllFiles = await fs.readdir(plOut);
for (const f of listAllFiles) {
if (f.match(/(\.d)?\.ts$/i) != null) {
await fs.remove(path.join(plOut, f));
}
}
}
}
console.log('Copying configuration schemas');
for (const plugin of plugins) {
const plOut = path.join(outDir, plugin.name);
const schemaFile = path.join(plOut, 'schema.json');
const outSchemaFile = path.join(outDir, `${plugin.name}.schema.json`);
if (await fs.pathExists(schemaFile)) {
await fs.copy(schemaFile, outSchemaFile);
}
}
console.log('Creating tarballs');
for (const plugin of plugins) {
const plOut = path.join(outDir, plugin.name);
const fileName = `${plOut}.plugin.tgz`;
await tar.c({
gzip: true,
file: fileName,
C: outDir,
}, [plugin.name]);
// Create checksum of tarball
const checksum = await takeChecksum(fileName);
const metaPlugin = meta.plugins.find((item: { name: string }) => item.name === plugin.name);
if (metaPlugin && checksum) {
metaPlugin.checksum = checksum;
}
}
console.log('Creating repository index');
await fs.writeJSON(path.join(outDir, 'repository.json'), {
created: Math.floor(Date.now() / 1000),
name: meta.name,
plugins: meta.plugins,
$schema: REPOSITORY_SCHEMA,
});
if (doDeploy == null) {
console.log('Done!');
return;
}
deploy(meta.name, location, outDir, doDeploy);
}