Skip to content

Add Anime_Cursor

Add Anime_Cursor #1038

Workflow file for this run

# Re-tests a pull request when a maintainer, the PR's author or the GitHub
# account the AppImage comes from comments "/retest" on it, e.g. after a new
# upstream release or a fix to the test.
#
# Like code/retest-prs.sh it closes and reopens the PR, so that the Test
# workflow runs again with the current workflow files from master (re-running
# an old run would reuse the old ones). That needs SCREENSHOT_UPLOAD_TOKEN (a
# personal token): a reopen done with GITHUB_TOKEN starts no workflows. Without
# it, the last Test run of the PR's head is re-run instead.
#
# On a merged PR it opens a new PR instead, which changes only the trailing
# newline of the merged PR's files in data/ (only their first line is read),
# so that Test runs for those entries again. The merged PR then points to the
# new one and is locked, so that further comments go to the new PR; and while a
# re-test of the same merged PR is open, or was started in the last 30 minutes, no
# further PR is opened (re-test PRs merge within minutes, so asking again would
# only repeat the same test).
#
# Nothing from the PR is checked out or run here; only the API is used.
name: Retest
on:
issue_comment:
types: [created]
concurrency:
group: retest-${{ github.event.issue.number }}
cancel-in-progress: false
jobs:
retest:
if: >-
github.repository == 'AppImage/appimage.github.io' &&
github.event.issue.pull_request &&
startsWith(github.event.comment.body, '/retest') &&
github.event.comment.user.type != 'Bot'
runs-on: ubuntu-latest
permissions:
actions: write
contents: read # read data/ files via the API (writes use the personal token)
issues: write
pull-requests: write
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 }}
PR_AUTHOR: ${{ github.event.issue.user.login }}
steps:
# master, never the PR: only for the scripts named below
- uses: actions/checkout@v4
with:
ref: master
sparse-checkout: |
code/upstream-owner.sh
code/repo-url-for-entry.sh
code/fetch-releases.sh
code/find-appimage.sh
sparse-checkout-cone-mode: false
- name: Retest
run: |
react() { gh api -X POST "repos/$REPO/issues/comments/$COMMENT_ID/reactions" -f content="$1" >/dev/null || true ; }
reply() { gh pr comment "$PR" -R "$REPO" --body "$1" ; }
lc() { tr 'A-Z' 'a-z' <<<"$1" ; }
# A merged pull request is finished: lock it, so that further comments
# (e.g. repeated /retest) go to the re-test pull request it points to
lock_old() { gh api -X PUT "repos/$REPO/issues/$PR/lock" -f lock_reason=resolved >/dev/null 2>&1 || true ; }
# Who may: maintainers, the PR's author, and the GitHub account the
# AppImage comes from (auto-discovered PRs are opened by a
# maintainer, so there the upstream author is not the PR's author).
# The URL is read from the PR's data/ files via the API.
ALLOWED=false
case "$ASSOCIATION" in OWNER|MEMBER|COLLABORATOR) ALLOWED=true ;; esac
[ "$(lc "$COMMENTER")" = "$(lc "$PR_AUTHOR")" ] && ALLOWED=true
if [ "$ALLOWED" != true ] ; then
SHA=$(gh api "repos/$REPO/pulls/$PR" --jq .head.sha)
for FILE in $(gh api --paginate "repos/$REPO/pulls/$PR/files" --jq '.[] | select(.filename | startswith("data/")) | select(.status != "removed") | .filename' | 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)
OWNER=$(bash code/upstream-owner.sh "$URL")
[ -n "$OWNER" ] && [ "$(lc "$OWNER")" = "$(lc "$COMMENTER")" ] && ALLOWED=true
done
fi
if [ "$ALLOWED" != true ] ; then
react confused
reply "\`/retest\` can be used by the author of this pull request, by the GitHub account the AppImage comes from, and by maintainers."
exit 0
fi
react eyes
STATE=$(gh api "repos/$REPO/pulls/$PR" --jq .state)
MERGED=$(gh api "repos/$REPO/pulls/$PR" --jq .merged)
if [ "$STATE" != open ] && [ "$MERGED" != true ] ; then
reply "This pull request is closed; reopen it (or open a new one) to test it again."
exit 0
fi
if [ "$MERGED" = true ] ; then
# A merged PR cannot be tested again itself: open a new PR that
# touches its entries in data/ (only the trailing newline changes;
# only the first line is read), so that Test runs for them. With
# the personal token, so that its Test workflow actually starts.
if [ -z "$PAT" ] ; then
reply "Could not re-test: this pull request is merged, and opening a new one to test it needs the \`SCREENSHOT_UPLOAD_TOKEN\` secret. A maintainer can re-test the entry from the Actions tab instead."
exit 1
fi
NAMES=""
for FILE in $(gh api --paginate "repos/$REPO/pulls/$PR/files" --jq '.[] | select(.filename | startswith("data/")) | select(.status != "removed") | .filename' | head -n 5) ; do
N=${FILE#data/}
[[ "$N" =~ ^[A-Za-z0-9_+-][A-Za-z0-9._+-]*$ ]] || continue
gh api "repos/$REPO/contents/data/$N?ref=master" --jq .sha >/dev/null 2>&1 && NAMES="$NAMES $N"
done
NAMES=${NAMES# }
if [ -z "$NAMES" ] ; then
reply "Could not re-test: the entries of this pull request are no longer in \`data/\` on master."
exit 0
fi
# One re-test PR per merged PR at a time: while one is open, or was
# started in the last 30 minutes (they merge within minutes, and a
# new one would test the same thing), point to it instead
EXISTING=$(gh api "repos/$REPO/pulls?state=all&per_page=100" \
--jq ".[] | select(.head.ref | startswith(\"retest/$PR-\")) | select(.state == \"open\" or ((.created_at | fromdateiso8601) > (now - 1800))) | .html_url" | head -n 1)
if [ -n "$EXISTING" ] ; then
reply "A re-test of this pull request's entries was started already: $EXISTING. Please follow it there; asking again right away would only repeat the same test."
lock_old
react rocket
exit 0
fi
BRANCH="retest/$PR-$(date -u +%Y%m%d%H%M%S)"
BASE=$(gh api "repos/$REPO/git/ref/heads/master" --jq .object.sha)
GH_TOKEN="$PAT" gh api -X POST "repos/$REPO/git/refs" -f ref="refs/heads/$BRANCH" -f sha="$BASE" >/dev/null
CHANGES=""
for N in $NAMES ; do
gh api "repos/$REPO/contents/data/$N?ref=master" > file.json
jq -r .content file.json | base64 -d > file.txt
# An entry that points to the AppImage of one particular release
# would test that old release again whatever is published since:
# point it to the repository instead (if its releases have an
# AppImage), so that this and every later test takes the newest.
# Otherwise only toggle the trailing newline.
FIRST=$(head -n 1 file.txt | tr -d '\r')
NEWURL=$(bash code/repo-url-for-entry.sh "$FIRST" "$N" || true)
if [ -n "$NEWURL" ] ; then
{ echo "$NEWURL" ; tail -n +2 file.txt ; } > file.new
mv file.new file.txt
CHANGES="$CHANGES"$'\n\n'"- \`data/$N\` pointed to one particular release (\`$FIRST\`); it now points to the repository (\`$NEWURL\`), so that the newest release is tested."
elif [ "$(tail -c 1 file.txt | od -An -tx1 | tr -d ' ')" = 0a ] ; then
truncate -s -1 file.txt
else
printf '\n' >> file.txt
fi
GH_TOKEN="$PAT" gh api -X PUT "repos/$REPO/contents/data/$N" -f branch="$BRANCH" \
-f message="Re-test $N (requested in #$PR)" -f content="$(base64 -w 0 file.txt)" \
-f sha="$(jq -r .sha file.json)" >/dev/null
done
URL=$(GH_TOKEN="$PAT" gh api -X POST "repos/$REPO/pulls" -f base=master -f head="$BRANCH" \
-f title="Re-test $(echo "$NAMES" | sed 's/ /, /g')" \
-f body="Re-test of \`data/$(echo "$NAMES" | sed 's/ /\`, \`data\//g')\`, requested with \`/retest\` by @$COMMENTER in #$PR, which is merged already.$CHANGES" \
--jq .html_url)
reply "This pull request is merged, so its entries are tested again in a new pull request: $URL. Please follow the test there (comment \`/retest\` there to test again); this conversation is locked now."
lock_old
react rocket
exit 0
fi
if [ -n "$PAT" ] ; then
# Close and reopen: a new Test run with the current workflow files
S=$(GH_TOKEN="$PAT" gh api -X PATCH "repos/$REPO/pulls/$PR" -f state=closed --jq .state || true)
sleep 3
S=$(GH_TOKEN="$PAT" gh api -X PATCH "repos/$REPO/pulls/$PR" -f state=open --jq .state || true)
if [ "$S" == open ] ; then
echo "Closed and reopened #$PR"
react rocket
exit 0
fi
# Never leave the PR closed
gh api -X PATCH "repos/$REPO/pulls/$PR" -f state=open >/dev/null || true
echo "Could not close and reopen #$PR with SCREENSHOT_UPLOAD_TOKEN; re-running the last test instead"
fi
# Fallback: re-run the last Test run of the PR's head (old workflow files)
SHA=$(gh api "repos/$REPO/pulls/$PR" --jq .head.sha)
RUN=$(gh api "repos/$REPO/actions/workflows/test.yml/runs?head_sha=$SHA&event=pull_request&per_page=1" --jq '.workflow_runs[0].id // empty')
if [ -z "$RUN" ] ; then
reply "Could not re-test: there is no test run for the latest commit of this pull request (the test only runs for pull requests that change files in \`data/\`). Pushing a new commit, or closing and reopening the pull request, starts one."
exit 1
fi
gh api -X POST "repos/$REPO/actions/runs/$RUN/rerun" >/dev/null
echo "Re-running run $RUN of #$PR"
react rocket