mirror of
https://forgejo.stefka.eu/jiriks74/create-pull-request.git
synced 2025-01-18 16:01:06 +01:00
Redesign from request-to-parent to push-to-fork
This commit is contained in:
parent
1a182d0679
commit
053b501145
11 changed files with 563 additions and 157 deletions
|
@ -7,10 +7,11 @@ const CHERRYPICK_EMPTY =
|
|||
|
||||
export async function tryFetch(
|
||||
git: GitCommandManager,
|
||||
remote: string,
|
||||
branch: string
|
||||
): Promise<boolean> {
|
||||
try {
|
||||
await git.fetch([`${branch}:refs/remotes/origin/${branch}`])
|
||||
await git.fetch([`${branch}:refs/remotes/${remote}/${branch}`], remote)
|
||||
return true
|
||||
} catch {
|
||||
return false
|
||||
|
@ -74,13 +75,15 @@ function splitLines(multilineString: string): string[] {
|
|||
export async function createOrUpdateBranch(
|
||||
git: GitCommandManager,
|
||||
commitMessage: string,
|
||||
baseInput: string,
|
||||
branch: string
|
||||
base: string,
|
||||
branch: string,
|
||||
branchRemoteName: string
|
||||
): Promise<CreateOrUpdateBranchResult> {
|
||||
// Get the working base. This may or may not be the actual base.
|
||||
const workingBase = await git.symbolicRef('HEAD', ['--short'])
|
||||
// If the base is not specified it is assumed to be the working base.
|
||||
const base = baseInput ? baseInput : workingBase
|
||||
base = base ? base : workingBase
|
||||
const baseRemote = 'origin'
|
||||
|
||||
// Set the default return values
|
||||
const result: CreateOrUpdateBranchResult = {
|
||||
|
@ -101,7 +104,7 @@ export async function createOrUpdateBranch(
|
|||
|
||||
// Perform fetch and reset the working base
|
||||
// Commits made during the workflow will be removed
|
||||
await git.fetch([`${workingBase}:${workingBase}`], 'origin', ['--force'])
|
||||
await git.fetch([`${workingBase}:${workingBase}`], baseRemote, ['--force'])
|
||||
|
||||
// If the working base is not the base, rebase the temp branch commits
|
||||
if (workingBase != base) {
|
||||
|
@ -109,7 +112,7 @@ export async function createOrUpdateBranch(
|
|||
`Rebasing commits made to branch '${workingBase}' on to base branch '${base}'`
|
||||
)
|
||||
// Checkout the actual base
|
||||
await git.fetch([`${base}:${base}`], 'origin', ['--force'])
|
||||
await git.fetch([`${base}:${base}`], baseRemote, ['--force'])
|
||||
await git.checkout(base)
|
||||
// Cherrypick commits from the temporary branch starting from the working base
|
||||
const commits = await git.revList(
|
||||
|
@ -128,11 +131,11 @@ export async function createOrUpdateBranch(
|
|||
// Reset the temp branch to the working index
|
||||
await git.checkout(tempBranch, 'HEAD')
|
||||
// Reset the base
|
||||
await git.fetch([`${base}:${base}`], 'origin', ['--force'])
|
||||
await git.fetch([`${base}:${base}`], baseRemote, ['--force'])
|
||||
}
|
||||
|
||||
// Try to fetch the pull request branch
|
||||
if (!(await tryFetch(git, branch))) {
|
||||
if (!(await tryFetch(git, branchRemoteName, branch))) {
|
||||
// The pull request branch does not exist
|
||||
core.info(`Pull request branch '${branch}' does not exist yet.`)
|
||||
// Create the pull request branch
|
||||
|
@ -150,7 +153,7 @@ export async function createOrUpdateBranch(
|
|||
} else {
|
||||
// The pull request branch exists
|
||||
core.info(
|
||||
`Pull request branch '${branch}' already exists as remote branch 'origin/${branch}'`
|
||||
`Pull request branch '${branch}' already exists as remote branch '${branchRemoteName}/${branch}'`
|
||||
)
|
||||
// Checkout the pull request branch
|
||||
await git.checkout(branch)
|
||||
|
@ -166,7 +169,7 @@ export async function createOrUpdateBranch(
|
|||
// Check if the pull request branch has been updated
|
||||
// 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, `origin/${branch}`, branch))) {
|
||||
if (!(await isEven(git, `${branchRemoteName}/${branch}`, branch))) {
|
||||
result.action = 'updated'
|
||||
core.info(`Updated branch '${branch}'`)
|
||||
} else {
|
||||
|
|
|
@ -27,7 +27,7 @@ export interface Inputs {
|
|||
milestone: number
|
||||
draft: boolean
|
||||
branch: string
|
||||
requestToParent: boolean
|
||||
pushToFork: string
|
||||
base: string
|
||||
branchSuffix: string
|
||||
}
|
||||
|
@ -54,17 +54,42 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
|
|||
inputs.body = inputs.body ? inputs.body : DEFAULT_BODY
|
||||
inputs.branch = inputs.branch ? inputs.branch : DEFAULT_BRANCH
|
||||
|
||||
// Determine the GitHub repository from git config
|
||||
// This will be the target repository for the pull request branch
|
||||
core.startGroup('Determining the checked out repository')
|
||||
// Init the GitHub client
|
||||
const githubHelper = new GitHubHelper(inputs.token)
|
||||
|
||||
core.startGroup('Determining the base and head repositories')
|
||||
// Determine the base repository from git config
|
||||
const remoteUrl = await git.tryGetRemoteUrl()
|
||||
const remote = utils.getRemoteDetail(remoteUrl)
|
||||
const baseRemote = utils.getRemoteDetail(remoteUrl)
|
||||
// Determine the head repository; the target for the pull request branch
|
||||
const branchRemoteName = inputs.pushToFork ? 'fork' : 'origin'
|
||||
const branchRepository = inputs.pushToFork
|
||||
? inputs.pushToFork
|
||||
: baseRemote.repository
|
||||
if (inputs.pushToFork) {
|
||||
// Check if the supplied fork is really a fork of the base
|
||||
const parentRepository = await githubHelper.getRepositoryParent(
|
||||
branchRepository
|
||||
)
|
||||
if (parentRepository != baseRemote.repository) {
|
||||
throw new Error(
|
||||
`Repository '${branchRepository}' is not a fork of '${baseRemote.repository}'. Unable to continue.`
|
||||
)
|
||||
}
|
||||
// Add a remote for the fork
|
||||
const remoteUrl = utils.getRemoteUrl(
|
||||
baseRemote.protocol,
|
||||
branchRepository
|
||||
)
|
||||
await git.exec(['remote', 'add', 'fork', remoteUrl])
|
||||
}
|
||||
core.endGroup()
|
||||
core.info(
|
||||
`Pull request branch target repository set to ${remote.repository}`
|
||||
`Pull request branch target repository set to ${branchRepository}`
|
||||
)
|
||||
|
||||
if (remote.protocol == 'HTTPS') {
|
||||
// Configure auth
|
||||
if (baseRemote.protocol == 'HTTPS') {
|
||||
core.startGroup('Configuring credential for HTTPS authentication')
|
||||
await gitAuthHelper.configureToken(inputs.token)
|
||||
core.endGroup()
|
||||
|
@ -158,18 +183,19 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
|
|||
git,
|
||||
inputs.commitMessage,
|
||||
inputs.base,
|
||||
inputs.branch
|
||||
inputs.branch,
|
||||
branchRemoteName
|
||||
)
|
||||
core.endGroup()
|
||||
|
||||
if (['created', 'updated'].includes(result.action)) {
|
||||
// The branch was created or updated
|
||||
core.startGroup(
|
||||
`Pushing pull request branch to 'origin/${inputs.branch}'`
|
||||
`Pushing pull request branch to '${branchRemoteName}/${inputs.branch}'`
|
||||
)
|
||||
await git.push([
|
||||
'--force-with-lease',
|
||||
'origin',
|
||||
branchRemoteName,
|
||||
`HEAD:refs/heads/${inputs.branch}`
|
||||
])
|
||||
core.endGroup()
|
||||
|
@ -179,8 +205,11 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
|
|||
|
||||
if (result.hasDiffWithBase) {
|
||||
// Create or update the pull request
|
||||
const githubHelper = new GitHubHelper(inputs.token)
|
||||
await githubHelper.createOrUpdatePullRequest(inputs, remote.repository)
|
||||
await githubHelper.createOrUpdatePullRequest(
|
||||
inputs,
|
||||
baseRemote.repository,
|
||||
branchRepository
|
||||
)
|
||||
} else {
|
||||
// If there is no longer a diff with the base delete the branch
|
||||
core.info(
|
||||
|
@ -190,7 +219,7 @@ export async function createPullRequest(inputs: Inputs): Promise<void> {
|
|||
await git.push([
|
||||
'--delete',
|
||||
'--force',
|
||||
'origin',
|
||||
branchRemoteName,
|
||||
`refs/heads/${inputs.branch}`
|
||||
])
|
||||
}
|
||||
|
|
|
@ -77,24 +77,25 @@ export class GitHubHelper {
|
|||
return pull.number
|
||||
}
|
||||
|
||||
async createOrUpdatePullRequest(
|
||||
inputs: Inputs,
|
||||
headRepository: string
|
||||
): Promise<void> {
|
||||
async getRepositoryParent(headRepository: string): Promise<string> {
|
||||
const {data: headRepo} = await this.octokit.repos.get({
|
||||
...this.parseRepository(headRepository)
|
||||
})
|
||||
|
||||
if (inputs.requestToParent && !headRepo.parent) {
|
||||
if (!headRepo.parent) {
|
||||
throw new Error(
|
||||
`The checked out repository is not a fork. Input 'request-to-parent' should be set to 'false'.`
|
||||
`Repository '${headRepository}' is not a fork. Unable to continue.`
|
||||
)
|
||||
}
|
||||
const baseRepository = inputs.requestToParent
|
||||
? headRepo.parent.full_name
|
||||
: headRepository
|
||||
return headRepo.parent.full_name
|
||||
}
|
||||
|
||||
const headBranch = `${headRepo.owner.login}:${inputs.branch}`
|
||||
async createOrUpdatePullRequest(
|
||||
inputs: Inputs,
|
||||
baseRepository: string,
|
||||
headRepository: string
|
||||
): Promise<void> {
|
||||
const [headOwner] = headRepository.split('/')
|
||||
const headBranch = `${headOwner}:${inputs.branch}`
|
||||
|
||||
// Create or update the pull request
|
||||
const pullNumber = await this.createOrUpdate(
|
||||
|
|
|
@ -20,7 +20,7 @@ async function run(): Promise<void> {
|
|||
milestone: Number(core.getInput('milestone')),
|
||||
draft: core.getInput('draft') === 'true',
|
||||
branch: core.getInput('branch'),
|
||||
requestToParent: core.getInput('request-to-parent') === 'true',
|
||||
pushToFork: core.getInput('push-to-fork'),
|
||||
base: core.getInput('base'),
|
||||
branchSuffix: core.getInput('branch-suffix')
|
||||
}
|
||||
|
|
|
@ -62,6 +62,12 @@ export function getRemoteDetail(remoteUrl: string): RemoteDetail {
|
|||
)
|
||||
}
|
||||
|
||||
export function getRemoteUrl(protocol: string, repository: string): string {
|
||||
return protocol == 'HTTPS'
|
||||
? `https://github.com/${repository}`
|
||||
: `git@github.com:${repository}.git`
|
||||
}
|
||||
|
||||
export function secondsSinceEpoch(): number {
|
||||
const now = new Date()
|
||||
return Math.round(now.getTime() / 1000)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue