'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread2(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } async function valueToTreeObject(octokit, owner, repo, path, value) { let mode = "100644"; if (value !== null && typeof value !== "string") { mode = value.mode || mode; } // Text files can be changed through the .content key if (typeof value === "string") { return { path, mode: mode, content: value }; } // Binary files need to be created first using the git blob API, // then changed by referencing in the .sha key const { data } = await octokit.request("POST /repos/{owner}/{repo}/git/blobs", _objectSpread2({ owner, repo }, value)); const blobSha = data.sha; return { path, mode: mode, sha: blobSha }; } async function createTree(state, changes) { const { octokit, owner, repo, ownerOrFork, latestCommitSha, latestCommitTreeSha } = state; const tree = (await Promise.all(Object.keys(changes.files).map(async path => { const value = changes.files[path]; if (value === null) { // Deleting a non-existent file from a tree leads to an "GitRPC::BadObjectState" error, // so we only attempt to delete the file if it exists. try { // https://developer.github.com/v3/repos/contents/#get-contents await octokit.request("HEAD /repos/{owner}/{repo}/contents/:path", { owner: ownerOrFork, repo, ref: latestCommitSha, path }); return { path, mode: "100644", sha: null }; } catch (error) { return; } } // When passed a function, retrieve the content of the file, pass it // to the function, then return the result if (typeof value === "function") { let result; try { const { data: file } = await octokit.request("GET /repos/{owner}/{repo}/contents/:path", { owner: ownerOrFork, repo, ref: latestCommitSha, path }); result = await value(Object.assign(file, { exists: true })); } catch (error) { // istanbul ignore if if (error.status !== 404) throw error; // @ts-ignore result = await value({ exists: false }); } if (result === null || typeof result === "undefined") return; return valueToTreeObject(octokit, ownerOrFork, repo, path, result); } return valueToTreeObject(octokit, ownerOrFork, repo, path, value); }))).filter(Boolean); if (tree.length === 0) { return null; } // https://developer.github.com/v3/git/trees/#create-a-tree const { data: { sha: newTreeSha } } = await octokit.request("POST /repos/{owner}/{repo}/git/trees", { owner: ownerOrFork, repo, base_tree: latestCommitTreeSha, tree }); return newTreeSha; } async function createCommit(state, treeCreated, changes) { const { octokit, repo, ownerOrFork, latestCommitSha } = state; const message = treeCreated ? changes.commit : typeof changes.emptyCommit === "string" ? changes.emptyCommit : changes.commit; // https://developer.github.com/v3/git/commits/#create-a-commit const { data: latestCommit } = await octokit.request("POST /repos/{owner}/{repo}/git/commits", { owner: ownerOrFork, repo, message, tree: state.latestCommitTreeSha, parents: [latestCommitSha] }); return latestCommit.sha; } async function composeCreatePullRequest(octokit, { owner, repo, title, body, base, head, createWhenEmpty, changes: changesOption, draft = false, forceFork = false, update = false }) { var _branchInfo$repositor, _branchInfo$repositor2, _branchInfo$repositor3, _branchInfo$repositor4; const changes = Array.isArray(changesOption) ? changesOption : [changesOption]; if (changes.length === 0) throw new Error('[octokit-plugin-create-pull-request] "changes" cannot be an empty array'); const state = { octokit, owner, repo }; // https://developer.github.com/v3/repos/#get-a-repository const { data: repository, headers } = await octokit.request("GET /repos/{owner}/{repo}", { owner, repo }); const isUser = !!headers["x-oauth-scopes"]; if (!repository.permissions) { throw new Error("[octokit-plugin-create-pull-request] Missing authentication"); } if (!base) { base = repository.default_branch; } state.ownerOrFork = owner; if (forceFork || isUser && !repository.permissions.push) { // https://developer.github.com/v3/users/#get-the-authenticated-user const user = await octokit.request("GET /user"); // https://developer.github.com/v3/repos/forks/#list-forks const forks = await octokit.request("GET /repos/{owner}/{repo}/forks", { owner, repo }); const hasFork = forks.data.find( /* istanbul ignore next - fork owner can be null, but we don't test that */ fork => fork.owner && fork.owner.login === user.data.login); if (!hasFork) { // https://developer.github.com/v3/repos/forks/#create-a-fork await octokit.request("POST /repos/{owner}/{repo}/forks", { owner, repo }); } state.ownerOrFork = user.data.login; } // https://developer.github.com/v3/repos/commits/#list-commits-on-a-repository const { data: [latestCommit] } = await octokit.request("GET /repos/{owner}/{repo}/commits", { owner, repo, sha: base, per_page: 1 }); state.latestCommitSha = latestCommit.sha; state.latestCommitTreeSha = latestCommit.commit.tree.sha; const baseCommitTreeSha = latestCommit.commit.tree.sha; for (const change of changes) { let treeCreated = false; if (change.files && Object.keys(change.files).length) { const latestCommitTreeSha = await createTree(state, change); if (latestCommitTreeSha) { state.latestCommitTreeSha = latestCommitTreeSha; treeCreated = true; } } if (treeCreated || change.emptyCommit !== false) { state.latestCommitSha = await createCommit(state, treeCreated, change); } } const hasNoChanges = baseCommitTreeSha === state.latestCommitTreeSha; if (hasNoChanges && createWhenEmpty === false) { return null; } const branchInfo = await octokit.graphql(` query ($owner: String!, $repo: String!, $head: String!) { repository(name: $repo, owner: $owner) { ref(qualifiedName: $head) { associatedPullRequests(first: 1, states: OPEN) { edges { node { id number url } } } } } }`, { owner: state.ownerOrFork, repo, head }); const branchExists = !!branchInfo.repository.ref; const existingPullRequest = (_branchInfo$repositor = branchInfo.repository.ref) === null || _branchInfo$repositor === void 0 ? void 0 : (_branchInfo$repositor2 = _branchInfo$repositor.associatedPullRequests) === null || _branchInfo$repositor2 === void 0 ? void 0 : (_branchInfo$repositor3 = _branchInfo$repositor2.edges) === null || _branchInfo$repositor3 === void 0 ? void 0 : (_branchInfo$repositor4 = _branchInfo$repositor3[0]) === null || _branchInfo$repositor4 === void 0 ? void 0 : _branchInfo$repositor4.node; if (existingPullRequest && !update) { throw new Error(`[octokit-plugin-create-pull-request] Pull request already exists: ${existingPullRequest.url}. Set update=true to enable updating`); } if (branchExists) { // https://docs.github.com/en/rest/git/refs#update-a-reference await octokit.request("PATCH /repos/{owner}/{repo}/git/refs/{ref}", { owner: state.ownerOrFork, repo, sha: state.latestCommitSha, ref: `heads/${head}`, force: true }); } else { // https://developer.github.com/v3/git/refs/#create-a-reference await octokit.request("POST /repos/{owner}/{repo}/git/refs", { owner: state.ownerOrFork, repo, sha: state.latestCommitSha, ref: `refs/heads/${head}` }); } const pullRequestOptions = { owner, repo, head: `${state.ownerOrFork}:${head}`, base, title, body, draft }; if (existingPullRequest) { // https://docs.github.com/en/rest/pulls/pulls#update-a-pull-request return await octokit.request("PATCH /repos/{owner}/{repo}/pulls/{pull_number}", _objectSpread2({ pull_number: existingPullRequest.number }, pullRequestOptions)); } else { // https://developer.github.com/v3/pulls/#create-a-pull-request return await octokit.request("POST /repos/{owner}/{repo}/pulls", pullRequestOptions); } } const VERSION = "3.13.1"; /** * @param octokit Octokit instance */ function createPullRequest(octokit) { return { createPullRequest: composeCreatePullRequest.bind(null, octokit) }; } createPullRequest.VERSION = VERSION; exports.composeCreatePullRequest = composeCreatePullRequest; exports.createPullRequest = createPullRequest; //# sourceMappingURL=index.js.map