Add IRC_client #933
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
| # Re-tests a pull request whose test failed, without anyone having to type | |
| # "/retest": when a maintainer, the PR's author, or the GitHub account the | |
| # AppImage comes from says in a comment that the problem is fixed or asks | |
| # for a re-test | |
| # ("v1.2 is out", "fixed in 1.2", "could you re-run the test?"; see | |
| # code/retest-comment.sh), and the PR's latest test did not pass cleanly | |
| # (an error-* label, or no screenshot-ok). Reacts 🚀 to the comment. | |
| # | |
| # It closes and reopens the PR with code/retest-pr.sh, using | |
| # SCREENSHOT_UPLOAD_TOKEN (a reopen with GITHUB_TOKEN starts no workflows), | |
| # and skips PRs whose Test run for the current commit started in the last | |
| # 15 minutes. "/retest" (retest.yml) remains for explicit requests. A comment | |
| # asking how to test again (code/retest-question.sh) is answered once per PR. | |
| # | |
| # Nothing from the PR is checked out or run here: this runs from master and | |
| # reads the PR's files as text via the API. The comment is untrusted text: it | |
| # is passed via the environment and only matched against fixed patterns. | |
| name: Auto retest | |
| on: | |
| issue_comment: | |
| types: [created] | |
| jobs: | |
| comment: | |
| if: >- | |
| github.repository == 'AppImage/appimage.github.io' && | |
| github.event_name == 'issue_comment' && | |
| github.event.issue.pull_request && | |
| github.event.issue.state == 'open' && | |
| !startsWith(github.event.comment.body, '/') && | |
| github.event.comment.user.type != 'Bot' && | |
| !endsWith(github.event.comment.user.login, '[bot]') | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| concurrency: | |
| group: auto-retest-pr-${{ github.event.issue.number }} | |
| cancel-in-progress: false | |
| permissions: | |
| actions: read # find the latest Test run | |
| contents: read # read the PR's data/ file via the API | |
| issues: write # react to the comment, answer a "how do I re-test?" question | |
| pull-requests: write # reopen with GITHUB_TOKEN should the PAT fail | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| PAT: ${{ secrets.SCREENSHOT_UPLOAD_TOKEN }} | |
| REPO: ${{ github.repository }} | |
| PR: ${{ github.event.issue.number }} | |
| COMMENT_ID: ${{ github.event.comment.id }} | |
| COMMENTER: ${{ github.event.comment.user.login }} | |
| ASSOCIATION: ${{ github.event.comment.author_association }} | |
| BODY: ${{ github.event.comment.body }} | |
| steps: | |
| # master, not the PR | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| sparse-checkout: code | |
| - name: Re-test if the comment says it is fixed | |
| run: | | |
| if ! PHRASE=$(printf '%s\n' "$BODY" | bash code/retest-comment.sh) ; then | |
| echo "The comment does not ask for a re-test." | |
| # A question about HOW to test again gets the answer, once per PR | |
| # (to anyone: the answer changes nothing, it only names the command) | |
| if printf '%s\n' "$BODY" | bash code/retest-question.sh ; then | |
| MARKER='<!-- appimagehub-retest-howto -->' | |
| if gh api --paginate "repos/$REPO/issues/$PR/comments" --jq '.[].body' | grep -qF "$MARKER" ; then | |
| echo "Answered already." | |
| else | |
| { | |
| echo "$MARKER" | |
| echo 'To test this pull request again, comment `/retest` on it. It is also tested again automatically when you comment that a fix or a new release is out (e.g. "v1.2 is out, fixed in v1.2"). The author of the pull request, the GitHub account the AppImage comes from and maintainers can do either.' | |
| } > howto.md | |
| gh pr comment "$PR" -R "$REPO" --body-file howto.md | |
| fi | |
| fi | |
| exit 0 | |
| fi | |
| echo "The comment says: \"$PHRASE\"" | |
| INFO=$(gh api "repos/$REPO/pulls/$PR") | |
| AUTHOR=$(echo "$INFO" | jq -r .user.login) | |
| SHA=$(echo "$INFO" | jq -r .head.sha) | |
| LABELS=$(echo "$INFO" | jq -r '.labels[].name') | |
| if echo "$LABELS" | grep -qx screenshot-ok && ! echo "$LABELS" | grep -q '^error-' ; then | |
| echo "The latest test passed (screenshot-ok); nothing to do." | |
| exit 0 | |
| fi | |
| # The PR's data/ files; the test runs only for PRs that change some | |
| FILES=$(gh api --paginate "repos/$REPO/pulls/$PR/files" \ | |
| --jq '.[] | select(.filename | startswith("data/")) | select(.status != "removed") | .filename') | |
| if [ -z "$FILES" ] ; then | |
| echo "The pull request changes no file in data/; the test does not run for it." | |
| exit 0 | |
| fi | |
| lower() { echo "$1" | tr '[:upper:]' '[:lower:]' ; } | |
| WHO="" | |
| case "$ASSOCIATION" in OWNER|MEMBER|COLLABORATOR) WHO="a maintainer" ;; esac | |
| if [ -n "$WHO" ] ; then | |
| : | |
| elif [ "$(lower "$COMMENTER")" == "$(lower "$AUTHOR")" ] ; then | |
| WHO="the pull request's author" | |
| else | |
| # The GitHub account the AppImage comes from, from the first line | |
| # of the PR's data/ files at its head commit (text via the API) | |
| for FILE in $(echo "$FILES" | head -n 5) ; do | |
| URL=$(gh api -H "Accept: application/vnd.github.raw" "repos/$REPO/contents/$FILE?ref=$SHA" 2>/dev/null | head -n 1 || true) | |
| OWNER=$(bash code/upstream-owner.sh "$URL") | |
| if [ -n "$OWNER" ] && [ "$(lower "$OWNER")" == "$(lower "$COMMENTER")" ] ; then | |
| WHO="the account the AppImage comes from" | |
| fi | |
| done | |
| fi | |
| if [ -z "$WHO" ] ; then | |
| echo "$COMMENTER is neither a maintainer, nor the author of the pull request, nor the account the AppImage comes from." | |
| exit 0 | |
| fi | |
| echo "$COMMENTER is $WHO." | |
| RC=0 | |
| bash code/retest-pr.sh "$PR" || RC=$? | |
| case "$RC" in | |
| 0) gh api -X POST "repos/$REPO/issues/comments/$COMMENT_ID/reactions" -f content=rocket >/dev/null || true ;; | |
| 3) ;; # skipped (see the log), e.g. a test is running already | |
| *) exit 1 ;; | |
| esac | |