Skip to content

Commit e5b72af

Browse files
witness-meVlad Nikolaenko
andauthored
fix(stepfunctions): Prevent opening Workflow Studio for invalid JSON/YAML; add save and deploy message handler (aws#6693)
## Problem 1. Deploy state machine workflow is not very visible to the customers 2. Currently when user is opening WFS with custom action in the side panel and has invalid JSON/YAML, the side panel opens and immediately closes (since WFS does not support invalid JSON/YAML). This experience does not look smooth. ## Solution 1. With Workflow Studio integration, we'll add `Save & Deploy` button to the UI which will save file, close WFS editor and start the deployment flow. Adding a message handler for this action 2. Adding a check for invalid JSON/YAML before attempting to open WFS in the side panel. If file is invalid, the panel will not be opened and the user will see a notification --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license. Co-authored-by: Vlad Nikolaenko <[email protected]>
1 parent 1b4f549 commit e5b72af

File tree

4 files changed

+65
-18
lines changed

4 files changed

+65
-18
lines changed

packages/core/src/stepFunctions/commands/publishStateMachine.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const localize = nls.loadMessageBundle()
1818
export async function publishStateMachine(
1919
awsContext: AwsContext,
2020
outputChannel: vscode.OutputChannel,
21-
region: string | undefined
21+
region?: string
2222
) {
2323
const logger: Logger = getLogger()
2424

packages/core/src/stepFunctions/workflowStudio/handleMessage.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { ToolkitError } from '../../shared/errors'
2525
import { WorkflowStudioApiHandler } from './workflowStudioApiHandler'
2626
import globals from '../../shared/extensionGlobals'
2727
import { getLogger } from '../../shared/logger/logger'
28+
import { publishStateMachine } from '../commands/publishStateMachine'
2829

2930
const localize = nls.loadMessageBundle()
3031

@@ -45,6 +46,9 @@ export async function handleMessage(message: Message, context: WebviewContext) {
4546
case Command.SAVE_FILE:
4647
void saveFileMessageHandler(message as SaveFileRequestMessage, context)
4748
break
49+
case Command.SAVE_FILE_AND_DEPLOY:
50+
void saveFileAndDeployMessageHandler(message as SaveFileRequestMessage, context)
51+
break
4852
case Command.AUTO_SYNC_FILE:
4953
void autoSyncFileMessageHandler(message as SyncFileRequestMessage, context)
5054
break
@@ -132,13 +136,13 @@ async function loadStageMessageHandler(context: WebviewContext) {
132136
* Handler for closing WFS custom editor. When called, disposes webview panel and opens default VSCode editor
133137
* @param context The context object containing the necessary information for the webview.
134138
*/
135-
export function closeCustomEditorMessageHandler(context: WebviewContext) {
136-
telemetry.stepfunctions_closeWorkflowStudio.run((span) => {
139+
export async function closeCustomEditorMessageHandler(context: WebviewContext) {
140+
await telemetry.stepfunctions_closeWorkflowStudio.run(async (span) => {
137141
span.record({
138142
id: context.fileId,
139143
})
140144
context.panel.dispose()
141-
void vscode.commands.executeCommand('vscode.openWith', context.textDocument.uri, 'default')
145+
await vscode.commands.executeCommand('vscode.openWith', context.textDocument.uri, 'default')
142146
})
143147
}
144148

@@ -174,6 +178,18 @@ async function saveFileMessageHandler(request: SaveFileRequestMessage, context:
174178
})
175179
}
176180

181+
/**
182+
* Handler for saving a file and starting the state machine deployment flow, while also switching to default editor.
183+
* Triggered when the user triggers 'Save and Deploy' action in WFS
184+
* @param request The request message containing the file contents.
185+
* @param context The webview context containing the necessary information for saving the file.
186+
*/
187+
async function saveFileAndDeployMessageHandler(request: SaveFileRequestMessage, context: WebviewContext) {
188+
await saveFileMessageHandler(request, context)
189+
await closeCustomEditorMessageHandler(context)
190+
await publishStateMachine(globals.awsContext, globals.outputChannel)
191+
}
192+
177193
/**
178194
* Handler for auto syncing a file from the webview which updates the workspace but does not save the file.
179195
* Triggered on every code change from WFS, including invalid JSON.

packages/core/src/stepFunctions/workflowStudio/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export enum MessageType {
3535
export enum Command {
3636
INIT = 'INIT',
3737
SAVE_FILE = 'SAVE_FILE',
38+
SAVE_FILE_AND_DEPLOY = 'SAVE_FILE_AND_DEPLOY',
3839
AUTO_SYNC_FILE = 'AUTO_SYNC_FILE',
3940
FILE_CHANGED = 'FILE_CHANGED',
4041
LOAD_STAGE = 'LOAD_STAGE',

packages/core/src/stepFunctions/workflowStudio/workflowStudioEditorProvider.ts

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,49 @@ let clientId = ''
3030
export class WorkflowStudioEditorProvider implements vscode.CustomTextEditorProvider {
3131
public static readonly viewType = 'workflowStudio.asl'
3232

33+
/**
34+
* Opens a file in the Workflow Studio editor, after validating the document.
35+
* @param uri The URI of the document to open in the Workflow Studio editor.
36+
* @param params Optional parameters to customize the WebView panel.
37+
*/
3338
public static async openWithWorkflowStudio(
3439
uri: vscode.Uri,
3540
params?: Parameters<typeof vscode.window.createWebviewPanel>[2]
3641
) {
37-
await vscode.commands.executeCommand('vscode.openWith', uri, WorkflowStudioEditorProvider.viewType, params)
42+
const document = await vscode.workspace.openTextDocument(uri)
43+
await telemetry.stepfunctions_openWorkflowStudio.run(async () => {
44+
await this.validateAndThrowIfInvalid(document)
45+
await vscode.commands.executeCommand('vscode.openWith', uri, WorkflowStudioEditorProvider.viewType, params)
46+
})
47+
}
48+
49+
/**
50+
* Validates the document to ensure it is either valid JSON or YAML.
51+
* If the document is invalid, a warning is shown (if specified) and an error is thrown to stop further execution.
52+
* @param document The document to validate.
53+
* @param alertOnError If true, shows a warning message when the document is invalid. Defaults to `false`.
54+
*/
55+
private static async validateAndThrowIfInvalid(
56+
document: vscode.TextDocument,
57+
alertOnError?: boolean
58+
): Promise<void> {
59+
const isInvalidJson = isInvalidJsonFile(document)
60+
const isInvalidYaml = isInvalidYamlFile(document)
61+
62+
if (isInvalidJson || isInvalidYaml) {
63+
const language = isInvalidJson ? 'JSON' : 'YAML'
64+
const errorKey = isInvalidJson ? 'InvalidJSONContent' : 'InvalidYAMLContent'
65+
66+
if (alertOnError) {
67+
void vscode.window.showErrorMessage(i18n(`AWS.stepFunctions.workflowStudio.actions.${errorKey}`))
68+
}
69+
70+
throw ToolkitError.chain(
71+
`Invalid ${language} file`,
72+
`The Workflow Studio editor was not opened because the ${language} in the file is invalid`,
73+
{ code: errorKey }
74+
)
75+
}
3876
}
3977

4078
/**
@@ -114,20 +152,12 @@ export class WorkflowStudioEditorProvider implements vscode.CustomTextEditorProv
114152
webviewPanel.dispose()
115153
}
116154

117-
const isInvalidJson = isInvalidJsonFile(document)
118-
const isInvalidYaml = isInvalidYamlFile(document)
119-
120-
if (isInvalidJson || isInvalidYaml) {
121-
const language = isInvalidJson ? 'JSON' : 'YAML'
122-
const errorKey = isInvalidJson ? 'InvalidJSONContent' : 'InvalidYAMLContent'
123-
155+
try {
156+
await WorkflowStudioEditorProvider.validateAndThrowIfInvalid(document, true)
157+
} catch (e) {
158+
// If the document is invalid, reopen it with the default editor and re-throw the error
124159
await reopenWithDefaultEditor()
125-
void vscode.window.showWarningMessage(i18n(`AWS.stepFunctions.workflowStudio.actions.${errorKey}`))
126-
throw ToolkitError.chain(
127-
`Invalid ${language} file`,
128-
`The Workflow Studio editor was not opened because the ${language} in the file is invalid`,
129-
{ code: errorKey }
130-
)
160+
throw e
131161
}
132162

133163
if (!this.webviewHtml) {

0 commit comments

Comments
 (0)