PR: Find branches without PR's #830
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: "PR: Find branches without PR's" | |
on: | |
push: | |
branches: | |
- "main" | |
paths: | |
- ".github/workflows/create-prs-for-stale-branches.yml" | |
schedule: | |
- cron: "0 1 * * *" | |
concurrency: | |
group: ${{github.workflow}}-${{github.ref}} | |
cancel-in-progress: false | |
jobs: | |
build-matrix: | |
runs-on: ubuntu-latest | |
permissions: | |
contents: read | |
steps: | |
- name: "Initialise Workspace" | |
if: startsWith(runner.name, 'buildagent-') | |
shell: bash | |
run: sudo chown -R "$USER:$USER" "$GITHUB_WORKSPACE" | |
- name: "Info" | |
shell: bash | |
run: | | |
echo "Repo: ${{github.repository}}" | |
echo "Owner: ${{github.repository_owner}}" | |
- name: "Ensure JQ is installed" | |
shell: bash | |
run: sudo apt install -y jq | |
- name: "Checkout Source" | |
uses: actions/[email protected] | |
with: | |
fetch-depth: 0 | |
fetch-tags: true | |
ref: main | |
repository: ${{github.repository}} | |
- name: "Create matrix of branches" | |
id: set-matrix | |
shell: bash | |
run: | | |
echo "branches=$(git branch --remote --format='%(refname:short)' | grep -Po 'origin/\K[^*]*' | grep -vE 'HEAD|release/|hotfix/' | jq -R -s -c 'split("\n")[:-1]')" >> "$GITHUB_OUTPUT" | |
outputs: | |
branches: ${{steps.set-matrix.outputs.branches}} | |
check-branch: | |
needs: build-matrix | |
runs-on: ubuntu-latest | |
permissions: | |
contents: write | |
pull-requests: write | |
strategy: | |
matrix: | |
branch: ${{fromJson(needs.build-matrix.outputs.branches)}} | |
env: | |
BRANCH: ${{matrix.branch}} | |
CREATE_DRAFT: true | |
REPO_STATUS: private | |
steps: | |
- name: "Initialise Workspace" | |
if: startsWith(runner.name, 'buildagent-') | |
shell: bash | |
run: sudo chown -R "$USER:$USER" "$GITHUB_WORKSPACE" | |
- name: "Harden Security" | |
uses: step-security/[email protected] | |
with: | |
egress-policy: audit | |
disable-sudo: true | |
allowed-endpoints: > | |
api.github.com:443 | |
api.osv.dev:443 | |
api.securityscorecards.dev:443 | |
codeload.github.com:443 | |
fulcio.sigstore.dev:443 | |
github.com:443 | |
oss-fuzz-build-logs.storage.googleapis.com:443 | |
rekor.sigstore.dev:443 | |
tuf-repo-cdn.sigstore.dev:443 | |
www.bestpractices.dev:443 | |
- name: "Checkout Source" | |
uses: actions/[email protected] | |
with: | |
fetch-depth: 0 | |
fetch-tags: true | |
ref: main | |
repository: ${{github.repository}} | |
- name: "Check Repo Visibility" | |
if: github.repository_owner != 'funfair-tech' | |
uses: credfeto/[email protected] | |
id: visibility | |
with: | |
repository: ${{github.repository}} | |
token: ${{secrets.SOURCE_PUSH_TOKEN}} | |
- name: "Override DRAFT Flag" | |
if: github.repository_owner != 'funfair-tech' && env.REPO_STATUS == 'private' | |
shell: bash | |
run: echo "CREATE_DRAFT=false" >> "$GITHUB_ENV" | |
- name: "Branch Detection" | |
id: detection | |
shell: bash | |
run: | | |
echo "defaultbranch=$(git remote show origin | grep -Po 'HEAD\sbranch:\s+\K[^.*]*')" >> "$GITHUB_OUTPUT" | |
echo "DEFAULT_BRANCH=$(git remote show origin | grep -Po 'HEAD\sbranch:\s+\K[^.*]*')" >> "$GITHUB_ENV" | |
# On Default branch | |
- name: "On Default Branch" | |
if: steps.detection.outputs.defaultbranch == matrix.branch | |
uses: actions/[email protected] | |
with: | |
script: | | |
core.info("On Default branch - don't do anything"); | |
# On Non-Default branch | |
- name: "On Non-Default branch" | |
if: steps.detection.outputs.defaultbranch != matrix.branch | |
uses: actions/[email protected] | |
with: | |
script: | | |
core.info('On non-default branch'); | |
- name: "Find Existing PR" | |
if: steps.detection.outputs.defaultbranch != matrix.branch | |
uses: juliangruber/[email protected] | |
id: find-pull-request | |
with: | |
branch: "${{env.BRANCH}}" | |
- name: "Display Found PR" | |
if: steps.detection.outputs.defaultbranch != matrix.branch | |
shell: bash | |
run: echo "Pull Request ${{steps.find-pull-request.outputs.number}} (${{steps.find-pull-request.outputs.head-sha}})" | |
- name: "Check Branch Status" | |
if: steps.detection.outputs.defaultbranch != matrix.branch && steps.find-pull-request.outputs.number == '' | |
shell: bash | |
run: | |
echo "Check to see if ${{env.DEFAULT_BRANCH}} is ahead or behind ${{matrix.branch}}..." | |
git rev-list --left-right --count "origin/${{env.DEFAULT_BRANCH}}...origin/${{matrix.branch}}" | |
git rev-list --left-right --count "origin/${{env.DEFAULT_BRANCH}}...origin/${{matrix.branch}}" | awk '{ print "${{env.BRANCH}} is behind ${{env.DEFAULT_BRANCH}} by "$1" commit(s)" }' | |
git rev-list --left-right --count "origin/${{env.DEFAULT_BRANCH}}...origin/${{matrix.branch}}" | awk '{ print "${{matrix.BRANCH}} is ahead of ${{env.DEFAULT_BRANCH}} by "$2" commit(s)" }' | |
env: | |
DEFAULT_BRANCH: ${{steps.detection.outputs.defaultbranch}} | |
- name: "Get last update time of branch" | |
if: steps.detection.outputs.defaultbranch != matrix.branch && steps.find-pull-request.outputs.number == '' | |
id: lastupdate | |
shell: bash | |
run: echo "time=$(git log -1 --format=@%ct origin/${{env.BRANCH}})" >> "$GITHUB_OUTPUT" | |
- name: "Check Ahead and Behind Status" | |
if: steps.detection.outputs.defaultbranch != matrix.branch && steps.find-pull-request.outputs.number == '' | |
id: aheadbehind | |
shell: bash | |
run: > | |
{ \ | |
git rev-list --left-right --count "origin/${{env.DEFAULT_BRANCH}}...origin/${{env.BRANCH}}" \ | |
| awk '{ print "behind="$1 }' ; \ | |
git rev-list --left-right --count "origin/${{env.DEFAULT_BRANCH}}...origin/${{env.BRANCH}}" \ | |
| awk '{ print "ahead="$2 }' ; \ | |
echo "dayssinceupdate=$((($(date +%s)-$(date +%s --date ${{env.LAST_UPDATE}}))/(3600*24)))" ; \ | |
echo "COMMIT_MSG=$(git log -1 --pretty=%B "${{env.ORIGIN_DEFAULT_BRANCH}}")" ; \ | |
} >> "$GITHUB_OUTPUT" | |
env: | |
DEFAULT_BRANCH: ${{steps.detection.outputs.defaultbranch}} | |
ORIGIN_DEFAULT_BRANCH: origin/${{steps.detection.outputs.defaultbranch}} | |
LAST_UPDATE: ${{steps.lastupdate.outputs.time}} | |
# Non-default - ahead of default branch, and no -re-existing PR then create one. | |
- name: "Read PR Template" | |
if: |- | |
steps.detection.outputs.defaultbranch != matrix.branch | |
&& steps.find-pull-request.outputs.number == '' | |
&& steps.aheadbehind.outputs.ahead != 0 | |
&& steps.aheadbehind.outputs.dayssinceupdate > 7 | |
id: pr-template | |
uses: juliangruber/[email protected] | |
with: | |
path: ./.github/PULL_REQUEST_TEMPLATE.md | |
- name: "Create PR" | |
if: |- | |
steps.detection.outputs.defaultbranch != matrix.branch | |
&& steps.find-pull-request.outputs.number == '' | |
&& steps.aheadbehind.outputs.ahead != 0 | |
&& steps.aheadbehind.outputs.dayssinceupdate > 7 | |
id: open-pr | |
uses: repo-sync/[email protected] | |
with: | |
source_branch: ${{matrix.branch}} # If blank, default: triggered branch | |
destination_branch: ${{steps.detection.outputs.defaultbranch}} # If blank, default: master | |
pr_assignee: "${{github.actor}}" # Comma-separated list (no spaces) | |
pr_label: "auto-pr,stale" # Comma-separated list (no spaces) | |
pr_draft: ${{env.CREATE_DRAFT}} # Creates pull request as draft | |
pr_title: "${{steps.aheadbehind.outputs.COMMIT_MSG}} [No commits for ${{steps.aheadbehind.outputs.dayssinceupdate}} days]" | |
pr_body: "${{steps.pr-template.outputs.content}}" | |
github_token: ${{github.token}} | |
- name: "New PR Details" | |
if: |- | |
steps.detection.outputs.defaultbranch != matrix.branch | |
&& steps.find-pull-request.outputs.number == '' | |
&& steps.aheadbehind.outputs.ahead != 0 | |
&& steps.aheadbehind.outputs.dayssinceupdate > 7 | |
uses: actions/[email protected] | |
with: | |
script: | | |
core.info('URL: ${{steps.open-pr.outputs.pr_url}}'); | |
core.info('PR: ${{steps.open-pr.outputs.pr_number}}'); | |
core.info('CF: ${{steps.open-pr.outputs.has_changed_files}}'); | |
- name: "Update PR Labels" | |
if: steps.open-pr.outputs.pr_number != '' | |
uses: actions/labeler@v5 | |
with: | |
repo-token: ${{secrets.SOURCE_PUSH_TOKEN}} | |
configuration-path: .github/labeler.yml | |
sync-labels: true | |
pr-number: ${{steps.open-pr.outputs.pr_number}} | |
- name: "Rebase" | |
if: |- | |
steps.detection.outputs.defaultbranch != matrix.branch | |
&& steps.find-pull-request.outputs.number == '' | |
&& steps.aheadbehind.outputs.behind != 0 | |
&& steps.aheadbehind.outputs.ahead != 0 | |
&& steps.aheadbehind.outputs.dayssinceupdate > 7 | |
uses: actions/[email protected] | |
with: | |
script: | | |
core.info('Rebase?'); | |
- name: "Delete Branch" | |
if: |- | |
steps.detection.outputs.defaultbranch != matrix.branch | |
&& steps.find-pull-request.outputs.number == '' | |
&& steps.aheadbehind.outputs.ahead == '0' | |
&& steps.aheadbehind.outputs.dayssinceupdate > 60 | |
uses: dawidd6/[email protected] | |
with: | |
github_token: ${{secrets.SOURCE_PUSH_TOKEN}} | |
branches: ${{matrix.branch}} | |
- name: "Statistics" | |
if: |- | |
steps.detection.outputs.defaultbranch != matrix.branch | |
&& steps.find-pull-request.outputs.number == '' | |
uses: actions/[email protected] | |
with: | |
script: | | |
core.info('Ahead: ${{steps.aheadbehind.outputs.ahead}}'); | |
core.info('Behind: ${{steps.aheadbehind.outputs.behind}}'); | |
core.info('Last Commit: ${{steps.aheadbehind.outputs.dayssinceupdate}} days ago'); |