Skip to content

Commit 9fc41c8

Browse files
Merge master into feature/ui-e2e-tests
2 parents 4ed1839 + 91120f2 commit 9fc41c8

File tree

19 files changed

+213
-84
lines changed

19 files changed

+213
-84
lines changed

packages/amazonq/test/e2e/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
*/
55

66
import { runTests } from 'aws-core-vscode/test'
7-
import { VSCODE_EXTENSION_ID } from 'aws-core-vscode/utils'
7+
import { VSCODE_EXTENSION_ID_CONSTANTS } from 'aws-core-vscode/utils'
88

99
export function run(): Promise<void> {
10-
return runTests(process.env.TEST_DIR ?? 'test/e2e', VSCODE_EXTENSION_ID.amazonq, [
10+
return runTests(process.env.TEST_DIR ?? 'test/e2e', VSCODE_EXTENSION_ID_CONSTANTS.amazonq, [
1111
'../../core/dist/src/testInteg/globalSetup.test.ts',
1212
])
1313
}

packages/amazonq/test/unit/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
*/
55

66
import { runTests } from 'aws-core-vscode/test'
7-
import { VSCODE_EXTENSION_ID } from 'aws-core-vscode/utils'
7+
import { VSCODE_EXTENSION_ID_CONSTANTS } from 'aws-core-vscode/utils'
88

99
export function run(): Promise<void> {
10-
return runTests(process.env.TEST_DIR ?? ['test/unit'], VSCODE_EXTENSION_ID.amazonq, [
10+
return runTests(process.env.TEST_DIR ?? ['test/unit'], VSCODE_EXTENSION_ID_CONSTANTS.amazonq, [
1111
'../../core/dist/src/test/globalSetup.test.ts',
1212
])
1313
}

packages/amazonq/test/web/testRunner.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* The following was influenced by this guide: https://code.visualstudio.com/api/extension-guides/web-extensions
88
*/
99

10-
import { VSCODE_EXTENSION_ID } from 'aws-core-vscode/utils'
10+
import { VSCODE_EXTENSION_ID_CONSTANTS } from 'aws-core-vscode/utils'
1111
import 'mocha' // Imports mocha for the browser, defining the `mocha` global.
1212
import * as vscode from 'vscode'
1313

@@ -47,12 +47,12 @@ function gatherTestFiles() {
4747
* So this function ensures the extension has fully activated.
4848
*/
4949
async function activateExtension() {
50-
const extId = VSCODE_EXTENSION_ID.amazonq
50+
const extId = VSCODE_EXTENSION_ID_CONSTANTS.amazonq
5151
const ext = vscode.extensions.getExtension(extId)
5252
if (!ext) {
5353
throw new Error(`Extension '${extId}' not found, can't activate it to run tests.`)
5454
}
55-
await vscode.extensions.getExtension(VSCODE_EXTENSION_ID.amazonq)?.activate()
55+
await vscode.extensions.getExtension(VSCODE_EXTENSION_ID_CONSTANTS.amazonq)?.activate()
5656
}
5757

5858
function runMochaTests(resolve: (value: void | PromiseLike<void>) => void, reject: (reason?: any) => void) {

packages/core/scripts/test/launchTestUtilities.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import packageJson from '../../package.json'
88
import { downloadAndUnzipVSCode, resolveCliArgsFromVSCodeExecutablePath } from '@vscode/test-electron'
99
import { join, resolve } from 'path'
1010
import { runTests } from '@vscode/test-electron'
11-
import { VSCODE_EXTENSION_ID } from '../../src/shared/extensions'
11+
import { VSCODE_EXTENSION_ID_CONSTANTS } from '../../src/shared/extensionIds'
1212
import { TestOptions } from '@vscode/test-electron/out/runTest'
1313

1414
const envvarVscodeTestVersion = 'VSCODE_TEST_VERSION'
@@ -79,14 +79,14 @@ async function getVSCodeCliArgs(params: {
7979
if (params.suite === 'integration' || params.suite === 'e2e') {
8080
disableExtensionsArgs = await getCliArgsToDisableExtensions(params.vsCodeExecutablePath, {
8181
except: [
82-
VSCODE_EXTENSION_ID.python,
83-
VSCODE_EXTENSION_ID.yaml,
84-
VSCODE_EXTENSION_ID.jupyter,
85-
VSCODE_EXTENSION_ID.go,
86-
VSCODE_EXTENSION_ID.java,
87-
VSCODE_EXTENSION_ID.javadebug,
88-
VSCODE_EXTENSION_ID.git,
89-
VSCODE_EXTENSION_ID.remotessh,
82+
VSCODE_EXTENSION_ID_CONSTANTS.python,
83+
VSCODE_EXTENSION_ID_CONSTANTS.yaml,
84+
VSCODE_EXTENSION_ID_CONSTANTS.jupyter,
85+
VSCODE_EXTENSION_ID_CONSTANTS.go,
86+
VSCODE_EXTENSION_ID_CONSTANTS.java,
87+
VSCODE_EXTENSION_ID_CONSTANTS.javadebug,
88+
VSCODE_EXTENSION_ID_CONSTANTS.git,
89+
VSCODE_EXTENSION_ID_CONSTANTS.remotessh.id,
9090
],
9191
})
9292
disableWorkspaceTrustArg = [disableWorkspaceTrust]
@@ -160,11 +160,11 @@ async function setupVSCodeTestInstance(suite: SuiteName): Promise<string> {
160160

161161
// Only certain test suites require specific vscode extensions to be installed
162162
if (suite === 'e2e' || suite === 'integration') {
163-
await installVSCodeExtension(vsCodeExecutablePath, VSCODE_EXTENSION_ID.python)
164-
await installVSCodeExtension(vsCodeExecutablePath, VSCODE_EXTENSION_ID.yaml)
165-
await installVSCodeExtension(vsCodeExecutablePath, VSCODE_EXTENSION_ID.go)
166-
await installVSCodeExtension(vsCodeExecutablePath, VSCODE_EXTENSION_ID.java)
167-
await installVSCodeExtension(vsCodeExecutablePath, VSCODE_EXTENSION_ID.javadebug)
163+
await installVSCodeExtension(vsCodeExecutablePath, VSCODE_EXTENSION_ID_CONSTANTS.python)
164+
await installVSCodeExtension(vsCodeExecutablePath, VSCODE_EXTENSION_ID_CONSTANTS.yaml)
165+
await installVSCodeExtension(vsCodeExecutablePath, VSCODE_EXTENSION_ID_CONSTANTS.go)
166+
await installVSCodeExtension(vsCodeExecutablePath, VSCODE_EXTENSION_ID_CONSTANTS.java)
167+
await installVSCodeExtension(vsCodeExecutablePath, VSCODE_EXTENSION_ID_CONSTANTS.javadebug)
168168
}
169169

170170
console.log('VS Code Test instance has been set up')

packages/core/src/awsService/sagemaker/detached-server/server.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ import { execFile } from 'child_process'
1717

1818
const pollInterval = 30 * 60 * 100 // 30 minutes
1919

20+
/**
21+
* Generic IDE process patterns for detection across all VS Code forks
22+
* Supports: VS Code, Cursor, Kiro, Windsurf, and other forks
23+
*/
24+
const IDE_PROCESS_PATTERNS = {
25+
windows: /Code\.exe|Cursor\.exe|Kiro\.exe|Windsurf\.exe/i,
26+
darwin: /(Visual Studio Code( - Insiders)?|Cursor|Kiro|Windsurf)\.app\/Contents\/MacOS\/Electron/,
27+
linux: /^(code(-insiders)?|cursor|kiro|windsurf|electron)$/i,
28+
}
29+
2030
const server = http.createServer((req: IncomingMessage, res: ServerResponse) => {
2131
const parsedUrl = url.parse(req.url || '', true)
2232

@@ -62,12 +72,13 @@ function checkVSCodeWindows(): Promise<boolean> {
6272
const platform = os.platform()
6373

6474
if (platform === 'win32') {
65-
execFile('tasklist', ['/FI', 'IMAGENAME eq Code.exe'], (err, stdout) => {
75+
// Check for any VS Code fork process
76+
execFile('tasklist', [], (err, stdout) => {
6677
if (err) {
6778
resolve(false)
6879
return
6980
}
70-
resolve(/Code\.exe/i.test(stdout))
81+
resolve(IDE_PROCESS_PATTERNS.windows.test(stdout))
7182
})
7283
} else if (platform === 'darwin') {
7384
execFile('ps', ['aux'], (err, stdout) => {
@@ -76,9 +87,7 @@ function checkVSCodeWindows(): Promise<boolean> {
7687
return
7788
}
7889

79-
const found = stdout
80-
.split('\n')
81-
.some((line) => /Visual Studio Code( - Insiders)?\.app\/Contents\/MacOS\/Electron/.test(line))
90+
const found = stdout.split('\n').some((line) => IDE_PROCESS_PATTERNS.darwin.test(line))
8291
resolve(found)
8392
})
8493
} else {
@@ -88,7 +97,7 @@ function checkVSCodeWindows(): Promise<boolean> {
8897
return
8998
}
9099

91-
const found = stdout.split('\n').some((line) => /^(code(-insiders)?|electron)$/i.test(line.trim()))
100+
const found = stdout.split('\n').some((line) => IDE_PROCESS_PATTERNS.linux.test(line.trim()))
92101
resolve(found)
93102
})
94103
}
@@ -99,7 +108,7 @@ async function monitorVSCodeAndExit() {
99108
while (true) {
100109
const found = await checkVSCodeWindows()
101110
if (!found) {
102-
console.log('No VSCode windows found. Shutting down detached server.')
111+
console.log('No IDE windows found. Shutting down detached server.')
103112
process.exit(0)
104113
}
105114
await new Promise((r) => setTimeout(r, pollInterval))
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
// eslint-disable-next-line @typescript-eslint/naming-convention
7+
export const VSCODE_REMOTE_SSH_EXTENSION = {
8+
cursor: {
9+
id: 'anysphere.remote-ssh',
10+
minVersion: '1.0.2',
11+
},
12+
vscode: {
13+
id: 'ms-vscode-remote.remote-ssh',
14+
minVersion: '0.74.0',
15+
},
16+
} as const
17+
18+
/**
19+
* Extension IDs that don't require runtime vscode access.
20+
* Safe to import in test environments.
21+
*/
22+
// eslint-disable-next-line @typescript-eslint/naming-convention
23+
export const VSCODE_EXTENSION_ID_CONSTANTS = {
24+
awstoolkit: 'amazonwebservices.aws-toolkit-vscode',
25+
amazonq: 'amazonwebservices.amazon-q-vscode',
26+
python: 'ms-python.python',
27+
// python depends on jupyter plugin
28+
jupyter: 'ms-toolsai.jupyter',
29+
yaml: 'redhat.vscode-yaml',
30+
go: 'golang.go',
31+
java: 'redhat.java',
32+
javadebug: 'vscjava.vscode-java-debug',
33+
dotnet: 'ms-dotnettools.csdevkit',
34+
git: 'vscode.git',
35+
// default to VSCode in test environment
36+
remotessh: VSCODE_REMOTE_SSH_EXTENSION.vscode,
37+
} as const

packages/core/src/shared/extensions.ts

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,37 @@ import { TelemetryService } from './telemetry/telemetryService'
1010
import { CredentialsStore } from '../auth/credentials/store'
1111
import { SamCliContext } from './sam/cli/samCliContext'
1212
import { UriHandler } from './vscode/uriHandler'
13+
import { VSCODE_EXTENSION_ID_CONSTANTS, VSCODE_REMOTE_SSH_EXTENSION } from './extensionIds'
1314

15+
// Determine the remote SSH extension based on the editor
16+
const getRemoteSshExtension = () => {
17+
const appName = vscode?.env?.appName?.toLowerCase()
18+
if (!appName) {
19+
return VSCODE_REMOTE_SSH_EXTENSION.vscode
20+
}
21+
22+
// Check each IDE key in the extension map
23+
for (const key of Object.keys(VSCODE_REMOTE_SSH_EXTENSION)) {
24+
if (appName.includes(key)) {
25+
return VSCODE_REMOTE_SSH_EXTENSION[key as keyof typeof VSCODE_REMOTE_SSH_EXTENSION]
26+
}
27+
}
28+
29+
return VSCODE_REMOTE_SSH_EXTENSION.vscode
30+
}
31+
32+
// For actual use in IDE, not test environment
1433
// eslint-disable-next-line @typescript-eslint/naming-convention
1534
export const VSCODE_EXTENSION_ID = {
16-
awstoolkit: 'amazonwebservices.aws-toolkit-vscode',
17-
amazonq: 'amazonwebservices.amazon-q-vscode',
18-
python: 'ms-python.python',
19-
// python depends on jupyter plugin
20-
jupyter: 'ms-toolsai.jupyter',
21-
yaml: 'redhat.vscode-yaml',
22-
go: 'golang.go',
23-
java: 'redhat.java',
24-
javadebug: 'vscjava.vscode-java-debug',
25-
dotnet: 'ms-dotnettools.csdevkit',
26-
git: 'vscode.git',
27-
remotessh: 'ms-vscode-remote.remote-ssh',
28-
} as const
29-
30-
export const vscodeExtensionMinVersion = {
31-
remotessh: '0.74.0',
35+
...VSCODE_EXTENSION_ID_CONSTANTS,
36+
get remotessh(): { readonly id: string; readonly minVersion: string } {
37+
return getRemoteSshExtension()
38+
},
3239
}
3340

41+
// Re-export for backward compatibility
42+
export { VSCODE_REMOTE_SSH_EXTENSION }
43+
3444
/** @deprecated Use `extensionGlobals.ts:globals` instead. */
3545
export interface ExtContext {
3646
extensionContext: vscode.ExtensionContext

packages/core/src/shared/remoteSession.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import * as vscode from 'vscode'
77
import * as nls from 'vscode-nls'
88
const localize = nls.loadMessageBundle()
99

10+
import { getIdeInfo } from './vscode/env'
1011
import { Settings } from '../shared/settings'
1112
import { showConfirmationMessage, showMessageWithCancel } from './utilities/messages'
1213
import { CancellationError, Timeout } from './utilities/timeoutUtils'
1314
import { isExtensionInstalled, showInstallExtensionMsg } from './utilities/vsCodeUtils'
14-
import { VSCODE_EXTENSION_ID, vscodeExtensionMinVersion } from './extensions'
15+
import { VSCODE_EXTENSION_ID } from './extensions'
1516
import { Err, Result } from '../shared/utilities/result'
1617
import { ToolkitError, UnknownError } from './errors'
1718
import { getLogger } from './logger/logger'
@@ -31,7 +32,7 @@ export enum RemoteSessionError {
3132
}
3233

3334
export interface MissingTool {
34-
readonly name: 'code' | 'ssm' | 'ssh'
35+
readonly name: string
3536
readonly reason?: string
3637
}
3738

@@ -108,19 +109,19 @@ export async function ensureDependencies(): Promise<Result<DependencyPaths, Canc
108109
}
109110

110111
export async function ensureRemoteSshInstalled(): Promise<void> {
111-
if (!isExtensionInstalled(VSCODE_EXTENSION_ID.remotessh, vscodeExtensionMinVersion.remotessh)) {
112+
if (!isExtensionInstalled(VSCODE_EXTENSION_ID.remotessh.id, VSCODE_EXTENSION_ID.remotessh.minVersion)) {
112113
showInstallExtensionMsg(
113-
VSCODE_EXTENSION_ID.remotessh,
114+
VSCODE_EXTENSION_ID.remotessh.id,
114115
'Remote SSH',
115116
'Connecting to Dev Environment',
116-
vscodeExtensionMinVersion.remotessh
117+
VSCODE_EXTENSION_ID.remotessh.minVersion
117118
)
118119

119-
if (isExtensionInstalled(VSCODE_EXTENSION_ID.remotessh)) {
120+
if (isExtensionInstalled(VSCODE_EXTENSION_ID.remotessh.id)) {
120121
throw new ToolkitError('Remote SSH extension version is too low', {
121122
cancelled: true,
122123
code: RemoteSessionError.ExtensionVersionTooLow,
123-
details: { expected: vscodeExtensionMinVersion.remotessh },
124+
details: { expected: VSCODE_EXTENSION_ID.remotessh.minVersion },
124125
})
125126
} else {
126127
throw new ToolkitError('Remote SSH extension not installed', {
@@ -146,8 +147,11 @@ async function ensureSsmCli() {
146147
export async function ensureTools() {
147148
const [vsc, ssh, ssm] = await Promise.all([getVscodeCliPath(), findSshPath(), ensureSsmCli()])
148149

150+
const ideInfo = getIdeInfo()
151+
const cliName = ideInfo.cliName
152+
149153
const missing: MissingTool[] = []
150-
pushIf(missing, vsc === undefined, { name: 'code' })
154+
pushIf(missing, vsc === undefined, { name: cliName })
151155
pushIf(missing, ssh === undefined, { name: 'ssh' })
152156

153157
if (ssm.isErr()) {

packages/core/src/shared/utilities/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
export { isExtensionInstalled, isExtensionActive } from './vsCodeUtils'
77
export { VSCODE_EXTENSION_ID } from '../extensions'
8+
export { VSCODE_EXTENSION_ID_CONSTANTS } from '../extensionIds'
89
export * from './functionUtils'
910
export * as messageUtils from './messages'
1011
export * as CommentUtils from './commentUtils'

packages/core/src/shared/utilities/pathFind.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { Settings } from '../settings'
1212
import { getLogger } from '../logger/logger'
1313
import { mergeResolvedShellPath } from '../env/resolveEnv'
1414
import { matchesPattern } from './textUtilities'
15+
import { getIdeInfo } from '../vscode/env'
1516

1617
/** Full path to VSCode CLI. */
1718
let vscPath: string
@@ -52,7 +53,7 @@ export async function tryRun(
5253
}
5354

5455
/**
55-
* Gets the fullpath to `code` (VSCode CLI), or falls back to "code" (not
56+
* Gets the fullpath to the IDE CLI (code, cursor, kiro, windsurf, etc.), or falls back to the CLI name (not
5657
* absolute) if it works.
5758
*
5859
* @see https://github.com/microsoft/vscode-test/blob/4bdccd4c386813a8158b0f9b96f31cbbecbb3374/lib/util.ts#L133
@@ -62,27 +63,30 @@ export async function getVscodeCliPath(): Promise<string | undefined> {
6263
return vscPath
6364
}
6465

66+
const ideInfo = getIdeInfo()
67+
const cliName = ideInfo.cliName || 'code'
68+
6569
const vscExe = process.argv0
6670
// https://github.com/microsoft/vscode-test/blob/4bdccd4c386813a8158b0f9b96f31cbbecbb3374/lib/util.ts#L133
6771
const vscs = [
6872
// Special case for flatpak (steamdeck). #V896741845
6973
// https://github.com/flathub/com.visualstudio.code/blob/master/code.sh
70-
'/app/bin/code',
74+
`/app/bin/${cliName}`,
7175
// Note: macOS does not have a separate "code-insiders" binary.
72-
path.resolve(`${vscode.env.appRoot}/bin/code`), // macOS
73-
path.resolve(`${vscode.env.appRoot}/../../bin/code`), // Windows
74-
path.resolve(`${vscode.env.appRoot}/../../bin/code-insiders`), // Windows
76+
path.resolve(`${vscode.env.appRoot}/bin/${cliName}`), // macOS
77+
path.resolve(`${vscode.env.appRoot}/../../bin/${cliName}`), // Windows
78+
path.resolve(`${vscode.env.appRoot}/../../bin/${cliName}-insiders`), // Windows
7579
// Linux example "appRoot": vscode-linux-x64-1.42.0/VSCode-linux-x64/resources/app
76-
path.resolve(`${vscode.env.appRoot}/code`),
77-
path.resolve(vscExe, '../bin/code-insiders'),
78-
path.resolve(vscExe, '../bin/code'),
79-
path.resolve(vscExe, '../../bin/code-insiders'),
80-
path.resolve(vscExe, '../../bin/code'),
81-
'/usr/bin/code',
82-
'code', // $PATH
80+
path.resolve(`${vscode.env.appRoot}/${cliName}`),
81+
path.resolve(vscExe, `../bin/${cliName}-insiders`),
82+
path.resolve(vscExe, `../bin/${cliName}`),
83+
path.resolve(vscExe, `../../bin/${cliName}-insiders`),
84+
path.resolve(vscExe, `../../bin/${cliName}`),
85+
`/usr/bin/${cliName}`,
86+
cliName, // $PATH
8387
]
8488
for (const vsc of vscs) {
85-
if (!vsc || (vsc !== 'code' && !(await fs.exists(vsc)))) {
89+
if (!vsc || (vsc !== cliName && !(await fs.exists(vsc)))) {
8690
continue
8791
}
8892
if (await tryRun(vsc, ['--version'])) {

0 commit comments

Comments
 (0)