Snow White in the Mirror Realm [PCSG00787] #1272
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
# this code adapted from https://github.com/xenia-project/game-compatibility/blob/master/.github/workflows/autoclose.yml | |
# Copyright (c) 2015, | |
# All rights reserved. | |
# Redistribution and use in source and binary forms, with or without | |
# modification, are permitted provided that the following conditions are met: | |
# * Redistributions of source code must retain the above copyright notice, this | |
# list of conditions and the following disclaimer. | |
# * Redistributions in binary form must reproduce the above copyright notice, | |
# this list of conditions and the following disclaimer in the documentation | |
# and/or other materials provided with the distribution. | |
# * Neither the name of game-compatibility nor the names of its | |
# contributors may be used to endorse or promote products derived from | |
# this software without specific prior written permission. | |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
# Modifyied for Vita3K | |
# TODO: add check screenshots and log provide. | |
# I don't think pull_request needs auto moderation | |
# Original code contains for pull request but I delete it | |
name: Compatibility bot | |
on: | |
issues: | |
types: [opened, edited] | |
issue_comment: | |
types: created #, edited] | |
jobs: | |
automoderation: | |
runs-on: ubuntu-latest | |
if: github.repository == 'Vita3K/compatibility' | |
steps: | |
- uses: actions/checkout@v4 | |
- name: checking an issue | |
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 }} | |
run: | | |
case $GITHUB_EVENT_NAME in | |
issues) | |
github_event_name_friendly=issue | |
## can be make this better? | |
issue_body_trim1() { | |
issue_body_trim1=$(echo "$issue_body" | grep -i "$1") | |
} | |
issue_body_trim2() { | |
issue_body_trim2=$(echo "$issue_body" | grep -i "$1" -A 10) | |
};; | |
issue_comment) | |
issue_comment_body_trim() { | |
issue_comment_body_trim=$(echo "$issue_comment_body" | grep -i "$1" -A 10) | |
} | |
issue_comment_author_whitelist=(Zangetsu38 othmanead nishinji Macdu illusionMan1212 EXtremeExploit GamingDucking Croden1999 saturnsky tasle1001 spacemul gymzatan) | |
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=1 | |
break | |
fi | |
done | |
github_event_name_friendly='issue comment';; | |
esac | |
compatibility_report_invalidate() { | |
echo "$1" | |
compatibility_report_invalid_reasons+=$'\n'" * $1" | |
} | |
if [ $GITHUB_EVENT_NAME != issue_comment ]; then | |
# Check issue title | |
if [[ "$issue_title" =~ ^(.+ \[PCS[A-Z]{1}[0-9]{5}\]|.+ \[NPXS10007\])$ ]]; 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: "Vita3K", name: "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 | |
elif [ $GITHUB_EVENT_NAME = issues ]; then | |
compatibility_report_invalidate 'Title is invalid.' | |
fi | |
if [ $GITHUB_EVENT_NAME = issues ]; then | |
# Check Vita3K version | |
if [[ "${issue_body,,}" =~ "commit hash" ]]; then | |
issue_body_trim1 'Commit hash' | |
if [[ "$issue_body_trim1" =~ (.+ https://github.com/vita3k/vita3k/commit/[0-9a-f]{5,40}) ]]; then | |
echo 'Commit hash is valid.' | |
else | |
compatibility_report_invalidate 'Commit hash is invalid or missing.' | |
fi | |
else | |
compatibility_report_invalidate "Issue doesn't follow the template. (Commit hash)" | |
fi | |
# Check Android issue | |
if [[ "${issue_body,,}" =~ "os" ]]; then | |
issue_body_trim1 'OS' | |
if [[ "$issue_body_trim1" =~ (.+ Android) ]]; then | |
compatibility_report_invalidate 'Android issue detected.' | |
else | |
echo 'Android is not detected' | |
fi | |
else | |
compatibility_report_invalidate "Issue doesn't follow the template. (OS)" | |
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: "Vita3K", name: "compatibility") { | |
labels(first:100, after:$endCursor) { | |
nodes { | |
name | |
} | |
pageInfo { | |
hasNextPage | |
endCursor | |
} | |
} | |
} | |
} | |
') | |
repository_labels_invalid=("invalid issue" "duplicate issue" ) | |
case $GITHUB_EVENT_NAME in | |
issues) | |
if [[ "${issue_body,,}" =~ "recommended labels" ]]; then | |
issue_body_trim2 'Recommended labels' | |
issue_labels_body=$(echo "$issue_body_trim2" | sed '/# Recommended labels/d'| sed '/<!--[^>]*-->/d') | |
for repository_label in "${repository_labels[@]}"; do | |
if [[ "${issue_labels_body,,}" =~ "${repository_label,,}" ]]; then | |
echo "Valid label detected: $repository_label" | |
labels_to_add+=("$repository_label") | |
fi | |
done | |
if [ -n "$labels_to_add" ]; then | |
status_label_list=("Nothing" "Bootable" "Intro" "Menu" "Ingame -" "Ingame +" "Playable") | |
issue_labels_state_count=0 | |
for status_labels in "${status_label_list[@]}"; do | |
for adding_labels in "${labels_to_add[@]}"; do | |
if [[ "$status_labels" == "$adding_labels" ]]; then | |
issue_labels_state_count=$((issue_labels_state_count + 1)) | |
fi | |
done | |
done | |
echo "Status label count: $issue_labels_state_count" | |
if [[ $issue_labels_state_count -eq 1 ]]; 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 | |
else | |
compatibility_report_invalidate "Issue doesn't follow the template. (Recommended labels)" | |
fi;; | |
# code for comment | |
issue_comment) | |
if [ -n "$issue_comment_author_whitelisted" ]; then | |
if [[ "${issue_comment_body,,}" =~ "recommended labels" ]]; then | |
issue_comment_body_trim 'Recommended labels' | |
issue_comment_labels_body=$(echo "${issue_comment_body_trim,,}" | sed '/# recommended labels/d' | sed '/<!--[^>]*-->/d') | |
echo "issue comment labels body: $issue_comment_labels_body" | |
for repository_label in "${repository_labels[@]}"; do | |
if [[ "${issue_comment_labels_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 | |
else | |
echo "Issue comment didn't suggest any label." | |
fi | |
if [ -z "$issue_labels_invalid_used" ]; then | |
echo 'No invalid labels were used.' | |
if [ -n "$labels_to_add" ]; then | |
status_label_list=("Nothing" "Bootable" "Intro" "Menu" "Ingame -" "Ingame +" "Playable") | |
issue_labels_state_count=0 | |
for status_labels in "${status_label_list[@]}"; do | |
for adding_labels in "${labels_to_add[@]}"; do | |
if [[ "$status_labels" == "$adding_labels" ]]; then | |
issue_labels_state_count=$((issue_labels_state_count + 1)) | |
fi | |
done | |
done | |
echo "Status label count: $issue_labels_state_count" | |
if [[ $issue_labels_state_count -eq 1 ]]; then | |
echo 'State label was provided. Removing old labels' | |
echo "Removing label(s): ${issue_labels[@]}" | |
for removing_labels in "${issue_labels[@]}"; do | |
gh issue edit $issue_number --remove-label "${removing_labels}" | |
done | |
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.' | |
else | |
echo 'State label is missing.' | |
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;; | |
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]} && $GITHUB_EVENT_NAME != issue_comment ]]; then ## Don't reopen by issue comment | |
## 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 | |
unset labels_to_add ## TODO: Is there a better way of doing this? | |
echo "$github_event_name_friendly is invalid." | |
## Closing "invalid" (i.e. potentially outdated) edited issues is too risky | |
if [[ ${{ github.event.action }} = opened && $GITHUB_EVENT_NAME != issue_comment ]]; then ## Only comment on 'opened' to prevent duplicate comments | |
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 templates." | |
comment_close_body+=$'\n'"Here is what's wrong with your compatibility report:" | |
comment_close_body+="$compatibility_report_invalid_reasons" | |
comment_close_body+=$'\n\n'"**Don't submit a new issue.** Just edit this one and if it's valid it will be automatically reopened." | |
comment_close_body+=$'\n\n'"If you want help with Vita3K and/or your game go to our Discord server's #help channel: https://discord.gg/6aGwQzh" | |
gh "${github_event_name_friendly,,}" comment $issue_number -b "$comment_close_body" | |
if [ -n "$issue_duplicates" ]; then | |
labels_to_add="${repository_labels_invalid[1]}" | |
else | |
labels_to_add="${repository_labels_invalid[0]}" | |
fi | |
fi | |
fi | |
if [ -n "$labels_to_add" ]; then | |
echo "Adding label(s): ${labels_to_add[@]}" | |
for adding_labels in "${labels_to_add[@]}"; do | |
## + and - are special characters in bash, so we need to escape them | |
if [[ "$adding_labels" =~ "Ingame -" ]]; then | |
gh issue edit $issue_number --add-label 'Ingame -' | |
elif [[ "$adding_labels" =~ "Ingame +" ]]; then | |
gh issue edit $issue_number --add-label 'Ingame +' | |
else | |
gh issue edit $issue_number --add-label "${adding_labels}" | |
fi | |
done | |
fi |