blob: 77529bf3d365f0bb8f78ca3bf792de9681ac4e07 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
import {existsSync, writeFileSync, mkdirSync, unlinkSync} from 'fs';
import {createServer} from 'net';
import process from 'process';
import {program} from 'commander';
import {scan} from './scan.js';
import {watchAndDeploy, globalWatcher} from './watch.js';
import {setDryRun, deploy} from './deploy.js';
import {undeploy, setDryRun as setUndeployDryRun} from './undeploy.js';
import {build} from './client.js';
async function signalHandler() {
console.log('Termination requested.');
if (globalWatcher) {
console.log("☠️ SIGKILL - Stopping watcher");
await globalWatcher.close();
}
unlinkSync(expanduser('~/.ops/tmp/deploy.pid'));
process.kill(process.getpgrp(), 'SIGKILL');
process.exit(0); // should not be reached but just in case...
}
function checkPort() {
const server = createServer();
server.listen(8080, '127.0.0.1');
server.on('error', () => {
console.log('deployment mode already active (or something listening in 127.0.0.1:8080)');
server.close();
});
server.on('listening', () => server.close());
}
function expanduser(path) {
return path.replace(/^~(?=$|\/|\\)/, process.env.HOME || process.env.USERPROFILE);
}
async function main() {
const pid = process.pid;
process.on('SIGTERM', signalHandler);
process.on('SIGKILL', signalHandler);
const pidfile = expanduser('~/.ops/tmp/deploy.pid');
console.log('PID', pid);
mkdirSync(expanduser('~/.ops/tmp'), {recursive: true});
writeFileSync(pidfile, pid.toString());
program
.description('Deployer')
.argument('<directory>', 'The mandatory first argument')
.option('-n, --dry-run', 'Dry Run')
.option('-f, --fast', 'Fast deploy mode')
.option('-d, --deploy', 'Deploy')
.option('-w, --watch', 'Watch for changes')
.option('-s, --single <string>', 'Deploy a single action, either a single file or a directory.', '')
.option('-u, --undeploy', 'Undeploy actions and packages from the current project')
.parse(process.argv);
const options = program.opts();
const directory = program.args[0];
setDryRun(options.dryRun);
setUndeployDryRun(options.dryRun);
process.chdir(directory);
if (options.undeploy) {
// Undeploy actions and packages from the current project
let success;
if (options.single !== '') {
// If a single action is specified, undeploy just that action
let action = options.single;
if (!action.startsWith('packages/')) {
action = `packages/${action}`;
}
// Extract the package and action name
const parts = action.split('/');
if (parts.length >= 3) {
const pkg = parts[1];
const actionName = parts[2].split('.')[0]; // Remove file extension if present
success = undeploy(`${pkg}/${actionName}`);
} else {
// If the format is already package/action
success = undeploy(action);
}
} else {
// Otherwise, undeploy all actions and packages from the current project
success = undeploy();
}
if (!success) {
process.exit(1);
}
process.exit(0);
} else if (options.watch) {
checkPort();
if (!options.fast) {
await scan();
await build();
}
await watchAndDeploy();
} else if (options.deploy) {
await scan();
await build()
process.exit(0);
} else if (options.single !== '') {
let action = options.single;
if (!action.startsWith('packages/')) {
action = `packages/${action}`;
}
if (!existsSync(action)) {
console.log(`❌ action ${action} not found: must be either a file or a directory under packages`);
return;
}
console.log(`Deploying ${action}`);
await deploy(action);
process.exit(0);
} else {
program.help();
}
}
main().catch(err => {
console.error(err);
process.exit(1);
});
setInterval(() => {}, 1000);