From 07196c3c72b59c5f00c8edddce3c3d4ff8ba8b11 Mon Sep 17 00:00:00 2001 From: Kamil Pajdzik <41709775+kpajdzik@users.noreply.github.com> Date: Mon, 18 Mar 2019 12:36:20 -0700 Subject: [PATCH] Add GitHub AutoPR branch cleanup script (#4904) * Add GitHub AutoPR branch cleanup script * Fix octokit breaking changes * Remove TypeScript compilation from Travis CI --- .scripts/github.ts | 85 ++++++++++++++++++++++++++++++++++++++++++++++ .travis.yml | 4 --- package.json | 3 ++ tsconfig.json | 20 +++++++++++ 4 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 .scripts/github.ts create mode 100644 tsconfig.json diff --git a/.scripts/github.ts b/.scripts/github.ts new file mode 100644 index 0000000000..ad9406ece7 --- /dev/null +++ b/.scripts/github.ts @@ -0,0 +1,85 @@ +/** + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for + * license information. + */ + +import Octokit, { PullRequestsListParams } from '@octokit/rest'; +import { exec as execWithCallback } from "child_process"; + +const _repositoryOwner = "Azure"; + +function _validatePersonalAccessToken(token: string): void { + if (!token) { + const text = + `Github personal access token was not found as a script parameter or as an + environmental variable. Please visit https://github.com/settings/tokens, + generate new token with "repo" scope and pass it with -token switch or set + it as environmental variable named SDK_GEN_GITHUB_TOKEN.` + + console.log(text); + } +} + +function getToken(): string { + const token: string = process.env.SDK_GEN_GITHUB_TOKEN || ""; + _validatePersonalAccessToken(token); + + return token; +} + +function getAuthenticatedClient(): Octokit { + const octokit = new Octokit(); + octokit.authenticate({ type: "token", token: getToken() }); + return octokit; +} + +async function exec(command: string): Promise { + console.log(`Executing ${command}`); + return new Promise((resolve, reject) => { + execWithCallback(command, (error, stdout) => { + if (error) { + reject(error); + } + + resolve(stdout); + }); + }); +} + +async function cleanBranches() { + const octokit = getAuthenticatedClient(); + const params: PullRequestsListParams = { + owner: _repositoryOwner, + repo: "azure-sdk-for-node", + state: "open" + } + + let pullRequestsResponse = await octokit.pullRequests.list(params); + + do { + const autoPullRequests = pullRequestsResponse.data.filter(pr => pr.title.startsWith("[AutoPR")).map(pr => pr.head.ref); + console.log(JSON.stringify(autoPullRequests, undefined, " ")); + console.log(JSON.stringify(autoPullRequests.length, undefined, " ")); + + for (const branch of autoPullRequests) { + try { + await exec(`git push origin :${branch}`); + } catch (err) { + console.log(`Branch ${branch} doesn't exist. Skipping. Error: [${err}]`); + } + } + + if (octokit.hasFirstPage(pullRequestsResponse)) { + pullRequestsResponse = await octokit.getNextPage(pullRequestsResponse); + } else { + break; + } + } while (true); +} + +try { + cleanBranches(); +} catch (err) { + console.error(err); +} diff --git a/.travis.yml b/.travis.yml index 9a3614f6f4..a344149e46 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,3 @@ sudo: false node_js: - "8" - "6" - -before_script: - - npm i -g typescript - - tsc \ No newline at end of file diff --git a/package.json b/package.json index 332155fa05..7d64583ef0 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "uuid": "^3.0.1" }, "devDependencies": { + "@octokit/rest": "^15.17.0", "@types/request": "^2.0.3", "adal-node": "^0.1.22", "async": "^2.5.0", @@ -80,6 +81,8 @@ "random-js": "1.0.4", "should": "^8.3.1", "sinon": "^2.1.0", + "tslib": "^1.9.3", + "typescript": "^3.1.6", "xmlbuilder": "0.4.3", "yargs": "3.29.0" }, diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000000..ff14e64b37 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ + "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ + "lib": ["es2017"], /* Specify library files to be included in the compilation. */ + "importHelpers": true, /* Import emit helpers from 'tslib'. */ + "strict": true, /* Enable all strict type-checking options. */ + "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + "strictNullChecks": true, /* Enable strict null checks. */ + "strictFunctionTypes": true, /* Enable strict checking of function types. */ + "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + "noUnusedLocals": true, /* Report errors on unused locals. */ + "noUnusedParameters": true, /* Report errors on unused parameters. */ + "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + } +}