|
2 | 2 | * Copyright (c) Gitpod. All rights reserved. |
3 | 3 | * Licensed under the MIT License. See License.txt in the project root for license information. |
4 | 4 | *--------------------------------------------------------------------------------------------*/ |
5 | | -import * as vscode from 'vscode'; |
6 | | -import * as semver from 'semver'; |
7 | | -import { retry } from './common/async'; |
8 | | -import { ILogService } from './services/logService'; |
9 | | - |
10 | | -export class GitpodVersion { |
11 | | - static MAX_VERSION = '9999.99.99'; |
12 | | - static MIN_VERSION = '0.0.0'; |
13 | | - |
14 | | - static Max = new GitpodVersion(GitpodVersion.MAX_VERSION); |
15 | | - static Min = new GitpodVersion(GitpodVersion.MIN_VERSION); |
16 | | - |
17 | | - readonly version: string; |
18 | | - readonly raw: string; |
19 | | - |
20 | | - constructor(gitpodVersion: string) { |
21 | | - this.raw = gitpodVersion; |
22 | | - this.version = GitpodVersion.MIN_VERSION; |
23 | | - |
24 | | - // Check for yyyy.mm.dd format |
25 | | - const match = /(?:\.|-|^)(\d{4}\.\d{1,2}\.\d{1,2})(?:\.|-|$)/.exec(gitpodVersion); |
26 | | - if (match) { |
27 | | - // Remove leading zeros to make it a valid semver |
28 | | - const [yy, mm, dd] = match[1].split('.'); |
29 | | - gitpodVersion = `${parseInt(yy, 10)}.${parseInt(mm, 10)}.${parseInt(dd, 10)}`; |
30 | | - |
31 | | - } |
32 | | - |
33 | | - if (semver.valid(gitpodVersion)) { |
34 | | - this.version = gitpodVersion; |
35 | | - } |
36 | | - } |
37 | | -} |
38 | | - |
39 | | -let cacheGitpodVersion: { host: string; version: GitpodVersion } | undefined; |
40 | | -async function getOrFetchVersionInfo(serviceUrl: string, logger: ILogService) { |
41 | | - if (serviceUrl === 'https://gitpod.io') { |
42 | | - // SaaS default allow all features, should proper handle SaaS feature support if needed in the future |
43 | | - return { |
44 | | - host: serviceUrl, |
45 | | - version: GitpodVersion.Max, |
46 | | - }; |
47 | | - } |
48 | | - |
49 | | - if (serviceUrl === cacheGitpodVersion?.host) { |
50 | | - return cacheGitpodVersion; |
51 | | - } |
52 | | - |
53 | | - const versionEndPoint = `${serviceUrl}/api/version`; |
54 | | - let gitpodRawVersion: string | undefined; |
55 | | - try { |
56 | | - gitpodRawVersion = await retry(async () => { |
57 | | - const controller = new AbortController(); |
58 | | - setTimeout(() => controller.abort(), 1500); |
59 | | - const resp = await fetch(versionEndPoint, { signal: controller.signal }); |
60 | | - if (!resp.ok) { |
61 | | - throw new Error(`Responded with ${resp.status} ${resp.statusText}`); |
62 | | - } |
63 | | - return resp.text(); |
64 | | - }, 1000, 3); |
65 | | - } catch (e) { |
66 | | - logger.error(`Error while fetching ${versionEndPoint}`, e); |
67 | | - } |
68 | | - |
69 | | - if (!gitpodRawVersion) { |
70 | | - logger.info(`Failed to fetch version from ${versionEndPoint}, some feature will be disabled`); |
71 | | - return { |
72 | | - host: serviceUrl, |
73 | | - version: GitpodVersion.Min, |
74 | | - }; |
75 | | - } |
76 | | - |
77 | | - logger.info(`Got version from: ${serviceUrl} version: ${gitpodRawVersion}`); |
78 | | - |
79 | | - cacheGitpodVersion = { |
80 | | - host: serviceUrl, |
81 | | - version: new GitpodVersion(gitpodRawVersion) |
82 | | - }; |
83 | | - return cacheGitpodVersion; |
84 | | -} |
85 | | - |
86 | | -export async function getGitpodVersion(gitpodHost: string, logger: ILogService) { |
87 | | - const serviceUrl = new URL(gitpodHost).toString().replace(/\/$/, ''); |
88 | | - const versionInfo = await getOrFetchVersionInfo(serviceUrl, logger); |
89 | | - return versionInfo.version; |
90 | | -} |
91 | | - |
92 | | -type Feature = | |
93 | | - 'SSHPublicKeys' | |
94 | | - 'localHeartbeat'; |
95 | | - |
96 | | -export function isFeatureSupported(gitpodVersion: GitpodVersion, feature: Feature) { |
97 | | - switch (feature) { |
98 | | - case 'SSHPublicKeys': |
99 | | - case 'localHeartbeat': |
100 | | - return semver.gte(gitpodVersion.version, '2022.7.0'); // Don't use leading zeros |
101 | | - } |
102 | | -} |
103 | | - |
104 | | -export async function isOauthInspectSupported(gitpodHost: string,) { |
105 | | - const serviceUrl = new URL(gitpodHost).toString().replace(/\/$/, ''); |
106 | | - const endpoint = `${serviceUrl}/api/oauth/inspect?client=${vscode.env.uriScheme}-gitpod`; |
107 | | - try { |
108 | | - const controller = new AbortController(); |
109 | | - setTimeout(() => controller.abort(), 1500); |
110 | | - const resp = await fetch(endpoint, { signal: controller.signal }); |
111 | | - if (resp.ok) { |
112 | | - return true; |
113 | | - } |
114 | | - } catch { |
115 | | - } |
116 | | - |
117 | | - return false; |
118 | | -} |
119 | 5 |
|
120 | 6 | export enum ScopeFeature { |
121 | 7 | SSHPublicKeys = 'function:getSSHPublicKeys', |
|
0 commit comments