4D5309C9 - Forza Horizon #433
Workflow file for this run
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: Autoclose | |
on: | |
issues: | |
types: [opened, edited] | |
issue_comment: | |
types: created #, edited] | |
pull_request: # Yes, someone actually did this; | |
types: opened # https://github.com/xenia-project/game-compatibility/pull/1501 | |
jobs: | |
autoclose: | |
runs-on: ubuntu-latest | |
steps: | |
- uses: actions/checkout@v2 # Needed by gh | |
# TODO: Use cache if issue/label count are the same | |
#- uses: actions/cache@v2 | |
# with: | |
# path: cache | |
# restore-keys: cache | |
- name: Autoclose | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
issue_number: ${{ github.event.issue.number }} | |
issue_author: ${{ github.event.issue.user.login }} | |
issue_title: ${{ github.event.issue.title }} | |
issue_labels: ${{ join(github.event.issue.labels.*.name) }} | |
issue_body: ${{ github.event.issue.body }} | |
issue_state: ${{ github.event.issue.state }} | |
issue_comment_author: ${{ github.event.comment.user.login }} | |
issue_comment_body: ${{ github.event.comment.body }} | |
pull_request_number: ${{ github.event.pull_request.number }} | |
pull_request_author: ${{ github.event.pull_request.user.login }} | |
pull_request_title: ${{ github.event.pull_request.title }} | |
pull_request_body: ${{ github.event.pull_request.body }} | |
run: | | |
# TODO: Use cache to avoid API limits(?) | |
# TODO: Check issues/log/screenshots(?) | |
case "$GITHUB_EVENT_NAME" in | |
issues) | |
github_event_name_friendly='Issue' | |
function issue_body_trim() { | |
issue_body_trim=$(echo "$issue_body" | grep "### $1" -A 2 | tail +3) | |
} | |
;; | |
issue_comment) | |
issue_comment_author_whitelist=(benvanik BillieBlueberry CookiePLMonster DrChat emoose Etokapa gibbed Gliniak halotroop2288 illusion0001 Margen67 Nighterlev Prism019 randprint Razzile Triang3l ZolaKluke) | |
for whitelisted_author in "${issue_comment_author_whitelist[@]}"; do | |
if [ "$issue_comment_author" = "$whitelisted_author" ] && [ -z "$issue_comment_author_whitelisted" ]; then | |
issue_comment_author_whitelisted='true' | |
break | |
fi | |
done | |
if [ -n "$issue_comment_author_whitelisted" ]; then | |
github_event_name_friendly='Issue comment' | |
fi | |
;; | |
pull_request) | |
github_event_name_friendly='PR' | |
;; | |
esac | |
function compatibility_report_invalidate() { | |
echo "$1" | |
compatibility_report_invalid_reasons+=$'\n'" * $1" | |
} | |
if [ "$GITHUB_EVENT_NAME" != 'issue_comment' ]; then | |
if [ "$GITHUB_EVENT_NAME" = 'pull_request' ]; then | |
issue_title="$pull_request_title" | |
fi | |
# Check issue/pull request title | |
## TODO: Fix validation of '######## - ' | |
if [[ "$issue_title" =~ ^([0-9A-F]{8} - .+)$ ]]; then | |
if [ "$GITHUB_EVENT_NAME" = 'issues' ]; then | |
echo 'Title is valid.' | |
## Check for duplicate(s) | |
if [ '${{ github.event.action }}' = 'opened' ]; then | |
repository_issues_json=$(gh api graphql --jq '.data.repository[]' --paginate -f query=' | |
query($endCursor: String) { | |
repository(owner: "xenia-canary", name: "game-compatibility") { | |
issues(first:100, states:OPEN, after:$endCursor) { | |
nodes { | |
number | |
title | |
} | |
pageInfo { | |
hasNextPage | |
endCursor | |
} | |
} | |
} | |
} | |
') | |
readarray -t issue_numbers < <(jq -r '.nodes[].number' <<<"$repository_issues_json") | |
readarray -t issue_titles < <(jq -r '.nodes[].title' <<<"${repository_issues_json,,}") | |
issue_title_lowercase="${issue_title,,}" | |
## Skip 1 to skip empty entry (TODO: Is this a hack?) | |
for (( i = 0; i <= $(( ${#issue_numbers[@]} - 1 )); i++ )); do | |
if [[ "$issue_title_lowercase" =~ "${issue_titles[$i]}" ]] && [[ "$issue_number" != "${issue_numbers[$i]}" ]]; then | |
issue_duplicates=$'\n'" * #${issue_numbers[$i]}" | |
fi | |
done | |
fi | |
if [ -z "$issue_duplicates" ]; then | |
echo "Issue probably isn't a duplicate." | |
else | |
compatibility_report_invalidate "Issue is a duplicate of:$issue_duplicates" | |
fi | |
else | |
compatibility_report_invalidate "Compatibility reports can't be pull requests." | |
fi | |
elif [ "$GITHUB_EVENT_NAME" = 'issues' ]; then | |
compatibility_report_invalidate 'Title is invalid.' | |
elif [ "$GITHUB_EVENT_NAME" = 'pull_request' ]; then | |
echo 'Pull request is probably valid.' | |
fi | |
if [ "$GITHUB_EVENT_NAME" = 'issues' ]; then | |
# Check Xenia version | |
issue_body_trim 'Xenia version' | |
if [[ "$issue_body_trim" =~ https://github.com/xenia-canary/xenia-canary/commit/[0-9a-f]{5,40} ]]; then | |
echo 'Version is valid.' | |
else | |
compatibility_report_invalidate 'Version is invalid or missing.' | |
fi | |
fi | |
fi | |
# Check Labels | |
readarray -t repository_labels < <(gh api graphql --paginate --jq '.data.repository.labels.nodes[].name' -f query=' | |
query($endCursor: String) { | |
repository(owner: "xenia-project", name: "game-compatibility") { | |
labels(first:100, after:$endCursor) { | |
nodes { | |
name | |
} | |
pageInfo { | |
hasNextPage | |
endCursor | |
} | |
} | |
} | |
} | |
') | |
repository_labels_invalid=(issue-{invalid,duplicate,superseded,cluttered} state-crash-OBSOLETE) | |
case "$GITHUB_EVENT_NAME" in | |
issues) | |
issue_body_trim Labels | |
issue_labels_body=($( | |
echo "$issue_body_trim" | | |
awk '{ | |
gsub(/ *( *,|\|| -* ?| ?-* | *|--+|\++|\\+|\/|and|&|;|:) */," "); | |
gsub(/^\s+|\s+$|\s+(?=\s)/,""); | |
}1 | |
') | |
) | |
if (( "${#issue_labels_body[@]}" > 0 && "${#issue_labels_body[@]}" < 50 )); then | |
for issue_label in "${issue_labels_body[@]}"; do | |
if [[ "${repository_labels[@]}" =~ "$issue_label" ]] && [[ ! "${repository_labels_invalid[@]}" =~ "$issue_label" ]]; then | |
echo "Valid label detected: $issue_label" | |
labels_to_add+="${issue_label}," | |
else | |
echo "Invalid label detected: $issue_label" | |
issue_labels_invalid_used+=$'\n'" * $issue_label" | |
fi | |
done | |
if [ -z "$issue_labels_invalid_used" ]; then | |
echo 'No invalid labels were used.' | |
else | |
compatibility_report_invalidate "Invalid label(s) provided;$issue_labels_invalid_used" | |
fi | |
else ## Abort if 0 or more than 50 | |
echo 'Too many or not enough labels were detected. Skipping...' | |
fi | |
if [ -n "$labels_to_add" ]; then | |
## Remove trailing comma | |
labels_to_add="${labels_to_add/%,/}" | |
repository_labels_marketplace=(delisted homebrew indie nodownload unlisted unreleased) | |
for repository_marketplace_label in "${repository_labels_marketplace[@]}"; do | |
if [[ "$labels_to_add" =~ "marketplace-$repository_marketplace_label" ]]; then | |
echo "Marketplace link is ${repository_marketplace_label}." | |
fi | |
done | |
issue_labels_state_count=$(echo "$labels_to_add" | grep -o state- | wc -l) | |
if [ $issue_labels_state_count -eq 1 ] && [[ ! "$labels_to_add" =~ 'state-crash-OBSOLETE' ]]; then | |
echo 'State label was provided.' | |
elif [ $issue_labels_state_count -gt 1 ]; then | |
compatibility_report_invalidate 'Multiple state labels were provided.' | |
else | |
compatibility_report_invalidate 'State label is invalid or missing.' | |
fi | |
else | |
compatibility_report_invalidate 'Labels are invalid or missing.' | |
fi | |
issue_body_trim 'Xbox 360 Marketplace link' | |
if [[ "$labels_to_add" =~ 'marketplace' ]] || [[ "$issue_body_trim" =~ https://marketplace.xbox.com/.* ]]; then | |
echo 'Marketplace link and/or label(s) are present.' | |
else | |
compatibility_report_invalidate 'Marketplace link and/or label(s) are invalid or missing.' | |
fi | |
;; | |
issue_comment) | |
if [ "$issue_comment_author_whitelisted" = 'true' ]; then | |
for repository_label in "${repository_labels[@]}"; do | |
if [[ "$issue_comment_body" =~ "$repository_label" ]]; then | |
if [[ ! "${repository_labels_invalid[@]}" =~ "$repository_label" ]]; then | |
echo "Valid label detected: $repository_label" | |
labels_to_add+="${repository_label}," | |
else | |
issue_labels_invalid_used+=$'\n'" * $repository_label" | |
fi | |
fi | |
done | |
if [ -z "$issue_labels_invalid_used" ]; then | |
echo 'No invalid labels were used.' | |
if [ -n "$labels_to_add" ]; then | |
## Remove trailing comma | |
labels_to_add="${labels_to_add/%,/}" | |
issue_labels_state_count=$(echo "$labels_to_add" | grep -o state- | wc -l) | |
if [ $issue_labels_state_count -eq 1 ] && [[ ! "$labels_to_add" =~ 'state-crash-OBSOLETE' ]]; then | |
echo 'State label was provided.' | |
elif [ $issue_labels_state_count -gt 1 ]; then | |
unset labels_to_add ## TODO: Is there a better way of doing this? | |
compatibility_report_invalidate 'Multiple state labels were provided.' | |
fi | |
fi | |
else | |
unset labels_to_add ## TODO: Is there a better way of doing this? | |
compatibility_report_invalidate "Invalid label(s) provided;$issue_labels_invalid_used" | |
fi | |
fi | |
;; | |
pull_request) | |
for repository_label in "${repository_labels[@]}"; do | |
if [[ "$pull_request_body" =~ "$repository_label" ]] && [[ ! "$repository_label" =~ regression|trap ]]; then | |
compatibility_report_invalidate "Compatibility reports can't be pull requests." | |
break | |
fi | |
done | |
;; | |
esac | |
if [ -z "$compatibility_report_invalid_reasons" ]; then | |
echo "$github_event_name_friendly is valid." | |
if [ "$issue_state" = 'closed' ] && [[ "$issue_labels" =~ ${repository_labels_invalid[0]}|${repository_labels_invalid[1]} ]]; then | |
## TODO: Hide (or delete) the close comment if issue is reopened | |
gh issue edit $issue_number --remove-label "${repository_labels_invalid[0]},${repository_labels_invalid[1]}" | |
gh issue reopen $issue_number | |
fi | |
else | |
echo "$github_event_name_friendly is invalid." | |
## Closing "invalid" (i.e. potentially outdated) edited issues is too risky | |
if [ '${{ github.event.action }}' = 'opened' ]; then ## Only comment on 'opened' to prevent duplicate comments | |
if [ "$GITHUB_EVENT_NAME" = 'pull_request' ]; then | |
issue_number="$pull_request_number" | |
issue_author="$pull_request_author" | |
fi | |
gh "${github_event_name_friendly,,}" close $issue_number | |
comment_close_body="@$issue_author your ${github_event_name_friendly,,} was automatically closed because it didn't follow the [issue/report guidelines](https://github.com/xenia-canary/game-compatibility#reportissue-guidelines)." | |
comment_close_body+=$'\n'"Here is what's wrong with your compatibility report:" | |
comment_close_body+="$compatibility_report_invalid_reasons" | |
if [ "$GITHUB_EVENT_NAME" = 'issues' ]; then | |
comment_close_body+=$'\n\n'"**Don't submit a new ${github_event_name_friendly,,}.** Just edit this one and if it's valid it will be automatically reopened." | |
fi | |
comment_close_body+=$'\n\n'"If you want help with Xenia and/or your game go to our Discord server's #help channel: https://discord.gg/Q9mxZf9" | |
gh "${github_event_name_friendly,,}" comment $issue_number -b "$comment_close_body" | |
labels_to_add="${repository_labels_invalid[0]}" | |
if [ -n "$issue_duplicates" ]; then | |
labels_to_add+=",${repository_labels_invalid[1]}" | |
fi | |
fi | |
fi | |
if [ -n "$labels_to_add" ]; then | |
if [ -n "$issue_comment_author_whitelisted" ]; then | |
github_event_name_friendly='Issue' | |
fi | |
gh "${github_event_name_friendly,,}" edit $issue_number --add-label "$labels_to_add" | |
fi |