Skip to content

Commit

Permalink
feat: add build command
Browse files Browse the repository at this point in the history
  • Loading branch information
remie committed Apr 20, 2024
1 parent ff345c6 commit a42b0d9
Show file tree
Hide file tree
Showing 6 changed files with 397 additions and 6 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"@rollup/plugin-json": "6.1.0",
"@rollup/plugin-node-resolve": "15.2.3",
"@rollup/plugin-terser": "0.4.4",
"@types/dockerode": "3.3.28",
"@types/js-yaml": "4",
"@types/node": "18.16.0",
"@types/pg": "8",
Expand All @@ -66,6 +67,7 @@
"chokidar": "3.6.0",
"commander": "12.0.0",
"docker-compose": "0.24.8",
"dockerode": "4.0.2",
"exit-hook": "4.0.0",
"fast-xml-parser": "4.3.6",
"js-yaml": "4.1.0",
Expand Down
109 changes: 109 additions & 0 deletions src/commands/build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/env node

import { watch } from 'chokidar';
import { Option, program } from 'commander';
import { asyncExitHook, gracefulExit } from 'exit-hook';
import { resolve } from 'path';
import { cwd } from 'process';

import { AMPS } from '../helpers/amps';
import { Docker } from '../helpers/docker';
import { getApplicationByName } from '../helpers/getApplication';
import { isRecursiveBuild } from '../helpers/isRecursiveBuild';
import { showRecursiveBuildWarning } from '../helpers/showRecursiveBuildWarning';

(async () => {
const options = program
.name('dcdx build')
.description('Build & install the Atlassian Data Center plugin from the current directory.\nYou can add Maven build arguments after the command options.')
.usage('[options] [...maven_arguments]')
.addOption(new Option('-w, --watch <patterns...>', 'Additional list of glob patterns used to watch for file changes'))
.addOption(new Option('-P, --activate-profiles <arg>', 'Comma-delimited list of profiles to activate'))
.addOption(new Option('-o, --outputDirectory <directory>', 'Output directory where QuickReload will look for generated JAR files').default('target'))
.allowUnknownOption(true)
.parse(process.argv)
.opts();

if (!AMPS.isAtlassianPlugin()) {
console.log('Unable to find an Atlassian Plugin project in the current directory 🤔');
gracefulExit();
}

const application = AMPS.getApplication();
if (!application) {
console.log('The Atlassian Plugin project does not contain an AMPS configuration, unable to detect product 😰');
gracefulExit();
process.exit();
}

const Application = getApplicationByName(application);
if (!Application) {
console.log('The Atlassian Plugin project does not contain an AMPS configuration, unable to detect product 😰');
process.exit();
}

const mavenOpts = program.args.slice();
if (options.activateProfiles) {
mavenOpts.push(...[ '-P', options.activateProfiles ]);
}

console.log(`Looking for running instances of ${application}`);
const containerIds = await Docker.getRunningContainerIds(application);
if (containerIds.length > 1) {
console.log(`There are multple running instance of ${application}, unable to determine which one to use`);
gracefulExit(0);
return;
}

const containerId = containerIds[0];
if (!containerId) {
console.log(`Could not find running instance of ${application}, please make sure they are running first!`);
gracefulExit(0);
return;
}

console.log('Watching filesystem for changes to source files (QuickReload)');
let lastBuildCompleted = new Date().getTime();
const patterns = Array.isArray(options.watch) ? options.watch : [ options.watch ];
const quickReload = watch([ '**/*', ...patterns ], {
cwd: cwd(),
usePolling: true,
interval: 2 * 1000,
binaryInterval: 2 * 1000,
awaitWriteFinish: true,
persistent: true,
atomic: true
});

asyncExitHook(async () => {
console.log(`Stopping filesystem watcher... ⏳`);
await quickReload.close();
console.log(`Successfully stopped all running processes 💪`);
}, { wait: 30 * 1000 });

quickReload.on('change', async (path) => {
if (path.startsWith(options.outputDirectory) && path.toLowerCase().endsWith('.jar')) {
console.log('Found updated JAR file, uploading them to QuickReload');
await Docker.copy(resolve(path), `${containerId}:/opt/quickreload/`)
.then(() => console.log('Finished uploading JAR file to QuickReload'))
.catch(err => console.log('Failed to upload JAR file to QuickReload', err));
lastBuildCompleted = new Date().getTime();
} else if (!path.startsWith(options.outputDirectory)) {
if (isRecursiveBuild(lastBuildCompleted)) {
showRecursiveBuildWarning(options.outputDirectory);
} else {
console.log('Detected file change, rebuilding Atlasian Plugin for QuickReload');
await AMPS.build(mavenOpts).catch(() => Promise.resolve());
}
}
});

await AMPS.build(mavenOpts).catch(() => Promise.resolve());
lastBuildCompleted = new Date().getTime();
})();

process.on('SIGINT', () => {
console.log(`Received term signal, trying to stop gracefully 💪`);
gracefulExit();
});

File renamed without changes.
31 changes: 31 additions & 0 deletions src/helpers/docker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { spawn } from 'child_process';
import Dockerode from 'dockerode';
import { cwd } from 'process';

import { SupportedApplications } from '../types/SupportedApplications';

const docker = new Dockerode();

export class Docker {

public static async getRunningContainerIds(application: SupportedApplications) {
const containers = await docker.listContainers({ filters: {
status: [ 'running' ],
label: [ `com.docker.compose.service=${application}` ]
}});
return containers.map(item => item.Id);
}

public static async copy(sourcePath: string, destinationPath:string) {
return new Promise<void>((resolve, reject) => {
const docker = spawn(
'docker',
[ 'cp', sourcePath, destinationPath ],
{ cwd: cwd(), stdio: 'inherit' }
);
docker.on('error', reject)
docker.on('exit', (code) => (code === 0) ? resolve() : reject(new Error(`Docker exited with code ${code}`)));
});
}

}
5 changes: 5 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ program
.version(version)
.showHelpAfterError(true);

// ------------------------------------------------------------------------------------------ Build

program
.command('build', 'Build & install the Atlassian Data Center plugin from the current directory', { executableFile: './commands/build.js' });

// ------------------------------------------------------------------------------------------ Start

program
Expand Down
Loading

0 comments on commit a42b0d9

Please sign in to comment.