PR: Find branches without PR's #1605
This file contains hidden or 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
| --- # PR: find branches without open pull requests | |
| # Maintain in repo: funfair-server-template | |
| name: "PR: Find branches without PR's" | |
| on: | |
| push: | |
| branches: | |
| - "main" | |
| paths: | |
| - ".github/workflows/create-prs-for-stale-branches.yml" | |
| - ".github/actions/find-pull-request/**" | |
| - ".github/actions/read-file/**" | |
| - ".github/actions/create-pull-request/**" | |
| - ".github/actions/sync-labels/**" | |
| - ".github/actions/delete-branch/**" | |
| schedule: | |
| - cron: "0 1 * * *" | |
| concurrency: | |
| group: ${{github.workflow}}-${{github.ref}} | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| jobs: | |
| build-matrix: | |
| runs-on: [self-hosted, linux, build] | |
| steps: | |
| - name: "Initialise Workspace" | |
| if: runner.environment == 'self-hosted' | |
| shell: bash | |
| run: sudo chown -R "$USER:$USER" "$GITHUB_WORKSPACE" | |
| - name: "Set Active Environment" | |
| shell: bash | |
| run: | | |
| { | |
| echo "ACTIVE_RUNNER_NAME=${{runner.name}}" | |
| echo "ACTIVE_HOSTNAME=$HOSTNAME" | |
| echo "ACTIVE_USER=$USER" | |
| } >> "$GITHUB_ENV" | |
| - 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/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| clean: true | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| ref: main | |
| repository: ${{github.repository}} | |
| - name: "Create matrix of branches" | |
| id: set-matrix | |
| shell: bash | |
| run: | | |
| BRANCHES=$(git branch --remote --format='%(refname:short)' \ | |
| | grep -Po 'origin/\K[^*]*' \ | |
| | grep -vE 'HEAD|release/|hotfix/' \ | |
| | jq -R -s -c 'split("\n")[:-1]') | |
| echo "branches=$BRANCHES" >> "$GITHUB_OUTPUT" | |
| outputs: | |
| branches: ${{steps.set-matrix.outputs.branches}} | |
| check-branch: | |
| needs: build-matrix | |
| runs-on: [self-hosted, linux, build] | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| strategy: | |
| matrix: | |
| branch: ${{fromJson(needs.build-matrix.outputs.branches)}} | |
| env: | |
| BRANCH: ${{matrix.branch}} | |
| steps: | |
| - name: "Initialise Workspace" | |
| if: runner.environment == 'self-hosted' | |
| shell: bash | |
| run: sudo chown -R "$USER:$USER" "$GITHUB_WORKSPACE" | |
| - name: "Set Active Environment" | |
| shell: bash | |
| run: | | |
| { | |
| echo "ACTIVE_RUNNER_NAME=${{runner.name}}" | |
| echo "ACTIVE_HOSTNAME=$HOSTNAME" | |
| echo "ACTIVE_USER=$USER" | |
| } >> "$GITHUB_ENV" | |
| - name: "Checkout Source" | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| clean: true | |
| fetch-depth: 0 | |
| fetch-tags: true | |
| ref: main | |
| repository: ${{github.repository}} | |
| - name: "Check Required Secrets" | |
| shell: bash | |
| run: | | |
| if [ -z "${{secrets.SOURCE_PUSH_TOKEN}}" ]; then | |
| echo "::error::SOURCE_PUSH_TOKEN is required but not set" | |
| exit 1 | |
| fi | |
| - 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/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 | |
| 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/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 | |
| with: | |
| script: | | |
| core.info('On non-default branch'); | |
| - name: "Find Existing PR" | |
| if: steps.detection.outputs.defaultbranch != matrix.branch | |
| uses: ./.github/actions/find-pull-request | |
| 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}}..." | |
| COUNTS=$(git rev-list --left-right --count "origin/${{env.DEFAULT_BRANCH}}...origin/${{matrix.branch}}") | |
| echo "$COUNTS" | awk '{ print "${{env.BRANCH}} is behind ${{env.DEFAULT_BRANCH}} by "$1" commit(s)" }' | |
| echo "$COUNTS" | 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: ./.github/actions/read-file | |
| with: | |
| path: ./.github/PULL_REQUEST_TEMPLATE.md | |
| - name: "Check Required Secrets" | |
| if: |- | |
| steps.detection.outputs.defaultbranch != matrix.branch | |
| && steps.find-pull-request.outputs.number == '' | |
| && steps.aheadbehind.outputs.ahead != 0 | |
| && steps.aheadbehind.outputs.dayssinceupdate > 7 | |
| shell: bash | |
| run: | | |
| if [ -z "${{secrets.PR_CREATE_TOKEN}}" ]; then | |
| echo "::error::PR_CREATE_TOKEN is required but not set" | |
| exit 1 | |
| fi | |
| - 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: ./.github/actions/create-pull-request | |
| with: | |
| github-token: ${{secrets.PR_CREATE_TOKEN}} | |
| source-branch: ${{matrix.branch}} | |
| destination-branch: ${{steps.detection.outputs.defaultbranch}} | |
| assignee: ${{github.actor}} | |
| labels: "auto-pr,stale" | |
| draft: true | |
| title: "${{steps.aheadbehind.outputs.COMMIT_MSG}} [No commits for ${{steps.aheadbehind.outputs.dayssinceupdate}} days]" | |
| body: "${{steps.pr-template.outputs.content}}" | |
| - 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/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 | |
| 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: "Check Required Secrets" | |
| if: steps.open-pr.outputs.pr_number != '' | |
| shell: bash | |
| run: | | |
| if [ -z "${{secrets.SOURCE_PUSH_TOKEN}}" ]; then | |
| echo "::error::SOURCE_PUSH_TOKEN is required but not set" | |
| exit 1 | |
| fi | |
| - name: "Update PR Labels" | |
| if: steps.open-pr.outputs.pr_number != '' | |
| uses: ./.github/actions/sync-labels | |
| with: | |
| github-token: ${{secrets.SOURCE_PUSH_TOKEN}} | |
| 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/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 | |
| with: | |
| script: | | |
| core.info('Rebase?'); | |
| - name: "Check Required Secrets" | |
| if: |- | |
| steps.detection.outputs.defaultbranch != matrix.branch | |
| && steps.find-pull-request.outputs.number == '' | |
| && steps.aheadbehind.outputs.ahead == '0' | |
| && steps.aheadbehind.outputs.dayssinceupdate > 60 | |
| shell: bash | |
| run: | | |
| if [ -z "${{secrets.SOURCE_PUSH_TOKEN}}" ]; then | |
| echo "::error::SOURCE_PUSH_TOKEN is required but not set" | |
| exit 1 | |
| fi | |
| - 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: ./.github/actions/delete-branch | |
| with: | |
| github-token: ${{secrets.SOURCE_PUSH_TOKEN}} | |
| branch: ${{matrix.branch}} | |
| - name: "Statistics" | |
| if: |- | |
| steps.detection.outputs.defaultbranch != matrix.branch | |
| && steps.find-pull-request.outputs.number == '' | |
| uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 | |
| 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'); |