From def2c8f518c6e70701641c5a326458a69f42a2fd Mon Sep 17 00:00:00 2001 From: Ayoub Kaanich <kayoub5@live.com> Date: Wed, 15 Aug 2018 07:57:09 +0200 Subject: [PATCH] refactor: Prepare GitHub storage for Git storage (#2378) Contains GitHub specific changes from #2323 --- lib/platform/github/index.js | 11 +- lib/platform/github/storage.js | 863 +++++++++++++++++---------------- 2 files changed, 459 insertions(+), 415 deletions(-) diff --git a/lib/platform/github/index.js b/lib/platform/github/index.js index afcbac8762..efc9dcd7c6 100644 --- a/lib/platform/github/index.js +++ b/lib/platform/github/index.js @@ -77,6 +77,10 @@ async function getRepos(token, endpoint) { } function cleanRepo() { + // istanbul ignore if + if (config.storage) { + config.storage.cleanRepo(); + } // In theory most of this isn't necessary. In practice.. get.reset(); config = {}; @@ -179,7 +183,8 @@ async function initRepo({ // This shouldn't be necessary, but occasional strange errors happened until it was added config.issueList = null; config.prList = null; - config.storage = new Storage(config); + config.storage = new Storage(); + await config.storage.initRepo(config); logger.debug('Prefetching prList and fileList'); await Promise.all([getPrList(), getFileList()]); if (forkMode) { @@ -225,7 +230,7 @@ async function initRepo({ // Wait an arbitrary 30s to hopefully give GitHub enough time for forking to complete await delay(30000); } - config.storage = new Storage(config); + await config.storage.initRepo(config); } // istanbul ignore if if (mirrorMode) { @@ -334,7 +339,7 @@ async function setBaseBranch(branchName) { logger.debug(`Setting baseBranch to ${branchName}`); config.baseBranch = branchName; config.baseCommitSHA = null; - config.storage = new Storage(config); + config.storage.setBaseBranch(branchName); await getFileList(branchName); } } diff --git a/lib/platform/github/storage.js b/lib/platform/github/storage.js index ad9bf0baf3..a9bd11550a 100644 --- a/lib/platform/github/storage.js +++ b/lib/platform/github/storage.js @@ -5,472 +5,511 @@ const get = require('./gh-got-wrapper'); const { expandError } = require('./util'); class Storage { - constructor(config) { + constructor() { // config - this.config = config; - this.gitAuthor = config.gitAuthor; - this.gitPrivateKey = config.gitPrivateKey; - this.forkToken = config.forkToken; - this.repository = config.repository; - this.baseBranch = config.baseBranch; + let config = {}; // cache - this.branchFiles = {}; - this.branchList = null; - } + let branchFiles = {}; + let branchList = null; - // Returns true if branch exists, otherwise false - async branchExists(branchName) { - if (!this.branchList) { - logger.debug('Retrieving branchList'); - this.branchList = (await get( - `repos/${this.repository}/branches?per_page=100`, - { - paginate: true, - } - )).body.map(branch => branch.name); - logger.debug({ branchList: this.branchList }, 'Retrieved branchList'); + Object.assign(this, { + initRepo, + cleanRepo, + branchExists, + commitFilesToBranch, + createBranch, + deleteBranch, + getAllRenovateBranches, + getBranchCommit, + getBranchLastCommitTime, + getCommitMessages, + getFile, + getFileList, + isBranchStale, + mergeBranch, + setBaseBranch, + }); + + function initRepo(args) { + cleanRepo(); + config = { ...args }; } - const res = this.branchList.includes(branchName); - logger.debug(`branchExists(${branchName})=${res}`); - return res; - } - // Get full file list - async getFileList(branchName) { - const branch = branchName || this.baseBranch; - if (this.branchFiles[branch]) { - return this.branchFiles[branch]; + function cleanRepo() { + branchFiles = {}; + branchList = null; } - try { - const res = await get( - `repos/${this.repository}/git/trees/${branch}?recursive=true` - ); - if (res.body.truncated) { - logger.warn( - { repository: this.repository }, - 'repository tree is truncated' - ); + + // Returns true if branch exists, otherwise false + async function branchExists(branchName) { + if (!branchList) { + logger.debug('Retrieving branchList'); + branchList = (await get( + `repos/${config.repository}/branches?per_page=100`, + { + paginate: true, + } + )).body.map(branch => branch.name); + logger.debug({ branchList }, 'Retrieved branchList'); } - const fileList = res.body.tree - .filter(item => item.type === 'blob' && item.mode !== '120000') - .map(item => item.path) - .sort(); - logger.debug(`Retrieved fileList with length ${fileList.length}`); - this.branchFiles[branch] = fileList; - return fileList; - } catch (err) /* istanbul ignore next */ { - if (err.statusCode === 409) { - logger.debug('Repository is not initiated'); - throw new Error('uninitiated'); + const res = branchList.includes(branchName); + logger.debug(`branchExists(${branchName})=${res}`); + return res; + } + + function setBaseBranch(branchName) { + if (branchName) { + logger.debug(`Setting baseBranch to ${branchName}`); + config.baseBranch = branchName; } - logger.info( - { repository: this.repository }, - 'Error retrieving git tree - no files detected' - ); - return []; } - } - async getAllRenovateBranches(branchPrefix) { - logger.trace('getAllRenovateBranches'); - try { - const allBranches = (await get( - `repos/${this.repository}/git/refs/heads/${branchPrefix}`, - { - paginate: true, - } - )).body; - return allBranches.reduce((arr, branch) => { - if (branch.ref.startsWith(`refs/heads/${branchPrefix}`)) { - arr.push(branch.ref.substring('refs/heads/'.length)); - } - if ( - branchPrefix.endsWith('/') && - branch.ref === `refs/heads/${branchPrefix.slice(0, -1)}` - ) { + // Get full file list + async function getFileList(branchName) { + const branch = branchName || config.baseBranch; + if (branchFiles[branch]) { + return branchFiles[branch]; + } + try { + const res = await get( + `repos/${config.repository}/git/trees/${branch}?recursive=true` + ); + if (res.body.truncated) { logger.warn( - `Pruning branch "${branchPrefix.slice( - 0, - -1 - )}" so that it does not block PRs` + { repository: config.repository }, + 'repository tree is truncated' ); - arr.push(branch.ref.substring('refs/heads/'.length)); } - return arr; - }, []); - } catch (err) /* istanbul ignore next */ { - return []; + const fileList = res.body.tree + .filter(item => item.type === 'blob' && item.mode !== '120000') + .map(item => item.path) + .sort(); + logger.debug(`Retrieved fileList with length ${fileList.length}`); + branchFiles[branch] = fileList; + return fileList; + } catch (err) /* istanbul ignore next */ { + if (err.statusCode === 409) { + logger.debug('Repository is not initiated'); + throw new Error('uninitiated'); + } + logger.info( + { repository: config.repository }, + 'Error retrieving git tree - no files detected' + ); + return []; + } } - } - async isBranchStale(branchName) { - // Check if branch's parent SHA = master SHA - logger.debug(`isBranchStale(${branchName})`); - const branchCommit = await this.getBranchCommit(branchName); - logger.debug(`branchCommit=${branchCommit}`); - const commitDetails = await getCommitDetails(this, branchCommit); - logger.trace({ commitDetails }, `commitDetails`); - const parentSha = commitDetails.parents[0].sha; - logger.debug(`parentSha=${parentSha}`); - const baseCommitSHA = await this.getBranchCommit(this.baseBranch); - logger.debug(`baseCommitSHA=${baseCommitSHA}`); - // Return true if the SHAs don't match - return parentSha !== baseCommitSHA; - } + async function getAllRenovateBranches(branchPrefix) { + logger.trace('getAllRenovateBranches'); + try { + const allBranches = (await get( + `repos/${config.repository}/git/refs/heads/${branchPrefix}`, + { + paginate: true, + } + )).body; + return allBranches.reduce((arr, branch) => { + if (branch.ref.startsWith(`refs/heads/${branchPrefix}`)) { + arr.push(branch.ref.substring('refs/heads/'.length)); + } + if ( + branchPrefix.endsWith('/') && + branch.ref === `refs/heads/${branchPrefix.slice(0, -1)}` + ) { + logger.warn( + `Pruning branch "${branchPrefix.slice( + 0, + -1 + )}" so that it does not block PRs` + ); + arr.push(branch.ref.substring('refs/heads/'.length)); + } + return arr; + }, []); + } catch (err) /* istanbul ignore next */ { + return []; + } + } - async deleteBranch(branchName) { - delete this.branchFiles[branchName]; - const options = this.forkToken ? { token: this.forkToken } : undefined; - try { - await get.delete( - `repos/${this.repository}/git/refs/heads/${branchName}`, - options - ); - } catch (err) /* istanbul ignore next */ { - if (err.message.startsWith('Reference does not exist')) { - logger.info({ branchName }, 'Branch to delete does not exist'); - } else { - logger.warn( - { err, body: err.response.body, branchName }, - 'Error deleting branch' + async function isBranchStale(branchName) { + // Check if branch's parent SHA = master SHA + logger.debug(`isBranchStale(${branchName})`); + const branchCommit = await getBranchCommit(branchName); + logger.debug(`branchCommit=${branchCommit}`); + const commitDetails = await getCommitDetails(branchCommit); + logger.trace({ commitDetails }, `commitDetails`); + const parentSha = commitDetails.parents[0].sha; + logger.debug(`parentSha=${parentSha}`); + const baseCommitSHA = await getBranchCommit(config.baseBranch); + logger.debug(`baseCommitSHA=${baseCommitSHA}`); + // Return true if the SHAs don't match + return parentSha !== baseCommitSHA; + } + + async function deleteBranch(branchName) { + delete branchFiles[branchName]; + const options = config.forkToken + ? { token: config.forkToken } + : undefined; + try { + await get.delete( + `repos/${config.repository}/git/refs/heads/${branchName}`, + options ); + } catch (err) /* istanbul ignore next */ { + if (err.message.startsWith('Reference does not exist')) { + logger.info({ branchName }, 'Branch to delete does not exist'); + } else { + logger.warn( + { err, body: err.response.body, branchName }, + 'Error deleting branch' + ); + } } } - } - async mergeBranch(branchName) { - logger.debug(`mergeBranch(${branchName})`); - const url = `repos/${this.repository}/git/refs/heads/${this.baseBranch}`; - const options = { - body: { - sha: await this.getBranchCommit(branchName), - }, - }; - try { - await get.patch(url, options); - } catch (err) { - logger.info( - expandError(err), - `Error pushing branch merge for ${branchName}` - ); - throw new Error('Branch automerge failed'); + async function mergeBranch(branchName) { + logger.debug(`mergeBranch(${branchName})`); + const url = `repos/${config.repository}/git/refs/heads/${ + config.baseBranch + }`; + const options = { + body: { + sha: await getBranchCommit(branchName), + }, + }; + try { + await get.patch(url, options); + } catch (err) { + logger.info( + expandError(err), + `Error pushing branch merge for ${branchName}` + ); + throw new Error('Branch automerge failed'); + } + // Delete branch + await deleteBranch(branchName); } - // Delete branch - await this.deleteBranch(branchName); - } - async getBranchLastCommitTime(branchName) { - try { - const res = await get( - `repos/${this.repository}/commits?sha=${branchName}` - ); - return new Date(res.body[0].commit.committer.date); - } catch (err) { - logger.error(expandError(err), `getBranchLastCommitTime error`); - return new Date(); + async function getBranchLastCommitTime(branchName) { + try { + const res = await get( + `repos/${config.repository}/commits?sha=${branchName}` + ); + return new Date(res.body[0].commit.committer.date); + } catch (err) { + logger.error(expandError(err), `getBranchLastCommitTime error`); + return new Date(); + } } - } - // Generic File operations + // Generic File operations - async getFile(filePath, branchName) { - logger.trace(`getFile(filePath=${filePath}, branchName=${branchName})`); - const branchFiles = await this.getFileList(branchName); - if (!branchFiles.includes(filePath)) { - return null; - } - let res; - try { - res = await get( - `repos/${this.repository}/contents/${encodeURI( - filePath - )}?ref=${branchName || this.baseBranch}` - ); - } catch (error) { - if (error.statusCode === 404) { - // If file not found, then return null JSON - logger.info({ filePath, branchName }, 'getFile 404'); + async function getFile(filePath, branchName) { + logger.trace(`getFile(filePath=${filePath}, branchName=${branchName})`); + if (!(await getFileList(branchName)).includes(filePath)) { return null; } - if ( - error.statusCode === 403 && - error.message && - error.message.startsWith('This API returns blobs up to 1 MB in size') - ) { - logger.info('Large file'); - // istanbul ignore if - if (branchName && branchName !== this.baseBranch) { - logger.info('Cannot retrieve large files from non-master branch'); - return null; - } - // istanbul ignore if - if (path.dirname(filePath) !== '.') { - logger.info('Cannot retrieve large files from non-root directories'); + let res; + try { + res = await get( + `repos/${config.repository}/contents/${encodeURI( + filePath + )}?ref=${branchName || config.baseBranch}` + ); + } catch (error) { + if (error.statusCode === 404) { + // If file not found, then return null JSON + logger.info({ filePath, branchName }, 'getFile 404'); return null; } - const treeUrl = `repos/${this.repository}/git/trees/${this.baseBranch}`; - const baseName = path.basename(filePath); - let fileSha; - (await get(treeUrl)).body.tree.forEach(file => { - if (file.path === baseName) { - fileSha = file.sha; + if ( + error.statusCode === 403 && + error.message && + error.message.startsWith('This API returns blobs up to 1 MB in size') + ) { + logger.info('Large file'); + // istanbul ignore if + if (branchName && branchName !== config.baseBranch) { + logger.info('Cannot retrieve large files from non-master branch'); + return null; } - }); - if (!fileSha) { - logger.warn('Could not locate file blob'); + // istanbul ignore if + if (path.dirname(filePath) !== '.') { + logger.info( + 'Cannot retrieve large files from non-root directories' + ); + return null; + } + const treeUrl = `repos/${config.repository}/git/trees/${ + config.baseBranch + }`; + const baseName = path.basename(filePath); + let fileSha; + (await get(treeUrl)).body.tree.forEach(file => { + if (file.path === baseName) { + fileSha = file.sha; + } + }); + if (!fileSha) { + logger.warn('Could not locate file blob'); + throw error; + } + res = await get(`repos/${config.repository}/git/blobs/${fileSha}`); + } else { + // Propagate if it's any other error throw error; } - res = await get(`repos/${this.repository}/git/blobs/${fileSha}`); - } else { - // Propagate if it's any other error - throw error; } + if (res && res.body.content) { + return Buffer.from(res.body.content, 'base64').toString(); + } + return null; } - if (res && res.body.content) { - return Buffer.from(res.body.content, 'base64').toString(); - } - return null; - } - // Add a new commit, create branch if not existing - async commitFilesToBranch( - branchName, - files, - message, - parentBranch = this.baseBranch - ) { - logger.debug( - `commitFilesToBranch('${branchName}', files, message, '${parentBranch})'` - ); - delete this.branchFiles[branchName]; - const parentCommit = await this.getBranchCommit(parentBranch); - const parentTree = await getCommitTree(this, parentCommit); - const fileBlobs = []; - // Create blobs - for (const file of files) { - const blob = await createBlob(this, file.contents); - fileBlobs.push({ - name: file.name, - blob, - }); - } - // Create tree - const tree = await createTree(this, parentTree, fileBlobs); - const commit = await createCommit(this, parentCommit, tree, message); - const isBranchExisting = await this.branchExists(branchName); - try { - if (isBranchExisting) { - await updateBranch(this, branchName, commit); - } else { - await this.createBranch(branchName, commit); + // Add a new commit, create branch if not existing + async function commitFilesToBranch( + branchName, + files, + message, + parentBranch = config.baseBranch + ) { + logger.debug( + `commitFilesToBranch('${branchName}', files, message, '${parentBranch})'` + ); + delete branchFiles[branchName]; + const parentCommit = await getBranchCommit(parentBranch); + const parentTree = await getCommitTree(parentCommit); + const fileBlobs = []; + // Create blobs + for (const file of files) { + const blob = await createBlob(file.contents); + fileBlobs.push({ + name: file.name, + blob, + }); + } + // Create tree + const tree = await createTree(parentTree, fileBlobs); + const commit = await createCommit(parentCommit, tree, message); + const isBranchExisting = await branchExists(branchName); + try { + if (isBranchExisting) { + await updateBranch(branchName, commit); + } else { + await createBranch(branchName, commit); + } + } catch (err) /* istanbul ignore next */ { + logger.debug({ + files: files.filter( + file => + !file.name.endsWith('package-lock.json') && + !file.name.endsWith('npm-shrinkwrap.json') && + !file.name.endsWith('yarn.lock') + ), + }); + throw err; } - } catch (err) /* istanbul ignore next */ { - logger.debug({ - files: files.filter( - file => - !file.name.endsWith('package-lock.json') && - !file.name.endsWith('npm-shrinkwrap.json') && - !file.name.endsWith('yarn.lock') - ), - }); - throw err; } - } - // Internal branch operations + // Internal branch operations - // Creates a new branch with provided commit - async createBranch(branchName, sha) { - logger.debug(`createBranch(${branchName})`); - const options = { - body: { - ref: `refs/heads/${branchName}`, - sha, - }, - }; - // istanbul ignore if - if (this.forkToken) { - options.token = this.forkToken; - } - try { + // Creates a new branch with provided commit + async function createBranch(branchName, sha) { + logger.debug(`createBranch(${branchName})`); + const options = { + body: { + ref: `refs/heads/${branchName}`, + sha, + }, + }; // istanbul ignore if - if (branchName.includes('/')) { - const [blockingBranch] = branchName.split('/'); - if (await this.branchExists(blockingBranch)) { - logger.warn({ blockingBranch }, 'Deleting blocking branch'); - await this.deleteBranch(blockingBranch); + if (config.forkToken) { + options.token = config.forkToken; + } + try { + // istanbul ignore if + if (branchName.includes('/')) { + const [blockingBranch] = branchName.split('/'); + if (await branchExists(blockingBranch)) { + logger.warn({ blockingBranch }, 'Deleting blocking branch'); + await deleteBranch(blockingBranch); + } + } + logger.debug({ options, branchName }, 'Creating branch'); + await get.post(`repos/${config.repository}/git/refs`, options); + branchList.push(branchName); + logger.debug('Created branch'); + } catch (err) /* istanbul ignore next */ { + const headers = err.response.req.getHeaders(); + delete headers.token; + logger.warn( + { + err, + message: err.message, + responseBody: err.response.body, + headers, + options, + }, + 'Error creating branch' + ); + if (err.statusCode === 422) { + throw new Error('repository-changed'); } + throw err; } - logger.debug({ options, branchName }, 'Creating branch'); - await get.post(`repos/${this.repository}/git/refs`, options); - this.branchList.push(branchName); - logger.debug('Created branch'); - } catch (err) /* istanbul ignore next */ { - const headers = err.response.req.getHeaders(); - delete headers.token; - logger.warn( - { - err, - message: err.message, - responseBody: err.response.body, - headers, - options, - }, - 'Error creating branch' + } + + // Return the commit SHA for a branch + async function getBranchCommit(branchName) { + const res = await get( + `repos/${config.repository}/git/refs/heads/${branchName}` ); - if (err.statusCode === 422) { - throw new Error('repository-changed'); - } - throw err; + return res.body.object.sha; } - } - // Return the commit SHA for a branch - async getBranchCommit(branchName) { - const res = await get( - `repos/${this.repository}/git/refs/heads/${branchName}` - ); - return res.body.object.sha; - } + async function getCommitMessages() { + logger.debug('getCommitMessages'); + const res = await get(`repos/${config.repository}/commits`); + return res.body.map(commit => commit.commit.message); + } - async getCommitMessages() { - logger.debug('getCommitMessages'); - const res = await get(`repos/${this.repository}/commits`); - return res.body.map(commit => commit.commit.message); - } -} + // Internal: Updates an existing branch to new commit sha + async function updateBranch(branchName, commit) { + logger.debug(`Updating branch ${branchName} with commit ${commit}`); + const options = { + body: { + sha: commit, + force: true, + }, + }; + // istanbul ignore if + if (config.forkToken) { + options.token = config.forkToken; + } + try { + await get.patch( + `repos/${config.repository}/git/refs/heads/${branchName}`, + options + ); + } catch (err) /* istanbul ignore next */ { + if (err.statusCode === 422) { + logger.info(expandError(err), 'Branch no longer exists - exiting'); + throw new Error('repository-changed'); + } + throw err; + } + } + // Low-level commit operations -// Internal: Updates an existing branch to new commit sha -async function updateBranch(self, branchName, commit) { - logger.debug(`Updating branch ${branchName} with commit ${commit}`); - const options = { - body: { - sha: commit, - force: true, - }, - }; - // istanbul ignore if - if (self.forkToken) { - options.token = self.forkToken; - } - try { - await get.patch( - `repos/${self.repository}/git/refs/heads/${branchName}`, - options - ); - } catch (err) /* istanbul ignore next */ { - if (err.statusCode === 422) { - logger.info(expandError(err), 'Branch no longer exists - exiting'); - throw new Error('repository-changed'); + // Create a blob with fileContents and return sha + async function createBlob(fileContents) { + logger.debug('Creating blob'); + const options = { + body: { + encoding: 'base64', + content: Buffer.from(fileContents).toString('base64'), + }, + }; + // istanbul ignore if + if (config.forkToken) { + options.token = config.forkToken; + } + return (await get.post(`repos/${config.repository}/git/blobs`, options)) + .body.sha; } - throw err; - } -} -// Low-level commit operations -// Create a blob with fileContents and return sha -async function createBlob(self, fileContents) { - logger.debug('Creating blob'); - const options = { - body: { - encoding: 'base64', - content: Buffer.from(fileContents).toString('base64'), - }, - }; - // istanbul ignore if - if (self.forkToken) { - options.token = self.forkToken; - } - return (await get.post(`repos/${self.repository}/git/blobs`, options)).body - .sha; -} + // Return the tree SHA for a commit + async function getCommitTree(commit) { + logger.debug(`getCommitTree(${commit})`); + return (await get(`repos/${config.repository}/git/commits/${commit}`)) + .body.tree.sha; + } -// Return the tree SHA for a commit -async function getCommitTree(self, commit) { - logger.debug(`getCommitTree(${commit})`); - return (await get(`repos/${self.repository}/git/commits/${commit}`)).body.tree - .sha; -} + // Create a tree and return SHA + async function createTree(baseTree, files) { + logger.debug(`createTree(${baseTree}, files)`); + const body = { + base_tree: baseTree, + tree: [], + }; + files.forEach(file => { + body.tree.push({ + path: file.name, + mode: '100644', + type: 'blob', + sha: file.blob, + }); + }); + logger.trace({ body }, 'createTree body'); + const options = { body }; + // istanbul ignore if + if (config.forkToken) { + options.token = config.forkToken; + } + return (await get.post(`repos/${config.repository}/git/trees`, options)) + .body.sha; + } -// Create a tree and return SHA -async function createTree(self, baseTree, files) { - logger.debug(`createTree(${baseTree}, files)`); - const body = { - base_tree: baseTree, - tree: [], - }; - files.forEach(file => { - body.tree.push({ - path: file.name, - mode: '100644', - type: 'blob', - sha: file.blob, - }); - }); - logger.trace({ body }, 'createTree body'); - const options = { body }; - // istanbul ignore if - if (self.forkToken) { - options.token = self.forkToken; - } - return (await get.post(`repos/${self.repository}/git/trees`, options)).body - .sha; -} + // Create a commit and return commit SHA + async function createCommit(parent, tree, message) { + logger.debug(`createCommit(${parent}, ${tree}, ${message})`); + const { gitAuthor, gitPrivateKey } = config; + const now = moment(); + let author; + if (gitAuthor) { + logger.trace('Setting gitAuthor'); + author = { + name: gitAuthor.name, + email: gitAuthor.address, + date: now.format(), + }; + } + const body = { + message, + parents: [parent], + tree, + }; + if (author) { + body.author = author; + // istanbul ignore if + if (gitPrivateKey) { + logger.debug('Found gitPrivateKey'); + const privKeyObj = openpgp.key.readArmored(gitPrivateKey).keys[0]; + const commit = `tree ${tree}\nparent ${parent}\nauthor ${ + author.name + } <${author.email}> ${now.format('X ZZ')}\ncommitter ${ + author.name + } <${author.email}> ${now.format('X ZZ')}\n\n${message}`; + const { signature } = await openpgp.sign({ + data: openpgp.util.str2Uint8Array(commit), + privateKeys: privKeyObj, + detached: true, + armor: true, + }); + body.signature = signature; + } + } + const options = { + body, + }; + // istanbul ignore if + if (config.forkToken) { + options.token = config.forkToken; + } + return (await get.post(`repos/${config.repository}/git/commits`, options)) + .body.sha; + } -// Create a commit and return commit SHA -async function createCommit(self, parent, tree, message) { - logger.debug(`createCommit(${parent}, ${tree}, ${message})`); - const { gitAuthor, gitPrivateKey } = self; - const now = moment(); - let author; - if (gitAuthor) { - logger.trace('Setting gitAuthor'); - author = { - name: gitAuthor.name, - email: gitAuthor.address, - date: now.format(), - }; - } - const body = { - message, - parents: [parent], - tree, - }; - if (author) { - body.author = author; - // istanbul ignore if - if (gitPrivateKey) { - logger.debug('Found gitPrivateKey'); - const privKeyObj = openpgp.key.readArmored(gitPrivateKey).keys[0]; - const commit = `tree ${tree}\nparent ${parent}\nauthor ${author.name} <${ - author.email - }> ${now.format('X ZZ')}\ncommitter ${author.name} <${ - author.email - }> ${now.format('X ZZ')}\n\n${message}`; - const { signature } = await openpgp.sign({ - data: openpgp.util.str2Uint8Array(commit), - privateKeys: privKeyObj, - detached: true, - armor: true, - }); - body.signature = signature; + async function getCommitDetails(commit) { + logger.debug(`getCommitDetails(${commit})`); + const results = await get( + `repos/${config.repository}/git/commits/${commit}` + ); + return results.body; } } - const options = { - body, - }; - // istanbul ignore if - if (self.forkToken) { - options.token = self.forkToken; - } - return (await get.post(`repos/${self.repository}/git/commits`, options)).body - .sha; -} - -async function getCommitDetails(self, commit) { - logger.debug(`getCommitDetails(${commit})`); - const results = await get(`repos/${self.repository}/git/commits/${commit}`); - return results.body; } module.exports = Storage; -- GitLab