From 60d21e9c4314d5144c9ebdd4fd851ee5f06b0f0d Mon Sep 17 00:00:00 2001 From: Przemek Rzad Date: Wed, 24 Jul 2024 20:18:58 +0200 Subject: [PATCH] Introduce a workflow updating the wishlist leaderboards (#5085) - Closes https://github.com/paritytech/eng-automation/issues/11 The workflow periodically updates the leaderboards of the wishlist issues: https://github.com/paritytech/polkadot-sdk/issues/3900 and https://github.com/paritytech/polkadot-sdk/issues/3901 The code is adopted from [here](https://github.com/kianenigma/wishlist-tracker), with slight modifications. Previously, the score could be increased by the same person adding different reactions. Also, some wishes have a score of 0 - even thought there is a wish for them, because the author was not counted. Now, the score is a unique count of upvoters of the desired issue, upvoters of the wish comment, and the author of the wish comment. I changed the format to include the `Last updated:` at the bottom - it will be automatically updated. --- .../scripts/update-wishlist-leaderboard.py | 79 +++++++++++++++++++ .../misc-update-wishlist-leaderboard.yml | 36 +++++++++ 2 files changed, 115 insertions(+) create mode 100644 .github/scripts/update-wishlist-leaderboard.py create mode 100644 .github/workflows/misc-update-wishlist-leaderboard.yml diff --git a/.github/scripts/update-wishlist-leaderboard.py b/.github/scripts/update-wishlist-leaderboard.py new file mode 100644 index 000000000000..caa30bec846d --- /dev/null +++ b/.github/scripts/update-wishlist-leaderboard.py @@ -0,0 +1,79 @@ +from github import Github +import re +import os +from datetime import date + +g = Github(os.getenv("GH_TOKEN")) + +# Regex pattern to match wish format: +wish_pattern = re.compile( + r"I wish for:? (https://github\.com/([a-zA-Z0-9_.-]+)/([a-zA-Z0-9_.-]+)/issues/(\d+))" +) + +wishlist_issue = g.get_repo(os.getenv("WISHLIST_REPOSITORY")).get_issue( + int(os.getenv("WISHLIST_ISSUE_NUMBER")) +) +new_leaderboard = ( + "| Feature Request | Summary | Votes | Status |\n| --- | --- | --- | --- |\n" +) +wishes = {} +issue_details = {} + +for comment in wishlist_issue.get_comments(): + # in the comment body, if there is a string `#(\d)`, replace it with + # https://github.com/paritytech/polkadot-sdk/issues/(number) + updated_body = re.sub( + r"#(\d+)", r"https://github.com/paritytech/polkadot-sdk/issues/\1", comment.body + ) + + matches = wish_pattern.findall(updated_body) + for match in matches: + url, org, repo_name, issue_id = match + issue_key = (url, org, repo_name, issue_id) + if issue_key not in wishes: + wishes[issue_key] = [] + + # Get the author and upvoters of the wish comment. + wishes[issue_key].append(comment.user.id) + wishes[issue_key].extend( + [ + reaction.user.id + for reaction in comment.get_reactions() + if reaction.content in ["+1", "heart", "rocket"] + ] + ) + + # Get upvoters of the desired issue. + desired_issue = g.get_repo(f"{org}/{repo_name}").get_issue(int(issue_id)) + wishes[issue_key].extend( + [ + reaction.user.id + for reaction in desired_issue.get_reactions() + if reaction.content in ["+1", "heart", "rocket"] + ] + ) + issue_details[url] = [ + desired_issue.title, + "👾 Open" if desired_issue.state == "open" else "✅Closed", + ] + +# Count unique wishes - the author of the wish, upvoters of the wish, and upvoters of the desired issue. +for key in wishes: + wishes[key] = len(list(set(wishes[key]))) + +# Sort wishes by count and add to the markdown table +sorted_wishes = sorted(wishes.items(), key=lambda x: x[1], reverse=True) +for (url, _, _, _), count in sorted_wishes: + [summary, status] = issue_details.get(url, "No summary available") + new_leaderboard += f"| {url} | {summary} | {count} | {status} |\n" +new_leaderboard += f"\n> Last updated: {date.today().strftime('%Y-%m-%d')}\n" +print(new_leaderboard) + +new_content = re.sub( + r"(\| Feature Request \|)(.*?)(> Last updated:)(.*?\n)", + new_leaderboard, + wishlist_issue.body, + flags=re.DOTALL, +) + +wishlist_issue.edit(body=new_content) diff --git a/.github/workflows/misc-update-wishlist-leaderboard.yml b/.github/workflows/misc-update-wishlist-leaderboard.yml new file mode 100644 index 000000000000..a825c4641124 --- /dev/null +++ b/.github/workflows/misc-update-wishlist-leaderboard.yml @@ -0,0 +1,36 @@ +name: Update wishlist leaderboard + +on: + schedule: + # Run every 3 hours + - cron: '0 */3 * * *' + +permissions: + contents: read + issues: write + +jobs: + update-wishlist-leaderboard: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install PyGithub + - name: Update developer wishlist + env: + GH_TOKEN: ${{ github.token }} + WISHLIST_REPOSITORY: "paritytech/polkadot-sdk" + WISHLIST_ISSUE_NUMBER: "3900" + run: python .github/scripts/update-wishlist-leaderboard.py + - name: Update user wishlist + env: + GH_TOKEN: ${{ github.token }} + WISHLIST_REPOSITORY: "paritytech/polkadot-sdk" + WISHLIST_ISSUE_NUMBER: "3901" + run: python .github/scripts/update-wishlist-leaderboard.py