From 8b130fcb692638e077672f67dc8b0857e5e37e1e Mon Sep 17 00:00:00 2001 From: "Michael B. Klein" Date: Wed, 6 Dec 2023 14:28:34 +0000 Subject: [PATCH] Refactor dependabot config --- .github/dependabot.yml | 3 +- .github/workflows/build.yml | 4 +- combine-prs.yml | 156 ++++++++++++++++++++++++++++++++++++ mix.exs | 4 +- 4 files changed, 161 insertions(+), 6 deletions(-) create mode 100644 combine-prs.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e50dc34..93408cc 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,6 +7,5 @@ updates: time: "11:00" labels: - "dependencies" - - "automerge" open-pull-requests-limit: 10 - target-branch: dependencies + target-branch: main diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fe89d16..b68f7ba 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,8 +6,8 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - otp: ["24", "25"] - elixir: ["1.13", "1.14"] + otp: ["25", "26"] + elixir: ["1.13", "1.14", "1.15"] env: MIX_ENV: test steps: diff --git a/combine-prs.yml b/combine-prs.yml new file mode 100644 index 0000000..cfa851c --- /dev/null +++ b/combine-prs.yml @@ -0,0 +1,156 @@ +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: 'dependabot' + mustBeGreen: + description: 'Only combine PRs that are green (status is success). Set to false if repo does not run checks' + type: boolean + required: true + default: true + combineBranchName: + description: 'Name of the branch to combine PRs into' + required: true + default: 'combined-dependencies' + combinePullRequestTitle: + description: 'Title of the combined Pull Request' + required: true + default: 'Dependency Rollup' + ignoreLabel: + description: 'Exclude PRs with this label' + required: true + default: 'nocombine' + +# 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 + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + - uses: actions/github-script@v6 + id: create-combined-pr + name: Create Combined PR + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const pulls = await github.paginate('GET /repos/:owner/:repo/pulls', { + owner: context.repo.owner, + repo: context.repo.repo + }); + let branchesAndPRStrings = []; + let baseBranch = null; + let baseBranchSHA = 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 prefix: ' + branch); + let statusOK = true; + if(${{ github.event.inputs.mustBeGreen }}) { + console.log('Checking green status: ' + branch); + const stateQuery = `query($owner: String!, $repo: String!, $pull_number: Int!) { + repository(owner: $owner, name: $repo) { + pullRequest(number:$pull_number) { + commits(last: 1) { + nodes { + commit { + statusCheckRollup { + state + } + } + } + } + } + } + }` + const vars = { + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pull['number'] + }; + const result = await github.graphql(stateQuery, vars); + const [{ commit }] = result.repository.pullRequest.commits.nodes; + const state = commit.statusCheckRollup.state + console.log('Validating status: ' + state); + if(state != 'SUCCESS') { + console.log('Discarding ' + branch + ' with status ' + state); + 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); + const prString = '#' + pull['number'] + ' ' + pull['title']; + branchesAndPRStrings.push({ branch, prString }); + baseBranch = pull['base']['ref']; + baseBranchSHA = pull['base']['sha']; + } + } + } + if (branchesAndPRStrings.length == 0) { + core.setFailed('No PRs/branches matched criteria'); + return; + } + try { + await github.rest.git.createRef({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: 'refs/heads/' + '${{ github.event.inputs.combineBranchName }}', + sha: baseBranchSHA + }); + } catch (error) { + console.log(error); + core.setFailed('Failed to create combined branch - maybe a branch by that name already exists?'); + return; + } + + let combinedPRs = []; + let mergeFailedPRs = []; + for(const { branch, prString } of branchesAndPRStrings) { + try { + await github.rest.repos.merge({ + owner: context.repo.owner, + repo: context.repo.repo, + base: '${{ github.event.inputs.combineBranchName }}', + head: branch, + }); + console.log('Merged branch ' + branch); + combinedPRs.push(prString); + } catch (error) { + console.log('Failed to merge branch ' + branch); + mergeFailedPRs.push(prString); + } + } + + console.log('Creating combined PR'); + const combinedPRsString = combinedPRs.join('\n'); + let body = '✅ This PR was created by the Combine PRs action by combining the following PRs:\n' + combinedPRsString; + if(mergeFailedPRs.length > 0) { + const mergeFailedPRsString = mergeFailedPRs.join('\n'); + body += '\n\n⚠️ The following PRs were left out due to merge conflicts:\n' + mergeFailedPRsString + } + await github.rest.pulls.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: '${{ github.event.inputs.combinePullRequestTitle }}', + head: '${{ github.event.inputs.combineBranchName }}', + base: baseBranch, + body: body + }); diff --git a/mix.exs b/mix.exs index 51db0bb..17aec34 100644 --- a/mix.exs +++ b/mix.exs @@ -1,14 +1,14 @@ defmodule Authoritex.MixProject do use Mix.Project - @version "1.0.2" + @version "1.0.3" @url "https://github.com/nulib/authoritex" def project do [ app: :authoritex, version: @version, - elixir: "~> 1.9", + elixir: "~> 1.13", name: "Authoritex", description: "An Elixir library for searching and fetching controlled vocabulary authority terms",