Skip to content

combine-prs

combine-prs #14

Workflow file for this run

# Workflow for combining pull requests by renovate
name: combine-prs
# Controls when the action will run - in this case triggered manually
on:
workflow_dispatch:
inputs:
branchPrefix:
description: 'Branch prefix to find combinable PRs based on'
required: true
default: 'renovate'
mustBeGreen:
description: 'Only combine PRs that are green (status is success)'
required: true
default: true
combineBranchName:
description: 'Name of the branch to combine PRs into'
required: true
default: 'renovate-dependencies-grouped'
ignoreLabel:
description: 'Exclude PRs with this label'
required: true
default: 'nocombine'
prTitle:
description: 'Title of the pull request submitted'
default: 'chore: combine renovate upgrades'
required: true
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "combine-prs"
combine-prs:
# The type of runner that the job will run on
runs-on: ubuntu-latest
environment: 'Combine PR'
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
- uses: tibdex/github-app-token@v1
id: generate-token
with:
app_id: ${{ secrets.APP_ID }}
private_key: ${{ secrets.APP_PRIVATE_KEY }}
- uses: actions/github-script@v6
id: fetch-branch-names
name: Fetch branch names
with:
github-token: ${{ steps.generate-token.outputs.token }}
script: |
const CI_TEST_THAT_NEEDS_TO_BE_GREEN = [
'codecov/patch',
'SonarCloud',
'SonarCloud Code Analysis',
'test-support-scripts',
'test-code-generation',
'build-and-test (windows-latest)',
'build-and-test (macos-latest)',
'Run Sorald Buildbreaker',
'build-and-test (ubuntu-latest)'
]
const pulls = await github.paginate('GET /repos/:owner/:repo/pulls', {
owner: context.repo.owner,
repo: context.repo.repo
});
branches = [];
prs = [];
base_branch = null;
for (const pull of pulls) {
const branch = pull['head']['ref'];
console.log('Pull for branch: ' + branch);
if (branch.startsWith('${{ github.event.inputs.branchPrefix }}')) {
console.log('Branch matched: ' + branch);
statusOK = true;
if(${{ github.event.inputs.mustBeGreen }}) {
console.log('Checking green status: ' + branch);
const check_runs = await github.paginate('GET /repos/{owner}/{repo}/commits/{ref}/check-runs', {
owner: context.repo.owner,
repo: context.repo.repo,
ref: branch
});
for (const check of check_runs) {
if (CI_TEST_THAT_NEEDS_TO_BE_GREEN.includes(check.name)) {
if (check.conclusion !== 'success') {
console.log(
'Discarding ' + branch + ' because ' + check.name + '\'s conclusion is not success. It is: ' + check.conclusion
);
statusOK = false;
}
}
}
}
console.log('Checking labels: ' + branch);
const labels = pull['labels'];
for(const label of labels) {
const labelName = label['name'];
console.log('Checking label: ' + labelName);
if(labelName == '${{ github.event.inputs.ignoreLabel }}') {
console.log('Discarding ' + branch + ' with label ' + labelName);
statusOK = false;
}
}
if (statusOK) {
console.log('Adding branch to array: ' + branch);
branches.push(branch);
prs.push('#' + pull['number'] + ' ' + pull['title']);
base_branch = pull['base']['ref'];
}
}
}
if (branches.length == 0) {
core.setFailed('No PRs/branches matched criteria');
return;
}
core.setOutput('base-branch', base_branch);
core.setOutput('prs-string', prs.join('\n'));
combined = branches.join(' ')
console.log('Combined: ' + combined);
return combined
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v3.5.2
with:
fetch-depth: 0
token: ${{ steps.generate-token.outputs.token }}
# Creates a branch with other PR branches merged together
- name: Created combined branch
id: combined-branch
env:
BASE_BRANCH: ${{ steps.fetch-branch-names.outputs.base-branch }}
BRANCHES_TO_COMBINE: ${{ steps.fetch-branch-names.outputs.result }}
COMBINE_BRANCH_NAME: ${{ github.event.inputs.combineBranchName }}
run: |
echo "$BRANCHES_TO_COMBINE"
sourcebranches="${BRANCHES_TO_COMBINE%\"}"
sourcebranches="${sourcebranches#\"}"
basebranch="${BASE_BRANCH%\"}"
basebranch="${basebranch#\"}"
git config pull.rebase false
git config user.name github-actions
git config user.email github-actions@github.com
echo "$COMBINE_BRANCH_NAME"
echo "$basebranch"
git checkout -b $COMBINE_BRANCH_NAME
git pull origin $sourcebranches --no-edit
git push origin $COMBINE_BRANCH_NAME
# Creates a PR with the new combined branch
- uses: actions/github-script@v6
name: Create Combined Pull Request
env:
PRS_STRING: ${{ steps.fetch-branch-names.outputs.prs-string }}
with:
github-token: ${{ steps.generate-token.outputs.token }}
script: |
const prString = process.env.PRS_STRING;
const body = 'This PR was created by the Combine PRs action by combining the following PRs:\n' + prString;
await github.rest.pulls.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: '${{ github.event.inputs.prTitle }}',
head: '${{ github.event.inputs.combineBranchName }}',
base: '${{ steps.fetch-branch-names.outputs.base-branch }}',
body: body
});