mirror of
https://github.com/denoland/deno.git
synced 2024-12-29 18:49:07 -05:00
237 lines
7.6 KiB
TypeScript
Executable file
237 lines
7.6 KiB
TypeScript
Executable file
#!/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;
|
||
}
|