Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Report PRs with required status failures #12

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,20 @@ inputs:
required: true
default: 0

outputs: {}
outputs:
failed:
description: "Was mergeabot unable to process any PRs?"
value: ${{ steps.automerge.outputs.failed }}

failed-urls:
description: "List of PRs which were unable to be processed"
value: ${{ steps.automerge.outputs.failed-urls }}

runs:
using: composite
steps:
- name: Auto-merge Dependabot PRs
- id: automerge
name: Auto-merge Dependabot PRs
shell: bash
run: ${{ github.action_path }}/bin/automerge-prs
env:
Expand Down
65 changes: 59 additions & 6 deletions bin/automerge-prs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,16 @@
set -euo pipefail
shopt -s nullglob

if [[ ! "$STRATEGY" =~ merge|rebase|squash ]]; then
echo "Invalid strategy: must be merge, rebase, or squash" >&2
exit 64
fi
# Matches action defaults
: "${EXCLUDE_TITLE_REGEX:=""}"
: "${QUARANTINE_DAYS:=5}"
: "${STRATEGY:=rebase}"
: "${REMOVE_REVIEWERS:=true}"

# Except DRY_RUN=1 is better default if being run locally
: "${DRY_RUN:=1}"

: "${DRY_RUN:=0}"
# required: GH_REPO

: "${GH_ACTOR:=""}"
: "${GH_EVENT:=""}"
Expand All @@ -16,6 +20,14 @@ fi
: "${GH_PR_TITLE:=""}"
: "${GH_PR_HEAD_REF:=""}"

# Actions interface
: "${GITHUB_OUTPUT:=/dev/null}"

if [[ ! "$STRATEGY" =~ merge|rebase|squash ]]; then
echo "Invalid strategy: must be merge, rebase, or squash" >&2
exit 64
fi

is_dependabot() {
[[ "$GH_ACTOR" == 'dependabot[bot]' ]] && [[ "$GH_EVENT" == 'pull_request' ]]
}
Expand Down Expand Up @@ -79,12 +91,20 @@ EOM
exit 0
fi

read -r defaultBranch < \
<(gh repo view "$GH_REPO" --json defaultBranchRef --jq '.defaultBranchRef.name')

gh api \
"/repos/$GH_REPO/branches/$defaultBranch/protection" \
--jq '.required_status_checks.contexts[]' |
sort >"$tmp/required-statuses.txt"
Comment on lines +97 to +100
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, so this requires a permission that I'm not sure Actions is able to even request.

That might be a deal-breaker for this whole idea.

Copy link
Member Author

@pbrisbin pbrisbin May 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the choices are:

  1. Ask for the list of required statuses as an input, or
  2. Do this if any status checks fail

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there some way to attempt a merge, which would be rejected if a required status is failed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good idea. I don't know what happens if a bot tries to merge around branch protections, I guess we'd have to test it.


now_s=$(date +"%s")
since_s=$((now_s - (QUARANTINE_DAYS * 24 * 60 * 60)))
since=$(date -d "@$since_s" +"%Y-%m-%d")

search="author:app/dependabot updated:<$since"
fields='number,title,headRefName,author,updatedAt,reviewDecision'
fields='number,title,headRefName,author,updatedAt,reviewDecision,statusCheckRollup'

gh_pr list --search "$search" --limit 1000 --json "$fields" --jq '.[]' |
while IFS=$'\n' read -r ln; do
Expand All @@ -93,6 +113,7 @@ gh_pr list --search "$search" --limit 1000 --json "$fields" --jq '.[]' |
done

found=0
failed=()

for json in "$tmp"/*.json; do
number=$(jq --raw-output '.number' "$json")
Expand All @@ -116,6 +137,27 @@ for json in "$tmp"/*.json; do
continue
fi

jq --raw-output '.statusCheckRollup[] | select(.conclusion=="FAILURE") | .name' "$json" | sort >"$tmp/$number-failed-statuses.txt"
comm -12 "$tmp/required-statuses.txt" "$tmp/$number-failed-statuses.txt" >"$tmp/$number-required-failed-statuses.txt"

read -r failedStatuses < <(paste -sd ' ' "$tmp/$number-required-failed-statuses.txt")
read -r failedStatusesCount < <(wc -l <"$tmp/$number-required-failed-statuses.txt")

if ((failedStatusesCount == 1)); then
statusesHave='status has'
else
statusesHave='statuses have'
fi

if [[ -n "$failedStatuses" ]]; then
failed+=("$number")
printf ' \e[1;31m!!\e[0m %d required %s failed: \e[35m%s\e[0m\n' \
"$failedStatusesCount" \
"$statusesHave" \
"$failedStatuses"
continue
fi

case "$reviewDecision" in
CHANGES_REQUESTED)
printf ' \e[1;37m=>\e[0m \e[33mSkip\e[0m (changes requested)\n'
Expand All @@ -136,6 +178,17 @@ for json in "$tmp"/*.json; do
esac
done

if ((${#failed})); then
echo "Warning: the following PRs cannot be auto-merged:"
echo "failed=true" >>"$GITHUB_OUTPUT"
echo "failed-urls<<EOM" >>"$GITHUB_OUTPUT"
for number in "${failed[@]}"; do
printf 'https://github.com/%s/pull/%s\n' "$GH_REPO" "$number"
done | tee -a "$GITHUB_OUTPUT"
echo "EOM" >>"$GITHUB_OUTPUT"

fi

if ((!found)); then
echo "No Dependabot PRs found older than $since."
fi
Loading