Skip to content

Commit afcd80d

Browse files
authored
Right click option for building an EE when execution-environment.yml is recognized (#1778)
* Right click option for building an EE when execution-environment.yml is recognized * Use spawnsync instead of exec to avoid security hotspot * Move code from extension.ts and import from utils * Set env * Remove env * Use runCommand function from utils instead of spawnSync * Tests * Get correct notification box * Wait for notification to appear * Change expect to match Build successful/failed message * Execute command from palette * Fix tests and correction to directory path for builder
1 parent cd04869 commit afcd80d

File tree

4 files changed

+143
-1
lines changed

4 files changed

+143
-1
lines changed

package.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"activationEvents": [
33
"onLanguage:yaml",
4+
"onLanguage:yml",
45
"workspaceContains:tox-ansible.ini",
56
"onWebviewPanel:ansible-home"
67
],
@@ -444,6 +445,10 @@
444445
{
445446
"command": "ansible.open-language-server-logs",
446447
"title": "Ansible: Open Language Server Logs"
448+
},
449+
{
450+
"command": "extension.buildExecutionEnvironment",
451+
"title": "Build Ansible execution environment"
447452
}
448453
],
449454
"configuration": [
@@ -795,13 +800,23 @@
795800
"group": "2_main@1",
796801
"command": "ansible.lightspeed.playbookExplanation",
797802
"when": "redhat.ansible.lightspeedSuggestionsEnabled && editorLangId == ansible"
803+
},
804+
{
805+
"when": "resourceFilename == 'execution-environment.yml' || resourceFilename == 'execution-environment.yaml'",
806+
"command": "extension.buildExecutionEnvironment",
807+
"group": "navigation"
798808
}
799809
],
800810
"explorer/context": [
801811
{
802812
"group": "2_main@1",
803813
"submenu": "ansible.playbook.run",
804814
"when": "isFileSystemResource && resourceLangId == ansible"
815+
},
816+
{
817+
"when": "resourceFilename == 'execution-environment.yml' || resourceFilename == 'execution-environment.yaml'",
818+
"command": "extension.buildExecutionEnvironment",
819+
"group": "navigation"
805820
}
806821
],
807822
"view/title": [

src/extension.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import { PlaybookFeedbackEvent } from "./interfaces/lightspeed";
7575
import { CreateDevfile } from "./features/contentCreator/createDevfilePage";
7676
import { CreateSampleExecutionEnv } from "./features/contentCreator/createSampleExecutionEnvPage";
7777
import { CreateDevcontainer } from "./features/contentCreator/createDevcontainerPage";
78+
import { rightClickEEBuildCommand } from "./features/utils/buildExecutionEnvironment";
7879

7980
export let client: LanguageClient;
8081
export let lightSpeedManager: LightSpeedManager;
@@ -168,6 +169,10 @@ export async function activate(context: ExtensionContext): Promise<void> {
168169

169170
vscode.commands.executeCommand("setContext", "lightspeedConnectReady", true);
170171

172+
const eeBuilderCommand = rightClickEEBuildCommand(
173+
"extension.buildExecutionEnvironment",
174+
);
175+
171176
context.subscriptions.push(
172177
vscode.commands.registerCommand(
173178
LightSpeedCommands.LIGHTSPEED_STATUS_BAR_CLICK,
@@ -827,6 +832,7 @@ export async function activate(context: ExtensionContext): Promise<void> {
827832
lsOutputChannel.show();
828833
}),
829834
);
835+
context.subscriptions.push(eeBuilderCommand);
830836
}
831837

832838
const startClient = async (
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import * as vscode from "vscode";
2+
import * as path from "path";
3+
import { withInterpreter } from "../utils/commandRunner";
4+
import { SettingsManager } from "../../settings";
5+
import { runCommand } from "../contentCreator/utils";
6+
7+
export function rightClickEEBuildCommand(commandId: string): vscode.Disposable {
8+
return vscode.commands.registerCommand(commandId, async (uri: vscode.Uri) => {
9+
if (!uri?.fsPath) {
10+
const getFileFromEditor = vscode.window.activeTextEditor;
11+
if (!getFileFromEditor) {
12+
vscode.window.showErrorMessage(
13+
"No file selected and no active file found!",
14+
);
15+
return;
16+
}
17+
const filePath = getFileFromEditor.document.uri.fsPath;
18+
if (
19+
!filePath.endsWith("execution-environment.yml") &&
20+
!filePath.endsWith("execution-environment.yaml")
21+
) {
22+
vscode.window.showErrorMessage(
23+
"Active file is not an execution environment file!",
24+
);
25+
return;
26+
}
27+
uri = getFileFromEditor.document.uri;
28+
}
29+
30+
const filePath = uri.fsPath;
31+
const dirPath = path.dirname(filePath);
32+
33+
const builderCommand = `ansible-builder build -f ${filePath} -c ${dirPath}/context`;
34+
35+
vscode.window.showInformationMessage(`Running: ${builderCommand}`);
36+
37+
if (!dirPath) {
38+
vscode.window.showErrorMessage("Could not determine workspace folder.");
39+
return;
40+
}
41+
42+
try {
43+
const extSettings = new SettingsManager();
44+
await extSettings.initialize();
45+
46+
const { command, env } = withInterpreter(
47+
extSettings.settings,
48+
builderCommand,
49+
"",
50+
);
51+
52+
const result = await runCommand(command, env);
53+
54+
if (result.status === "failed") {
55+
vscode.window.showErrorMessage(
56+
`Build failed with status ${result.status}: \n${result.output.trim()}`,
57+
);
58+
return;
59+
}
60+
61+
vscode.window.showInformationMessage(
62+
`Build successful:\n${result.output.trim()}`,
63+
);
64+
} catch (error) {
65+
vscode.window.showErrorMessage(
66+
`Unexpected error: ${(error as Error).message}`,
67+
);
68+
}
69+
});
70+
}

test/ui-test/contentCreatorUiTest.ts

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import { By, EditorView, WebElement } from "vscode-extension-tester";
1+
import {
2+
By,
3+
EditorView,
4+
WebElement,
5+
Workbench,
6+
InputBox,
7+
} from "vscode-extension-tester";
28
import {
39
getWebviewByLocator,
410
sleep,
@@ -180,6 +186,51 @@ describe("Test Ansible sample execution environment file scaffolding", () => {
180186
"Create Sample Ansible Execution Environment",
181187
);
182188
});
189+
190+
it("Executes the build command from the right-click menu", async function () {
191+
const workbench = new Workbench();
192+
193+
await workbenchExecuteCommand("Build Ansible execution environment");
194+
let notifications = await workbench.getNotifications();
195+
const errorNotification = notifications.find(async (notification) => {
196+
return (await notification.getMessage()).includes(
197+
"No file selected and no active file found!",
198+
);
199+
});
200+
if (!errorNotification) throw new Error("Notification not found");
201+
202+
await workbenchExecuteCommand("File: New Untitled Text file");
203+
await workbenchExecuteCommand("Build Ansible execution environment");
204+
notifications = await workbench.getNotifications();
205+
const fileTypeError = notifications.find(async (notification) => {
206+
return (await notification.getMessage()).includes(
207+
"Active file is not an execution environment file!",
208+
);
209+
});
210+
if (!fileTypeError) throw new Error("Notification not found");
211+
212+
await workbenchExecuteCommand("Go to File...");
213+
const inputBox = await InputBox.create();
214+
await inputBox.setText(
215+
path.join(os.homedir(), "execution-environment.yml"),
216+
);
217+
await inputBox.confirm();
218+
await workbenchExecuteCommand("Build Ansible execution environment");
219+
220+
await new Promise((resolve) => setTimeout(resolve, 3000));
221+
notifications = await workbench.getNotifications();
222+
const buildResultNotification = notifications.find(async (notification) => {
223+
const message = await notification.getMessage();
224+
return (
225+
message.includes("Build successful") || message.includes("Build failed")
226+
);
227+
});
228+
if (!buildResultNotification) throw new Error("Notification not found");
229+
230+
expect(await buildResultNotification.getMessage()).to.match(
231+
/^Build (successful|failed)/,
232+
);
233+
});
183234
});
184235

185236
describe("Test collection plugins scaffolding", () => {

0 commit comments

Comments
 (0)