Build: Added new publish script.
This commit is contained in:
parent
22dee96f51
commit
e986b09e58
7
misc/admin/lib/changelog.d.ts
vendored
7
misc/admin/lib/changelog.d.ts
vendored
@ -1 +1,8 @@
|
||||
export declare type Change = {
|
||||
title: string;
|
||||
version: string;
|
||||
date: string;
|
||||
content: string;
|
||||
};
|
||||
export declare function generate(): Promise<string>;
|
||||
export declare function getLatestChange(): Change;
|
||||
|
@ -104,3 +104,30 @@ function generate() {
|
||||
});
|
||||
}
|
||||
exports.generate = generate;
|
||||
function getLatestChange() {
|
||||
let result = null;
|
||||
const lines = fs_1.default.readFileSync(changelogPath).toString().split("\n");
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
const match = line.match(/ethers\/([^\(]*)\(([^\)]*)\)/);
|
||||
if (match) {
|
||||
if (result) {
|
||||
break;
|
||||
}
|
||||
result = {
|
||||
title: line.trim(),
|
||||
version: match[1].trim(),
|
||||
date: match[2].trim(),
|
||||
content: ""
|
||||
};
|
||||
}
|
||||
else if (result) {
|
||||
if (!line.trim().match(/^-+$/)) {
|
||||
result.content += line.trim() + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
result.content = result.content.trim();
|
||||
return result;
|
||||
}
|
||||
exports.getLatestChange = getLatestChange;
|
||||
|
15
misc/admin/lib/cmds/publish.d.ts
vendored
Normal file
15
misc/admin/lib/cmds/publish.d.ts
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
/// <reference types="node" />
|
||||
import AWS from 'aws-sdk';
|
||||
declare type PutInfo = {
|
||||
ACL: "public-read";
|
||||
Body: string | Buffer;
|
||||
Bucket: string;
|
||||
ContentType: string;
|
||||
Key: string;
|
||||
};
|
||||
export declare function putObject(s3: AWS.S3, info: PutInfo): Promise<{
|
||||
name: string;
|
||||
hash: string;
|
||||
}>;
|
||||
export declare function invalidate(cloudfront: AWS.CloudFront, distributionId: string): Promise<string>;
|
||||
export {};
|
203
misc/admin/lib/cmds/publish.js
Normal file
203
misc/admin/lib/cmds/publish.js
Normal file
@ -0,0 +1,203 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const aws_sdk_1 = __importDefault(require("aws-sdk"));
|
||||
const fs_1 = __importDefault(require("fs"));
|
||||
const changelog_1 = require("../changelog");
|
||||
const config_1 = require("../config");
|
||||
const depgraph_1 = require("../depgraph");
|
||||
const git_1 = require("../git");
|
||||
const github_1 = require("../github");
|
||||
const local = __importStar(require("../local"));
|
||||
const log_1 = require("../log");
|
||||
const npm = __importStar(require("../npm"));
|
||||
const path_1 = require("../path");
|
||||
const utils_1 = require("../utils");
|
||||
const USER_AGENT = "ethers-dist@0.0.1";
|
||||
const TAG = "latest";
|
||||
function putObject(s3, info) {
|
||||
return new Promise((resolve, reject) => {
|
||||
s3.putObject(info, function (error, data) {
|
||||
if (error) {
|
||||
reject(error);
|
||||
}
|
||||
else {
|
||||
resolve({
|
||||
name: info.Key,
|
||||
hash: data.ETag.replace(/"/g, '')
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.putObject = putObject;
|
||||
function invalidate(cloudfront, distributionId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
cloudfront.createInvalidation({
|
||||
DistributionId: distributionId,
|
||||
InvalidationBatch: {
|
||||
CallerReference: `${USER_AGENT}-${parseInt(String((new Date()).getTime() / 1000))}`,
|
||||
Paths: {
|
||||
Quantity: 1,
|
||||
Items: [
|
||||
"/\*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}, function (error, data) {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
return;
|
||||
}
|
||||
resolve(data.Invalidation.Id);
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.invalidate = invalidate;
|
||||
(function () {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const dirnames = depgraph_1.getOrdered();
|
||||
// @TODO: Fail if there are any untracked files or unchecked in files
|
||||
const publish = {};
|
||||
const progressUpdate = log_1.getProgressBar(log_1.colorify.bold("Finding updated packages..."));
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
progressUpdate(i / dirnames.length);
|
||||
let dirname = dirnames[i];
|
||||
let info = local.getPackage(dirname);
|
||||
let npmInfo = yield npm.getPackage(dirname);
|
||||
// No change in version, no need to publish
|
||||
if (info.version === npmInfo.version) {
|
||||
continue;
|
||||
}
|
||||
// Get the latest commit this package was modified at
|
||||
const path = path_1.resolve("packages", dirname);
|
||||
const gitHead = yield git_1.getGitTag(path);
|
||||
if (gitHead == null) {
|
||||
throw new Error("hmmm...");
|
||||
}
|
||||
publish[dirname] = {
|
||||
name: info.name,
|
||||
gitHead: gitHead,
|
||||
oldVersion: (npmInfo ? npmInfo.version : "NEW"),
|
||||
newVersion: info.version
|
||||
};
|
||||
}
|
||||
progressUpdate(1);
|
||||
console.log(log_1.colorify.bold(`Found ${Object.keys(publish).length} updated pacakges...`));
|
||||
Object.keys(publish).forEach((dirname) => {
|
||||
const info = publish[dirname];
|
||||
console.log(` ${log_1.colorify.blue(info.name)} ${utils_1.repeat(" ", 50 - info.name.length - info.oldVersion.length)} ${info.oldVersion} ${log_1.colorify.bold("=>")} ${log_1.colorify.green(info.newVersion)}`);
|
||||
});
|
||||
const publishNames = Object.keys(publish);
|
||||
publishNames.sort((a, b) => (dirnames.indexOf(a) - dirnames.indexOf(b)));
|
||||
// Load the token from the encrypted store
|
||||
const options = {
|
||||
access: "public",
|
||||
npmVersion: USER_AGENT,
|
||||
tag: TAG
|
||||
};
|
||||
try {
|
||||
const token = (yield config_1.config.get("npm-token")).trim().split("=");
|
||||
options[token[0]] = token[1];
|
||||
}
|
||||
catch (error) {
|
||||
switch (error.message) {
|
||||
case "wrong password":
|
||||
console.log(log_1.colorify.bold("Wrong password"));
|
||||
break;
|
||||
case "cancelled":
|
||||
break;
|
||||
default:
|
||||
console.log(error);
|
||||
}
|
||||
console.log(log_1.colorify.red("Aborting."));
|
||||
return;
|
||||
}
|
||||
console.log(log_1.colorify.bold("Publishing:"));
|
||||
for (let i = 0; i < publishNames.length; i++) {
|
||||
const dirname = publishNames[i];
|
||||
const path = path_1.resolve("packages", dirname);
|
||||
const pathJson = path_1.resolve("packages", dirname, "package.json");
|
||||
const { gitHead, name, newVersion } = publish[dirname];
|
||||
console.log(` ${log_1.colorify.blue(name)} @ ${log_1.colorify.green(newVersion)}`);
|
||||
local.updateJson(pathJson, { gitHead: gitHead }, true);
|
||||
const info = utils_1.loadJson(pathJson);
|
||||
yield npm.publish(path, info, options);
|
||||
local.updateJson(pathJson, { gitHead: undefined }, true);
|
||||
}
|
||||
if (publishNames.indexOf("ethers") >= 0) {
|
||||
const change = changelog_1.getLatestChange();
|
||||
const awsAccessId = yield config_1.config.get("aws-upload-scripts-accesskey");
|
||||
const awsSecretKey = yield config_1.config.get("aws-upload-scripts-secretkey");
|
||||
// Publish tagged release on GitHub
|
||||
{
|
||||
// The password above already succeeded
|
||||
const username = yield config_1.config.get("github-user");
|
||||
const password = yield config_1.config.get("github-release");
|
||||
const gitCommit = yield git_1.getGitTag(path_1.resolve("CHANGELOG.md"));
|
||||
// Publish the release
|
||||
const beta = false;
|
||||
const link = yield github_1.createRelease(username, password, change.version, change.title, change.content, beta, gitCommit);
|
||||
console.log(`${log_1.colorify.bold("Published release:")} ${link}`);
|
||||
}
|
||||
// Upload libs to the CDN (as ethers-v5.0 and ethers-5.0.x)
|
||||
{
|
||||
const bucketName = yield config_1.config.get("aws-upload-scripts-bucket");
|
||||
const originRoot = yield config_1.config.get("aws-upload-scripts-root");
|
||||
const s3 = new aws_sdk_1.default.S3({
|
||||
apiVersion: '2006-03-01',
|
||||
accessKeyId: awsAccessId,
|
||||
secretAccessKey: awsSecretKey
|
||||
});
|
||||
// Upload the libs to ethers-v5.0 and ethers-5.0.x
|
||||
const fileInfos = [
|
||||
{ filename: "packages/ethers/dist/ethers.esm.min.js", key: `ethers-${change.version.substring(1)}.esm.min.js` },
|
||||
{ filename: "packages/ethers/dist/ethers.umd.min.js", key: `ethers-${change.version.substring(1)}.umd.min.js` },
|
||||
{ filename: "packages/ethers/dist/ethers.esm.min.js", key: "ethers-5.0.esm.min.js" },
|
||||
{ filename: "packages/ethers/dist/ethers.umd.min.js", key: "ethers-5.0.umd.min.js" },
|
||||
];
|
||||
for (let i = 0; i < fileInfos.length; i++) {
|
||||
const { filename, key } = fileInfos[i];
|
||||
const status = yield putObject(s3, {
|
||||
ACL: "public-read",
|
||||
Body: fs_1.default.readFileSync(path_1.resolve(filename)),
|
||||
Bucket: bucketName,
|
||||
ContentType: "application/javascript; charset=utf-8",
|
||||
Key: (originRoot + key)
|
||||
});
|
||||
console.log(status);
|
||||
console.log(`${log_1.colorify.bold("Uploaded:")} https://cdn.ethers.io/lib/${key}`);
|
||||
}
|
||||
}
|
||||
// Flush the edge caches
|
||||
{
|
||||
const distributionId = yield config_1.config.get("aws-upload-scripts-distribution-id");
|
||||
const cloudfront = new aws_sdk_1.default.CloudFront({
|
||||
//apiVersion: '2006-03-01',
|
||||
accessKeyId: awsAccessId,
|
||||
secretAccessKey: awsSecretKey
|
||||
});
|
||||
const invalidationId = yield invalidate(cloudfront, distributionId);
|
||||
console.log(`${log_1.colorify.bold("Invalidating Edge Cache:")} ${invalidationId}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
2
misc/admin/lib/geturl.d.ts
vendored
2
misc/admin/lib/geturl.d.ts
vendored
@ -12,5 +12,7 @@ export declare type Options = {
|
||||
headers?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
user?: string;
|
||||
password?: string;
|
||||
};
|
||||
export declare function getUrl(href: string, options?: Options): Promise<GetUrlResponse>;
|
||||
|
@ -77,6 +77,9 @@ function getUrl(href, options) {
|
||||
method: (options.method || "GET"),
|
||||
headers: (options.headers || {}),
|
||||
};
|
||||
if (options.user && options.password) {
|
||||
request.auth = `${options.user}:${options.password}`;
|
||||
}
|
||||
let req = null;
|
||||
switch (nonnull(url.protocol)) {
|
||||
case "http:":
|
||||
|
1
misc/admin/lib/github.d.ts
vendored
Normal file
1
misc/admin/lib/github.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
export declare function createRelease(user: string, password: string, tagName: string, title: string, body: string, prerelease?: boolean, commit?: string): Promise<string>;
|
35
misc/admin/lib/github.js
Normal file
35
misc/admin/lib/github.js
Normal file
@ -0,0 +1,35 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const geturl_1 = require("./geturl");
|
||||
function createRelease(user, password, tagName, title, body, prerelease, commit) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const result = yield geturl_1.getUrl("https:/\/api.github.com/repos/ethers-io/ethers.js/releases", {
|
||||
body: Buffer.from(JSON.stringify({
|
||||
tag_name: tagName,
|
||||
target_commitish: (commit || "master"),
|
||||
name: title,
|
||||
body: body,
|
||||
//draft: true,
|
||||
draft: false,
|
||||
prerelease: !!prerelease
|
||||
})),
|
||||
method: "POST",
|
||||
headers: {
|
||||
"User-Agent": "ethers-io"
|
||||
},
|
||||
user: user,
|
||||
password: password
|
||||
});
|
||||
return JSON.parse(Buffer.from(result.body).toString("utf8")).html_url;
|
||||
});
|
||||
}
|
||||
exports.createRelease = createRelease;
|
2
misc/admin/lib/log.d.ts
vendored
2
misc/admin/lib/log.d.ts
vendored
@ -8,5 +8,5 @@ export declare type PromptOptions = {
|
||||
defaultChoice?: string;
|
||||
mask?: string;
|
||||
};
|
||||
export declare function getPrompt(prompt: string, options: PromptOptions): Promise<string>;
|
||||
export declare function getPrompt(prompt: string, options?: PromptOptions): Promise<string>;
|
||||
export declare function getPassword(prompt: string): Promise<string>;
|
||||
|
@ -14,8 +14,8 @@ function getProgressBar(action) {
|
||||
lastProgress = progress;
|
||||
return;
|
||||
}
|
||||
//process.stdin.setRawMode(false);
|
||||
//process.stdin.pause();
|
||||
process.stdin.setRawMode(false);
|
||||
process.stdin.pause();
|
||||
if (progress === lastProgress || lastProgress === 100) {
|
||||
return;
|
||||
}
|
||||
@ -134,7 +134,7 @@ function _getPrompt(prompt, options, callback) {
|
||||
}
|
||||
function getPrompt(prompt, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
_getPrompt(prompt, options, (ctrlC, password) => {
|
||||
_getPrompt(prompt, (options || {}), (ctrlC, password) => {
|
||||
if (ctrlC) {
|
||||
return reject(new Error("cancelled"));
|
||||
}
|
||||
|
2
misc/admin/lib/npm.d.ts
vendored
2
misc/admin/lib/npm.d.ts
vendored
@ -1,2 +1,4 @@
|
||||
import { Options } from "libnpmpublish";
|
||||
import { Package } from "./local";
|
||||
export declare function getPackage(name: string, version?: string): Promise<Package>;
|
||||
export declare function publish(path: string, manifest: any, options: Options): Promise<void>;
|
||||
|
@ -12,9 +12,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const libnpmpublish_1 = require("libnpmpublish");
|
||||
const semver_1 = __importDefault(require("semver"));
|
||||
const geturl_1 = require("./geturl");
|
||||
const local_1 = require("./local");
|
||||
const log_1 = require("./log");
|
||||
const cache = {};
|
||||
function getPackageInfo(name) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
@ -60,3 +62,21 @@ function getPackage(name, version) {
|
||||
});
|
||||
}
|
||||
exports.getPackage = getPackage;
|
||||
function publish(path, manifest, options) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
yield libnpmpublish_1.publish(path, manifest, options);
|
||||
}
|
||||
catch (error) {
|
||||
// We need an OTP
|
||||
if (error.code === "EOTP") {
|
||||
const otp = yield log_1.getPrompt(log_1.colorify.bold("Enter OTP: "));
|
||||
options.otp = otp.replace(" ", "");
|
||||
// Retry with the new OTP
|
||||
return yield publish(path, manifest, options);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.publish = publish;
|
||||
|
@ -9,6 +9,13 @@ import { getDateTime, repeat } from "./utils";
|
||||
|
||||
const changelogPath = resolve("CHANGELOG.md");
|
||||
|
||||
export type Change = {
|
||||
title: string;
|
||||
version: string;
|
||||
date: string;
|
||||
content: string;
|
||||
};
|
||||
|
||||
export async function generate(): Promise<string> {
|
||||
const lines = fs.readFileSync(changelogPath).toString().trim().split("\n");
|
||||
|
||||
@ -88,3 +95,28 @@ export async function generate(): Promise<string> {
|
||||
return output.join("\n");
|
||||
}
|
||||
|
||||
export function getLatestChange(): Change {
|
||||
let result: Change = null;
|
||||
|
||||
const lines = fs.readFileSync(changelogPath).toString().split("\n");
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
const match = line.match(/ethers\/([^\(]*)\(([^\)]*)\)/);
|
||||
if (match) {
|
||||
if (result) { break; }
|
||||
result = {
|
||||
title: line.trim(),
|
||||
version: match[1].trim(),
|
||||
date: match[2].trim(),
|
||||
content: ""
|
||||
};
|
||||
} else if (result) {
|
||||
if (!line.trim().match(/^-+$/)) {
|
||||
result.content += line.trim() + "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
result.content = result.content.trim();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
213
misc/admin/src.ts/cmds/publish.ts
Normal file
213
misc/admin/src.ts/cmds/publish.ts
Normal file
@ -0,0 +1,213 @@
|
||||
import AWS from 'aws-sdk';
|
||||
import fs from "fs";
|
||||
|
||||
import { getLatestChange } from "../changelog";
|
||||
import { config } from "../config";
|
||||
import { getOrdered } from "../depgraph";
|
||||
import { getGitTag } from "../git";
|
||||
import { createRelease } from "../github";
|
||||
import * as local from "../local";
|
||||
import { colorify, getProgressBar } from "../log";
|
||||
import * as npm from "../npm";
|
||||
import { resolve } from "../path";
|
||||
import { loadJson, repeat } from "../utils";
|
||||
|
||||
const USER_AGENT = "ethers-dist@0.0.1";
|
||||
const TAG = "latest";
|
||||
|
||||
type PutInfo = {
|
||||
ACL: "public-read";
|
||||
Body: string | Buffer;
|
||||
Bucket: string;
|
||||
ContentType: string;
|
||||
Key: string;
|
||||
}
|
||||
|
||||
export function putObject(s3: AWS.S3, info: PutInfo): Promise<{ name: string, hash: string }> {
|
||||
return new Promise((resolve, reject) => {
|
||||
s3.putObject(info, function(error, data) {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve({
|
||||
name: info.Key,
|
||||
hash: data.ETag.replace(/"/g, '')
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function invalidate(cloudfront: AWS.CloudFront, distributionId: string): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
cloudfront.createInvalidation({
|
||||
DistributionId: distributionId,
|
||||
InvalidationBatch: {
|
||||
CallerReference: `${ USER_AGENT }-${ parseInt(String((new Date()).getTime() / 1000)) }`,
|
||||
Paths: {
|
||||
Quantity: 1,
|
||||
Items: [
|
||||
"/\*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}, function(error, data) {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
return;
|
||||
}
|
||||
resolve(data.Invalidation.Id);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
(async function() {
|
||||
const dirnames = getOrdered();
|
||||
|
||||
// @TODO: Fail if there are any untracked files or unchecked in files
|
||||
|
||||
const publish: Record<string, { name: string, gitHead: string, oldVersion: string, newVersion: string }> = { };
|
||||
|
||||
const progressUpdate = getProgressBar(colorify.bold("Finding updated packages..."));
|
||||
for (let i = 0; i < dirnames.length; i++) {
|
||||
progressUpdate(i / dirnames.length);
|
||||
|
||||
let dirname = dirnames[i];
|
||||
|
||||
let info = local.getPackage(dirname);
|
||||
let npmInfo = await npm.getPackage(dirname);
|
||||
|
||||
// No change in version, no need to publish
|
||||
if (info.version === npmInfo.version) { continue; }
|
||||
|
||||
// Get the latest commit this package was modified at
|
||||
const path = resolve("packages", dirname);
|
||||
const gitHead = await getGitTag(path);
|
||||
if (gitHead == null) { throw new Error("hmmm..."); }
|
||||
|
||||
publish[dirname] = {
|
||||
name: info.name,
|
||||
gitHead: gitHead,
|
||||
oldVersion: (npmInfo ? npmInfo.version: "NEW"),
|
||||
newVersion: info.version
|
||||
};
|
||||
}
|
||||
progressUpdate(1);
|
||||
|
||||
console.log(colorify.bold(`Found ${ Object.keys(publish).length } updated pacakges...`));
|
||||
Object.keys(publish).forEach((dirname) => {
|
||||
const info = publish[dirname];
|
||||
console.log(` ${ colorify.blue(info.name) } ${ repeat(" ", 50 - info.name.length - info.oldVersion.length) } ${ info.oldVersion } ${ colorify.bold("=>") } ${ colorify.green(info.newVersion) }`);
|
||||
});
|
||||
|
||||
const publishNames = Object.keys(publish);
|
||||
publishNames.sort((a, b) => (dirnames.indexOf(a) - dirnames.indexOf(b)));
|
||||
|
||||
// Load the token from the encrypted store
|
||||
const options: Record<string, string> = {
|
||||
access: "public",
|
||||
npmVersion: USER_AGENT,
|
||||
tag: TAG
|
||||
};
|
||||
|
||||
try {
|
||||
const token = (await config.get("npm-token")).trim().split("=");
|
||||
options[token[0]] = token[1];
|
||||
} catch (error) {
|
||||
switch (error.message) {
|
||||
case "wrong password":
|
||||
console.log(colorify.bold("Wrong password"));
|
||||
break;
|
||||
case "cancelled":
|
||||
break;
|
||||
default:
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
console.log(colorify.red("Aborting."));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(colorify.bold("Publishing:"));
|
||||
for (let i = 0; i < publishNames.length; i++) {
|
||||
const dirname = publishNames[i];
|
||||
const path = resolve("packages", dirname);
|
||||
const pathJson = resolve("packages", dirname, "package.json");
|
||||
|
||||
const { gitHead, name, newVersion } = publish[dirname];
|
||||
console.log(` ${ colorify.blue(name) } @ ${ colorify.green(newVersion) }`);
|
||||
|
||||
local.updateJson(pathJson, { gitHead: gitHead }, true);
|
||||
const info = loadJson(pathJson);
|
||||
await npm.publish(path, info, options);
|
||||
local.updateJson(pathJson, { gitHead: undefined }, true);
|
||||
}
|
||||
|
||||
if (publishNames.indexOf("ethers") >= 0) {
|
||||
const change = getLatestChange();
|
||||
|
||||
const awsAccessId = await config.get("aws-upload-scripts-accesskey");
|
||||
const awsSecretKey = await config.get("aws-upload-scripts-secretkey");
|
||||
|
||||
// Publish tagged release on GitHub
|
||||
{
|
||||
// The password above already succeeded
|
||||
const username = await config.get("github-user");
|
||||
const password = await config.get("github-release");
|
||||
|
||||
const gitCommit = await getGitTag(resolve("CHANGELOG.md"));
|
||||
|
||||
// Publish the release
|
||||
const beta = false;
|
||||
const link = await createRelease(username, password, change.version, change.title, change.content, beta, gitCommit);
|
||||
console.log(`${ colorify.bold("Published release:") } ${ link }`);
|
||||
}
|
||||
|
||||
// Upload libs to the CDN (as ethers-v5.0 and ethers-5.0.x)
|
||||
{
|
||||
const bucketName = await config.get("aws-upload-scripts-bucket");
|
||||
const originRoot = await config.get("aws-upload-scripts-root");
|
||||
|
||||
const s3 = new AWS.S3({
|
||||
apiVersion: '2006-03-01',
|
||||
accessKeyId: awsAccessId,
|
||||
secretAccessKey: awsSecretKey
|
||||
});
|
||||
|
||||
// Upload the libs to ethers-v5.0 and ethers-5.0.x
|
||||
const fileInfos: Array<{ filename: string, key: string }> = [
|
||||
{ filename: "packages/ethers/dist/ethers.esm.min.js", key: `ethers-${ change.version.substring(1) }.esm.min.js` },
|
||||
{ filename: "packages/ethers/dist/ethers.umd.min.js", key: `ethers-${ change.version.substring(1) }.umd.min.js` },
|
||||
{ filename: "packages/ethers/dist/ethers.esm.min.js", key: "ethers-5.0.esm.min.js" },
|
||||
{ filename: "packages/ethers/dist/ethers.umd.min.js", key: "ethers-5.0.umd.min.js" },
|
||||
];
|
||||
|
||||
for (let i = 0; i < fileInfos.length; i++) {
|
||||
const { filename, key } = fileInfos[i];
|
||||
const status = await putObject(s3, {
|
||||
ACL: "public-read",
|
||||
Body: fs.readFileSync(resolve(filename)),
|
||||
Bucket: bucketName,
|
||||
ContentType: "application/javascript; charset=utf-8",
|
||||
Key: (originRoot + key)
|
||||
});
|
||||
console.log(status);
|
||||
|
||||
console.log(`${ colorify.bold("Uploaded:") } https://cdn.ethers.io/lib/${ key }`);
|
||||
}
|
||||
}
|
||||
|
||||
// Flush the edge caches
|
||||
{
|
||||
const distributionId = await config.get("aws-upload-scripts-distribution-id");
|
||||
|
||||
const cloudfront = new AWS.CloudFront({
|
||||
//apiVersion: '2006-03-01',
|
||||
accessKeyId: awsAccessId,
|
||||
secretAccessKey: awsSecretKey
|
||||
});
|
||||
const invalidationId = await invalidate(cloudfront, distributionId);
|
||||
console.log(`${ colorify.bold("Invalidating Edge Cache:") } ${ invalidationId }`);
|
||||
}
|
||||
}
|
||||
})();
|
@ -12,7 +12,11 @@ export type GetUrlResponse = {
|
||||
export type Options = {
|
||||
method?: string,
|
||||
body?: Uint8Array
|
||||
|
||||
headers?: { [ key: string] : string },
|
||||
|
||||
user?: string,
|
||||
password?: string,
|
||||
};
|
||||
|
||||
function getResponse(request: http.ClientRequest): Promise<GetUrlResponse> {
|
||||
@ -72,7 +76,7 @@ export async function getUrl(href: string, options?: Options): Promise<GetUrlRes
|
||||
// to this request object
|
||||
const url = parse(href);
|
||||
|
||||
const request = {
|
||||
const request: http.ClientRequestArgs = {
|
||||
protocol: nonnull(url.protocol),
|
||||
hostname: nonnull(url.hostname),
|
||||
port: nonnull(url.port),
|
||||
@ -82,6 +86,10 @@ export async function getUrl(href: string, options?: Options): Promise<GetUrlRes
|
||||
headers: (options.headers || { }),
|
||||
};
|
||||
|
||||
if (options.user && options.password) {
|
||||
request.auth = `${ options.user }:${ options.password }`;
|
||||
}
|
||||
|
||||
let req: http.ClientRequest = null;
|
||||
switch (nonnull(url.protocol)) {
|
||||
case "http:":
|
||||
|
27
misc/admin/src.ts/github.ts
Normal file
27
misc/admin/src.ts/github.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { getUrl } from "./geturl";
|
||||
|
||||
export async function createRelease(user: string, password: string, tagName: string, title: string, body: string, prerelease?: boolean, commit?: string): Promise<string> {
|
||||
const result = await getUrl("https:/\/api.github.com/repos/ethers-io/ethers.js/releases", {
|
||||
body: Buffer.from(JSON.stringify({
|
||||
tag_name: tagName,
|
||||
target_commitish: (commit || "master"),
|
||||
name: title,
|
||||
body: body,
|
||||
//draft: true,
|
||||
draft: false,
|
||||
prerelease: !!prerelease
|
||||
})),
|
||||
method: "POST",
|
||||
|
||||
headers: {
|
||||
"User-Agent": "ethers-io"
|
||||
},
|
||||
|
||||
user: user,
|
||||
password: password
|
||||
});
|
||||
|
||||
|
||||
return JSON.parse(Buffer.from(result.body).toString("utf8")).html_url;
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ export function getProgressBar(action: string): (percent: number) => void {
|
||||
return;
|
||||
}
|
||||
|
||||
//process.stdin.setRawMode(false);
|
||||
//process.stdin.pause();
|
||||
process.stdin.setRawMode(false);
|
||||
process.stdin.pause();
|
||||
|
||||
if (progress === lastProgress || lastProgress === 100) { return; }
|
||||
lastProgress = progress;
|
||||
@ -151,9 +151,9 @@ function _getPrompt(prompt: string, options: PromptOptions, callback: (ctrlC: bo
|
||||
stdin.on('data', handler);
|
||||
}
|
||||
|
||||
export function getPrompt(prompt: string, options: PromptOptions): Promise<string> {
|
||||
export function getPrompt(prompt: string, options?: PromptOptions): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
_getPrompt(prompt, options, (ctrlC, password) => {
|
||||
_getPrompt(prompt, (options || { }), (ctrlC, password) => {
|
||||
if (ctrlC) {
|
||||
return reject(new Error("cancelled"));
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
|
||||
import { Options, publish as npmPublish } from "libnpmpublish";
|
||||
import semver from "semver";
|
||||
|
||||
import { getUrl } from "./geturl";
|
||||
import { Package, getPackage as _getPackage } from "./local";
|
||||
import { colorify, getPrompt } from "./log";
|
||||
|
||||
|
||||
const cache: Record<string, any> = { };
|
||||
@ -46,3 +48,21 @@ export async function getPackage(name: string, version?: string): Promise<Packag
|
||||
_ethers_nobuild: !!info._ethers_nobuild,
|
||||
};
|
||||
}
|
||||
|
||||
export async function publish(path: string, manifest: any, options: Options): Promise<void> {
|
||||
try {
|
||||
await npmPublish(path, manifest, options);
|
||||
|
||||
} catch (error) {
|
||||
|
||||
// We need an OTP
|
||||
if (error.code === "EOTP") {
|
||||
const otp = await getPrompt(colorify.bold("Enter OTP: "));
|
||||
options.otp = otp.replace(" ", "");
|
||||
|
||||
// Retry with the new OTP
|
||||
return await publish(path, manifest, options);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
23
misc/admin/thirdparty.d.ts
vendored
23
misc/admin/thirdparty.d.ts
vendored
@ -2,18 +2,21 @@ declare module "aes-js" {
|
||||
export class Counter {
|
||||
constructor(iv: Uint8Array);
|
||||
}
|
||||
|
||||
export namespace ModeOfOperation {
|
||||
class cbc{
|
||||
constructor(key: Uint8Array, iv: Uint8Array);
|
||||
decrypt(data: Uint8Array): Uint8Array;
|
||||
encrypt(data: Uint8Array): Uint8Array;
|
||||
}
|
||||
|
||||
class ctr{
|
||||
constructor(key: Uint8Array, counter: Counter);
|
||||
decrypt(data: Uint8Array): Uint8Array;
|
||||
encrypt(data: Uint8Array): Uint8Array;
|
||||
}
|
||||
}
|
||||
|
||||
export namespace padding {
|
||||
export namespace pkcs7 {
|
||||
export function strip(data: Uint8Array): Uint8Array;
|
||||
@ -21,19 +24,13 @@ declare module "aes-js" {
|
||||
}
|
||||
}
|
||||
|
||||
declare module "tar" {
|
||||
export type CreateOptions = {
|
||||
sync?: boolean,
|
||||
cwd?: string,
|
||||
prefix?: string,
|
||||
gzip?: boolean,
|
||||
portable?: boolean,
|
||||
mtime?: Date
|
||||
declare module "libnpmpublish" {
|
||||
export type Options = {
|
||||
access?: "public" | "restricted";
|
||||
npmVersion?: string;
|
||||
otp?: string;
|
||||
token?: string;
|
||||
};
|
||||
|
||||
export interface Readable {
|
||||
read(): Buffer;
|
||||
}
|
||||
|
||||
export function create(options: CreateOptions, files: Array<string>): Readable;
|
||||
export function publish(path: string, manifest: string, options: Options): Promise<void>
|
||||
}
|
||||
|
@ -40,7 +40,7 @@
|
||||
"build-libs": "node ./misc/admin/lib/cmds/update-exports.js && npm run _build-cjs && npm run _build-esm && node ./misc/admin/lib/cmds/set-build-option cjs && node packages/asm/generate.js && chmod 755 packages/*/lib/bin/*.js",
|
||||
"build-all": "npm run build-libs && npm run build-dist",
|
||||
"update-versions": "npm run clean && npm install && npm run spell-check && npm run build-all && node ./misc/admin/lib/cmds/bump-versions && npm run build-all && node ./misc/admin/lib/cmds/update-hashes && node ./misc/admin/lib/cmds/update-changelog",
|
||||
"TODO-publish-all": "node ./admin/cmds/publish",
|
||||
"publish-all": "node ./misc/admin/lib/cmds/publish",
|
||||
"TODO-sync-github": "node ./admin/cmds/cache-github"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -70,8 +70,7 @@
|
||||
"rollup-pluginutils": "2.8.1",
|
||||
"scrypt-js": "3.0.1",
|
||||
"semver": "^5.6.0",
|
||||
"typescript": "3.8.3",
|
||||
"uglify-es": "3.3.9"
|
||||
"typescript": "3.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/parser": "7.8.4",
|
||||
|
Loading…
Reference in New Issue
Block a user