Path: blob/main/extensions/copilot/test/simulation/fixtures/generate/issue-7772/builds.ts
13405 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See LICENSE in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import chalk from 'chalk';6import { rmSync } from 'fs';7import { dirname, join } from 'path';8import { LOGGER, Platform, platform, Runtime } from './constants';9import { fileGet, jsonGet } from './fetch';10import { exists, getBuildPath, unzip } from './files';1112export interface IBuild {13readonly runtime: Runtime;14readonly commit: string;15}1617interface IBuildMetadata {18readonly url: string;19readonly productVersion: string;20readonly sha256hash: string;21}2223class Builds {2425async fetchBuilds(runtime = Runtime.WebLocal, goodCommit?: string, badCommit?: string, releasedOnly?: boolean): Promise<IBuild[]> {2627// Fetch all released insider builds28const allBuilds = await this.fetchAllBuilds(runtime, releasedOnly);2930let goodCommitIndex = allBuilds.length - 1; // last build (oldest) by default31let badCommitIndex = 0; // first build (newest) by default3233if (typeof goodCommit === 'string') {34const candidateGoodCommitIndex = this.indexOf(goodCommit, allBuilds);35if (typeof candidateGoodCommitIndex !== 'number') {36throw new Error(`Provided good commit ${chalk.green(goodCommit)} was not found in the list of insiders builds. Try running with ${chalk.green('--releasedOnly')} to support older builds.`);37}3839goodCommitIndex = candidateGoodCommitIndex;40}4142if (typeof badCommit === 'string') {43const candidateBadCommitIndex = this.indexOf(badCommit, allBuilds);44if (typeof candidateBadCommitIndex !== 'number') {45throw new Error(`Provided bad commit ${chalk.green(badCommit)} was not found in the list of insiders builds. Try running with ${chalk.green('--releasedOnly')} to support older builds.`);46}4748badCommitIndex = candidateBadCommitIndex;49}5051if (badCommitIndex >= goodCommitIndex) {52throw new Error(`Provided bad commit ${chalk.green(badCommit)} cannot be older or same as good commit ${chalk.green(goodCommit)}.`);53}5455// Build a range based on the bad and good commits if any56const buildsInRange = allBuilds.slice(badCommitIndex, goodCommitIndex + 1);5758// Drop those builds that are not on main branch59return buildsInRange;60}6162private indexOf(commit: string, builds: IBuild[]): number | undefined {63for (let i = 0; i < builds.length; i++) {64const build = builds[i];65if (build.commit === commit) {66return i;67}68}6970return undefined;71}7273private async fetchAllBuilds(runtime: Runtime, releasedOnly = false): Promise<IBuild[]> {74const url = `https://update.code.visualstudio.com/api/commits/insider/${this.getBuildApiName(runtime)}?released=${releasedOnly}`;75console.log(`${chalk.gray('[build]')} fetching all builds from ${chalk.green(url)}...`);76const commits = await jsonGet<Array<string>>(url);7778return commits.map(commit => ({ commit, runtime }));79}8081private getBuildApiName(runtime: Runtime): string {82switch (runtime) {83case Runtime.WebLocal:84case Runtime.WebRemote:85switch (platform) {86case Platform.MacOSX64:87case Platform.MacOSArm:88return 'server-darwin-web';89case Platform.LinuxX64:90case Platform.LinuxArm:91return 'server-linux-x64-web';92case Platform.WindowsX64:93case Platform.WindowsArm:94return 'server-win32-x64-web';95}9697case Runtime.DesktopLocal:98switch (platform) {99case Platform.MacOSX64:100return 'darwin';101case Platform.MacOSArm:102return 'darwin-arm64';103case Platform.LinuxX64:104return 'linux-x64';105case Platform.LinuxArm:106return 'linux-arm64';107case Platform.WindowsX64:108return 'win32-x64';109case Platform.WindowsArm:110return 'win32-arm64';111}112}113}114115async installBuild({ runtime, commit }: IBuild, options?: { forceReDownload: boolean }): Promise<void> {116const buildName = await this.getBuildArchiveName({ runtime, commit });117118const path = join(getBuildPath(commit), buildName);119120const pathExists = await exists(path);121if (pathExists && !options?.forceReDownload) {122if (LOGGER.verbose) {123console.log(`${chalk.gray('[build]')} using ${chalk.green(path)} for the next build to try`);124}125126return; // assume the build is cached127}128129if (pathExists && options?.forceReDownload) {130console.log(`${chalk.gray('[build]')} deleting ${chalk.green(getBuildPath(commit))} and retrying download`);131rmSync(getBuildPath(commit), { recursive: true });132}133134// Download135const url = `https://update.code.visualstudio.com/commit:${commit}/${this.getPlatformName(runtime)}/insider`;136console.log(`${chalk.gray('[build]')} downloading build from ${chalk.green(url)}...`);137await fileGet(url, path);138139const sha256 = (await this.fetchBuildMeta({ runtime, commit })).sha256hash;140console.log(`${chalk.gray('[build]')} validating build sha256 hash...`);141142143// Unzip144let destination: string;145if (runtime === Runtime.DesktopLocal && platform === Platform.WindowsX64 || platform === Platform.WindowsArm) {146// zip does not contain a single top level folder to use...147destination = path.substring(0, path.lastIndexOf('.zip'));148} else {149// zip contains a single top level folder to use150destination = dirname(path);151}152console.log(`${chalk.gray('[build]')} unzipping build to ${chalk.green(destination)}...`);153await unzip(path, destination);154}155156private async getBuildArchiveName({ runtime, commit }: IBuild): Promise<string> {157switch (runtime) {158159// We currently do not have ARM enabled servers160// so we fallback to x64 until we ship ARM.161case Runtime.WebLocal:162case Runtime.WebRemote:163switch (platform) {164case Platform.MacOSX64:165return 'vscode-server-darwin-x64-web.zip';166case Platform.MacOSArm:167return 'vscode-server-darwin-arm64-web.zip';168case Platform.LinuxX64:169return 'vscode-server-linux-arm64-web.tar.gz';170case Platform.LinuxArm:171return 'vscode-server-linux-x64-web.tar.gz';172case Platform.WindowsX64:173case Platform.WindowsArm:174return 'vscode-server-win32-x64-web.zip';175}176177// Every platform has its own name scheme, hilarious right?178// - macOS: just the name, nice! (e.g. VSCode-darwin.zip)179// - Linux: includes some unix timestamp (e.g. code-insider-x64-1639979337.tar.gz)180// - Windows: includes the version (e.g. VSCode-win32-x64-1.64.0-insider.zip)181case Runtime.DesktopLocal:182switch (platform) {183case Platform.MacOSX64:184return 'VSCode-darwin.zip';185case Platform.MacOSArm:186return 'VSCode-darwin-arm64.zip';187case Platform.LinuxX64:188case Platform.LinuxArm:189return (await this.fetchBuildMeta({ runtime, commit })).url.split('/').pop()!; // e.g. https://az764295.vo.msecnd.net/insider/807bf598bea406dcb272a9fced54697986e87768/code-insider-x64-1639979337.tar.gz190case Platform.WindowsX64:191case Platform.WindowsArm: {192const buildMeta = await this.fetchBuildMeta({ runtime, commit });193194return platform === Platform.WindowsX64 ? `VSCode-win32-x64-${buildMeta.productVersion}.zip` : `VSCode-win32-arm64-${buildMeta.productVersion}.zip`;195}196}197}198}199200async getBuildName({ runtime, commit }: IBuild): Promise<string> {201switch (runtime) {202case Runtime.WebLocal:203case Runtime.WebRemote:204switch (platform) {205case Platform.MacOSX64:206return 'vscode-server-darwin-x64-web';207case Platform.MacOSArm:208return 'vscode-server-darwin-arm64-web';209case Platform.LinuxX64:210return 'vscode-server-linux-arm64-web';211case Platform.LinuxArm:212return 'vscode-server-linux-x64-web';213case Platform.WindowsX64:214case Platform.WindowsArm:215return 'vscode-server-win32-x64-web';216}217218// Here, only Windows does not play by our rules and adds the version number219// - Windows: includes the version (e.g. VSCode-win32-x64-1.64.0-insider)220case Runtime.DesktopLocal:221switch (platform) {222case Platform.MacOSX64:223case Platform.MacOSArm:224return 'Visual Studio Code - Insiders.app';225case Platform.LinuxX64:226return 'VSCode-linux-x64';227case Platform.LinuxArm:228return 'VSCode-linux-arm64';229case Platform.WindowsX64:230case Platform.WindowsArm: {231const buildMeta = await this.fetchBuildMeta({ runtime, commit });232233return platform === Platform.WindowsX64 ? `VSCode-win32-x64-${buildMeta.productVersion}` : `VSCode-win32-arm64-${buildMeta.productVersion}`;234}235}236}237}238239private getPlatformName(runtime: Runtime): string {240switch (runtime) {241case Runtime.WebLocal:242case Runtime.WebRemote:243switch (platform) {244case Platform.MacOSX64:245return 'server-darwin-web';246case Platform.MacOSArm:247return 'server-darwin-arm64-web';248case Platform.LinuxX64:249return 'server-linux-x64-web';250case Platform.LinuxArm:251return 'server-linux-arm64-web';252case Platform.WindowsX64:253case Platform.WindowsArm:254return 'server-win32-x64-web';255}256257case Runtime.DesktopLocal:258switch (platform) {259case Platform.MacOSX64:260return 'darwin';261case Platform.MacOSArm:262return 'darwin-arm64';263case Platform.LinuxX64:264return 'linux-x64';265case Platform.LinuxArm:266return 'linux-arm64';267case Platform.WindowsX64:268return 'win32-x64-archive';269case Platform.WindowsArm: {270return 'win32-arm64-archive';271}272}273}274}275276private fetchBuildMeta({ runtime, commit }: IBuild): Promise<IBuildMetadata> {277return jsonGet<IBuildMetadata>(`https://update.code.visualstudio.com/api/versions/commit:${commit}/${this.getBuildApiName(runtime)}/insider`);278}279280async getBuildExecutable({ runtime, commit }: IBuild): Promise<string> {281const buildPath = getBuildPath(commit);282const buildName = await builds.getBuildName({ runtime, commit });283284switch (runtime) {285case Runtime.WebLocal:286case Runtime.WebRemote:287switch (platform) {288case Platform.MacOSX64:289case Platform.MacOSArm:290case Platform.LinuxX64:291case Platform.LinuxArm: {292const oldLocation = join(buildPath, buildName, 'server.sh');293if (await exists(oldLocation)) {294return oldLocation; // only valid until 1.64.x295}296297return join(buildPath, buildName, 'bin', 'code-server-insiders');298}299case Platform.WindowsX64:300case Platform.WindowsArm: {301const oldLocation = join(buildPath, buildName, 'server.cmd');302if (await exists(oldLocation)) {303return oldLocation; // only valid until 1.64.x304}305306return join(buildPath, buildName, 'bin', 'code-server-insiders.cmd');307}308}309310case Runtime.DesktopLocal:311switch (platform) {312case Platform.MacOSX64:313case Platform.MacOSArm:314return join(buildPath, buildName, 'Contents', 'MacOS', 'Electron')315case Platform.LinuxX64:316case Platform.LinuxArm:317return join(buildPath, buildName, 'code-insiders')318case Platform.WindowsX64:319case Platform.WindowsArm:320return join(buildPath, buildName, 'Code - Insiders.exe')321}322}323}324}325326export const builds = new Builds();327328329