Skip to content

Commit d872c71

Browse files
committed
feat: Add a pre-filled sudo password
1 parent 6e7aba1 commit d872c71

11 files changed

Lines changed: 72 additions & 36 deletions

File tree

codify.json

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@
1212
"$PYENV_ROOT/bin",
1313
"$BUN_INSTALL/bin",
1414
"$DENO_INSTALL/bin",
15+
"~/.jenv/bin",
16+
"~/a/random/path",
17+
"$NVM_DIR/.bin/2",
1518
"$NVM_DIR/.bin/3"
1619
],
17-
"declarationsOnly": true
20+
"declarationsOnly": true,
21+
"name": "1"
1822
},
1923
{
2024
"type": "homebrew",
@@ -35,6 +39,11 @@
3539
"cirrus",
3640
"expect",
3741
"git-lfs",
42+
"groff",
43+
"hyperfine",
44+
"jenv",
45+
"jq",
46+
"mas",
3847
"openjdk@11",
3948
"openjdk@17",
4049
"openjdk@21",
@@ -104,20 +113,20 @@
104113
"type": "aws-cli"
105114
},
106115
{
107-
"type": "git-clone",
116+
"type": "git-repository",
108117
"directory": "~/Projects/codify-homebrew-plugin",
109118
"repository": "git@github.com:kevinwang5658/codify-homebrew-plugin.git"
110119
},
111120
{
112121
"type": "vscode"
113122
},
114123
{
115-
"type": "git-clone",
124+
"type": "git-repository",
116125
"directory": "~/Projects/codify-plugin-lib",
117126
"repository": "git@github.com:kevinwang5658/codify-plugin-lib.git"
118127
},
119128
{
120-
"type": "git-clone",
129+
"type": "git-repository",
121130
"directory": "~/Projects/codify",
122131
"repository": "git@github.com:kevinwang5658/codify.git"
123132
},
@@ -176,37 +185,37 @@
176185
"region": "us-east-1"
177186
},
178187
{
179-
"type": "git-clone",
188+
"type": "git-repository",
180189
"directory": "~/Projects/codify-homebrew-plugin",
181190
"repository": "git@github.com:kevinwang5658/codify-homebrew-plugin.git"
182191
},
183192
{
184-
"type": "git-clone",
193+
"type": "git-repository",
185194
"directory": "~/Projects/codify-homebrew-plugin",
186195
"repository": "git@github.com:kevinwang5658/codify-homebrew-plugin.git"
187196
},
188197
{
189-
"type": "git-clone",
198+
"type": "git-repository",
190199
"directory": "~/Projects/codify-homebrew-plugin",
191200
"repository": "git@github.com:kevinwang5658/codify-homebrew-plugin.git"
192201
},
193202
{
194-
"type": "git-clone",
203+
"type": "git-repository",
195204
"directory": "~/Projects/codify-homebrew-plugin",
196205
"repository": "git@github.com:kevinwang5658/codify-homebrew-plugin.git"
197206
},
198207
{
199-
"type": "git-clone",
208+
"type": "git-repository",
200209
"directory": "~/Projects/codify-homebrew-plugin",
201210
"repository": "git@github.com:kevinwang5658/codify-homebrew-plugin.git"
202211
},
203212
{
204-
"type": "git-clone",
213+
"type": "git-repository",
205214
"directory": "~/Projects/codify-homebrew-plugin",
206215
"repository": "git@github.com:kevinwang5658/codify-homebrew-plugin.git"
207216
},
208217
{
209-
"type": "git-clone",
218+
"type": "git-repository",
210219
"directory": "~/Projects/codify-homebrew-plugin",
211220
"repository": "git@github.com:kevinwang5658/codify-homebrew-plugin.git"
212221
}
Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
import { Flags } from '@oclif/core'
22

3-
import { BaseCommand } from '../../common/base-command.js';
4-
import { ApplyOrchestrator } from '../../orchestrators/apply.js';
3+
import { BaseCommand } from '../common/base-command.js';
4+
import { ApplyOrchestrator } from '../orchestrators/apply.js';
55

