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 4 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
50 changes: 28 additions & 22 deletions packages/local-refresh/src/actions/CopyAppDistFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@ const phpAppDirectories = phpAppDirectoryNames.map((dir) => path.resolve(__dirna
export default class ResetDatabase 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,22 +53,26 @@ export default class ResetDatabase implements ActionInterface {
});
}

const { files } = await prompts({
type: "multiselect",
name: "files",
message: "Which config files do you want to copy?",
choices: Array.from(appConfigDistFiles.keys()).map((file) => ({
title: appConfigDistFiles.get(file) || file,
value: file,
})),
hint: "- Space to select. Return to submit",
});
if (!noInteraction) {
const { files } = await prompts({
type: "multiselect",
name: "files",
message: "Which config files do you want to copy?",
choices: Array.from(appConfigDistFiles.keys()).map((file) => ({
title: appConfigDistFiles.get(file) || file,
value: file,
})),
hint: "- Space to select. Return to submit",
});

if (!files) {
return false;
}

if (!files) {
return false;
this.filesToCopy = files;
}

this.filesToCopy = files;
this.filesToCopy = Array.from(appConfigDistFiles.keys());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would break the interactive version. Let's move the non-interactive version conditional to early exit after we have a list of files.

Something like this?

// ...
for (const dir of phpAppDirectories) {
  // ...
}

// ...
if (noInteraction) {
  this.filesToCopy = Array.from(appConfigDistFiles.keys());
}

// ...
const { files } = await prompts({
  // ...
});
// ...


return this.filesToCopy.length > 0;
}
Expand Down
6 changes: 5 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 Down
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
76 changes: 41 additions & 35 deletions packages/local-refresh/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,52 +16,58 @@
);
};

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; this will execute the following: composer install, copy app dist files (all), reset database (full), create liquibase.properties file, flush redis, and reset ldap.",
jerotire marked this conversation as resolved.
Show resolved Hide resolved
)
.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 {
await instance.execute(progressBarFactory());
} 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