Skip to content

Instantly share code, notes, and snippets.

@Sy1v4in
Created June 1, 2023 10:41
Show Gist options
  • Save Sy1v4in/0d481cd5463f8fdb1404417e190ab2bc to your computer and use it in GitHub Desktop.
Save Sy1v4in/0d481cd5463f8fdb1404417e190ab2bc to your computer and use it in GitHub Desktop.
A simple script using zx that synchronizes the staging branch with the main one and merging the PR labelized win in-staging
#!/usr/bin/env zx
import 'zx/globals'
import { Octokit } from '@octokit/rest'
const octokit = new Octokit({
auth: process.env.GH_TOKEN,
})
const currentBranch = async () => $`git branch --show-current`
const checkIfLocalRepoIsClean = async () => $`git diff --quiet`
const branchesToSynchronize = async (repository, targetBranchName) => {
const pullRequests = await octokit.rest.pulls.list(repository)
return pullRequests.data.filter(isOnTargetBranch(targetBranchName)).map(branchName)
}
const isOnTargetBranch = targetBranch => pr =>
pr.labels.some(label => label.name.includes(targetBranch))
const branchName = pr => pr.head.ref
const checkout = async (branch, { pull = false, create = false } = {}) => {
const options = create ? '-b' : ''
await $`git checkout ${options} ${branch}`
pull && (await $`git pull`)
}
const createBranch = async branch => {
await nothrow($`git branch -D ${branch}`)
await checkout(branch, { create: true })
}
const merge = async branch => {
await $`git merge origin/${branch} --no-verify`
}
const abortMerge = async () => {
await $`git merge --abort`
}
const pushForce = async branch => $`git push --force --set-upstream origin ${branch}`
const synchronizeBranches = async ({ repository, sourceBranch, targetBranch }) => {
await checkIfLocalRepoIsClean()
const previousBranch = await currentBranch()
await checkout(sourceBranch, { pull: true })
await createBranch(targetBranch)
const branchesForWhichTheMergeHasFailed = []
const branches = await branchesToSynchronize(repository, targetBranch)
for (let branch of branches) {
try {
await merge(branch)
} catch (e) {
console.error(`Could not merge branch ${branch}`)
branchesForWhichTheMergeHasFailed.push(branch)
await abortMerge()
}
}
if (branchesForWhichTheMergeHasFailed.length > 0) {
console.log(`List of branches that have fail when merged on ${targetBranch}:`)
branchesForWhichTheMergeHasFailed.forEach(branch => console.log(`\t• ${branch}`))
console.log(`They have to be merge manually`)
return
}
if (branches.length > 0) {
await pushForce(targetBranch)
}
await checkout(previousBranch)
}
await synchronizeBranches({
repository: { owner: 'TheMenu', repo: 'social-backend' },
sourceBranch: 'main',
targetBranch: 'staging',
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment