Skip to content

Commit

Permalink
Add codeowners update (DefinitelyTyped#33654)
Browse files Browse the repository at this point in the history
* Add update-codeowners script

Right now it works but doesn't open a PR for you.
Also not present as an npm script.

* Dump in a bunch of code from TS

* A few fixes and updates

1. Fix package.json formatting.
2. Adapt copied code from TS.

* Ready to test locally

* Fix git add

* Put everything in one Promise chain

Also start compiling JS files in scripts/
  • Loading branch information
sandersn authored Mar 6, 2019
1 parent e004e12 commit 1c4ca4d
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 7 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"scripts": {
"compile-scripts": "tsc -p scripts",
"not-needed": "node scripts/not-needed.js",
"update-codeowners": "node scripts/update-codeowners.js",
"test": "node node_modules/types-publisher/bin/tester/test.js --run-from-definitely-typed",
"lint": "dtslint types"
},
Expand Down
11 changes: 4 additions & 7 deletions scripts/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
{
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"module": "commonjs",
"target": "es6",
"noImplicitAny": true,
"strictNullChecks": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"strict": true,
"baseUrl": "../types",
"typeRoots": [
"../types"
],
"types": [],
"forceConsistentCasingInFileNames": true
}
}
}
126 changes: 126 additions & 0 deletions scripts/update-codeowners.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/// <reference lib="esnext.asynciterable" />
// Must reference esnext.asynciterable lib, since octokit uses AsyncIterable internally
const cp = require("child_process");
const Octokit = require("@octokit/rest");
const { AllPackages, getDefinitelyTyped, loggerWithErrors,
parseDefinitions, parseNProcesses, clean } = require("types-publisher");
const { writeFile } = require("fs-extra");

async function main() {
const options = { definitelyTypedPath: ".", progress: false, parseInParallel: true };
const log = loggerWithErrors()[0];

clean();
const dt = await getDefinitelyTyped(options, log);
await parseDefinitions(dt, { nProcesses: parseNProcesses(), definitelyTypedPath: "." }, log);
const allPackages = await AllPackages.read(dt);
const typings = allPackages.allTypings();
const maxPathLen = Math.max(...typings.map(t => t.subDirectoryPath.length));
const entries = mapDefined(typings, t => getEntry(t, maxPathLen));
await writeFile([options.definitelyTypedPath, ".github", "CODEOWNERS"].join("/"), `${header}\n\n${entries.join("\n")}\n`, { encoding: "utf-8" });
}

const token = /** @type {string} */(process.env.GH_TOKEN);
const gh = new Octokit();
const reviewers = ["weswigham", "sandersn", "RyanCavanaugh"]
const now = new Date();
const branchName = `codeowner-update-${now.getFullYear()}${padNum(now.getMonth())}${padNum(now.getDay())}`;
const remoteUrl = `https://${token}@github.com/DefinitelyTyped/DefinitelyTyped.git`;
runSequence([
["git", ["checkout", "."]], // reset any changes
]);

main().then(() => {
runSequence([
["git", ["checkout", "-b", branchName]], // create a branch
["git", ["add", ".github/CODEOWNERS"]], // Add CODEOWNERS
["git", ["commit", "-m", `"Update CODEOWNERS"`]], // Commit all changes
["git", ["remote", "add", "fork", remoteUrl]], // Add the remote fork
["git", ["push", "--set-upstream", "fork", branchName, "-f"]] // push the branch
]);

gh.authenticate({
type: "token",
token,
});
return gh.pulls.create({
owner: "DefinitelyTyped",
repo: "DefinitelyTyped",
maintainer_can_modify: true,
title: `🤖 CODEOWNERS has changed`,
head: `DefinitelyTyped:${branchName}`,
base: "master",
body:
`Please review the diff and merge if no changes are unexpected.
cc ${reviewers.map(r => "@" + r).join(" ")}`,
})
}).then(r => {
const num = r.data.number;
console.log(`Pull request ${num} created.`);
return gh.pulls.createReviewRequest({
owner: "DefinitelyTyped",
repo: "DefinitelyTyped",
number: num,
reviewers,
});
}).then(() => {
console.log(`Reviewers requested, done.`);
}).catch(e => {
console.error(e);
process.exit(1);
});

/** @param {[string, string[]][]} tasks */
function runSequence(tasks) {
for (const task of tasks) {
console.log(`${task[0]} ${task[1].join(" ")}`);
const result = cp.spawnSync(task[0], task[1], { timeout: 100000, shell: true, stdio: "inherit" });
if (result.status !== 0) throw new Error(`${task[0]} ${task[1].join(" ")} failed: ${result.stderr && result.stderr.toString()}`);
}
}

/** @param {number} number */
function padNum(number) {
const str = "" + number;
return str.length >= 2 ? str : "0" + str;
}


const header =
`# This file is generated.
# Add yourself to the "Definitions by:" list instead.
# See https://github.com/DefinitelyTyped/DefinitelyTyped#edit-an-existing-package`;

/**
* @param { { contributors: ReadonlyArray<{githubUsername?: string }>, subDirectoryPath: string} } pkg
* @param {number} maxPathLen
* @return {string | undefined}
*/
function getEntry(pkg, maxPathLen) {
const users = mapDefined(pkg.contributors, c => c.githubUsername);
if (!users.length) {
return undefined;
}

const path = `${pkg.subDirectoryPath}/`.padEnd(maxPathLen);
return `/types/${path} ${users.map(u => `@${u}`).join(" ")}`;
}

/**
* @template T,U
* @param {ReadonlyArray<T>} arr
* @param {(t: T) => U | undefined} mapper
* @return U[]
*/
function mapDefined(arr, mapper) {
const out = [];
for (const a of arr) {
const res = mapper(a);
if (res !== undefined) {
out.push(res);
}
}
return out;
}

0 comments on commit 1c4ca4d

Please sign in to comment.