1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-18 13:22:55 -05:00
denoland-deno/tools/release/npm/build.ts

237 lines
7.6 KiB
TypeScript
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env -S deno run -A --lock=tools/deno.lock.json
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// NOTICE: This deployment/npm folder was lifted from https://github.com/dprint/dprint/blob/0ba79811cc96d2dee8e0cf766a8c8c0fc44879c2/deployment/npm/
// with permission (Copyright 2019-2023 David Sherret)
import $ from "jsr:@david/dax@^0.42.0";
// @ts-types="npm:@types/decompress@4.2.7"
import decompress from "npm:decompress@4.2.1";
import { parseArgs } from "@std/cli/parse-args";
interface Package {
zipFileName: string;
os: "win32" | "darwin" | "linux";
cpu: "x64" | "arm64";
libc?: "glibc" | "musl";
}
const args = parseArgs(Deno.args, {
boolean: ["publish"],
});
const packages: Package[] = [{
zipFileName: "deno-x86_64-pc-windows-msvc.zip",
os: "win32",
cpu: "x64",
}, {
// use x64_64 until there's an arm64 build
zipFileName: "deno-x86_64-pc-windows-msvc.zip",
os: "win32",
cpu: "arm64",
}, {
zipFileName: "deno-x86_64-apple-darwin.zip",
os: "darwin",
cpu: "x64",
}, {
zipFileName: "deno-aarch64-apple-darwin.zip",
os: "darwin",
cpu: "arm64",
}, {
zipFileName: "deno-x86_64-unknown-linux-gnu.zip",
os: "linux",
cpu: "x64",
libc: "glibc",
}, {
zipFileName: "deno-aarch64-unknown-linux-gnu.zip",
os: "linux",
cpu: "arm64",
libc: "glibc",
}];
const markdownText = `# Deno
[Deno](https://www.deno.com)
([/ˈdiːnoʊ/](http://ipa-reader.xyz/?text=%CB%88di%CB%90no%CA%8A), pronounced
\`dee-no\`) is a JavaScript, TypeScript, and WebAssembly runtime with secure
defaults and a great developer experience. It's built on [V8](https://v8.dev/),
[Rust](https://www.rust-lang.org/), and [Tokio](https://tokio.rs/).
Learn more about the Deno runtime
[in the documentation](https://docs.deno.com/runtime/manual).
`;
const currentDir = $.path(import.meta.url).parentOrThrow();
const rootDir = currentDir.parentOrThrow().parentOrThrow().parentOrThrow();
const outputDir = currentDir.join("./dist");
const scopeDir = outputDir.join("@deno");
const denoDir = outputDir.join("deno");
const version = resolveVersion();
$.logStep(`Publishing ${version}...`);
await $`rm -rf ${outputDir}`;
await $`mkdir -p ${denoDir} ${scopeDir}`;
// setup Deno packages
{
$.logStep(`Setting up deno ${version}...`);
const pkgJson = {
"name": "deno",
"version": version,
"description": "A modern runtime for JavaScript and TypeScript.",
"bin": "bin.cjs",
"repository": {
"type": "git",
"url": "git+https://github.com/denoland/deno.git",
},
"keywords": [
"runtime",
"typescript",
],
"author": "the Deno authors",
"license": "MIT",
"bugs": {
"url": "https://github.com/denoland/deno/issues",
},
"homepage": "https://deno.com",
// for yarn berry (https://github.com/dprint/dprint/issues/686)
"preferUnplugged": true,
"scripts": {
"postinstall": "node ./install.cjs",
},
optionalDependencies: packages
.map((pkg) => `@deno/${getPackageNameNoScope(pkg)}`)
.reduce((obj, pkgName) => ({ ...obj, [pkgName]: version }), {}),
};
currentDir.join("bin.cjs").copyFileToDirSync(denoDir);
currentDir.join("install_api.cjs").copyFileToDirSync(denoDir);
currentDir.join("install.cjs").copyFileToDirSync(denoDir);
denoDir.join("package.json").writeJsonPrettySync(pkgJson);
rootDir.join("LICENSE.md").copyFileSync(denoDir.join("LICENSE"));
denoDir.join("README.md").writeTextSync(markdownText);
// ensure the test files don't get published
denoDir.join(".npmignore").writeTextSync("deno\ndeno.exe\n");
// setup each binary package
for (const pkg of packages) {
const pkgName = getPackageNameNoScope(pkg);
$.logStep(`Setting up @deno/${pkgName}...`);
const pkgDir = scopeDir.join(pkgName);
const zipPath = pkgDir.join("output.zip");
await $`mkdir -p ${pkgDir}`;
// download and extract the zip file
const zipUrl =
`https://github.com/denoland/deno/releases/download/v${version}/${pkg.zipFileName}`;
await $.request(zipUrl).showProgress().pipeToPath(zipPath);
await decompress(zipPath.toString(), pkgDir.toString());
zipPath.removeSync();
// create the package.json and readme
pkgDir.join("README.md").writeTextSync(
`# @denoland/${pkgName}\n\n${pkgName} distribution of [Deno](https://deno.land).\n`,
);
pkgDir.join("package.json").writeJsonPrettySync({
"name": `@deno/${pkgName}`,
"version": version,
"description": `${pkgName} distribution of Deno`,
"repository": {
"type": "git",
"url": "git+https://github.com/denoland/deno.git",
},
// force yarn to unpack
"preferUnplugged": true,
"author": "David Sherret",
"license": "MIT",
"bugs": {
"url": "https://github.com/denoland/deno/issues",
},
"homepage": "https://deno.land",
"os": [pkg.os],
"cpu": [pkg.cpu],
libc: pkg.libc == null ? undefined : [pkg.libc],
});
}
}
// verify that the package is created correctly
{
$.logStep("Verifying packages...");
const testPlatform = Deno.build.os == "windows"
? (Deno.build.arch === "x86_64" ? "@deno/win32-x64" : "@deno/win32-arm64")
: Deno.build.os === "darwin"
? (Deno.build.arch === "x86_64" ? "@deno/darwin-x64" : "@deno/darwin-arm64")
: "@deno/linux-x64-glibc";
outputDir.join("package.json").writeJsonPrettySync({
workspaces: [
"deno",
// There seems to be a bug with npm workspaces where this doesn't
// work, so for now make some assumptions and only include the package
// that works on the CI for the current operating system
// ...packages.map(p => `@deno/${getPackageNameNoScope(p)}`),
testPlatform,
],
});
const denoExe = Deno.build.os === "windows" ? "deno.exe" : "deno";
await $`npm install`.cwd(denoDir);
// ensure the post-install script adds the executable to the deno package,
// which is necessary for faster caching and to ensure the vscode extension
// picks it up
if (!denoDir.join(denoExe).existsSync()) {
throw new Error("Deno executable did not exist after post install");
}
// run once after post install created deno, once with a simulated readonly file system, once creating the cache and once with
await $`node bin.cjs -v && rm ${denoExe} && DENO_SIMULATED_READONLY_FILE_SYSTEM=1 node bin.cjs -v && node bin.cjs -v && node bin.cjs -v`
.cwd(denoDir);
if (!denoDir.join(denoExe).existsSync()) {
throw new Error("Deno executable did not exist when lazily initialized");
}
}
// publish if necessary
if (args.publish) {
for (const pkg of packages) {
const pkgName = getPackageNameNoScope(pkg);
$.logStep(`Publishing @deno/${pkgName}...`);
if (await checkPackagePublished(`@deno/${pkgName}`)) {
$.logLight(" Already published.");
continue;
}
const pkgDir = scopeDir.join(pkgName);
await $`cd ${pkgDir} && npm publish --provenance --access public`;
}
$.logStep(`Publishing deno...`);
await $`cd ${denoDir} && npm publish --provenance --access public`;
}
function getPackageNameNoScope(name: Package) {
const libc = name.libc == null ? "" : `-${name.libc}`;
return `${name.os}-${name.cpu}${libc}`;
}
function resolveVersion() {
const firstArg = args._[0];
if (
firstArg != null &&
typeof firstArg === "string" &&
firstArg.trim().length > 0
) {
return firstArg;
}
const version = (rootDir.join("cli/Cargo.toml").readTextSync().match(
/version = "(.*?)"/,
))?.[1];
if (version == null) {
throw new Error("Could not resolve version.");
}
return version;
}
async function checkPackagePublished(pkgName: string) {
const result = await $`npm info ${pkgName}@${version}`.quiet().noThrow();
return result.code === 0;
}