Skip to content
Merged
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
29 changes: 17 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ USAGE
* [`codify plugins`](#codify-plugins)
* [`codify plugins:install PLUGIN...`](#codify-pluginsinstall-plugin)
* [`codify plugins:inspect PLUGIN...`](#codify-pluginsinspect-plugin)
* [`codify plugins:install PLUGIN...`](#codify-pluginsinstall-plugin-1)
* [`codify plugins:install PLUGIN...`](#codify-pluginsinstall-plugin)
* [`codify plugins:link PLUGIN`](#codify-pluginslink-plugin)
* [`codify plugins:uninstall PLUGIN...`](#codify-pluginsuninstall-plugin)
* [`codify plugins:uninstall PLUGIN...`](#codify-pluginsuninstall-plugin-1)
* [`codify plugins:uninstall PLUGIN...`](#codify-pluginsuninstall-plugin-2)
* [`codify plugins:uninstall PLUGIN...`](#codify-pluginsuninstall-plugin)
* [`codify plugins:uninstall PLUGIN...`](#codify-pluginsuninstall-plugin)
* [`codify plugins update`](#codify-plugins-update)
* [`codify uninstall`](#codify-uninstall)

Expand All @@ -47,7 +47,7 @@ describe the command here

```
USAGE
$ codify apply [FILE] [--json] [-o plain|default|debug|json] [--debug] [-p <value>]
$ codify apply [FILE] [--json] [--debug] [-o plain|default|debug|json] [-s] [-p <value>]

ARGUMENTS
FILE file to read
Expand All @@ -56,6 +56,7 @@ FLAGS
-o, --output=<option> [default: default]
<options: plain|default|debug|json>
-p, --path=<value> path to project
-s, --secure
--debug

GLOBAL FLAGS
Expand Down Expand Up @@ -97,7 +98,7 @@ describe the command here

```
USAGE
$ codify plan [FILE] [--json] [-o plain|default|debug|json] [--debug] [-f] [-n <value>] [-p <value>]
$ codify plan [FILE] [--json] [--debug] [-o plain|default|debug|json] [-s] [-f] [-n <value>] [-p <value>]

ARGUMENTS
FILE file to read
Expand All @@ -108,6 +109,7 @@ FLAGS
-o, --output=<option> [default: default]
<options: plain|default|debug|json>
-p, --path=<value> path to project
-s, --secure
--debug

GLOBAL FLAGS
Expand Down Expand Up @@ -143,7 +145,7 @@ EXAMPLES
$ codify plugins
```

_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v3.9.4/src/commands/plugins/index.ts)_
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v3.10.1/src/commands/plugins/index.ts)_

## `codify plugins:install PLUGIN...`

Expand Down Expand Up @@ -208,7 +210,8 @@ EXAMPLES
$ codify plugins:inspect myplugin
```

_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v3.9.4/src/commands/plugins/inspect.ts)_
_See
code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v3.10.1/src/commands/plugins/inspect.ts)_

## `codify plugins:install PLUGIN...`

Expand Down Expand Up @@ -248,7 +251,8 @@ EXAMPLES
$ codify plugins:install someuser/someplugin
```

_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v3.9.4/src/commands/plugins/install.ts)_
_See
code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v3.10.1/src/commands/plugins/install.ts)_

## `codify plugins:link PLUGIN`

Expand Down Expand Up @@ -278,7 +282,7 @@ EXAMPLES
$ codify plugins:link myplugin
```

_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v3.9.4/src/commands/plugins/link.ts)_
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v3.10.1/src/commands/plugins/link.ts)_

## `codify plugins:uninstall PLUGIN...`

Expand Down Expand Up @@ -327,7 +331,7 @@ ALIASES
```

_See
code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v3.9.4/src/commands/plugins/uninstall.ts)_
code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v3.10.1/src/commands/plugins/uninstall.ts)_

## `codify plugins:uninstall PLUGIN...`

Expand Down Expand Up @@ -368,19 +372,20 @@ DESCRIPTION
Update installed plugins.
```

_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v3.9.4/src/commands/plugins/update.ts)_
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v3.10.1/src/commands/plugins/update.ts)_

## `codify uninstall`

describe the command here

```
USAGE
$ codify uninstall [--json] [-o plain|default|debug|json] [--debug]
$ codify uninstall [--json] [--debug] [-o plain|default|debug|json] [-s]

FLAGS
-o, --output=<option> [default: default]
<options: plain|default|debug|json>
-s, --secure
--debug

GLOBAL FLAGS
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"ajv": "^8.12.0",
"ajv-formats": "^3.0.1",
"chalk": "^5.3.0",
"codify-schemas": "1.0.37",
"codify-schemas": "1.0.38",
"debug": "^4.3.4",
"ink": "^4.4.1",
"parse-json": "^8.1.0",
Expand Down
2 changes: 1 addition & 1 deletion src/commands/apply/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default class Apply extends BaseCommand {

const resolvedPath = path.resolve(flags.path ?? '.');

const planResult = await PlanOrchestrator.run(resolvedPath);
const planResult = await PlanOrchestrator.run(resolvedPath, flags.secure);
this.reporter.displayPlan(planResult.plan);

// Short circuit and exit if every change is NOOP
Expand Down
2 changes: 1 addition & 1 deletion src/commands/plan/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default class Plan extends BaseCommand {

const resolvedPath = path.resolve(flags.path ?? '.');

const { plan } = await PlanOrchestrator.run(resolvedPath);
const { plan } = await PlanOrchestrator.run(resolvedPath, flags.secure);
this.reporter.displayPlan(plan);

process.exit(0);
Expand Down
8 changes: 3 additions & 5 deletions src/commands/uninstall.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { UninstallOrchestrator } from '../orchestrators/uninstall.js';
import { BaseCommand } from '../common/base-command.js';
import { UninstallOrchestrator } from '../orchestrators/uninstall.js';

export default class Uninstall extends BaseCommand {
static description = 'describe the command here'
Expand All @@ -8,12 +8,10 @@ export default class Uninstall extends BaseCommand {
'<%= config.bin %> <%= command.id %>',
]

static flags = {}

static strict = false;

public async run(): Promise<void> {
const { raw } = await this.parse(Uninstall)
const { flags, raw } = await this.parse(Uninstall)

const args = raw
.filter((r) => r.type === 'arg')
Expand All @@ -23,7 +21,7 @@ export default class Uninstall extends BaseCommand {
throw new Error('A resource id must be specified for uninstall. Ex: "codify uninstall homebrew"')
}

await UninstallOrchestrator.run(args);
await UninstallOrchestrator.run(args, flags.secure);

process.exit(0);
}
Expand Down
23 changes: 19 additions & 4 deletions src/common/base-command.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Command, Flags } from '@oclif/core';
import { FlagOutput } from '@oclif/core/lib/interfaces/parser.js';
import chalk from 'chalk';
import { SudoRequestData } from 'codify-schemas';
import createDebug from 'debug';

import { ctx, Event } from '../events/context.js';
Expand All @@ -15,7 +16,11 @@ export abstract class BaseCommand extends Command {
char: 'o',
default: 'default',
options: ['plain', 'default', 'debug', 'json'],
})()
})(),
'secure': Flags.boolean({
char: 's',
default: false,
})
}

protected reporter!: Reporter;
Expand All @@ -31,9 +36,19 @@ export abstract class BaseCommand extends Command {
const reporterType = this.getReporterType(flags);
this.reporter = ReporterFactory.create(reporterType)

ctx.on(Event.SUDO_REQUEST, async (pluginName: string, command: string) => {
await this.reporter.promptSudo(pluginName, command);
ctx.sudoRequestGranted(pluginName);
if (flags.secure) {
console.log(chalk.blue('Running Codify in secure mode. Sudo will be prompted every time'));
}

ctx.on(Event.SUDO_REQUEST, async (pluginName: string, data: SudoRequestData) => {
try {
const result = await this.reporter.promptSudo(pluginName, data, flags.secure);
ctx.sudoRequestGranted(pluginName, result);

// This listener is outside of the base-command callstack. We have to manually catch the error.
} catch (error) {
this.catch(error as Error);
}
});
}

Expand Down
4 changes: 2 additions & 2 deletions src/common/orchestrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { ctx, SubProcessName } from '../events/context.js';
import { DependencyMap, PluginCollection } from '../plugins/plugin-collection.js';

export const CommonOrchestrator = {
async initializePlugins(project?: Project): Promise<{
async initializePlugins(project?: Project, secureMode = false): Promise<{
dependencyMap: DependencyMap
pluginCollection: PluginCollection,
}> {
ctx.subprocessStarted(SubProcessName.INITIALIZE_PLUGINS)
const pluginCollection = new PluginCollection();
const dependencyMap = await pluginCollection.initialize(project);
const dependencyMap = await pluginCollection.initialize(project, secureMode);
ctx.subprocessFinished(SubProcessName.INITIALIZE_PLUGINS)

return { dependencyMap, pluginCollection };
Expand Down
30 changes: 16 additions & 14 deletions src/events/context.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
import type { SudoRequestData, SudoRequestResponseData } from 'codify-schemas';

import { EventEmitter } from 'node:events';

export enum Event {
STDOUT = 'stdout',
STDERR = 'stderr',
PLUGIN_STDOUT = 'plugin_stdout',
PLUGIN_STDERR = 'plugin_stderr',
DEBUG = 'debug',
OUTPUT = 'output',
PROCESS_START = 'process_start',
PLUGIN_STDERR = 'plugin_stderr',
PLUGIN_STDOUT = 'plugin_stdout',
PROCESS_FINISH = 'process_finish',
SUB_PROCESS_START = 'sub_process_start',
PROCESS_START = 'process_start',
STDERR = 'stderr',
STDOUT = 'stdout',
SUB_PROCESS_FINISH = 'sub_process_finish',
SUB_PROCESS_START = 'sub_process_start',
SUDO_REQUEST = 'sudo_request',
SUDO_REQUEST_GRANTED = 'sudo_request_granted',
}

export enum ProcessName {
PLAN = 'plan',
APPLY = 'apply',
PLAN = 'plan',
UNINSTALL = 'uninstall',
}

export enum SubProcessName {
PARSE = 'parse',
APPLYING_RESOURCE = 'apply_resource',
GENERATE_PLAN = 'generate_plan',
INITIALIZE_PLUGINS = 'initialize_plugins',
PARSE = 'parse',
VALIDATE = 'validate',
GENERATE_PLAN = 'generate_plan',
APPLYING_RESOURCE = 'apply_resource',
}

export const ctx = new class {
Expand Down Expand Up @@ -79,12 +81,12 @@ export const ctx = new class {
this.emitter.emit(Event.SUB_PROCESS_FINISH, name, additionalName);
}

sudoRequested(pluginName: string, command: string) {
this.emitter.emit(Event.SUDO_REQUEST, pluginName, command);
sudoRequested(pluginName: string, data: SudoRequestData) {
this.emitter.emit(Event.SUDO_REQUEST, pluginName, data);
}

sudoRequestGranted(pluginName: string) {
this.emitter.emit(Event.SUDO_REQUEST_GRANTED, pluginName);
sudoRequestGranted(pluginName: string, data: SudoRequestResponseData) {
this.emitter.emit(Event.SUDO_REQUEST_GRANTED, pluginName, data);
}

async subprocess<T>(name: string, run: () => Promise<T>): Promise<T> {
Expand Down
4 changes: 2 additions & 2 deletions src/orchestrators/plan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export interface PlanOrchestratorResponse {
}

export const PlanOrchestrator = {
async run(path: string): Promise<PlanOrchestratorResponse> {
async run(path: string, secureMode: boolean): Promise<PlanOrchestratorResponse> {
ctx.processStarted(ProcessName.PLAN)

ctx.subprocessStarted(SubProcessName.PARSE);
Expand All @@ -24,7 +24,7 @@ export const PlanOrchestrator = {
project.addXCodeToolsConfig();
ctx.subprocessFinished(SubProcessName.PARSE);

const { dependencyMap, pluginCollection } = await CommonOrchestrator.initializePlugins(project);
const { dependencyMap, pluginCollection } = await CommonOrchestrator.initializePlugins(project, secureMode);
await createStartupShellScriptsIfNotExists();

ctx.subprocessStarted(SubProcessName.VALIDATE)
Expand Down
6 changes: 3 additions & 3 deletions src/orchestrators/uninstall.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { PlanResponseData, ResourceOperation } from 'codify-schemas';
import { randomUUID } from 'node:crypto';

import { CommonOrchestrator } from '../common/orchestrator.js';
import { ctx, ProcessName } from '../events/context.js';
import { createStartupShellScriptsIfNotExists } from '../utils/file.js';
import { CommonOrchestrator } from '../common/orchestrator.js';

export const UninstallOrchestrator = {
async run(typeIds: string[]): Promise<void> {
async run(typeIds: string[], secureMode: boolean): Promise<void> {
if (typeIds.length === 0) {
return;
}
Expand All @@ -18,7 +18,7 @@ export const UninstallOrchestrator = {
resourceType: type,
} as PlanResponseData))

const { pluginCollection } = await CommonOrchestrator.initializePlugins();
const { pluginCollection } = await CommonOrchestrator.initializePlugins(undefined, secureMode);
await createStartupShellScriptsIfNotExists();

ctx.processStarted(ProcessName.UNINSTALL);
Expand Down
8 changes: 4 additions & 4 deletions src/plugins/plugin-collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ export class PluginCollection {
private resourceToPluginMapping = new Map<string, string>()
private pluginToResourceMapping = new Map<string, string[]>()

async initialize(project?: Project): Promise<Map<string, string[]>> {
async initialize(project?: Project, secureMode = false): Promise<Map<string, string[]>> {
const plugins = await this.resolvePlugins(project);

for (const plugin of plugins) {
this.plugins.set(plugin.name, plugin)
}

const dependencyMap = await this.initializePlugins(plugins);
const dependencyMap = await this.initializePlugins(plugins, secureMode);
return dependencyMap;
}

Expand Down Expand Up @@ -93,10 +93,10 @@ export class PluginCollection {
return [...existingPlugins, ...configPlugins];
}

private async initializePlugins(plugins: Plugin[]): Promise<Map<string, string[]>> {
private async initializePlugins(plugins: Plugin[], secureMode: boolean): Promise<Map<string, string[]>> {
const responses = await Promise.all(
plugins.map(async (p) => {
const initializeResult = await p.initialize();
const initializeResult = await p.initialize(secureMode);
return [p.name, initializeResult.resourceDefinitions] as const
})
);
Expand Down
Loading