@atomist/automation-client
Version:
Atomist API for software low-level client
204 lines (203 loc) • 8.66 kB
JavaScript
;
/*
* Copyright © 2019 Atomist, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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 axios_1 = require("axios");
const ActionResult_1 = require("../../action/ActionResult");
const gitHub_1 = require("../../util/gitHub");
const logger_1 = require("../../util/logger");
const AbstractRemoteRepoRef_1 = require("./AbstractRemoteRepoRef");
const validationPatterns_1 = require("./params/validationPatterns");
const ProjectOperationCredentials_1 = require("./ProjectOperationCredentials");
const RepoId_1 = require("./RepoId");
exports.GitHubDotComBase = "https://api.github.com";
const FullGitHubDotComBase = "https://api.github.com/";
/**
* GitHub repo ref
*/
class GitHubRepoRef extends AbstractRemoteRepoRef_1.AbstractRemoteRepoRef {
/**
* Create a GitHubRepoRef instance. It may be easier to use [[GitHubRepoRef.from]].
* @param owner Repo owner
* @param repo Repo name
* @param sha Commit SHA to checkout
* @param rawApiBase Full GitHub API base URL
* @param path Path within the Git repository to use as project root
* @param branch Branch to checkout
* @param rawRemoteBase Full GitHub remote base URL
*/
constructor(owner, repo, sha, rawApiBase = exports.GitHubDotComBase, path, branch, rawRemoteBase) {
super(rawApiBase === exports.GitHubDotComBase || rawApiBase === FullGitHubDotComBase ? RepoId_1.ProviderType.github_com : RepoId_1.ProviderType.ghe, rawRemoteBase || apiBaseToRemoteBase(rawApiBase), rawApiBase, owner, repo, sha, path, branch);
this.kind = "github";
}
/**
* Create a GitHubRepoRef instance.
* @param params Object with the following properties:
* owner: Repo owner
* repo: Repo name
* sha: Commit SHA to checkout
* rawApiBase: Full GitHub API base URL
* path: Path within the Git repository to use as project root
* branch: Branch to checkout
* rawRemoteBase: Full GitHub remote base URL
*/
static from(params) {
if (params.sha && !params.sha.match(validationPatterns_1.GitShaRegExp.pattern)) {
throw new Error("You provided an invalid SHA: " + params.sha);
}
const result = new GitHubRepoRef(params.owner, params.repo, params.sha, params.rawApiBase, params.path, params.branch);
return result;
}
createRemote(creds, description, visibility) {
if (!ProjectOperationCredentials_1.isTokenCredentials(creds)) {
throw new Error("Only token auth supported");
}
return gitHub_1.createRepo(creds.token, this, description, visibility === "private")
.then(() => ActionResult_1.successOn(this));
}
setUserConfig(credentials, project) {
const config = headers(credentials);
return Promise.all([
axios_1.default.get(`${this.scheme}${this.apiBase}/user`, config),
axios_1.default.get(`${this.scheme}${this.apiBase}/user/public_emails`, config),
])
.then(results => {
const name = results[0].data.name || results[0].data.login;
let email = results[0].data.email;
if (!email && results[1].data && results[1].data.length > 0) {
email = results[1].data[0].email;
}
if (name && email) {
return project.setUserConfig(name, email);
}
else {
return project.setUserConfig("Atomist Bot", "bot@atomist.com");
}
})
.catch(() => project.setUserConfig("Atomist Bot", "bot@atomist.com"))
.then(ActionResult_1.successOn);
}
raisePullRequest(credentials, title, body, head, base) {
return __awaiter(this, void 0, void 0, function* () {
const url = `${this.scheme}${this.apiBase}/repos/${this.owner}/${this.repo}`;
const config = headers(credentials);
// Check if PR already exists on the branch
const pr = (yield axios_1.default.get(`${url}/pulls?state=open&head=${this.owner}:${head}`, config)).data;
if (!!pr && pr.length > 0) {
try {
yield axios_1.default.patch(`${url}/pulls/${pr[0].number}`, {
title,
}, config);
yield axios_1.default.post(`${url}/issues/${pr[0].number}/comments`, {
body: beautifyPullRequestBody(body),
}, config);
return {
target: this,
success: true,
};
}
catch (e) {
logger_1.logger.error(`Error attempting to add PR comment. ${url} ${e}`);
throw e;
}
}
else {
return axios_1.default.post(`${url}/pulls`, {
title,
body: beautifyPullRequestBody(body),
head,
base,
}, config)
.then(axiosResponse => {
return {
target: this,
success: true,
axiosResponse,
};
})
.catch(err => {
logger_1.logger.error(`Error attempting to raise PR. ${url} ${err}`);
return Promise.reject(err);
});
}
});
}
deleteRemote(creds) {
const url = `${this.scheme}${this.apiBase}/repos/${this.owner}/${this.repo}`;
return axios_1.default.delete(url, headers(creds))
.then(r => ActionResult_1.successOn(this));
}
}
exports.GitHubRepoRef = GitHubRepoRef;
function isGitHubRepoRef(rr) {
const maybe = rr;
return maybe && !!maybe.apiBase && maybe.kind === "github";
}
exports.isGitHubRepoRef = isGitHubRepoRef;
function headers(credentials) {
if (!ProjectOperationCredentials_1.isTokenCredentials(credentials)) {
throw new Error("Only token auth supported");
}
return {
headers: {
Authorization: `token ${credentials.token}`,
},
};
}
function apiBaseToRemoteBase(rawApiBase) {
if (rawApiBase.includes("api.github.com")) {
return "https://github.com";
}
if (rawApiBase.includes("api/v3")) {
return rawApiBase.substring(0, rawApiBase.indexOf("api/v3"));
}
return rawApiBase;
}
// exported for testing
function beautifyPullRequestBody(body) {
const tagRegEx = /(\[[-\w]+:[-\w:=\/\.]+\])/gm;
let tagMatches = tagRegEx.exec(body);
const tags = [];
while (!!tagMatches) {
tags.push(tagMatches[1]);
tagMatches = tagRegEx.exec(body);
}
if (tags.length > 0) {
const newBody = body.replace(/\[[-\w]+:[-\w:=\/\.]+\]/g, "")
.replace(/\n\s*\n\s*\n/g, "\n\n")
.trim();
return `${newBody}
---
<details>
<summary>Tags</summary>
<br/>
${tags.sort().map(t => `<code>${t}</code>`).join("<br/>")}
</details>`;
}
return body;
}
exports.beautifyPullRequestBody = beautifyPullRequestBody;
//# sourceMappingURL=GitHubRepoRef.js.map