66
export default class Apply extends BaseCommand {
77
static description = 'Apply a codify file onto the system. A plan of the changes is first generated and a list of changes will be shown before proceeding'
88

9+
static flags = {
10+
'sudoPassword': Flags.string({
11+
optional: true,
12+
description: 'Pre-fill the sudo password to automatically use for any commands that require elevated permissions.',
13+
char: 'S'
14+
}),
15+
}
16+
917
static examples = [
1018
'<%= config.bin %> <%= command.id %>',
1119
'<%= config.bin %> <%= command.id %> --path ~',
@@ -21,7 +29,8 @@ export default class Apply extends BaseCommand {
2129

2230
await ApplyOrchestrator.run({
2331
path: flags.path,
24-
secure: flags.secure,
32+
// secure: flags.secure,
33+
sudoPassword: flags.sudoPassword,
2534
}, this.reporter);
2635

2736
process.exit(0);

src/commands/destroy.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Flags } from '@oclif/core';
12
import { BaseCommand } from '../common/base-command.js';
23
import { DestroyOrchestrator } from '../orchestrators/destroy.js';
34

@@ -7,6 +8,15 @@ export default class Destroy extends BaseCommand {
78
static examples = [
89
'<%= config.bin %> <%= command.id %> homebrew nvm',
910
]
11+
12+
static flags = {
13+
'sudoPassword': Flags.string({
14+
optional: true,
15+
description: 'Pre-fill the sudo password to automatically use for any commands that require elevated permissions.',
16+
char: 'S',
17+
helpValue: '<password>'
18+
}),
19+
}
1020

1121
public async run(): Promise<void> {
1222
const { flags, raw } = await this.parse(Destroy)
@@ -26,7 +36,7 @@ export default class Destroy extends BaseCommand {
2636
await DestroyOrchestrator.run({
2737
ids: args,
2838
path: flags.path,
29-
secureMode: flags.secure,
39+
defaultSudoPassword: flags.sudoPassword,
3040
}, this.reporter)
3141

3242
process.exit(0);
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import { Args, Flags } from '@oclif/core'
2-
import * as path from 'node:path';
3-
4-
import { PlanOrchestrator } from '../../orchestrators/plan.js';
5-
import { BaseCommand } from '../../common/base-command.js';
1+
import { BaseCommand } from '../common/base-command.js';
2+
import { PlanOrchestrator } from '../orchestrators/plan.js';
63

74
export default class Plan extends BaseCommand {
85
static description = 'Generate a plan based on a codify.json file. This plan will list ' +

src/common/base-command.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,16 @@ import { prettyPrintError } from './errors.js';
1010

1111
export abstract class BaseCommand extends Command {
1212
static baseFlags = {
13-
'debug': Flags.boolean(),
13+
'debug': Flags.boolean({
14+
description: 'Add additional debug logs.'
15+
}),
1416
'output': Flags.option({
1517
char: 'o',
1618
default: 'default',
1719
options: ['plain', 'default', 'json'],
20+
description: 'Control the output format of Codify.',
1821
})(),
19-
'secure': Flags.boolean({
20-
char: 's',
21-
default: false,
22-
}),
23-
path: Flags.string({ char: 'p', description: 'Path to codify.json file' }),
22+
path: Flags.string({ char: 'p', description: 'Path to run Codify from.' }),
2423
}
2524

2625
protected reporter!: Reporter;

src/orchestrators/apply.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { PlanOrchestrator } from './plan.js';
66
export interface ApplyArgs {
77
path?: string;
88
secure?: boolean;
9+
sudoPassword?: string;
910
}
1011

1112
export const ApplyOrchestrator = {

src/orchestrators/destroy.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export interface DestroyArgs {
1111
ids: string[];
1212
path?: string;
1313
secureMode?: boolean;
14+
defaultSudoPassword?: string;
1415
}
1516

1617
export class DestroyOrchestrator {

src/orchestrators/initialize-plugins.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export interface InitializeArgs {
1313
secure?: boolean;
1414
transformProject?: (project: Project) => Project | Promise<Project>;
1515
allowEmptyProject?: boolean;
16+
defaultSudoPassword?: string;
1617
}
1718

1819
export interface InitializationResult {
@@ -37,7 +38,7 @@ export class PluginInitOrchestrator {
3738

3839
ctx.subprocessStarted(SubProcessName.INITIALIZE_PLUGINS)
3940
const pluginManager = new PluginManager();
40-
const typeIdsToDependenciesMap = await pluginManager.initialize(project, args.secure);
41+
const typeIdsToDependenciesMap = await pluginManager.initialize(project, args.secure, args.defaultSudoPassword);
4142
ctx.subprocessFinished(SubProcessName.INITIALIZE_PLUGINS)
4243

4344
return { typeIdsToDependenciesMap, pluginManager, project };

src/plugins/plugin-manager.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class PluginManager {
2828
private resourceToPluginMapping = new Map<string, string>()
2929
private pluginToResourceMapping = new Map<string, string[]>()
3030

31-
async initialize(project: Project | null, secureMode = false): Promise<DependencyMap> {
31+
async initialize(project: Project | null, secureMode = false, defaultSudoPassword?: string): Promise<DependencyMap> {
3232
const plugins = await this.resolvePlugins(project);
3333

3434
for (const plugin of plugins) {
@@ -37,7 +37,7 @@ export class PluginManager {
3737

3838
this.registerKillListeners(plugins)
3939

40-
const dependencyMap = await this.initializePlugins(plugins, secureMode);
40+
const dependencyMap = await this.initializePlugins(plugins, secureMode, defaultSudoPassword);
4141
return dependencyMap;
4242
}
4343

@@ -158,10 +158,10 @@ export class PluginManager {
158158
return PluginResolver.resolveAll(pluginDefinitions);
159159
}
160160

161-
private async initializePlugins(plugins: Plugin[], secureMode: boolean): Promise<Map<string, string[]>> {
161+
private async initializePlugins(plugins: Plugin[], secureMode: boolean, defaultSudoPassword?: string): Promise<Map<string, string[]>> {
162162
const responses = await Promise.all(
163163
plugins.map(async (p) => {
164-
const initializeResult = await p.initialize(secureMode);
164+
const initializeResult = await p.initialize(secureMode, defaultSudoPassword);
165165
return [p.name, initializeResult.resourceDefinitions] as const
166166
})
167167
);

src/plugins/plugin-process.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export function returnMessageCmd(cmd: string) {
2727
export class PluginProcess {
2828
process: ChildProcess;
2929

30-
static async start(pluginPath: string, name: string, secureMode: boolean): Promise<PluginProcess> {
30+
static async start(pluginPath: string, name: string, secureMode: boolean, defaultSudoPassword?: string): Promise<PluginProcess> {
3131
const isTypescript = pluginPath.endsWith('.ts');
3232
const isTsxInstalled = PluginProcess.isTsxInstalled();
3333

@@ -55,7 +55,7 @@ export class PluginProcess {
5555
throw new Error(`Plugin ${this.name} exited with code ${code}`);
5656
}
5757
})
58-
PluginProcess.handleSudoRequests(_process, name);
58+
PluginProcess.handleSudoRequests(_process, name, defaultSudoPassword);
5959

6060
return new PluginProcess(_process);
6161
}
@@ -64,7 +64,7 @@ export class PluginProcess {
6464
this.process = process;
6565
}
6666

67-
private static handleSudoRequests(process: ChildProcess, pluginName: string) {
67+
private static handleSudoRequests(process: ChildProcess, pluginName: string, sudoPassword?: string) {
6868
// Listen for incoming sudo incoming sudo requests
6969
process.on('message', (message) => {
7070
if (!PluginProcess.isIpcMessage(message)) {
@@ -77,6 +77,15 @@ export class PluginProcess {
7777
throw new Error(`Invalid sudo request from plugin ${pluginName}. ${JSON.stringify(sudoRequestValidator.errors, null, 2)}`);
7878
}
7979

80+
if (sudoPassword) {
81+
process.send({
82+
cmd: returnMessageCmd(MessageCmd.SUDO_REQUEST),
83+
requestId,
84+
data
85+
})
86+
return;
87+
}
88+
8089
// Send out sudo granted events
8190
ctx.once(Event.SUDO_REQUEST_GRANTED, (_pluginName, data) => {
8291
if (_pluginName === pluginName) {

0 commit comments

Comments
 (0)