4320041ed3
* 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>
2457 lines
73 KiB
TypeScript
2457 lines
73 KiB
TypeScript
import {
|
|
createOrUpdateBranch,
|
|
tryFetch,
|
|
getWorkingBaseAndType,
|
|
buildBranchCommits
|
|
} from '../lib/create-or-update-branch'
|
|
import * as fs from 'fs'
|
|
import {GitCommandManager} from '../lib/git-command-manager'
|
|
import * as path from 'path'
|
|
import {v4 as uuidv4} from 'uuid'
|
|
|
|
const REPO_PATH = '/git/local/repos/test-base'
|
|
const REMOTE_NAME = 'origin'
|
|
|
|
const TRACKED_FILE = 'a/tracked-file.txt'
|
|
const UNTRACKED_FILE = 'b/untracked-file.txt'
|
|
|
|
const DEFAULT_BRANCH = 'tests/main'
|
|
const NOT_BASE_BRANCH = 'tests/branch-that-is-not-the-base'
|
|
const NOT_EXIST_BRANCH = 'tests/branch-that-does-not-exist'
|
|
|
|
const INIT_COMMIT_MESSAGE = 'Add file to be a tracked file for tests'
|
|
const BRANCH = 'tests/create-pull-request/patch'
|
|
const BASE = DEFAULT_BRANCH
|
|
|
|
const FORK_REMOTE_URL = 'git://127.0.0.1/repos/test-fork.git'
|
|
const FORK_REMOTE_NAME = 'fork'
|
|
|
|
const ADD_PATHS_DEFAULT = []
|
|
const ADD_PATHS_MULTI = ['a', 'b']
|
|
const ADD_PATHS_WILDCARD = ['a/*.txt', 'b/*.txt']
|
|
|
|
async function createFile(filename: string, content?: string): Promise<string> {
|
|
const _content = content ? content : uuidv4()
|
|
const filepath = path.join(REPO_PATH, filename)
|
|
await fs.promises.mkdir(path.dirname(filepath), {recursive: true})
|
|
await fs.promises.writeFile(filepath, _content, {encoding: 'utf8'})
|
|
return _content
|
|
}
|
|
|
|
async function getFileContent(filename: string): Promise<string> {
|
|
const filepath = path.join(REPO_PATH, filename)
|
|
return await fs.promises.readFile(filepath, {encoding: 'utf8'})
|
|
}
|
|
|
|
interface ChangeContent {
|
|
tracked: string
|
|
untracked: string
|
|
}
|
|
|
|
async function createChanges(
|
|
trackedContent?: string,
|
|
untrackedContent?: string
|
|
): Promise<ChangeContent> {
|
|
return {
|
|
tracked: await createFile(TRACKED_FILE, trackedContent),
|
|
untracked: await createFile(UNTRACKED_FILE, untrackedContent)
|
|
}
|
|
}
|
|
|
|
interface Commits {
|
|
changes: ChangeContent
|
|
commitMsgs: string[]
|
|
}
|
|
|
|
async function createCommits(
|
|
git: GitCommandManager,
|
|
number = 2,
|
|
finalTrackedContent?: string,
|
|
finalUntrackedContent?: string
|
|
): Promise<Commits> {
|
|
let result: Commits = {
|
|
changes: {tracked: '', untracked: ''},
|
|
commitMsgs: []
|
|
}
|
|
for (let i = 1; i <= number; i++) {
|
|
if (i == number) {
|
|
result.changes = await createChanges(
|
|
finalTrackedContent,
|
|
finalUntrackedContent
|
|
)
|
|
} else {
|
|
result.changes = await createChanges()
|
|
}
|
|
const commitMessage = uuidv4()
|
|
await git.exec(['add', '-A'])
|
|
await git.commit(['-m', commitMessage])
|
|
result.commitMsgs.unshift(commitMessage)
|
|
}
|
|
return result
|
|
}
|
|
|
|
describe('create-or-update-branch tests', () => {
|
|
let git: GitCommandManager
|
|
let initCommitHash: string
|
|
|
|
beforeAll(async () => {
|
|
git = await GitCommandManager.create(REPO_PATH)
|
|
git.setIdentityGitOptions([
|
|
'-c',
|
|
'author.name=Author Name',
|
|
'-c',
|
|
'author.email=author@example.com',
|
|
'-c',
|
|
'committer.name=Committer Name',
|
|
'-c',
|
|
'committer.email=committer@example.com'
|
|
])
|
|
// Check there are no local changes that might be destroyed by running these tests
|
|
expect(await git.isDirty(true)).toBeFalsy()
|
|
// Fetch the default branch
|
|
await git.fetch(['main:refs/remotes/origin/main'])
|
|
|
|
// Create a "not base branch" for the test run
|
|
await git.checkout('main')
|
|
await git.checkout(NOT_BASE_BRANCH, 'HEAD')
|
|
await createFile(TRACKED_FILE)
|
|
await git.exec(['add', '-A'])
|
|
await git.commit(['-m', 'This commit should not appear in pr branches'])
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${NOT_BASE_BRANCH}`
|
|
])
|
|
|
|
// Create a new default branch for the test run with a tracked file
|
|
await git.checkout('main')
|
|
await git.checkout(DEFAULT_BRANCH, 'HEAD')
|
|
await createFile(TRACKED_FILE)
|
|
await git.exec(['add', '-A'])
|
|
await git.commit(['-m', INIT_COMMIT_MESSAGE])
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${DEFAULT_BRANCH}`
|
|
])
|
|
initCommitHash = await git.revParse('HEAD')
|
|
|
|
// Add a remote for the fork
|
|
await git.exec(['remote', 'add', FORK_REMOTE_NAME, FORK_REMOTE_URL])
|
|
})
|
|
|
|
async function beforeTest(): Promise<void> {
|
|
await git.fetch(
|
|
[`${DEFAULT_BRANCH}:${DEFAULT_BRANCH}`],
|
|
REMOTE_NAME,
|
|
['--force', '--update-head-ok'],
|
|
true
|
|
)
|
|
await git.checkout(DEFAULT_BRANCH)
|
|
}
|
|
|
|
async function afterTest(deleteRemote = true): Promise<void> {
|
|
await git.fetch(
|
|
[`${DEFAULT_BRANCH}:${DEFAULT_BRANCH}`],
|
|
REMOTE_NAME,
|
|
['--force', '--update-head-ok'],
|
|
true
|
|
)
|
|
await git.checkout(DEFAULT_BRANCH)
|
|
try {
|
|
// Get the upstream branch if it exists
|
|
const result = await git.exec([
|
|
'for-each-ref',
|
|
`--format=%(upstream:short)`,
|
|
`refs/heads/${BRANCH}`
|
|
])
|
|
const upstreamBranch = result.stdout.trim()
|
|
// Delete the local branch
|
|
await git.exec(['branch', '--delete', '--force', BRANCH])
|
|
// Delete the remote branch
|
|
if (deleteRemote && upstreamBranch) {
|
|
const remote = upstreamBranch.split('/')[0]
|
|
await git.push(['--delete', '--force', remote, `refs/heads/${BRANCH}`])
|
|
}
|
|
} catch {
|
|
/* empty */
|
|
}
|
|
}
|
|
|
|
beforeEach(async () => {
|
|
await beforeTest()
|
|
})
|
|
|
|
afterEach(async () => {
|
|
await afterTest()
|
|
// Reset default branch if it was committed to during the test
|
|
if ((await git.revParse('HEAD')) != initCommitHash) {
|
|
await git.exec(['reset', '--hard', initCommitHash])
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${DEFAULT_BRANCH}`
|
|
])
|
|
}
|
|
})
|
|
|
|
async function gitLogMatches(expectedCommitMsgs: string[]): Promise<boolean> {
|
|
const count = expectedCommitMsgs.length
|
|
const result = await git.exec(['log', `-${count}`, '--format=%s'])
|
|
const commitMsgs = result.stdout
|
|
.split('\n')
|
|
.map(s => s.trim())
|
|
.filter(x => x !== '')
|
|
for (var index in expectedCommitMsgs) {
|
|
if (expectedCommitMsgs[index] != commitMsgs[index]) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
it('tests if a branch exists and can be fetched', async () => {
|
|
expect(await tryFetch(git, REMOTE_NAME, NOT_BASE_BRANCH, 1)).toBeTruthy()
|
|
expect(await tryFetch(git, REMOTE_NAME, NOT_EXIST_BRANCH, 1)).toBeFalsy()
|
|
})
|
|
|
|
it('tests getWorkingBaseAndType on a checked out ref', async () => {
|
|
const [workingBase, workingBaseType] = await getWorkingBaseAndType(git)
|
|
expect(workingBase).toEqual(BASE)
|
|
expect(workingBaseType).toEqual('branch')
|
|
})
|
|
|
|
it('tests getWorkingBaseAndType on a checked out commit', async () => {
|
|
// Checkout the HEAD commit SHA
|
|
const headSha = await git.revParse('HEAD')
|
|
await git.exec(['checkout', headSha])
|
|
const [workingBase, workingBaseType] = await getWorkingBaseAndType(git)
|
|
expect(workingBase).toEqual(headSha)
|
|
expect(workingBaseType).toEqual('commit')
|
|
})
|
|
|
|
it('tests buildBranchCommits with no diff', async () => {
|
|
await git.checkout(BRANCH, BASE)
|
|
const branchCommits = await buildBranchCommits(git, BASE, BRANCH)
|
|
expect(branchCommits.length).toEqual(0)
|
|
})
|
|
|
|
it('tests buildBranchCommits with addition and modification', async () => {
|
|
await git.checkout(BRANCH, BASE)
|
|
await createChanges()
|
|
const UNTRACKED_EXE_FILE = 'a/script.sh'
|
|
const filepath = path.join(REPO_PATH, UNTRACKED_EXE_FILE)
|
|
await fs.promises.writeFile(filepath, '#!/usr/bin/env bash', {mode: 0o755})
|
|
await git.exec(['add', '-A'])
|
|
await git.commit(['-m', 'Test changes'])
|
|
|
|
const branchCommits = await buildBranchCommits(git, BASE, BRANCH)
|
|
|
|
expect(branchCommits.length).toEqual(1)
|
|
expect(branchCommits[0].subject).toEqual('Test changes')
|
|
expect(branchCommits[0].changes.length).toEqual(3)
|
|
expect(branchCommits[0].changes).toEqual([
|
|
{mode: '100755', path: UNTRACKED_EXE_FILE, status: 'A'},
|
|
{mode: '100644', path: TRACKED_FILE, status: 'M'},
|
|
{mode: '100644', path: UNTRACKED_FILE, status: 'A'}
|
|
])
|
|
})
|
|
|
|
it('tests buildBranchCommits with addition and deletion', async () => {
|
|
await git.checkout(BRANCH, BASE)
|
|
await createChanges()
|
|
const TRACKED_FILE_NEW_PATH = 'c/tracked-file.txt'
|
|
const filepath = path.join(REPO_PATH, TRACKED_FILE_NEW_PATH)
|
|
await fs.promises.mkdir(path.dirname(filepath), {recursive: true})
|
|
await fs.promises.rename(path.join(REPO_PATH, TRACKED_FILE), filepath)
|
|
await git.exec(['add', '-A'])
|
|
await git.commit(['-m', 'Test changes'])
|
|
|
|
const branchCommits = await buildBranchCommits(git, BASE, BRANCH)
|
|
|
|
expect(branchCommits.length).toEqual(1)
|
|
expect(branchCommits[0].subject).toEqual('Test changes')
|
|
expect(branchCommits[0].changes.length).toEqual(3)
|
|
expect(branchCommits[0].changes).toEqual([
|
|
{mode: '100644', path: TRACKED_FILE, status: 'D'},
|
|
{mode: '100644', path: UNTRACKED_FILE, status: 'A'},
|
|
{mode: '100644', path: TRACKED_FILE_NEW_PATH, status: 'A'}
|
|
])
|
|
})
|
|
|
|
it('tests buildBranchCommits with multiple commits', async () => {
|
|
await git.checkout(BRANCH, BASE)
|
|
for (let i = 0; i < 3; i++) {
|
|
await createChanges()
|
|
await git.exec(['add', '-A'])
|
|
await git.commit(['-m', `Test changes ${i}`])
|
|
}
|
|
|
|
const branchCommits = await buildBranchCommits(git, BASE, BRANCH)
|
|
|
|
expect(branchCommits.length).toEqual(3)
|
|
for (let i = 0; i < 3; i++) {
|
|
expect(branchCommits[i].subject).toEqual(`Test changes ${i}`)
|
|
expect(branchCommits[i].changes.length).toEqual(2)
|
|
const untrackedFileStatus = i == 0 ? 'A' : 'M'
|
|
expect(branchCommits[i].changes).toEqual([
|
|
{mode: '100644', path: TRACKED_FILE, status: 'M'},
|
|
{mode: '100644', path: UNTRACKED_FILE, status: untrackedFileStatus}
|
|
])
|
|
}
|
|
})
|
|
|
|
it('tests no changes resulting in no new branch being created', async () => {
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
expect(result.action).toEqual('none')
|
|
expect(await gitLogMatches([INIT_COMMIT_MESSAGE])).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with a tracked file change', async () => {
|
|
// Create a tracked file change
|
|
const trackedContent = await createFile(TRACKED_FILE)
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(trackedContent)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create a tracked file change
|
|
const _trackedContent = await createFile(TRACKED_FILE)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_trackedContent)
|
|
expect(
|
|
await gitLogMatches([_commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with an untracked file change', async () => {
|
|
// Create an untracked file change
|
|
const untrackedContent = await createFile(UNTRACKED_FILE)
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(untrackedContent)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create an untracked file change
|
|
const _untrackedContent = await createFile(UNTRACKED_FILE)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_untrackedContent)
|
|
expect(
|
|
await gitLogMatches([_commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with identical changes', async () => {
|
|
// The pull request branch will not be updated
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create identical tracked and untracked file changes
|
|
await createChanges(changes.tracked, changes.untracked)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('not-updated')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with commits on the base inbetween', async () => {
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create commits on the base
|
|
const commits = await createCommits(git)
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${DEFAULT_BRANCH}`
|
|
])
|
|
|
|
// Create tracked and untracked file changes
|
|
const _changes = await createChanges()
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([
|
|
_commitMessage,
|
|
...commits.commitMsgs,
|
|
INIT_COMMIT_MESSAGE
|
|
])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and then an update with no changes', async () => {
|
|
// This effectively reverts the branch back to match the base and results in no diff
|
|
|
|
// Save the default branch tracked content
|
|
const defaultTrackedContent = await getFileContent(TRACKED_FILE)
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Running with no update effectively reverts the branch back to match the base
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeFalsy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(defaultTrackedContent)
|
|
expect(await gitLogMatches([INIT_COMMIT_MESSAGE])).toBeTruthy()
|
|
})
|
|
|
|
it('tests create, commits on the base, and update with identical changes to the base', async () => {
|
|
// The changes on base effectively revert the branch back to match the base and results in no diff
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create commits on the base
|
|
const commits = await createCommits(git)
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${DEFAULT_BRANCH}`
|
|
])
|
|
|
|
// Create the same tracked and untracked file changes that were made to the base
|
|
const _changes = await createChanges(
|
|
commits.changes.tracked,
|
|
commits.changes.untracked
|
|
)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeFalsy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([...commits.commitMsgs, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create, commit with partial changes on the base, and update', async () => {
|
|
// This is an edge case where the changes for a single commit are partially merged to the base
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create a commit on the base with a partial merge of the changes
|
|
await createFile(TRACKED_FILE, changes.tracked)
|
|
const baseCommitMessage = uuidv4()
|
|
await git.exec(['add', '-A'])
|
|
await git.commit(['-m', baseCommitMessage])
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${DEFAULT_BRANCH}`
|
|
])
|
|
|
|
// Create the same tracked and untracked file changes
|
|
const _changes = await createChanges(changes.tracked, changes.untracked)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([
|
|
_commitMessage,
|
|
baseCommitMessage,
|
|
INIT_COMMIT_MESSAGE
|
|
])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create, squash merge, and update with identical changes', async () => {
|
|
// Branches that have been squash merged appear to have a diff with the base due to
|
|
// different commits for the same changes. To prevent creating pull requests
|
|
// unnecessarily we reset (rebase) the pull request branch when a reset would result
|
|
// in no diff with the base. This will reset any undeleted branches after merging.
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create a commit on the base with the same changes as the branch
|
|
// This simulates squash merge of the pull request
|
|
const commits = await createCommits(
|
|
git,
|
|
1,
|
|
changes.tracked,
|
|
changes.untracked
|
|
)
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${DEFAULT_BRANCH}`
|
|
])
|
|
|
|
// Create the same tracked and untracked file changes (no change on update)
|
|
const _changes = await createChanges(changes.tracked, changes.untracked)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeFalsy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([...commits.commitMsgs, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create, force push of base branch, and update with identical changes', async () => {
|
|
// If the base branch is force pushed to a different commit when there is an open
|
|
// pull request, the branch must be reset to rebase the changes on the base.
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Force push the base branch to a different commit
|
|
const amendedCommitMessage = uuidv4()
|
|
await git.commit(['--amend', '-m', amendedCommitMessage])
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${DEFAULT_BRANCH}`
|
|
])
|
|
|
|
// Create the same tracked and untracked file changes (no change on update)
|
|
const _changes = await createChanges(changes.tracked, changes.untracked)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([_commitMessage, amendedCommitMessage])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with commits on the working base (during the workflow)', async () => {
|
|
// Create commits on the working base
|
|
const commits = await createCommits(git)
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(commits.changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(
|
|
commits.changes.untracked
|
|
)
|
|
expect(
|
|
await gitLogMatches([...commits.commitMsgs, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create commits on the working base
|
|
const _commits = await createCommits(git)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_commits.changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(
|
|
_commits.changes.untracked
|
|
)
|
|
expect(
|
|
await gitLogMatches([..._commits.commitMsgs, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with changes and commits on the working base (during the workflow)', async () => {
|
|
// Create commits on the working base
|
|
const commits = await createCommits(git)
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([
|
|
commitMessage,
|
|
...commits.commitMsgs,
|
|
INIT_COMMIT_MESSAGE
|
|
])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create commits on the working base
|
|
const _commits = await createCommits(git)
|
|
// Create tracked and untracked file changes
|
|
const _changes = await createChanges()
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([
|
|
_commitMessage,
|
|
..._commits.commitMsgs,
|
|
INIT_COMMIT_MESSAGE
|
|
])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with changes and commits on the working base (during the workflow), and commits on the base inbetween', async () => {
|
|
// Create commits on the working base
|
|
const commits = await createCommits(git)
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([
|
|
commitMessage,
|
|
...commits.commitMsgs,
|
|
INIT_COMMIT_MESSAGE
|
|
])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create commits on the base
|
|
const commitsOnBase = await createCommits(git)
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${DEFAULT_BRANCH}`
|
|
])
|
|
|
|
// Create commits on the working base
|
|
const _commits = await createCommits(git)
|
|
// Create tracked and untracked file changes
|
|
const _changes = await createChanges()
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([
|
|
_commitMessage,
|
|
..._commits.commitMsgs,
|
|
...commitsOnBase.commitMsgs,
|
|
INIT_COMMIT_MESSAGE
|
|
])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update using a different remote from the base', async () => {
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
FORK_REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
FORK_REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create tracked and untracked file changes
|
|
const _changes = await createChanges()
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
FORK_REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([_commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with signoff on commit', async () => {
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
true,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
// Check signoff in commit body
|
|
const commitBody = (
|
|
await git.exec(['log', `-1`, '--format=%b'])
|
|
).stdout.trim()
|
|
expect(commitBody).toEqual(
|
|
'Signed-off-by: Committer Name <committer@example.com>'
|
|
)
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create tracked and untracked file changes
|
|
const _changes = await createChanges()
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
true,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([_commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
// Check signoff in commit body
|
|
const _commitBody = (
|
|
await git.exec(['log', `-1`, '--format=%b'])
|
|
).stdout.trim()
|
|
expect(_commitBody).toEqual(
|
|
'Signed-off-by: Committer Name <committer@example.com>'
|
|
)
|
|
})
|
|
|
|
it('tests create and update with multiple add-paths', async () => {
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_MULTI
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create tracked and untracked file changes
|
|
const _changes = await createChanges()
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_MULTI
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([_commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with wildcard add-paths', async () => {
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_WILDCARD
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create tracked and untracked file changes
|
|
const _changes = await createChanges()
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_WILDCARD
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([_commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create with add-paths resolving to no changes when other changes exist', async () => {
|
|
// Create tracked and untracked file changes
|
|
await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
['nonexistent/*']
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('none')
|
|
expect(await gitLogMatches([INIT_COMMIT_MESSAGE])).toBeTruthy()
|
|
})
|
|
|
|
it('tests create consecutive branches with restored changes from stash', async () => {
|
|
const BRANCHA = `${BRANCH}-a`
|
|
const BRANCHB = `${BRANCH}-b`
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const resultA = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCHA,
|
|
REMOTE_NAME,
|
|
false,
|
|
['a']
|
|
)
|
|
const resultB = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
'',
|
|
BRANCHB,
|
|
REMOTE_NAME,
|
|
false,
|
|
['b']
|
|
)
|
|
await git.checkout(BRANCHA)
|
|
expect(resultA.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
await git.checkout(BRANCHB)
|
|
expect(resultB.action).toEqual('created')
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Delete the local branches
|
|
await git.checkout(DEFAULT_BRANCH)
|
|
await git.exec(['branch', '--delete', '--force', BRANCHA])
|
|
await git.exec(['branch', '--delete', '--force', BRANCHB])
|
|
})
|
|
|
|
// Working Base is Not Base (WBNB)
|
|
|
|
it('tests no changes resulting in no new branch being created (WBNB)', async () => {
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('none')
|
|
expect(await gitLogMatches([INIT_COMMIT_MESSAGE])).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with a tracked file change (WBNB)', async () => {
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create a tracked file change
|
|
const trackedContent = await createFile(TRACKED_FILE)
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(trackedContent)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create a tracked file change
|
|
const _trackedContent = await createFile(TRACKED_FILE)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_trackedContent)
|
|
expect(
|
|
await gitLogMatches([_commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with an untracked file change (WBNB)', async () => {
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create an untracked file change
|
|
const untrackedContent = await createFile(UNTRACKED_FILE)
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(untrackedContent)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create an untracked file change
|
|
const _untrackedContent = await createFile(UNTRACKED_FILE)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_untrackedContent)
|
|
expect(
|
|
await gitLogMatches([_commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with identical changes (WBNB)', async () => {
|
|
// The pull request branch will not be updated
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create identical tracked and untracked file changes
|
|
await createChanges(changes.tracked, changes.untracked)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('not-updated')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with commits on the base inbetween (WBNB)', async () => {
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create commits on the base
|
|
const commits = await createCommits(git)
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${DEFAULT_BRANCH}`
|
|
])
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create tracked and untracked file changes
|
|
const _changes = await createChanges()
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([
|
|
_commitMessage,
|
|
commits.commitMsgs[0] // fetch depth of base is 1
|
|
])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and then an update with no changes (WBNB)', async () => {
|
|
// This effectively reverts the branch back to match the base and results in no diff
|
|
|
|
// Save the default branch tracked content
|
|
const defaultTrackedContent = await getFileContent(TRACKED_FILE)
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Running with no update effectively reverts the branch back to match the base
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeFalsy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(defaultTrackedContent)
|
|
expect(await gitLogMatches([INIT_COMMIT_MESSAGE])).toBeTruthy()
|
|
})
|
|
|
|
it('tests create, commits on the base, and update with identical changes to the base (WBNB)', async () => {
|
|
// The changes on base effectively revert the branch back to match the base and results in no diff
|
|
// This scenario will cause cherrypick to fail due to an empty commit.
|
|
// The commit is empty because the changes now exist on the base.
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create commits on the base
|
|
const commits = await createCommits(git)
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${DEFAULT_BRANCH}`
|
|
])
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create the same tracked and untracked file changes that were made to the base
|
|
const _changes = await createChanges(
|
|
commits.changes.tracked,
|
|
commits.changes.untracked
|
|
)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeFalsy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([
|
|
commits.commitMsgs[0] // fetch depth of base is 1
|
|
])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create, commit with partial changes on the base, and update (WBNB)', async () => {
|
|
// This is an edge case where the changes for a single commit are partially merged to the base
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create a commit on the base with a partial merge of the changes
|
|
await createFile(TRACKED_FILE, changes.tracked)
|
|
const baseCommitMessage = uuidv4()
|
|
await git.exec(['add', '-A'])
|
|
await git.commit(['-m', baseCommitMessage])
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${DEFAULT_BRANCH}`
|
|
])
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create the same tracked and untracked file changes
|
|
const _changes = await createChanges(changes.tracked, changes.untracked)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([
|
|
_commitMessage,
|
|
baseCommitMessage // fetch depth of base is 1
|
|
])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create, squash merge, and update with identical changes (WBNB)', async () => {
|
|
// Branches that have been squash merged appear to have a diff with the base due to
|
|
// different commits for the same changes. To prevent creating pull requests
|
|
// unnecessarily we reset (rebase) the pull request branch when a reset would result
|
|
// in no diff with the base. This will reset any undeleted branches after merging.
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create a commit on the base with the same changes as the branch
|
|
// This simulates squash merge of the pull request
|
|
const commits = await createCommits(
|
|
git,
|
|
1,
|
|
changes.tracked,
|
|
changes.untracked
|
|
)
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${DEFAULT_BRANCH}`
|
|
])
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create the same tracked and untracked file changes (no change on update)
|
|
const _changes = await createChanges(changes.tracked, changes.untracked)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeFalsy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([
|
|
commits.commitMsgs[0] // fetch depth of base is 1
|
|
])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create, force push of base branch, and update with identical changes (WBNB)', async () => {
|
|
// If the base branch is force pushed to a different commit when there is an open
|
|
// pull request, the branch must be reset to rebase the changes on the base.
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Force push the base branch to a different commit
|
|
const amendedCommitMessage = uuidv4()
|
|
await git.commit(['--amend', '-m', amendedCommitMessage])
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${DEFAULT_BRANCH}`
|
|
])
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create the same tracked and untracked file changes (no change on update)
|
|
const _changes = await createChanges(changes.tracked, changes.untracked)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([_commitMessage, amendedCommitMessage])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with commits on the working base (during the workflow) (WBNB)', async () => {
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create commits on the working base
|
|
const commits = await createCommits(git)
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(commits.changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(
|
|
commits.changes.untracked
|
|
)
|
|
expect(
|
|
await gitLogMatches([...commits.commitMsgs, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create commits on the working base
|
|
const _commits = await createCommits(git)
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_commits.changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(
|
|
_commits.changes.untracked
|
|
)
|
|
expect(
|
|
await gitLogMatches([..._commits.commitMsgs, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with changes and commits on the working base (during the workflow) (WBNB)', async () => {
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create commits on the working base
|
|
const commits = await createCommits(git)
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([
|
|
commitMessage,
|
|
...commits.commitMsgs,
|
|
INIT_COMMIT_MESSAGE
|
|
])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create commits on the working base
|
|
const _commits = await createCommits(git)
|
|
// Create tracked and untracked file changes
|
|
const _changes = await createChanges()
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([
|
|
_commitMessage,
|
|
..._commits.commitMsgs,
|
|
INIT_COMMIT_MESSAGE
|
|
])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with changes and commits on the working base (during the workflow), and commits on the base inbetween (WBNB)', async () => {
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create commits on the working base
|
|
const commits = await createCommits(git)
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([
|
|
commitMessage,
|
|
...commits.commitMsgs,
|
|
INIT_COMMIT_MESSAGE
|
|
])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create commits on the base
|
|
const commitsOnBase = await createCommits(git)
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${DEFAULT_BRANCH}`
|
|
])
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create commits on the working base
|
|
const _commits = await createCommits(git)
|
|
// Create tracked and untracked file changes
|
|
const _changes = await createChanges()
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([
|
|
_commitMessage,
|
|
..._commits.commitMsgs,
|
|
commitsOnBase.commitMsgs[0] // fetch depth of base is 1
|
|
])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update using a different remote from the base (WBNB)', async () => {
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
FORK_REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
FORK_REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Set the working base to a branch that is not the pull request base
|
|
await git.checkout(NOT_BASE_BRANCH)
|
|
|
|
// Create tracked and untracked file changes
|
|
const _changes = await createChanges()
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
FORK_REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([_commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
// Working Base is Not a Ref (WBNR)
|
|
// A commit is checked out leaving the repository in a "detached HEAD" state
|
|
|
|
it('tests create and update in detached HEAD state (WBNR)', async () => {
|
|
// Checkout the HEAD commit SHA
|
|
const headSha = await git.revParse('HEAD')
|
|
await git.checkout(headSha)
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Checkout the HEAD commit SHA
|
|
const _headSha = await git.revParse('HEAD')
|
|
await git.checkout(_headSha)
|
|
|
|
// Create tracked and untracked file changes
|
|
const _changes = await createChanges()
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([_commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
it('tests create and update with commits on the base inbetween, in detached HEAD state (WBNR)', async () => {
|
|
// Checkout the HEAD commit SHA
|
|
const headSha = await git.revParse('HEAD')
|
|
await git.checkout(headSha)
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(result.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Push pull request branch to remote
|
|
await git.push([
|
|
'--force-with-lease',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${BRANCH}`
|
|
])
|
|
|
|
await afterTest(false)
|
|
await beforeTest()
|
|
|
|
// Create commits on the base
|
|
const commitsOnBase = await createCommits(git)
|
|
await git.push([
|
|
'--force',
|
|
REMOTE_NAME,
|
|
`HEAD:refs/heads/${DEFAULT_BRANCH}`
|
|
])
|
|
|
|
// Checkout the HEAD commit SHA
|
|
const _headSha = await git.revParse('HEAD')
|
|
await git.checkout(_headSha)
|
|
|
|
// Create tracked and untracked file changes
|
|
const _changes = await createChanges()
|
|
const _commitMessage = uuidv4()
|
|
const _result = await createOrUpdateBranch(
|
|
git,
|
|
_commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
expect(_result.action).toEqual('updated')
|
|
expect(_result.hasDiffWithBase).toBeTruthy()
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(_changes.tracked)
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(_changes.untracked)
|
|
expect(
|
|
await gitLogMatches([
|
|
_commitMessage,
|
|
commitsOnBase.commitMsgs[0] // fetch depth of base is 1
|
|
])
|
|
).toBeTruthy()
|
|
})
|
|
|
|
// This failure mode is a limitation of the action. Controlling your own commits cannot be used in detached HEAD state.
|
|
// https://github.com/peter-evans/create-pull-request/issues/902
|
|
it('tests failure to create with commits on the working base (during the workflow) in detached HEAD state (WBNR)', async () => {
|
|
// Checkout the HEAD commit SHA
|
|
const headSha = await git.revParse('HEAD')
|
|
await git.checkout(headSha)
|
|
|
|
// Create commits on the working base
|
|
const commits = await createCommits(git)
|
|
const commitMessage = uuidv4()
|
|
const result = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCH,
|
|
REMOTE_NAME,
|
|
false,
|
|
ADD_PATHS_DEFAULT
|
|
)
|
|
await git.checkout(BRANCH)
|
|
// The action cannot successfully create the branch
|
|
expect(result.action).toEqual('none')
|
|
})
|
|
|
|
it('tests create consecutive branches with restored changes from stash in detached HEAD state (WBNR)', async () => {
|
|
// Checkout the HEAD commit SHA
|
|
const headSha = await git.revParse('HEAD')
|
|
await git.checkout(headSha)
|
|
|
|
const BRANCHA = `${BRANCH}-a`
|
|
const BRANCHB = `${BRANCH}-b`
|
|
|
|
// Create tracked and untracked file changes
|
|
const changes = await createChanges()
|
|
const commitMessage = uuidv4()
|
|
const resultA = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCHA,
|
|
REMOTE_NAME,
|
|
false,
|
|
['a']
|
|
)
|
|
const resultB = await createOrUpdateBranch(
|
|
git,
|
|
commitMessage,
|
|
BASE,
|
|
BRANCHB,
|
|
REMOTE_NAME,
|
|
false,
|
|
['b']
|
|
)
|
|
await git.checkout(BRANCHA)
|
|
expect(resultA.action).toEqual('created')
|
|
expect(await getFileContent(TRACKED_FILE)).toEqual(changes.tracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
await git.checkout(BRANCHB)
|
|
expect(resultB.action).toEqual('created')
|
|
expect(await getFileContent(UNTRACKED_FILE)).toEqual(changes.untracked)
|
|
expect(
|
|
await gitLogMatches([commitMessage, INIT_COMMIT_MESSAGE])
|
|
).toBeTruthy()
|
|
|
|
// Delete the local branches
|
|
await git.checkout(DEFAULT_BRANCH)
|
|
await git.exec(['branch', '--delete', '--force', BRANCHA])
|
|
await git.exec(['branch', '--delete', '--force', BRANCHB])
|
|
})
|
|
})
|