41b21bec3f3ef733af755db861ea0b3f2f0efe62
[e-mobility-charging-stations-simulator.git] / .github / workflows / combine-prs.yml
1 name: 'Combine PRs'
2
3 # Controls when the action will run - in this case triggered manually
4 on:
5 workflow_dispatch:
6 inputs:
7 branchPrefix:
8 description: 'Branch prefix to find combinable PRs based on'
9 required: true
10 default: 'dependabot'
11 mustBeGreen:
12 description: 'Only combine PRs that are green (status is success)'
13 required: true
14 default: true
15 combineBranchName:
16 description: 'Name of the branch to combine PRs into'
17 required: true
18 default: 'combine-prs-branch'
19 ignoreLabel:
20 description: 'Exclude PRs with this label'
21 required: true
22 default: 'nocombine'
23
24 # A workflow run is made up of one or more jobs that can run sequentially or in parallel
25 jobs:
26 # This workflow contains a single job called "combine-prs"
27 combine-prs:
28 # The type of runner that the job will run on
29 runs-on: ubuntu-latest
30
31 # Steps represent a sequence of tasks that will be executed as part of the job
32 steps:
33 - uses: actions/github-script@v6
34 id: create-combined-pr
35 name: Create Combined PR
36 with:
37 github-token: ${{secrets.GITHUB_TOKEN}}
38 script: |
39 const pulls = await github.paginate('GET /repos/:owner/:repo/pulls', {
40 owner: context.repo.owner,
41 repo: context.repo.repo
42 });
43 let branchesAndPRStrings = [];
44 let baseBranch = null;
45 let baseBranchSHA = null;
46 for (const pull of pulls) {
47 const branch = pull['head']['ref'];
48 console.log('Pull for branch: ' + branch);
49 if (branch.startsWith('${{ github.event.inputs.branchPrefix }}')) {
50 console.log('Branch matched prefix: ' + branch);
51 let statusOK = true;
52 if(${{ github.event.inputs.mustBeGreen }}) {
53 console.log('Checking green status: ' + branch);
54 const statusResponse = await github.rest.repos.getCombinedStatusForRef({
55 owner: context.repo.owner,
56 repo: context.repo.repo,
57 ref: branch
58 });
59 const state = statusResponse['data']['state'];
60 console.log('Validating status: ' + state);
61 if(state != 'success') {
62 console.log('Discarding ' + branch + ' with status ' + state);
63 statusOK = false;
64 }
65 }
66 console.log('Checking labels: ' + branch);
67 const labels = pull['labels'];
68 for(const label of labels) {
69 const labelName = label['name'];
70 console.log('Checking label: ' + labelName);
71 if(labelName == '${{ github.event.inputs.ignoreLabel }}') {
72 console.log('Discarding ' + branch + ' with label ' + labelName);
73 statusOK = false;
74 }
75 }
76 if (statusOK) {
77 console.log('Adding branch to array: ' + branch);
78 const prString = '#' + pull['number'] + ' ' + pull['title'];
79 branchesAndPRStrings.push({ branch, prString });
80 baseBranch = pull['base']['ref'];
81 baseBranchSHA = pull['base']['sha'];
82 }
83 }
84 }
85 if (branchesAndPRStrings.length == 0) {
86 core.setFailed('No PRs/branches matched criteria');
87 return;
88 }
89 try {
90 await github.rest.git.createRef({
91 owner: context.repo.owner,
92 repo: context.repo.repo,
93 ref: 'refs/heads/' + '${{ github.event.inputs.combineBranchName }}',
94 sha: baseBranchSHA
95 });
96 } catch (error) {
97 console.log(error);
98 core.setFailed('Failed to create combined branch - maybe a branch by that name already exists?');
99 return;
100 }
101
102 let combinedPRs = [];
103 let mergeFailedPRs = [];
104 for(const { branch, prString } of branchesAndPRStrings) {
105 try {
106 await github.rest.repos.merge({
107 owner: context.repo.owner,
108 repo: context.repo.repo,
109 base: '${{ github.event.inputs.combineBranchName }}',
110 head: branch,
111 });
112 console.log('Merged branch ' + branch);
113 combinedPRs.push(prString);
114 } catch (error) {
115 console.log('Failed to merge branch ' + branch);
116 mergeFailedPRs.push(prString);
117 }
118 }
119
120 console.log('Creating combined PR');
121 const combinedPRsString = combinedPRs.join('\n');
122 let body = '✅ This PR was created by the Combine PRs action by combining the following PRs:\n' + combinedPRsString;
123 if(mergeFailedPRs.length > 0) {
124 const mergeFailedPRsString = mergeFailedPRs.join('\n');
125 body += '\n\n⚠️ The following PRs were left out due to merge conflicts:\n' + mergeFailedPRsString
126 }
127 await github.rest.pulls.create({
128 owner: context.repo.owner,
129 repo: context.repo.repo,
130 title: 'Combined PR',
131 head: '${{ github.event.inputs.combineBranchName }}',
132 base: baseBranch,
133 body: body
134 });