From f65bb0512a6a4431ecccfbf01786f3611dba5ed7 Mon Sep 17 00:00:00 2001 From: Francesco Renzi Date: Wed, 10 Jun 2026 09:16:19 +0100 Subject: [PATCH 1/7] Gate debugger behind manual opt-in Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- package.json | 5 +++- src/configuration/configuration.ts | 37 +++++++++++++++++++++++++++- src/debugger/debugger.ts | 39 +++++++++++++++++++++++++++++- src/extension.ts | 13 +++++++--- 4 files changed, 87 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 93a81cb7..c6d9cf88 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,6 @@ "onView:workflows", "onView:settings", "onDebugResolve:github-actions-job", - "onCommand:github-actions.debugger.connect", "workspaceContains:**/.github/workflows/**", "workspaceContains:**/action.yml", "workspaceContains:**/action.yaml" @@ -535,6 +534,10 @@ { "command": "github-actions.sign-in", "when": "false" + }, + { + "command": "github-actions.debugger.connect", + "when": "github-actions.debugger.enabled" } ] } diff --git a/src/configuration/configuration.ts b/src/configuration/configuration.ts index d12711ac..c8437d63 100644 --- a/src/configuration/configuration.ts +++ b/src/configuration/configuration.ts @@ -4,13 +4,19 @@ import {resetGitHubContext} from "../git/repository"; const settingsKey = "github-actions"; const DEFAULT_GITHUB_API = "https://api.github.com"; +const reloadWindowAction = "Reload Window"; +const debuggerEnabledSettingsKey = getSettingsKey("debugger.enabled"); + +let debuggerSettingReloadPromptVisible = false; export function initConfiguration(context: vscode.ExtensionContext) { context.subscriptions.push( vscode.workspace.onDidChangeConfiguration(async e => { if (e.affectsConfiguration(getSettingsKey("workflows.pinned"))) { pinnedWorkflowsChangeHandlers.forEach(h => h()); - } else if ( + } + + if ( e.affectsConfiguration(getSettingsKey("use-enterprise")) || (useEnterprise() && (e.affectsConfiguration("github-enterprise.uri") || e.affectsConfiguration(getSettingsKey("remote-name")))) @@ -19,6 +25,10 @@ export function initConfiguration(context: vscode.ExtensionContext) { resetGitHubContext(); await vscode.commands.executeCommand("github-actions.explorer.refresh"); } + + if (e.affectsConfiguration(debuggerEnabledSettingsKey)) { + await promptToReloadForDebuggerSettingChange(); + } }) ); } @@ -64,6 +74,10 @@ export function getRemoteName(): string { return getConfiguration().get(getSettingsKey("remote-name"), "origin"); } +export function isDebuggerEnabled(): boolean { + return getConfiguration().get(debuggerEnabledSettingsKey, false); +} + export function useEnterprise(): boolean { return getConfiguration().get(getSettingsKey("use-enterprise"), false); } @@ -87,3 +101,24 @@ async function updateLanguageServerApiUrl(context: vscode.ExtensionContext) { await initLanguageServer(context); } + +async function promptToReloadForDebuggerSettingChange() { + if (debuggerSettingReloadPromptVisible) { + return; + } + + debuggerSettingReloadPromptVisible = true; + + try { + const selection = await vscode.window.showInformationMessage( + "Reload VS Code to apply the GitHub Actions debugger preview setting change.", + reloadWindowAction + ); + + if (selection === reloadWindowAction) { + await vscode.commands.executeCommand("workbench.action.reloadWindow"); + } + } finally { + debuggerSettingReloadPromptVisible = false; + } +} diff --git a/src/debugger/debugger.ts b/src/debugger/debugger.ts index cf7c15ec..594f590f 100644 --- a/src/debugger/debugger.ts +++ b/src/debugger/debugger.ts @@ -2,13 +2,16 @@ import * as crypto from "crypto"; import * as vscode from "vscode"; import {getClient} from "../api/api"; import {getSession, newSession} from "../auth/auth"; -import {getGitHubApiUri} from "../configuration/configuration"; +import {getGitHubApiUri, isDebuggerEnabled} from "../configuration/configuration"; import {log, logDebug, logError} from "../log"; import {parseJobUrl} from "./jobUrl"; import {validateTunnelUrl} from "./tunnelUrl"; import {WebSocketDapAdapter} from "./webSocketDapAdapter"; export const DEBUG_TYPE = "github-actions-job"; +const debuggerEnabledSettingSnippet = `"github-actions.debugger.enabled": true`; + +let debuggerRegistered = false; /** * Extension-private token store keyed by one-time nonce. Tokens are never @@ -16,7 +19,13 @@ export const DEBUG_TYPE = "github-actions-job"; */ const pendingTokens = new Map(); +export function registerDebuggerAvailabilityGuard(context: vscode.ExtensionContext): void { + context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider(DEBUG_TYPE, new ActionsDebugConfigurationProvider())); +} + export function registerDebugger(context: vscode.ExtensionContext): void { + debuggerRegistered = true; + context.subscriptions.push( vscode.debug.registerDebugAdapterDescriptorFactory(DEBUG_TYPE, new ActionsDebugAdapterFactory()) ); @@ -30,6 +39,34 @@ export function registerDebugger(context: vscode.ExtensionContext): void { ); } +class ActionsDebugConfigurationProvider implements vscode.DebugConfigurationProvider { + resolveDebugConfiguration( + _folder: vscode.WorkspaceFolder | undefined, + debugConfiguration: vscode.DebugConfiguration + ): vscode.DebugConfiguration | null { + if (vscode.env.uiKind !== vscode.UIKind.Desktop) { + void vscode.window.showInformationMessage("GitHub Actions job debugging is only available in desktop VS Code."); + return null; + } + + if (!isDebuggerEnabled()) { + void vscode.window.showInformationMessage( + `GitHub Actions job debugging is currently disabled. Add ${debuggerEnabledSettingSnippet} to settings.json and reload VS Code to enable it.` + ); + return null; + } + + if (!debuggerRegistered) { + void vscode.window.showInformationMessage( + "GitHub Actions job debugging was enabled, but VS Code must be reloaded before the debugger can be used." + ); + return null; + } + + return debugConfiguration; + } +} + async function connectToDebugger(): Promise { const rawUrl = await vscode.window.showInputBox({ title: "Connect to Actions Job Debugger", diff --git a/src/extension.ts b/src/extension.ts index 8ec7ea95..3179f401 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -19,7 +19,7 @@ import {registerAddVariable} from "./commands/variables/addVariable"; import {registerCopyVariable} from "./commands/variables/copyVariable"; import {registerDeleteVariable} from "./commands/variables/deleteVariable"; import {registerUpdateVariable} from "./commands/variables/updateVariable"; -import {initConfiguration} from "./configuration/configuration"; +import {initConfiguration, isDebuggerEnabled} from "./configuration/configuration"; import {getGitHubContext} from "./git/repository"; import {init as initLogger, log, revealLog} from "./log"; import {LogScheme} from "./logs/constants"; @@ -34,7 +34,9 @@ import {initResources} from "./treeViews/icons"; import {initTreeViews} from "./treeViews/treeViews"; import {deactivateLanguageServer, initLanguageServer} from "./workflow/languageServer"; import {registerSignIn} from "./commands/signIn"; -import {registerDebugger} from "./debugger/debugger"; +import {registerDebugger, registerDebuggerAvailabilityGuard} from "./debugger/debugger"; + +const debuggerEnabledContextKey = "github-actions.debugger.enabled"; export async function activate(context: vscode.ExtensionContext) { initLogger(); @@ -47,11 +49,13 @@ export async function activate(context: vscode.ExtensionContext) { // Prefetch git repository origin url const ghContext = hasSession && (await getGitHubContext()); const hasGitHubRepos = ghContext && ghContext.repos.length > 0; + const debuggerEnabled = vscode.env.uiKind === vscode.UIKind.Desktop && isDebuggerEnabled(); await Promise.all([ vscode.commands.executeCommand("setContext", "github-actions.signed-in", hasSession), vscode.commands.executeCommand("setContext", "github-actions.internet-access", canReachAPI), - vscode.commands.executeCommand("setContext", "github-actions.has-repos", hasGitHubRepos) + vscode.commands.executeCommand("setContext", "github-actions.has-repos", hasGitHubRepos), + vscode.commands.executeCommand("setContext", debuggerEnabledContextKey, debuggerEnabled) ]); initResources(context); @@ -92,9 +96,10 @@ export async function activate(context: vscode.ExtensionContext) { registerUnPinWorkflow(context); registerSignIn(context); + registerDebuggerAvailabilityGuard(context); // Debugger — only available in Desktop VS Code (requires Node.js for WebSocket) - if (vscode.env.uiKind === vscode.UIKind.Desktop) { + if (debuggerEnabled) { registerDebugger(context); } From 932855a30d941b10fc3c1554730bc78e53574168 Mon Sep 17 00:00:00 2001 From: Francesco Renzi Date: Wed, 10 Jun 2026 09:16:19 +0100 Subject: [PATCH 2/7] Document debugger opt-in flow Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- README.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 47cd40e3..4ede2ea5 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,16 @@ # GitHub Actions for VS Code -> **🐛 Actions Job Debugger (Preview):** To try the latest debugger build, download the `.vsix` artifact from the most recent [Build Debugger Extension](https://github.com/github/vscode-github-actions/actions/workflows/debugger-build.yml) workflow run. On the workflow run page, scroll to **Artifacts** and download **vscode-github-actions-debugger**. Then install it in VS Code by running `code --install-extension ` or via the Extensions view → `⋯` menu → **Install from VSIX…**. +> **🐛 Actions Job Debugger (Preview):** The debugger preview is intentionally off by default. To try the latest debugger build, download the `.vsix` artifact from the most recent [Build Debugger Extension](https://github.com/github/vscode-github-actions/actions/workflows/debugger-build.yml) workflow run. On the workflow run page, scroll to **Artifacts** and download **vscode-github-actions-debugger**. Then install it in VS Code by running `code --install-extension ` or via the Extensions view → `⋯` menu → **Install from VSIX…**. > -> Once installed, open the Command Palette (`Ctrl+Shift+P` / `Cmd+Shift+P`) and run **GitHub Actions: Connect to Actions Job Debugger…**. Paste the `wss://` tunnel URL from a debug-mode job and the extension will open a full debug session using your current GitHub credentials. +> Next, manually enable the preview in `settings.json`: +> +> ```json +> { +> "github-actions.debugger.enabled": true +> } +> ``` +> +> This opt-in is currently settings.json-only, so VS Code may show it as an unknown setting. After saving the change, reload VS Code. Once the window reloads, open the Command Palette (`Ctrl+Shift+P` / `Cmd+Shift+P`) and run **GitHub Actions: Debug Running Job…**. Paste the Actions job URL from a debug-mode job and the extension will open a full debug session using your current GitHub credentials. The GitHub Actions extension lets you manage your workflows, view the workflow run history, and helps with authoring workflows. From 34c4b504f7626af1910df0cb6ca1f8be77c4989a Mon Sep 17 00:00:00 2001 From: Francesco Renzi Date: Wed, 10 Jun 2026 09:51:59 +0100 Subject: [PATCH 3/7] Restore debugger command discovery Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- package.json | 3 ++- src/extension.ts | 5 +---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index c6d9cf88..a946875f 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "onView:workflows", "onView:settings", "onDebugResolve:github-actions-job", + "onCommand:github-actions.debugger.connect", "workspaceContains:**/.github/workflows/**", "workspaceContains:**/action.yml", "workspaceContains:**/action.yaml" @@ -537,7 +538,7 @@ }, { "command": "github-actions.debugger.connect", - "when": "github-actions.debugger.enabled" + "when": "config.github-actions.debugger.enabled && !isWeb" } ] } diff --git a/src/extension.ts b/src/extension.ts index 3179f401..be9a157f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -36,8 +36,6 @@ import {deactivateLanguageServer, initLanguageServer} from "./workflow/languageS import {registerSignIn} from "./commands/signIn"; import {registerDebugger, registerDebuggerAvailabilityGuard} from "./debugger/debugger"; -const debuggerEnabledContextKey = "github-actions.debugger.enabled"; - export async function activate(context: vscode.ExtensionContext) { initLogger(); @@ -54,8 +52,7 @@ export async function activate(context: vscode.ExtensionContext) { await Promise.all([ vscode.commands.executeCommand("setContext", "github-actions.signed-in", hasSession), vscode.commands.executeCommand("setContext", "github-actions.internet-access", canReachAPI), - vscode.commands.executeCommand("setContext", "github-actions.has-repos", hasGitHubRepos), - vscode.commands.executeCommand("setContext", debuggerEnabledContextKey, debuggerEnabled) + vscode.commands.executeCommand("setContext", "github-actions.has-repos", hasGitHubRepos) ]); initResources(context); From 1e2fa651c4d33b9d4bfe7535959c9f8470ff68a4 Mon Sep 17 00:00:00 2001 From: Francesco Renzi Date: Wed, 10 Jun 2026 09:51:59 +0100 Subject: [PATCH 4/7] Skip web reload prompt for debugger Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/configuration/configuration.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/configuration/configuration.ts b/src/configuration/configuration.ts index c8437d63..9be6cc7d 100644 --- a/src/configuration/configuration.ts +++ b/src/configuration/configuration.ts @@ -103,6 +103,10 @@ async function updateLanguageServerApiUrl(context: vscode.ExtensionContext) { } async function promptToReloadForDebuggerSettingChange() { + if (vscode.env.uiKind !== vscode.UIKind.Desktop) { + return; + } + if (debuggerSettingReloadPromptVisible) { return; } From b643483c3df19cb3af4b431b08fbeb19c72ef627 Mon Sep 17 00:00:00 2001 From: Francesco Renzi Date: Wed, 10 Jun 2026 10:29:18 +0100 Subject: [PATCH 5/7] Avoid reload action in development host Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/configuration/configuration.ts | 11 +++++++++-- src/debugger/debugger.ts | 6 ++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/configuration/configuration.ts b/src/configuration/configuration.ts index 9be6cc7d..567a1981 100644 --- a/src/configuration/configuration.ts +++ b/src/configuration/configuration.ts @@ -27,7 +27,7 @@ export function initConfiguration(context: vscode.ExtensionContext) { } if (e.affectsConfiguration(debuggerEnabledSettingsKey)) { - await promptToReloadForDebuggerSettingChange(); + await promptToReloadForDebuggerSettingChange(context); } }) ); @@ -102,7 +102,7 @@ async function updateLanguageServerApiUrl(context: vscode.ExtensionContext) { await initLanguageServer(context); } -async function promptToReloadForDebuggerSettingChange() { +async function promptToReloadForDebuggerSettingChange(context: vscode.ExtensionContext) { if (vscode.env.uiKind !== vscode.UIKind.Desktop) { return; } @@ -114,6 +114,13 @@ async function promptToReloadForDebuggerSettingChange() { debuggerSettingReloadPromptVisible = true; try { + if (context.extensionMode !== vscode.ExtensionMode.Production) { + await vscode.window.showInformationMessage( + "Reload VS Code manually to apply the GitHub Actions debugger preview setting change. Automatic reload is disabled in the Extension Development Host." + ); + return; + } + const selection = await vscode.window.showInformationMessage( "Reload VS Code to apply the GitHub Actions debugger preview setting change.", reloadWindowAction diff --git a/src/debugger/debugger.ts b/src/debugger/debugger.ts index 594f590f..b09abbb5 100644 --- a/src/debugger/debugger.ts +++ b/src/debugger/debugger.ts @@ -10,6 +10,8 @@ import {WebSocketDapAdapter} from "./webSocketDapAdapter"; export const DEBUG_TYPE = "github-actions-job"; const debuggerEnabledSettingSnippet = `"github-actions.debugger.enabled": true`; +const emptyWindowManualReloadMessage = + "If you enable it in an empty window, reload VS Code manually because the extension cannot prompt until it activates."; let debuggerRegistered = false; @@ -51,14 +53,14 @@ class ActionsDebugConfigurationProvider implements vscode.DebugConfigurationProv if (!isDebuggerEnabled()) { void vscode.window.showInformationMessage( - `GitHub Actions job debugging is currently disabled. Add ${debuggerEnabledSettingSnippet} to settings.json and reload VS Code to enable it.` + `GitHub Actions job debugging is currently disabled. Add ${debuggerEnabledSettingSnippet} to settings.json and reload VS Code to enable it. ${emptyWindowManualReloadMessage}` ); return null; } if (!debuggerRegistered) { void vscode.window.showInformationMessage( - "GitHub Actions job debugging was enabled, but VS Code must be reloaded before the debugger can be used." + `GitHub Actions job debugging was enabled, but VS Code must be reloaded before the debugger can be used. ${emptyWindowManualReloadMessage}` ); return null; } From fcb4fc84e8a7079a2ffa2b7bb232f49ca40f9fe1 Mon Sep 17 00:00:00 2001 From: Francesco Renzi Date: Wed, 10 Jun 2026 10:29:18 +0100 Subject: [PATCH 6/7] Clarify empty-window reload guidance Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4ede2ea5..2991ac20 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ > } > ``` > -> This opt-in is currently settings.json-only, so VS Code may show it as an unknown setting. After saving the change, reload VS Code. Once the window reloads, open the Command Palette (`Ctrl+Shift+P` / `Cmd+Shift+P`) and run **GitHub Actions: Debug Running Job…**. Paste the Actions job URL from a debug-mode job and the extension will open a full debug session using your current GitHub credentials. +> This opt-in is currently settings.json-only, so VS Code may show it as an unknown setting. After saving the change, reload VS Code. If you enable it in an empty or no-folder window, reload manually because the extension cannot prompt until it activates. Once the window reloads, open the Command Palette (`Ctrl+Shift+P` / `Cmd+Shift+P`) and run **GitHub Actions: Debug Running Job…**. Paste the Actions job URL from a debug-mode job and the extension will open a full debug session using your current GitHub credentials. The GitHub Actions extension lets you manage your workflows, view the workflow run history, and helps with authoring workflows. From 7257164c9d8b5460db7269e37098db843b4d1c5e Mon Sep 17 00:00:00 2001 From: Francesco Renzi Date: Wed, 10 Jun 2026 10:36:15 +0100 Subject: [PATCH 7/7] Format debugger guard messaging Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/debugger/debugger.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/debugger/debugger.ts b/src/debugger/debugger.ts index b09abbb5..8ab30343 100644 --- a/src/debugger/debugger.ts +++ b/src/debugger/debugger.ts @@ -22,7 +22,9 @@ let debuggerRegistered = false; const pendingTokens = new Map(); export function registerDebuggerAvailabilityGuard(context: vscode.ExtensionContext): void { - context.subscriptions.push(vscode.debug.registerDebugConfigurationProvider(DEBUG_TYPE, new ActionsDebugConfigurationProvider())); + context.subscriptions.push( + vscode.debug.registerDebugConfigurationProvider(DEBUG_TYPE, new ActionsDebugConfigurationProvider()) + ); } export function registerDebugger(context: vscode.ExtensionContext): void {