Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add --no-interaction support to local refresh #266

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/local-refresh/src/actions/ActionInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default interface ActionInterface {
*
* @return {Promise<boolean>} Whether the action should be executed.
*/
prompt(): Promise<boolean>;
prompt(noInteraction: boolean): Promise<boolean>;

/**
* Execute the action.
Expand Down
6 changes: 5 additions & 1 deletion packages/local-refresh/src/actions/ComposerInstall.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ const phpAppDirectoryNames = ["api", "selfserve", "internal"];
const phpAppDirectories = phpAppDirectoryNames.map((dir) => path.resolve(__dirname, `../../../../app/${dir}`));

export default class ComposerInstall implements ActionInterface {
async prompt(): Promise<boolean> {
async prompt(noInteraction: boolean): Promise<boolean> {
if (noInteraction) {
return true;
}

const { shouldInstall } = await prompts({
type: "confirm",
name: "shouldInstall",
Expand Down
27 changes: 17 additions & 10 deletions packages/local-refresh/src/actions/CopyAppDistFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,21 @@ const debug = createDebug("refresh:actions:CopyAppDistFiles");
const phpAppDirectoryNames = ["api", "selfserve", "internal"];
const phpAppDirectories = phpAppDirectoryNames.map((dir) => path.resolve(__dirname, `../../../../app/${dir}`));

export default class ResetDatabase implements ActionInterface {
export default class CopyAppDistFiles implements ActionInterface {
filesToCopy: string[] = [];

async prompt(): Promise<boolean> {
const { shouldCopy } = await prompts({
type: "confirm",
name: "shouldCopy",
message: "Copy the Laminas configuration dist files?",
warn: "This will overwrite existing configuration files.",
});
async prompt(noInteraction: boolean): Promise<boolean> {
if (!noInteraction) {
const { shouldCopy } = await prompts({
type: "confirm",
name: "shouldCopy",
message: "Copy the Laminas configuration dist files?",
warn: "This will overwrite existing configuration files.",
});

if (!shouldCopy) {
return false;
if (!shouldCopy) {
return false;
}
}

let appConfigDistFiles: Map<string, string> = new Map();
Expand Down Expand Up @@ -51,6 +53,11 @@ export default class ResetDatabase implements ActionInterface {
});
}

if (noInteraction) {
this.filesToCopy = Array.from(appConfigDistFiles.keys());
return this.filesToCopy.length > 0;
}

const { files } = await prompts({
type: "multiselect",
name: "files",
Expand Down
8 changes: 7 additions & 1 deletion packages/local-refresh/src/actions/FlushRedis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import { GenericBar } from "cli-progress";
const debug = createDebug("refresh:actions:FlushRedis");

export default class FlushRedis implements ActionInterface {
async prompt(): Promise<boolean> {
async prompt(noInteraction: boolean): Promise<boolean> {
if (noInteraction) {
return true;
}

const { shouldFlush } = await prompts({
type: "confirm",
name: "shouldFlush",
Expand All @@ -23,6 +27,8 @@ export default class FlushRedis implements ActionInterface {

exec(`docker compose exec redis redis-cli -c "FLUSHALL"`, debug);

progress.increment(1);

progress.stop();
}
}
9 changes: 8 additions & 1 deletion packages/local-refresh/src/actions/ResetDatabase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,14 @@ export default class ResetDatabase implements ActionInterface {
liquibasePropertiesFileName = `vol-app.liquibase.properties`;
createLiquibaseProperties = false;

async prompt(): Promise<boolean> {
async prompt(noInteraction: boolean): Promise<boolean> {
if (noInteraction) {
this.refreshType = DatabaseRefreshEnum.FULL;
this.etlDirectory = cache.getKey("etlDirectory") || this.etlDirectory;
this.createLiquibaseProperties = true;
return true;
}

const { shouldResetDatabase, refreshType } = await prompts([
{
type: "confirm",
Expand Down
6 changes: 5 additions & 1 deletion packages/local-refresh/src/actions/ResetLdap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import { GenericBar } from "cli-progress";
const debug = createDebug("refresh:actions:ResetLdap");

export default class ResetLdap implements ActionInterface {
async prompt(): Promise<boolean> {
async prompt(noInteraction: boolean): Promise<boolean> {
if (noInteraction) {
return true;
}

const { shouldRefresh } = await prompts({
type: "confirm",
name: "shouldRefresh",
Expand Down
83 changes: 46 additions & 37 deletions packages/local-refresh/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,61 +7,70 @@ import chalk from "chalk";
import cliProgress from "cli-progress";
import ActionInterface from "./actions/ActionInterface";

const progressBarFactory = () => {
const progressBarFactory = (name: string) => {
return new cliProgress.Bar(
{
clearOnComplete: true,
format: `${name.padEnd(20)} | {bar} {percentage}% | ETA: {eta_formatted} | Step: {value}/{total}`,
autopadding: true,
clearOnComplete: false,
},
cliProgress.Presets.shades_classic,
);
};

program.description("Script to refresh the local VOL application").action(async () => {
const actions = await Promise.all(
fs
.readdirSync(path.resolve(__dirname, "actions"))
.filter((file) => file.endsWith(".ts") && !file.endsWith("Interface.ts"))
.map((file) => import(`./actions/${file}`)),
);
program
.description("Script to refresh the local VOL application")
.option(
"-i, --no-interaction",
"Run in non-interactive mode; Does not ask any interactive question. All the actions will run with defaults.",
)
.action(async (options) => {
const actions = await Promise.all(
fs
.readdirSync(path.resolve(__dirname, "actions"))
.filter((file) => file.endsWith(".ts") && !file.endsWith("Interface.ts"))
.map((file) => import(`./actions/${file}`)),
);

const isActionInterface = (action: any): action is ActionInterface => {
return "prompt" in action && "execute" in action;
};
const isActionInterface = (action: any): action is ActionInterface => {
return "prompt" in action && "execute" in action;
};

for (const action of actions) {
const instance = new action.default();
for (const action of actions) {
const instance = new action.default();

if (isActionInterface(instance) === false) {
console.warn(chalk.red(`Error: ${instance.name} does not implement ActionInterface`));
continue;
}
if (isActionInterface(instance) === false) {
console.warn(chalk.red(`Error: ${instance.name} does not implement ActionInterface`));
continue;
}

const shouldRun = await instance.prompt();
const shouldRun = await instance.prompt(!options.interaction);

if (shouldRun) {
try {
await instance.execute(progressBarFactory());
} catch (e: unknown) {
if (e instanceof Error) {
console.error(`\n\n${chalk.red(e.message)}\n`);
if (shouldRun) {
try {
const progressBar = progressBarFactory(instance.constructor.name);
await instance.execute(progressBar);
} catch (e: unknown) {
if (e instanceof Error) {
console.error(`\n\n${chalk.red(e.message)}\n`);
}
}
}
}
}

const hostsFile = fs.readFileSync("/etc/hosts", "utf8");
const hostsFile = fs.readFileSync("/etc/hosts", "utf8");

if (!hostsFile.includes("local.olcs.dev-dvsacloud.uk")) {
console.warn(chalk.yellow(`/etc/hosts has not been updated with the local domains. Please run:`));
console.warn(
chalk.bgYellow(
`sudo echo "127.0.0.1 iuweb.local.olcs.dev-dvsacloud.uk ssweb.local.olcs.dev-dvsacloud.uk api.local.olcs.dev-dvsacloud.uk cdn.local.olcs.dev-dvsacloud.uk" >> /etc/hosts`,
),
);
}
if (!hostsFile.includes("local.olcs.dev-dvsacloud.uk")) {
Dismissed Show dismissed Hide dismissed
console.warn(chalk.yellow(`/etc/hosts has not been updated with the local domains. Please run:`));
console.warn(
chalk.bgYellow(
`sudo echo "127.0.0.1 iuweb.local.olcs.dev-dvsacloud.uk ssweb.local.olcs.dev-dvsacloud.uk api.local.olcs.dev-dvsacloud.uk cdn.local.olcs.dev-dvsacloud.uk" >> /etc/hosts`,
),
);
}

process.exit(0);
});
process.exit(0);
});

program.parse(process.argv);

Expand Down