|
3 | 3 | * Licensed under the MIT License. See License.txt in the project root for license information.
|
4 | 4 | *--------------------------------------------------------------------------------------------*/
|
5 | 5 |
|
| 6 | +import { v4 as uuid } from 'uuid'; |
6 | 7 | import { AutoTunnelRequest, ResolveSSHConnectionRequest, ResolveSSHConnectionResponse } from '@gitpod/local-app-api-grpcweb/lib/localapp_pb';
|
7 | 8 | import { LocalAppClient } from '@gitpod/local-app-api-grpcweb/lib/localapp_pb_service';
|
8 | 9 | import { NodeHttpTransport } from '@improbable-eng/grpc-web-node-http-transport';
|
@@ -736,7 +737,7 @@ export default class RemoteConnector extends Disposable {
|
736 | 737 | throw new Error('SSH password modal dialog, Canceled');
|
737 | 738 | }
|
738 | 739 |
|
739 |
| - private async ensureValidGitpodHost(gitpodHost: string, flow: UserFlowTelemetry): Promise<boolean>{ |
| 740 | + private async ensureValidGitpodHost(gitpodHost: string, flow: UserFlowTelemetry): Promise<boolean> { |
740 | 741 | const config = vscode.workspace.getConfiguration('gitpod');
|
741 | 742 | const currentGitpodHost = config.get<string>('host')!;
|
742 | 743 | if (new URL(gitpodHost).host !== new URL(currentGitpodHost).host) {
|
@@ -951,48 +952,84 @@ export default class RemoteConnector extends Disposable {
|
951 | 952 | }
|
952 | 953 | }
|
953 | 954 |
|
954 |
| - private async initializeRemoteExtensions(flow: UserFlowTelemetry) { |
| 955 | + private async initializeRemoteExtensions(flow: UserFlowTelemetry & { quiet: boolean, flowId: string }) { |
| 956 | + this.telemetry.sendUserFlowStatus('enabled', flow); |
955 | 957 | let syncData: { ref: string; content: string } | undefined;
|
956 | 958 | try {
|
957 | 959 | syncData = await this.settingsSync.readResource(SyncResource.Extensions);
|
958 | 960 | } catch (e) {
|
959 | 961 | if (e instanceof NoSyncStoreError) {
|
960 |
| - const addSyncProvider = 'Settings Sync: Enable Sign In with Gitpod'; |
961 |
| - const action = await this.notifications.showInformationMessage(`Could not install local extensions on remote workspace. Please enable [Settings Sync](https://www.gitpod.io/docs/ides-and-editors/settings-sync#enabling-settings-sync-in-vs-code-desktop) with Gitpod.`, { flow, id: 'no_sync_store' }, addSyncProvider); |
962 |
| - if (action === addSyncProvider) { |
963 |
| - vscode.commands.executeCommand('gitpod.syncProvider.add'); |
| 962 | + const msg = `Could not install local extensions on remote workspace. Please enable [Settings Sync](https://www.gitpod.io/docs/ides-and-editors/settings-sync#enabling-settings-sync-in-vs-code-desktop) with Gitpod.`; |
| 963 | + this.logger.error(msg); |
| 964 | + |
| 965 | + const status = 'no_sync_store'; |
| 966 | + if (flow.quiet) { |
| 967 | + this.telemetry.sendUserFlowStatus(status, flow); |
| 968 | + } else { |
| 969 | + const addSyncProvider = 'Settings Sync: Enable Sign In with Gitpod'; |
| 970 | + const action = await this.notifications.showInformationMessage(msg, { flow, id: status }, addSyncProvider); |
| 971 | + if (action === addSyncProvider) { |
| 972 | + vscode.commands.executeCommand('gitpod.syncProvider.add'); |
| 973 | + } |
964 | 974 | }
|
965 | 975 | } else if (e instanceof NoSettingsSyncSession) {
|
966 |
| - const enableSettingsSync = 'Enable Settings Sync'; |
967 |
| - const action = await this.notifications.showInformationMessage(`Could not install local extensions on remote workspace. Please enable [Settings Sync](https://www.gitpod.io/docs/ides-and-editors/settings-sync#enabling-settings-sync-in-vs-code-desktop).`, { flow, id: 'no_settings_sync' }, enableSettingsSync); |
968 |
| - if (action === enableSettingsSync) { |
969 |
| - vscode.commands.executeCommand('workbench.userDataSync.actions.turnOn'); |
| 976 | + const msg = `Could not install local extensions on remote workspace. Please enable [Settings Sync](https://www.gitpod.io/docs/ides-and-editors/settings-sync#enabling-settings-sync-in-vs-code-desktop) with Gitpod.`; |
| 977 | + this.logger.error(msg); |
| 978 | + |
| 979 | + const status = 'no_settings_sync'; |
| 980 | + if (flow.quiet) { |
| 981 | + this.telemetry.sendUserFlowStatus(status, flow); |
| 982 | + } else { |
| 983 | + const enableSettingsSync = 'Enable Settings Sync'; |
| 984 | + const action = await this.notifications.showInformationMessage(msg, { flow, id: status }, enableSettingsSync); |
| 985 | + if (action === enableSettingsSync) { |
| 986 | + vscode.commands.executeCommand('workbench.userDataSync.actions.turnOn'); |
| 987 | + } |
970 | 988 | }
|
971 | 989 | } else {
|
972 | 990 | this.logger.error('Error while fetching settings sync extension data:', e);
|
973 | 991 |
|
974 |
| - const seeLogs = 'See Logs'; |
975 |
| - const action = await this.notifications.showErrorMessage(`Error while fetching settings sync extension data.`, { flow, id: 'failed_to_fetch' }, seeLogs); |
976 |
| - if (action === seeLogs) { |
977 |
| - this.logger.show(); |
| 992 | + const status = 'failed_to_fetch'; |
| 993 | + if (flow.quiet) { |
| 994 | + this.telemetry.sendUserFlowStatus(status, flow); |
| 995 | + } else { |
| 996 | + const seeLogs = 'See Logs'; |
| 997 | + const action = await this.notifications.showErrorMessage(`Error while fetching settings sync extension data.`, { flow, id: status }, seeLogs); |
| 998 | + if (action === seeLogs) { |
| 999 | + this.logger.show(); |
| 1000 | + } |
978 | 1001 | }
|
979 | 1002 | }
|
980 | 1003 | return;
|
981 | 1004 | }
|
982 | 1005 |
|
983 | 1006 | const syncDataContent = parseSyncData(syncData.content);
|
984 | 1007 | if (!syncDataContent) {
|
985 |
| - this.telemetry.sendUserFlowStatus('failed_to_parse_content', flow); |
986 |
| - this.logger.error('Error while parsing sync data'); |
| 1008 | + const msg = `Error while parsing settings sync extension data.`; |
| 1009 | + this.logger.error(msg); |
| 1010 | + |
| 1011 | + const status = 'failed_to_parse_content'; |
| 1012 | + if (flow.quiet) { |
| 1013 | + this.telemetry.sendUserFlowStatus(status, flow); |
| 1014 | + } else { |
| 1015 | + await this.notifications.showErrorMessage(msg, { flow, id: status }); |
| 1016 | + } |
987 | 1017 | return;
|
988 | 1018 | }
|
989 | 1019 |
|
990 | 1020 | let extensions: ISyncExtension[];
|
991 | 1021 | try {
|
992 | 1022 | extensions = JSON.parse(syncDataContent.content);
|
993 | 1023 | } catch {
|
994 |
| - this.telemetry.sendUserFlowStatus('failed_to_parse_json', flow); |
995 |
| - this.logger.error('Error while parsing settings sync extension data, malformed json'); |
| 1024 | + const msg = `Error while parsing settings sync extension data, malformed JSON.`; |
| 1025 | + this.logger.error(msg); |
| 1026 | + |
| 1027 | + const status = 'failed_to_parse_json'; |
| 1028 | + if (flow.quiet) { |
| 1029 | + this.telemetry.sendUserFlowStatus(status, flow); |
| 1030 | + } else { |
| 1031 | + await this.notifications.showErrorMessage(msg, { flow, id: status }); |
| 1032 | + } |
996 | 1033 | return;
|
997 | 1034 | }
|
998 | 1035 |
|
@@ -1020,10 +1057,18 @@ export default class RemoteConnector extends Disposable {
|
1020 | 1057 | });
|
1021 | 1058 | this.telemetry.sendUserFlowStatus('synced', flow);
|
1022 | 1059 | } catch {
|
1023 |
| - const seeLogs = 'See Logs'; |
1024 |
| - const action = await this.notifications.showErrorMessage(`Error while installing local extensions on remote.`, { flow, id: 'failed' }, seeLogs); |
1025 |
| - if (action === seeLogs) { |
1026 |
| - this.logger.show(); |
| 1060 | + const msg = `Error while installing local extensions on remote.`; |
| 1061 | + this.logger.error(msg); |
| 1062 | + |
| 1063 | + const status = 'failed'; |
| 1064 | + if (flow.quiet) { |
| 1065 | + this.telemetry.sendUserFlowStatus(status, flow); |
| 1066 | + } else { |
| 1067 | + const seeLogs = 'See Logs'; |
| 1068 | + const action = await this.notifications.showErrorMessage(msg, { flow, id: status }, seeLogs); |
| 1069 | + if (action === seeLogs) { |
| 1070 | + this.logger.show(); |
| 1071 | + } |
1027 | 1072 | }
|
1028 | 1073 | }
|
1029 | 1074 | }
|
@@ -1066,13 +1111,13 @@ export default class RemoteConnector extends Disposable {
|
1066 | 1111 | this.logger.warn(`Local heartbeat not supported in ${connectionInfo.gitpodHost}, using version ${gitpodVersion.raw}`);
|
1067 | 1112 | }
|
1068 | 1113 |
|
1069 |
| - const syncExtensions = (await this.experiments.get<boolean>('gitpod.remote.syncExtensions', session.account.id, { gitpodHost: connectionInfo.gitpodHost }))!; |
1070 |
| - const userOverride = String(isUserOverrideSetting('gitpod.remote.syncExtensions')); |
1071 |
| - const syncExtFlow = { ...connectionInfo, gitpodVersion: gitpodVersion.raw, userId: session.account.id, flow: 'sync_local_extensions', userOverride }; |
1072 |
| - this.telemetry.sendUserFlowStatus(syncExtensions ? 'enabled' : 'disabled', syncExtFlow); |
1073 |
| - if (syncExtensions) { |
1074 |
| - this.initializeRemoteExtensions(syncExtFlow); |
1075 |
| - } |
| 1114 | + const syncExtFlow = { ...connectionInfo, gitpodVersion: gitpodVersion.raw, userId: session.account.id, flow: 'sync_local_extensions' }; |
| 1115 | + this.initializeRemoteExtensions({ ...syncExtFlow, quiet: true, flowId: uuid() }); |
| 1116 | + this.context.subscriptions.push(vscode.commands.registerCommand("gitpod.installLocalExtensions", () => { |
| 1117 | + this.initializeRemoteExtensions({ ...syncExtFlow, quiet: false, flowId: uuid() }); |
| 1118 | + })); |
| 1119 | + |
| 1120 | + vscode.commands.executeCommand('setContext', 'gitpod.inWorkspace', true); |
1076 | 1121 | }
|
1077 | 1122 |
|
1078 | 1123 | public override async dispose(): Promise<void> {
|
|
0 commit comments