Files
vscode/build/linux/debian/install-sysroot.js
Robo b5a6aa14a8 feat: switch to npm as default package manager (#226927)
* feat: move from yarn to npm

* chore: skip yarn.lock files

* fix: playwright download

* chore: fix compile and hygiene

* chore: bump vsce@2.17.0

Refs 8b49e9dfdf

* test: update results for bat and sh colorizer tests

* fix: add missing lock files for windows

* fix: switch to legacy-peer-deps

* chore: update markdown-it@14.1.0

Refs 737c95a129

esbuild step in extensions-ci-pr was previously using markdown-it
from root which had userland punycode and was able to compile successfully.

* ci: increase pr timeout for windows integration tests

* chore: fix product build

* build: ignore extension dev dependency for rcedit

* build: fix working directory inside container

* build: fix dependency generation

* npm: update dependencies

* ci: use global npmrc

* ci: update cache

* ci: setup global npmrc for private npm auth

* build: fix extension bundling

* chore: sync npm dependencies

* ci: debug env variables for container

* ci: fix win32 cli pipeline

* build: fix npmrc config usage for build/ and remote/ dirs

* fix: windows build

* fix: container builds

* fix: markdown-language-features tests and bundling

```
[03:58:22] Error: Command failed: /Users/demohan/.nvm/versions/node/v20.15.1/bin/node /Users/demohan/github/vscode/extensions/markdown-language-features/esbuild-notebook.js --outputRoot /Users/demohan/github/vscode/.build/extensions/markdown-language-features
✘ [ERROR] Could not resolve "punycode"

    extensions/markdown-language-features/node_modules/markdown-it/lib/index.js:14:27:
      14 │ var punycode     = require('punycode');
         ╵                            ~~~~~~~~~~

  The package "punycode" wasn't found on the file system but is built into node. Are you trying to bundle for node? You can use "platform: 'node'" to do that, which will remove this error.
```

Adds userland package based on beed9aee2c

* fix: container builds for distro

* chore: update yarn occurrences

* fixup! chore: bump vsce@2.17.0

Uses the closest version to `main` branch that does not
include d3cc84cdec
while still having the fix 8b49e9dfdf

* chore: sync npm dependencies

* chore: sync npm dependencies

* chore: sync npm dependencies

* chore: throw error when yarn is used for installation

* chore: add review feedback

* chore: switch exec => run where needed

* chore: npm sync dependencies

* fix: markdown-language-features bundling

```
✘ [ERROR] Could not resolve "punycode"

    extensions/markdown-language-features/node_modules/markdown-it/lib/index.js:14:27:
      14 │ var punycode     = require('punycode');
         ╵                            ~~~~~~~~~~

  The package "punycode" wasn't found on the file system but is built into node. Are you trying to bundle for node? You can use "platform: 'node'" to do that, which will remove this error.
```

Adds missing userland package based on markdown-it/markdown-it@beed9ae,
can be removed once we update markdown-it >= 14.1.0

* ci: rename no-yarn-lock-changes.yml

* chore: sync npm dependencies

* ci: restore no-yarn-lock-changes.yml

We can disable it in a separate PR to keep the required
checks happy and also need workflow edit perms.

* chore: sync npm dependencies

* ci: rebuild cache

* ci: fix no-package-lock-changes.yml

* chore: bump distro

* chore: rm yarn.lock files

* chore: rm yarn.lock files without dependencies

* chore: add vscode-selfhost-import-aid to postinstall dirs

* chore: bump distro
2024-09-06 22:18:02 +09:00

217 lines
9.7 KiB
JavaScript

"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getVSCodeSysroot = getVSCodeSysroot;
exports.getChromiumSysroot = getChromiumSysroot;
const child_process_1 = require("child_process");
const os_1 = require("os");
const fs = require("fs");
const https = require("https");
const path = require("path");
const crypto_1 = require("crypto");
const ansiColors = require("ansi-colors");
// Based on https://source.chromium.org/chromium/chromium/src/+/main:build/linux/sysroot_scripts/install-sysroot.py.
const URL_PREFIX = 'https://msftelectron.blob.core.windows.net';
const URL_PATH = 'sysroots/toolchain';
const REPO_ROOT = path.dirname(path.dirname(path.dirname(__dirname)));
const ghApiHeaders = {
Accept: 'application/vnd.github.v3+json',
'User-Agent': 'VSCode Build',
};
if (process.env.GITHUB_TOKEN) {
ghApiHeaders.Authorization = 'Basic ' + Buffer.from(process.env.GITHUB_TOKEN).toString('base64');
}
const ghDownloadHeaders = {
...ghApiHeaders,
Accept: 'application/octet-stream',
};
function getElectronVersion() {
const npmrc = fs.readFileSync(path.join(REPO_ROOT, '.npmrc'), 'utf8');
const electronVersion = /^target="(.*)"$/m.exec(npmrc)[1];
const msBuildId = /^ms_build_id="(.*)"$/m.exec(npmrc)[1];
return { electronVersion, msBuildId };
}
function getSha(filename) {
// CodeQL [SM04514] Hash logic cannot be changed due to external dependency, also the code is only used during build.
const hash = (0, crypto_1.createHash)('sha1');
// Read file 1 MB at a time
const fd = fs.openSync(filename, 'r');
const buffer = Buffer.alloc(1024 * 1024);
let position = 0;
let bytesRead = 0;
while ((bytesRead = fs.readSync(fd, buffer, 0, buffer.length, position)) === buffer.length) {
hash.update(buffer);
position += bytesRead;
}
hash.update(buffer.slice(0, bytesRead));
return hash.digest('hex');
}
function getVSCodeSysrootChecksum(expectedName) {
const checksums = fs.readFileSync(path.join(REPO_ROOT, 'build', 'checksums', 'vscode-sysroot.txt'), 'utf8');
for (const line of checksums.split('\n')) {
const [checksum, name] = line.split(/\s+/);
if (name === expectedName) {
return checksum;
}
}
return undefined;
}
/*
* Do not use the fetch implementation from build/lib/fetch as it relies on vinyl streams
* and vinyl-fs breaks the symlinks in the compiler toolchain sysroot. We use the native
* tar implementation for that reason.
*/
async function fetchUrl(options, retries = 10, retryDelay = 1000) {
try {
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 30 * 1000);
const version = '20240129-253798';
try {
const response = await fetch(`https://api.github.com/repos/Microsoft/vscode-linux-build-agent/releases/tags/v${version}`, {
headers: ghApiHeaders,
signal: controller.signal /* Typings issue with lib.dom.d.ts */
});
if (response.ok && (response.status >= 200 && response.status < 300)) {
console.log(`Fetch completed: Status ${response.status}.`);
const contents = Buffer.from(await response.arrayBuffer());
const asset = JSON.parse(contents.toString()).assets.find((a) => a.name === options.assetName);
if (!asset) {
throw new Error(`Could not find asset in release of Microsoft/vscode-linux-build-agent @ ${version}`);
}
console.log(`Found asset ${options.assetName} @ ${asset.url}.`);
const assetResponse = await fetch(asset.url, {
headers: ghDownloadHeaders
});
if (assetResponse.ok && (assetResponse.status >= 200 && assetResponse.status < 300)) {
const assetContents = Buffer.from(await assetResponse.arrayBuffer());
console.log(`Fetched response body buffer: ${ansiColors.magenta(`${assetContents.byteLength} bytes`)}`);
if (options.checksumSha256) {
const actualSHA256Checksum = (0, crypto_1.createHash)('sha256').update(assetContents).digest('hex');
if (actualSHA256Checksum !== options.checksumSha256) {
throw new Error(`Checksum mismatch for ${ansiColors.cyan(asset.url)} (expected ${options.checksumSha256}, actual ${actualSHA256Checksum}))`);
}
}
console.log(`Verified SHA256 checksums match for ${ansiColors.cyan(asset.url)}`);
const tarCommand = `tar -xz -C ${options.dest}`;
(0, child_process_1.execSync)(tarCommand, { input: assetContents });
console.log(`Fetch complete!`);
return;
}
throw new Error(`Request ${ansiColors.magenta(asset.url)} failed with status code: ${assetResponse.status}`);
}
throw new Error(`Request ${ansiColors.magenta('https://api.github.com')} failed with status code: ${response.status}`);
}
finally {
clearTimeout(timeout);
}
}
catch (e) {
if (retries > 0) {
console.log(`Fetching failed: ${e}`);
await new Promise(resolve => setTimeout(resolve, retryDelay));
return fetchUrl(options, retries - 1, retryDelay);
}
throw e;
}
}
async function getVSCodeSysroot(arch) {
let expectedName;
let triple;
const prefix = process.env['VSCODE_SYSROOT_PREFIX'] ?? '-glibc-2.28';
switch (arch) {
case 'amd64':
expectedName = `x86_64-linux-gnu${prefix}.tar.gz`;
triple = 'x86_64-linux-gnu';
break;
case 'arm64':
expectedName = `aarch64-linux-gnu${prefix}.tar.gz`;
triple = 'aarch64-linux-gnu';
break;
case 'armhf':
expectedName = `arm-rpi-linux-gnueabihf${prefix}.tar.gz`;
triple = 'arm-rpi-linux-gnueabihf';
break;
}
console.log(`Fetching ${expectedName} for ${triple}`);
const checksumSha256 = getVSCodeSysrootChecksum(expectedName);
if (!checksumSha256) {
throw new Error(`Could not find checksum for ${expectedName}`);
}
const sysroot = process.env['VSCODE_SYSROOT_DIR'] ?? path.join((0, os_1.tmpdir)(), `vscode-${arch}-sysroot`);
const stamp = path.join(sysroot, '.stamp');
const result = `${sysroot}/${triple}/${triple}/sysroot`;
if (fs.existsSync(stamp) && fs.readFileSync(stamp).toString() === expectedName) {
return result;
}
console.log(`Installing ${arch} root image: ${sysroot}`);
fs.rmSync(sysroot, { recursive: true, force: true });
fs.mkdirSync(sysroot);
await fetchUrl({
checksumSha256,
assetName: expectedName,
dest: sysroot
});
fs.writeFileSync(stamp, expectedName);
return result;
}
async function getChromiumSysroot(arch) {
const sysrootJSONUrl = `https://raw.githubusercontent.com/electron/electron/v${getElectronVersion().electronVersion}/script/sysroots.json`;
const sysrootDictLocation = `${(0, os_1.tmpdir)()}/sysroots.json`;
const result = (0, child_process_1.spawnSync)('curl', [sysrootJSONUrl, '-o', sysrootDictLocation]);
if (result.status !== 0) {
throw new Error('Cannot retrieve sysroots.json. Stderr:\n' + result.stderr);
}
const sysrootInfo = require(sysrootDictLocation);
const sysrootArch = `bullseye_${arch}`;
const sysrootDict = sysrootInfo[sysrootArch];
const tarballFilename = sysrootDict['Tarball'];
const tarballSha = sysrootDict['Sha1Sum'];
const sysroot = path.join((0, os_1.tmpdir)(), sysrootDict['SysrootDir']);
const url = [URL_PREFIX, URL_PATH, tarballSha, tarballFilename].join('/');
const stamp = path.join(sysroot, '.stamp');
if (fs.existsSync(stamp) && fs.readFileSync(stamp).toString() === url) {
return sysroot;
}
console.log(`Installing Debian ${arch} root image: ${sysroot}`);
fs.rmSync(sysroot, { recursive: true, force: true });
fs.mkdirSync(sysroot);
const tarball = path.join(sysroot, tarballFilename);
console.log(`Downloading ${url}`);
let downloadSuccess = false;
for (let i = 0; i < 3 && !downloadSuccess; i++) {
fs.writeFileSync(tarball, '');
await new Promise((c) => {
https.get(url, (res) => {
res.on('data', (chunk) => {
fs.appendFileSync(tarball, chunk);
});
res.on('end', () => {
downloadSuccess = true;
c();
});
}).on('error', (err) => {
console.error('Encountered an error during the download attempt: ' + err.message);
c();
});
});
}
if (!downloadSuccess) {
fs.rmSync(tarball);
throw new Error('Failed to download ' + url);
}
const sha = getSha(tarball);
if (sha !== tarballSha) {
throw new Error(`Tarball sha1sum is wrong. Expected ${tarballSha}, actual ${sha}`);
}
const proc = (0, child_process_1.spawnSync)('tar', ['xf', tarball, '-C', sysroot]);
if (proc.status) {
throw new Error('Tarball extraction failed with code ' + proc.status);
}
fs.rmSync(tarball);
fs.writeFileSync(stamp, url);
return sysroot;
}
//# sourceMappingURL=install-sysroot.js.map