Skip to content

Commit 84b9455

Browse files
committed
Added progress display for apply
1 parent 2e6a1ec commit 84b9455

6 files changed

Lines changed: 54 additions & 32 deletions

File tree

src/commands/apply/index.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { Args, Command, Flags } from '@oclif/core'
2+
import { ResourceOperation } from 'codify-schemas';
23
import path from 'node:path';
34

4-
import { DefaultReporter } from '../../ui/reporters/default-reporter.js';
5+
import { ApplyOrchestrator } from '../../orchestrators/apply.js';
56
import { PlanOrchestrator } from '../../orchestrators/plan.js';
7+
import { DefaultReporter } from '../../ui/reporters/default-reporter.js';
68

79
export default class Apply extends Command {
810
static args = {
@@ -40,15 +42,25 @@ export default class Apply extends Command {
4042

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

43-
const { plan } = await PlanOrchestrator.run(resolvedPath);
44-
reporter.displayPlan(plan);
45+
const planResult = await PlanOrchestrator.run(resolvedPath, false);
46+
47+
// Short circuit and exit if every change is NOOP
48+
if (planResult.plan.every((p) => p.operation === ResourceOperation.NOOP)) {
49+
console.log('No changes necessary. Exiting');
50+
await planResult.pluginCollection.destroy();
51+
return;
52+
}
53+
54+
reporter.displayPlan(planResult.plan);
4555

4656
const confirm = await reporter.promptApplyConfirmation()
4757

4858
if (!confirm) {
4959
return this.exit(0);
5060
}
5161

62+
await ApplyOrchestrator.run(planResult);
63+
5264
// this.exit(0);
5365

5466
}

src/events/context.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export enum SubProcessName {
2323
INITIALIZE_PLUGINS = 'initialize_plugins',
2424
VALIDATE = 'validate',
2525
GENERATE_PLAN = 'generate_plan',
26-
APPLY_RESOURCE = 'apply_resource',
26+
APPLYING_RESOURCE = 'apply_resource',
2727
}
2828

2929
export const ctx = new class {
@@ -68,12 +68,12 @@ export const ctx = new class {
6868
this.emitter.emit(Event.PROCESS_FINISH, name);
6969
}
7070

71-
subprocessStarted(name: string) {
72-
this.emitter.emit(Event.SUB_PROCESS_START, name);
71+
subprocessStarted(name: string, additionalName?: string) {
72+
this.emitter.emit(Event.SUB_PROCESS_START, name, additionalName);
7373
}
7474

75-
subprocessFinished(name: string) {
76-
this.emitter.emit(Event.SUB_PROCESS_FINISH, name);
75+
subprocessFinished(name: string, additionalName?: string) {
76+
this.emitter.emit(Event.SUB_PROCESS_FINISH, name, additionalName);
7777
}
7878

7979
async subprocess<T>(name: string, run: () => Promise<T>): Promise<T> {

src/orchestrators/apply.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
import { ResourceOperation } from 'codify-schemas';
22

3-
import { PlanOrchestrator } from './plan.js';
3+
import { ctx, ProcessName } from '../events/context.js';
4+
import { PlanOrchestratorResponse } from './plan.js';
45

56
export const ApplyOrchestrator = {
6-
async run(rootDirectory: string): Promise<void> {
7-
const { plan, pluginCollection } = await PlanOrchestrator.run(rootDirectory, false);
7+
async run(planResult: PlanOrchestratorResponse): Promise<void> {
8+
const { plan, pluginCollection } = planResult;
9+
const filteredPlan = plan
10+
.filter((p) => p.operation !== ResourceOperation.NOOP)
811

9-
// Short circuit and exit if every change is NOOP
10-
if (plan.every((p) => p.operation === ResourceOperation.NOOP)) {
11-
console.log('No changes necessary. Exiting');
12-
await pluginCollection.destroy();
13-
return;
14-
}
15-
16-
await pluginCollection.apply(plan);
12+
ctx.processStarted(ProcessName.APPLY);
13+
await pluginCollection.apply(filteredPlan);
1714
await pluginCollection.destroy();
15+
ctx.processFinished(ProcessName.APPLY);
1816
},
1917
};

src/orchestrators/plan.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import { ctx, ProcessName, SubProcessName } from '../events/context.js';
55
import { Parser } from '../parser/index.js';
66
import { PluginCollection } from '../plugins/plugin-collection.js';
77

8-
interface PlanOchestratorResponse {
8+
export interface PlanOrchestratorResponse {
99
plan: PlanResponseData[],
1010
pluginCollection: PluginCollection;
1111
project: Project;
1212
}
1313

1414
export const PlanOrchestrator = {
15-
async run(path: string, destroyPlugins = true): Promise<PlanOchestratorResponse> {
15+
async run(path: string, destroyPlugins = true): Promise<PlanOrchestratorResponse> {
1616
ctx.processStarted(ProcessName.PLAN)
1717

1818
ctx.subprocessStarted(SubProcessName.PARSE);

src/plugins/plugin-collection.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { PlanResponseData, ValidateResponseData } from 'codify-schemas';
22

33
import { Project } from '../entities/project.js';
4+
import { ctx, SubProcessName } from '../events/context.js';
45
import { groupBy } from '../utils/index.js';
56
import { Plugin } from './plugin.js';
67
import { PluginResolver } from './resolver.js';
@@ -62,12 +63,16 @@ export class PluginCollection {
6263

6364
async apply(planResponseData: PlanResponseData[]): Promise<void> {
6465
for (const { planId, resourceType } of planResponseData) {
66+
ctx.subprocessStarted(SubProcessName.APPLYING_RESOURCE, resourceType);
67+
6568
const pluginName = this.resourceToPluginMapping.get(resourceType);
6669
if (!pluginName) {
6770
throw new Error(`Internal error: unable to determine plugin for apply: ${resourceType}`);
6871
}
6972

7073
await this.plugins.get(pluginName)!.apply(planId);
74+
75+
ctx.subprocessFinished(SubProcessName.APPLYING_RESOURCE, resourceType);
7176
}
7277
}
7378

src/ui/reporters/default-reporter.tsx

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import { ProgressState, ProgressStatus } from '../components/progress/progress-d
99
import { DisplayPlanStateTransition, RenderEvent, RenderState, Reporter } from './reporter.js';
1010

1111
const ProgressLabelMapping = {
12-
[ProcessName.APPLY]: 'Codify plan',
12+
[ProcessName.APPLY]: 'Codify apply',
1313
[ProcessName.PLAN]: 'Codify plan',
14-
[SubProcessName.APPLY_RESOURCE]: 'Applying resource',
14+
[SubProcessName.APPLYING_RESOURCE]: 'Applying resource',
1515
[SubProcessName.GENERATE_PLAN]: 'Refresh states and generating plan',
1616
[SubProcessName.INITIALIZE_PLUGINS]: 'Initializing plugins',
1717
[SubProcessName.PARSE]: 'Parsing configs',
@@ -29,8 +29,8 @@ export class DefaultReporter implements Reporter {
2929
ctx.on(Event.OUTPUT, (args) => this.log(args));
3030
ctx.on(Event.PROCESS_START, (name) => this.onProcessStartEvent(name))
3131
ctx.on(Event.PROCESS_FINISH, (name) => this.onProcessFinishEvent(name))
32-
ctx.on(Event.SUB_PROCESS_START, (name) => this.onSubprocessStartEvent(name));
33-
ctx.on(Event.SUB_PROCESS_FINISH, (name) => this.onSubprocessFinishEvent(name))
32+
ctx.on(Event.SUB_PROCESS_START, (name, additionalName) => this.onSubprocessStartEvent(name, additionalName));
33+
ctx.on(Event.SUB_PROCESS_FINISH, (name, additionalName) => this.onSubprocessFinishEvent(name, additionalName))
3434
}
3535

3636
displayPlan(plan: PlanResponseData[]): void {
@@ -58,9 +58,10 @@ export class DefaultReporter implements Reporter {
5858
this.renderEmitter.emit(RenderEvent.STATE_TRANSITION, {
5959
nextState: RenderState.APPLYING,
6060
});
61+
62+
this.log('Do you want to apply the above changes? -> "Yes"')
6163
}
6264

63-
this.log(`Do you want to apply the above changes? -> ${continueApply ? '"Yes"' : '"No"'}`)
6465
return continueApply;
6566
}
6667

@@ -92,25 +93,31 @@ export class DefaultReporter implements Reporter {
9293

9394
}
9495

95-
private onSubprocessStartEvent(name: SubProcessName): void {
96-
const label = ProgressLabelMapping[name];
96+
private onSubprocessStartEvent(name: SubProcessName, additionalName?: string): void {
97+
const label = ProgressLabelMapping[name] + (additionalName
98+
? ' ' + additionalName
99+
: ''
100+
);
97101

98102
this.progressState?.subProgresses?.push({
99103
label,
100-
name,
104+
name: name + additionalName,
101105
status: ProgressStatus.IN_PROGRESS,
102106
});
103107

104108
this.log(`${label} started`)
105109
this.renderEmitter.emit(RenderEvent.PROGRESS_UPDATE, this.progressState);
106110
}
107111

108-
private onSubprocessFinishEvent(name: SubProcessName): void {
109-
const label = ProgressLabelMapping[name];
112+
private onSubprocessFinishEvent(name: SubProcessName, additionalName?: string): void {
113+
const label = ProgressLabelMapping[name] + (additionalName
114+
? ' ' + additionalName
115+
: ''
116+
);
110117

111118
const subProgress = this.progressState
112119
?.subProgresses
113-
?.find((p) => p.name === name);
120+
?.find((p) => p.name === name + additionalName);
114121

115122
if (!subProgress) {
116123
return;

0 commit comments

Comments
 (0)