mirror of
https://forgejo.stefka.eu/jiriks74/create-pull-request.git
synced 2025-01-18 16:01:06 +01:00
feat: signed commits (v7) (#3057)
* Add support for signed commits (#3055) * formatting * fix eslint and lint errors * shift setting the base to before the push * sign commits by default for testing * add debug lines * read to buffer not string and use non-legacy method to base64 * debug payload without contents * disable linter for debug code * fix filepath when using path input * try to fix head repo * remove commented code * Try refactor of file changes * add tests for building file changes * add build file changes test for binary files * refactor graphql code into github helper class * build file changes even when there is no diff * add function to get commit detail * fix format * build branch commits * use source mode for deleted files * try rest api route * fix check for branch existence * force push * try fix base tree * debug commit verification * debug commit verification * fix format and cleanup * add executable mode file to test * limit blob creation concurrency * only build commits when feature enabled * remove unused code * update readme link * update docs for commit signing * fix capital letter * update docs * add throttling * set default back to false * output head sha and verified status * log outputs * fix head sha output * default the operation output to none * output retryafter for secondary rate limit * use separate client for branch and pull operations * add maintainer-can-modify input * rename git-token to branch-token * fix branch token input * remove deprecated env output * update docs * fix doc * update docs * build branch commits when there is a diff with the base * check verification status of head commit when not known * fix verified output when no commit signing is being used * draft always-true * convert to draft on branch updates when there is a diff with base * update docs with blob size limit * catch errors during blob creation for debugging * parse empty commits * pass base commit to push signed commits * use parent commit details in create commit * use parent tree for base_tree * multipart tree creation * update docs * update readme about the permissions of the default token * fix edge case where changes are partially merged * add updating documentation * fix typo * update major version --------- Co-authored-by: Ravi <1299606+rustycl0ck@users.noreply.github.com>
This commit is contained in:
parent
0c2a66fe4a
commit
4320041ed3
20 changed files with 32759 additions and 8594 deletions
|
@ -1,5 +1,5 @@
|
|||
import * as core from '@actions/core'
|
||||
import {GitCommandManager} from './git-command-manager'
|
||||
import {GitCommandManager, Commit} from './git-command-manager'
|
||||
import {v4 as uuidv4} from 'uuid'
|
||||
|
||||
const CHERRYPICK_EMPTY =
|
||||
|
@ -47,6 +47,27 @@ export async function tryFetch(
|
|||
}
|
||||
}
|
||||
|
||||
export async function buildBranchCommits(
|
||||
git: GitCommandManager,
|
||||
base: string,
|
||||
branch: string
|
||||
): Promise<Commit[]> {
|
||||
const output = await git.exec(['log', '--format=%H', `${base}..${branch}`])
|
||||
const shas = output.stdout
|
||||
.split('\n')
|
||||
.filter(x => x !== '')
|
||||
.reverse()
|
||||
const commits: Commit[] = []
|
||||
for (const sha of shas) {
|
||||
const commit = await git.getCommit(sha)
|
||||
commits.push(commit)
|
||||
for (const unparsedChange of commit.unparsedChanges) {
|
||||
core.warning(`Skipping unexpected diff entry: ${unparsedChange}`)
|
||||
}
|
||||
}
|
||||
return commits
|
||||
}
|
||||
|
||||
// Return the number of commits that branch2 is ahead of branch1
|
||||
async function commitsAhead(
|
||||
git: GitCommandManager,
|
||||
|
@ -103,6 +124,22 @@ async function isEven(
|
|||
)
|
||||
}
|
||||
|
||||
// Return true if the specified number of commits on branch1 and branch2 have a diff
|
||||
async function commitsHaveDiff(
|
||||
git: GitCommandManager,
|
||||
branch1: string,
|
||||
branch2: string,
|
||||
depth: number
|
||||
): Promise<boolean> {
|
||||
const diff1 = (
|
||||
await git.exec(['diff', '--stat', `${branch1}..${branch1}~${depth}`])
|
||||
).stdout.trim()
|
||||
const diff2 = (
|
||||
await git.exec(['diff', '--stat', `${branch2}..${branch2}~${depth}`])
|
||||
).stdout.trim()
|
||||
return diff1 !== diff2
|
||||
}
|
||||
|
||||
function splitLines(multilineString: string): string[] {
|
||||
return multilineString
|
||||
.split('\n')
|
||||
|
@ -114,7 +151,9 @@ interface CreateOrUpdateBranchResult {
|
|||
action: string
|
||||
base: string
|
||||
hasDiffWithBase: boolean
|
||||
baseCommit: Commit
|
||||
headSha: string
|
||||
branchCommits: Commit[]
|
||||
}
|
||||
|
||||
export async function createOrUpdateBranch(
|
||||
|
@ -139,14 +178,6 @@ export async function createOrUpdateBranch(
|
|||
base = base ? base : workingBase
|
||||
const baseRemote = 'origin'
|
||||
|
||||
// Set the default return values
|
||||
const result: CreateOrUpdateBranchResult = {
|
||||
action: 'none',
|
||||
base: base,
|
||||
hasDiffWithBase: false,
|
||||
headSha: ''
|
||||
}
|
||||
|
||||
// Save the working base changes to a temporary branch
|
||||
const tempBranch = uuidv4()
|
||||
await git.checkout(tempBranch, 'HEAD')
|
||||
|
@ -226,6 +257,9 @@ export async function createOrUpdateBranch(
|
|||
? tempBranchCommitsAhead + FETCH_DEPTH_MARGIN
|
||||
: FETCH_DEPTH_MARGIN
|
||||
|
||||
let action = 'none'
|
||||
let hasDiffWithBase = false
|
||||
|
||||
// Try to fetch the pull request branch
|
||||
if (!(await tryFetch(git, branchRemoteName, branch, fetchDepth))) {
|
||||
// The pull request branch does not exist
|
||||
|
@ -233,9 +267,9 @@ export async function createOrUpdateBranch(
|
|||
// Create the pull request branch
|
||||
await git.checkout(branch, tempBranch)
|
||||
// Check if the pull request branch is ahead of the base
|
||||
result.hasDiffWithBase = await isAhead(git, base, branch)
|
||||
if (result.hasDiffWithBase) {
|
||||
result.action = 'created'
|
||||
hasDiffWithBase = await isAhead(git, base, branch)
|
||||
if (hasDiffWithBase) {
|
||||
action = 'created'
|
||||
core.info(`Created branch '${branch}'`)
|
||||
} else {
|
||||
core.info(
|
||||
|
@ -252,20 +286,26 @@ export async function createOrUpdateBranch(
|
|||
|
||||
// Reset the branch if one of the following conditions is true.
|
||||
// - If the branch differs from the recreated temp branch.
|
||||
// - If the number of commits ahead of the base branch differs between the branch and
|
||||
// temp branch. This catches a case where the base branch has been force pushed to
|
||||
// a new commit.
|
||||
// - If the recreated temp branch is not ahead of the base. This means there will be
|
||||
// no pull request diff after the branch is reset. This will reset any undeleted
|
||||
// branches after merging. In particular, it catches a case where the branch was
|
||||
// squash merged but not deleted. We need to reset to make sure it doesn't appear
|
||||
// to have a diff with the base due to different commits for the same changes.
|
||||
// - If the number of commits ahead of the base branch differs between the branch and
|
||||
// temp branch. This catches a case where the base branch has been force pushed to
|
||||
// a new commit.
|
||||
// - If the diff of the commits ahead of the base branch differs between the branch and
|
||||
// temp branch. This catches a case where changes have been partially merged to the
|
||||
// base. The overall diff is the same, but the branch needs to be rebased to show
|
||||
// the correct diff.
|
||||
//
|
||||
// For changes on base this reset is equivalent to a rebase of the pull request branch.
|
||||
const branchCommitsAhead = await commitsAhead(git, base, branch)
|
||||
if (
|
||||
(await git.hasDiff([`${branch}..${tempBranch}`])) ||
|
||||
branchCommitsAhead != tempBranchCommitsAhead ||
|
||||
!(tempBranchCommitsAhead > 0) // !isAhead
|
||||
!(tempBranchCommitsAhead > 0) || // !isAhead
|
||||
(await commitsHaveDiff(git, branch, tempBranch, tempBranchCommitsAhead))
|
||||
) {
|
||||
core.info(`Resetting '${branch}'`)
|
||||
// Alternatively, git switch -C branch tempBranch
|
||||
|
@ -276,21 +316,29 @@ export async function createOrUpdateBranch(
|
|||
// If the branch was reset or updated it will be ahead
|
||||
// It may be behind if a reset now results in no diff with the base
|
||||
if (!(await isEven(git, `${branchRemoteName}/${branch}`, branch))) {
|
||||
result.action = 'updated'
|
||||
action = 'updated'
|
||||
core.info(`Updated branch '${branch}'`)
|
||||
} else {
|
||||
result.action = 'not-updated'
|
||||
action = 'not-updated'
|
||||
core.info(
|
||||
`Branch '${branch}' is even with its remote and will not be updated`
|
||||
)
|
||||
}
|
||||
|
||||
// Check if the pull request branch is ahead of the base
|
||||
result.hasDiffWithBase = await isAhead(git, base, branch)
|
||||
hasDiffWithBase = await isAhead(git, base, branch)
|
||||
}
|
||||
|
||||
// Get the pull request branch SHA
|
||||
result.headSha = await git.revParse('HEAD')
|
||||
// Get the base and head SHAs
|
||||
const baseSha = await git.revParse(base)
|
||||
const baseCommit = await git.getCommit(baseSha)
|
||||
const headSha = await git.revParse(branch)
|
||||
|
||||
let branchCommits: Commit[] = []
|
||||
if (hasDiffWithBase) {
|
||||
// Build the branch commits
|
||||
branchCommits = await buildBranchCommits(git, base, branch)
|
||||
}
|
||||
|
||||
// Delete the temporary branch
|
||||
await git.exec(['branch', '--delete', '--force', tempBranch])
|
||||
|
@ -303,5 +351,12 @@ export async function createOrUpdateBranch(
|
|||
await git.stashPop()
|
||||
}
|
||||
|
||||
return result
|
||||
return {
|
||||
action: action,
|
||||
base: base,
|
||||
hasDiffWithBase: hasDiffWithBase,
|
||||
baseCommit: baseCommit,
|
||||
headSha: headSha,
|
||||
branchCommits: branchCommits
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue