From d8ac9a1bedb4adf9eabba790288b96b37d4af3de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Thiberg?= Date: Wed, 11 Sep 2024 20:33:11 +0200 Subject: [PATCH 01/12] feat: add lecture participation tracker using GitHub Actions --- .github/workflows/lecture_participation.yml | 36 +++ contributions/open-source/bthiberg/README.md | 53 +++++ tools/README.md | 25 +++ tools/track_participation.py | 224 +++++++++++++++++++ 4 files changed, 338 insertions(+) create mode 100644 .github/workflows/lecture_participation.yml create mode 100644 contributions/open-source/bthiberg/README.md create mode 100644 tools/track_participation.py diff --git a/.github/workflows/lecture_participation.yml b/.github/workflows/lecture_participation.yml new file mode 100644 index 0000000000..353dc2c9e4 --- /dev/null +++ b/.github/workflows/lecture_participation.yml @@ -0,0 +1,36 @@ +name: Lecture Participation Information + +on: + issue_comment: + types: [created] + +permissions: + issues: write + +jobs: + track-participation: + if: github.event.issue.title == 'Lecture participation tracker 2024' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Setup Python + uses: actions/setup-python@v2.2.1 + with: + python-version: '3.x' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + if [ -f ./tools/requirements.txt ]; then pip install -r ./tools/requirements.txt; fi + + - name: Set timezone to Europe/Stockholm + run: sudo timedatectl set-timezone Europe/Stockholm + + - name: Update participation tracker + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + REPO_FULLNAME: ${{ github.repository }} + TRACKER_ISSUE_NUMBER: ${{ github.event.issue.number }} + + run: python ./tools/track_participation.py --printMarkdown --publish diff --git a/contributions/open-source/bthiberg/README.md b/contributions/open-source/bthiberg/README.md new file mode 100644 index 0000000000..dcd523c65d --- /dev/null +++ b/contributions/open-source/bthiberg/README.md @@ -0,0 +1,53 @@ +# Assignment Proposal + +## Title + +CI job for live counting active participation + +## Names and KTH ID + +- Björn Thiberg (bthiberg@kth.se) + +## Deadline + +- Deadline 1 + +## Category + +- Open source + +## Description + +This document is 1. a task proposal for introducing a script and a GitHub Actions workflow to track lecture participation, and 2. the description of the PR which implementatis this. Very meta. + +The structure of both script and workflow YAML file is based on the already existing workflow for updating the Statistics of Student Registrations. It has a similar structure, can be run locally in the same way, and uses the same dependencies. + +How it's supposed to work: + +GitHub actions workflow +- The workflow is triggered on new issue comments, and proceeds if the issue title is “Lecture participation tracker 2024”. +- track_participation.py is run + +Python script (`track_participation.py`): +- Fetches all comments to the issue from the GitHub API +- If the author is a collaborator, or the comment is outside the commenting window (5 hours from the start of each lecture), the comment is ignored. +- Valid comments are stored in a dictionary, with keys for each student who has commented. +- The script generates a markdown table, similar to the one for tracking tasks, which displays the lectures each student has attended. +- The issue description is updated with this markdown table and a timestamp. + +I have tested that (in a copy of the repo): +- the workflow triggers correctly when a new comment is added to the tracker. +- comments made by collaborators are ignored as expected. +- comments made outside of the allowed window are not counted. +- valid comments update the participation tracker in the issue. +- timezones work as expected (don't quote me on this) + +I have not tested for more than two unique students/commenters, as would be the case in "production". + +Updating for newer years should only require changing the lecture dates constant in the Python code and the issue title in the YAML file. + +Closes #2459 + +**Relevance** + +This contribution sets up a CI job for a repository for a course in DevOps. diff --git a/tools/README.md b/tools/README.md index d5092d656d..a17f0797d2 100644 --- a/tools/README.md +++ b/tools/README.md @@ -58,3 +58,28 @@ This script is used to grade each student according to the number of task comple ### Usage ... + + +## track_participation.py + +Script used to track and display valid comments on lecture participation issue. + +### Requirements + +- Python 3 +- External modules + - PTable + - PyGithub + +### Usage +`python3 track_participation.py ----printPlain` + +`python3 track_participation.py ----printMarkdown --publish` + +| Option | Usage | Required | +|---|---|---| +|--printPlain| Print participation stats in plaintext | :x:| +|--printMarkdown| Print participation stats in markdown |:x:| +|--publish| Update the participation tracker issue |:x:| +|--help | Displays help info |:x:| + diff --git a/tools/track_participation.py b/tools/track_participation.py new file mode 100644 index 0000000000..b0c7eefcc2 --- /dev/null +++ b/tools/track_participation.py @@ -0,0 +1,224 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +# Filename: track_participation.py + +import sys +import os +import logging +from github import Github, GithubException +import getopt +from datetime import datetime, timedelta +from prettytable import PrettyTable + +PRINT_PARTICIPATION = False +PRINT_IN_MARKDOWN = False +PUBLISH = False + +GITHUB_TOKEN = os.getenv("GITHUB_TOKEN") +REPO_FULLNAME = os.getenv("REPO_FULLNAME") +ISSUE_NUMBER = os.getenv("TRACKER_ISSUE_NUMBER") + +# Lecture details +LECTURE_DATES_TO_NUMBER = { + "2024-09-04": 2, "2024-09-11": 3, "2024-09-18": 4, "2024-09-25": 5, + "2024-10-02": 6, "2024-10-09": 7 +} + +LECTURE_DATES_TO_START_TIME = { + "2024-09-04": 13, "2024-09-11": 13, "2024-09-18": 13, "2024-09-25": 13, + "2024-10-02": 13, "2024-10-09": 13 +} + +COMMENTING_DURATION_HOURS = 5 # 5 hours to give some leeway. + + +def main(): + handle_args(sys.argv[1:]) + + repo, issue = get_repo_and_issue() + + participation = get_participation(issue) + + print_content = "" + + if PRINT_PARTICIPATION: + print_content = get_participation_text(participation) + + if PRINT_IN_MARKDOWN: + print_content = get_participation_markdown(participation) + + if PUBLISH: + update_issue_description(participation, issue) + print("Updated issue description\n") + + print(print_content) + + +def get_repo_and_issue(): + """ + Attempts to fetch the GitHub repository and issue using environment variables. + Exits on failure. + """ + try: + github = Github(GITHUB_TOKEN) + repo = github.get_repo(REPO_FULLNAME) + issue = repo.get_issue(number=int(ISSUE_NUMBER)) + return repo, issue + except GithubException as e: + logging.error(f"GitHub API error: {str(e)}") + sys.exit(1) + + +def get_participation(tracking_issue): + """ + Gets participation by checking each comment on the tracker issue. + Adds the lecture to the comment author if comment exists. Except if: + comment is from collaborator + comment is made outside of allowed time. + """ + participation = {} + + try: + collaborators = {collaborator.login for collaborator in tracking_issue.repository.get_collaborators()} + except GithubException as e: + logging.error(f"GitHub API error: {str(e)}") + sys.exit(1) + + for comment in tracking_issue.get_comments(): + author = comment.user.login + comment_time = comment.created_at.astimezone() + + # Ignore collaborators' comments + if author in collaborators: + continue + + if is_valid_lecture_time(comment_time): + lecture_date = comment_time.strftime("%Y-%m-%d") + if author not in participation: + participation[author] = {lecture_date} + else: + participation[author].add(lecture_date) + + return participation + + +def is_valid_lecture_time(comment_time): + """ + Checks if the comment was made on a valid day and time. + """ + lecture_date_str = comment_time.strftime("%Y-%m-%d") + + if lecture_date_str not in LECTURE_DATES_TO_START_TIME: + # comment not made on a lecture day + return False + + lecture_start_hour = LECTURE_DATES_TO_START_TIME[lecture_date_str] + + allowed_period_start = comment_time.replace(hour=lecture_start_hour, minute=0, second=0, microsecond=0) + allowed_period_end = allowed_period_start + timedelta(hours=COMMENTING_DURATION_HOURS) + + # Check if the comment time falls within the valid window + return allowed_period_start <= comment_time <= allowed_period_end + + +def update_issue_description(participation, issue): + """ + Updates the repository issue description in markdown to reflect new participation. + """ + content = get_participation_markdown(participation) + try: + issue.edit(body=content) + except GithubException as e: + logging.error(f"GitHub API error: {str(e)}") + sys.exit(1) + + +def get_participation_markdown(participation): + """ + Returns markdown table representation of participation. + """ + current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + content = f"Here we track active participation in lectures.\n\n" + content += ("To do this, you record as a comment the question you make to presentations or demos during the " + "lectures.\n\n") + content += "Also, provide the title of the presentation/demo.\n\n" + content += f"### Lecture Participation Stats (Updated on {current_time})\n\n" + content += "| Index | Student Name | Number of Lectures Attended | Lecture(s) attended |\n" + content += "|-------|--------------|-------------------|----------------|\n" + + index = 1 + for author, lectures in participation.items(): + lecture_numbers = [f"L{LECTURE_DATES_TO_NUMBER[lecture]}" for lecture in sorted(lectures)] + lectures_list = " ".join(map(str, lecture_numbers)) + total_lectures = len(lectures) + content += f"| {index} | {author} | {total_lectures} | {lectures_list} |\n" + index += 1 + + return content + + +def get_participation_text(participation): + """ + Returns plaintext table representation of participation. + """ + current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + table = PrettyTable() + table.field_names = ["Index", "Student Name", "Number of Lectures Attended", "Lecture(s) attended"] + + index = 1 + for author, lectures in participation.items(): + lecture_numbers = [f"L{LECTURE_DATES_TO_NUMBER[lecture]}" for lecture in sorted(lectures)] + lectures_list = " ".join(map(str, lecture_numbers)) + total_lectures = len(lectures) + table.add_row([index, author, total_lectures, lectures_list]) + index += 1 + + return_str = f"Lecture Participation Stats (Updated on {current_time})\n\n" + return_str += table.get_string() + + return return_str + + +def handle_args(argv): + global PRINT_PARTICIPATION + global PRINT_IN_MARKDOWN + global PUBLISH + + try: + opts, args = getopt.getopt(argv, "hm", ["help", "printPlain", "printMarkdown", "publish"]) + except getopt.GetoptError as error: + logging.error(error) + print_help_info() + sys.exit(2) + + for opt, _ in opts: + if opt == "--help": + print_help_info() + sys.exit() + elif opt == "--printPlain": + PRINT_PARTICIPATION = True + elif opt == "--printMarkdown": + PRINT_IN_MARKDOWN = True + elif opt == "--publish": + PUBLISH = True + + +def print_help_info(): + print('') + print('DD2482 Student Lecture Participation Tracker Tool') + print('optional:') + print(' --printPlain Print lecture participation') + print(' --printMarkdown Print participation in markdown syntax') + print(' --publish Update the participation tracker issue') + print('') + print('track_participation.py --help to display this help info') + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + if not GITHUB_TOKEN or not REPO_FULLNAME or not ISSUE_NUMBER: + logging.error("Required environment variables (GITHUB_TOKEN, REPO_FULLNAME, ISSUE_NUMBER) are missing") + sys.exit(1) + main() From a0a9a869139e15c471e32f3e67f447ebf129e1cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Thiberg?= Date: Thu, 12 Sep 2024 16:23:09 +0200 Subject: [PATCH 02/12] use issue number instead of title --- .github/workflows/lecture_participation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lecture_participation.yml b/.github/workflows/lecture_participation.yml index 353dc2c9e4..1a7ed178b2 100644 --- a/.github/workflows/lecture_participation.yml +++ b/.github/workflows/lecture_participation.yml @@ -9,7 +9,7 @@ permissions: jobs: track-participation: - if: github.event.issue.title == 'Lecture participation tracker 2024' + if: github.event.issue.number == 2370 runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 From ab6b4e5231f6e237a1d2f2b9722bafb868bddb3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Thiberg?= Date: Thu, 12 Sep 2024 16:30:25 +0200 Subject: [PATCH 03/12] use newest versions of checkout and setup-python, pin python 3.11.8 --- .github/workflows/lecture_participation.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/lecture_participation.yml b/.github/workflows/lecture_participation.yml index 1a7ed178b2..7816951a6d 100644 --- a/.github/workflows/lecture_participation.yml +++ b/.github/workflows/lecture_participation.yml @@ -12,12 +12,12 @@ jobs: if: github.event.issue.number == 2370 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup Python - uses: actions/setup-python@v2.2.1 + uses: actions/setup-python@v5.2.0 with: - python-version: '3.x' + python-version: '3.11.8' - name: Install dependencies run: | From e8d30790c9ff1299a31ba53017b2a8b4b47b3ac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Thiberg?= Date: Thu, 12 Sep 2024 16:46:24 +0200 Subject: [PATCH 04/12] set timezone in script instead of workflow file --- .github/workflows/lecture_participation.yml | 3 --- tools/track_participation.py | 5 ++++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/lecture_participation.yml b/.github/workflows/lecture_participation.yml index 7816951a6d..d91d5c392a 100644 --- a/.github/workflows/lecture_participation.yml +++ b/.github/workflows/lecture_participation.yml @@ -24,9 +24,6 @@ jobs: python -m pip install --upgrade pip if [ -f ./tools/requirements.txt ]; then pip install -r ./tools/requirements.txt; fi - - name: Set timezone to Europe/Stockholm - run: sudo timedatectl set-timezone Europe/Stockholm - - name: Update participation tracker env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/tools/track_participation.py b/tools/track_participation.py index b0c7eefcc2..2cb6437f64 100644 --- a/tools/track_participation.py +++ b/tools/track_participation.py @@ -8,6 +8,7 @@ from github import Github, GithubException import getopt from datetime import datetime, timedelta +from zoneinfo import ZoneInfo from prettytable import PrettyTable PRINT_PARTICIPATION = False @@ -31,6 +32,8 @@ COMMENTING_DURATION_HOURS = 5 # 5 hours to give some leeway. +LECTURE_TIMEZONE = ZoneInfo("Europe/Stockholm") + def main(): handle_args(sys.argv[1:]) @@ -86,7 +89,7 @@ def get_participation(tracking_issue): for comment in tracking_issue.get_comments(): author = comment.user.login - comment_time = comment.created_at.astimezone() + comment_time = comment.created_at.astimezone(LECTURE_TIMEZONE) # Ignore collaborators' comments if author in collaborators: From a78f9314cdd739bbb5dc01f2ec82ac2bc249e6a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Thiberg?= Date: Thu, 12 Sep 2024 16:55:35 +0200 Subject: [PATCH 05/12] make default behavior be print in plaintext --- tools/README.md | 8 ++++++-- tools/track_participation.py | 13 ++++--------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/tools/README.md b/tools/README.md index a17f0797d2..f2e9b6cc1b 100644 --- a/tools/README.md +++ b/tools/README.md @@ -72,13 +72,17 @@ Script used to track and display valid comments on lecture participation issue. - PyGithub ### Usage -`python3 track_participation.py ----printPlain` + +Print the lecture participation in plaintext: + +`python3 track_participation.py` + +Print in markdown and update the issue: `python3 track_participation.py ----printMarkdown --publish` | Option | Usage | Required | |---|---|---| -|--printPlain| Print participation stats in plaintext | :x:| |--printMarkdown| Print participation stats in markdown |:x:| |--publish| Update the participation tracker issue |:x:| |--help | Displays help info |:x:| diff --git a/tools/track_participation.py b/tools/track_participation.py index 2cb6437f64..f1a3ee44a6 100644 --- a/tools/track_participation.py +++ b/tools/track_participation.py @@ -11,7 +11,6 @@ from zoneinfo import ZoneInfo from prettytable import PrettyTable -PRINT_PARTICIPATION = False PRINT_IN_MARKDOWN = False PUBLISH = False @@ -44,11 +43,10 @@ def main(): print_content = "" - if PRINT_PARTICIPATION: - print_content = get_participation_text(participation) - if PRINT_IN_MARKDOWN: print_content = get_participation_markdown(participation) + else: + print_content = get_participation_text(participation) if PUBLISH: update_issue_description(participation, issue) @@ -185,12 +183,11 @@ def get_participation_text(participation): def handle_args(argv): - global PRINT_PARTICIPATION global PRINT_IN_MARKDOWN global PUBLISH try: - opts, args = getopt.getopt(argv, "hm", ["help", "printPlain", "printMarkdown", "publish"]) + opts, args = getopt.getopt(argv, "hm", ["help", "printMarkdown", "publish"]) except getopt.GetoptError as error: logging.error(error) print_help_info() @@ -200,8 +197,6 @@ def handle_args(argv): if opt == "--help": print_help_info() sys.exit() - elif opt == "--printPlain": - PRINT_PARTICIPATION = True elif opt == "--printMarkdown": PRINT_IN_MARKDOWN = True elif opt == "--publish": @@ -211,8 +206,8 @@ def handle_args(argv): def print_help_info(): print('') print('DD2482 Student Lecture Participation Tracker Tool') + print('') print('optional:') - print(' --printPlain Print lecture participation') print(' --printMarkdown Print participation in markdown syntax') print(' --publish Update the participation tracker issue') print('') From 46064c3c713ed2114823ddbba627d75eaa9f3d56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Thiberg?= Date: Thu, 12 Sep 2024 17:14:12 +0200 Subject: [PATCH 06/12] Move configuration to external JSON file --- tools/track_participation.py | 19 ++++++------------- tools/track_participation_config.json | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 13 deletions(-) create mode 100644 tools/track_participation_config.json diff --git a/tools/track_participation.py b/tools/track_participation.py index f1a3ee44a6..f625cf2a3a 100644 --- a/tools/track_participation.py +++ b/tools/track_participation.py @@ -5,6 +5,7 @@ import sys import os import logging +import json from github import Github, GithubException import getopt from datetime import datetime, timedelta @@ -18,20 +19,12 @@ REPO_FULLNAME = os.getenv("REPO_FULLNAME") ISSUE_NUMBER = os.getenv("TRACKER_ISSUE_NUMBER") -# Lecture details -LECTURE_DATES_TO_NUMBER = { - "2024-09-04": 2, "2024-09-11": 3, "2024-09-18": 4, "2024-09-25": 5, - "2024-10-02": 6, "2024-10-09": 7 -} +config = json.load(open("track_participation_config.json")) -LECTURE_DATES_TO_START_TIME = { - "2024-09-04": 13, "2024-09-11": 13, "2024-09-18": 13, "2024-09-25": 13, - "2024-10-02": 13, "2024-10-09": 13 -} - -COMMENTING_DURATION_HOURS = 5 # 5 hours to give some leeway. - -LECTURE_TIMEZONE = ZoneInfo("Europe/Stockholm") +LECTURE_DATES_TO_NUMBER = config['LECTURE_DATES_TO_NUMBER'] +LECTURE_DATES_TO_START_TIME = config['LECTURE_DATES_TO_START_TIME'] +COMMENTING_DURATION_HOURS = config['COMMENTING_DURATION_HOURS'] +LECTURE_TIMEZONE = ZoneInfo(config['LECTURE_TIMEZONE']) def main(): diff --git a/tools/track_participation_config.json b/tools/track_participation_config.json new file mode 100644 index 0000000000..24722b026b --- /dev/null +++ b/tools/track_participation_config.json @@ -0,0 +1,20 @@ +{ + "LECTURE_DATES_TO_NUMBER": { + "2024-09-04": 2, + "2024-09-11": 3, + "2024-09-18": 4, + "2024-09-25": 5, + "2024-10-02": 6, + "2024-10-09": 7 + }, + "LECTURE_DATES_TO_START_TIME": { + "2024-09-04": 13, + "2024-09-11": 13, + "2024-09-18": 13, + "2024-09-25": 13, + "2024-10-02": 13, + "2024-10-09": 13 + }, + "COMMENTING_DURATION_HOURS": 5, + "LECTURE_TIMEZONE": "Europe/Stockholm" +} From 79ef6a48c549010d5492090b88e77c60057c13bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Thiberg?= Date: Thu, 12 Sep 2024 17:25:49 +0200 Subject: [PATCH 07/12] fix: use correct file path for config --- tools/track_participation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/track_participation.py b/tools/track_participation.py index f625cf2a3a..2e0713a16f 100644 --- a/tools/track_participation.py +++ b/tools/track_participation.py @@ -19,7 +19,7 @@ REPO_FULLNAME = os.getenv("REPO_FULLNAME") ISSUE_NUMBER = os.getenv("TRACKER_ISSUE_NUMBER") -config = json.load(open("track_participation_config.json")) +config = json.load(open("tools/track_participation_config.json")) LECTURE_DATES_TO_NUMBER = config['LECTURE_DATES_TO_NUMBER'] LECTURE_DATES_TO_START_TIME = config['LECTURE_DATES_TO_START_TIME'] From dcdb3fdcb848fa1997bdefb4ce9915c4814995e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Thiberg?= Date: Thu, 12 Sep 2024 23:15:40 +0200 Subject: [PATCH 08/12] remove task proposal --- contributions/open-source/bthiberg/README.md | 53 -------------------- 1 file changed, 53 deletions(-) delete mode 100644 contributions/open-source/bthiberg/README.md diff --git a/contributions/open-source/bthiberg/README.md b/contributions/open-source/bthiberg/README.md deleted file mode 100644 index dcd523c65d..0000000000 --- a/contributions/open-source/bthiberg/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# Assignment Proposal - -## Title - -CI job for live counting active participation - -## Names and KTH ID - -- Björn Thiberg (bthiberg@kth.se) - -## Deadline - -- Deadline 1 - -## Category - -- Open source - -## Description - -This document is 1. a task proposal for introducing a script and a GitHub Actions workflow to track lecture participation, and 2. the description of the PR which implementatis this. Very meta. - -The structure of both script and workflow YAML file is based on the already existing workflow for updating the Statistics of Student Registrations. It has a similar structure, can be run locally in the same way, and uses the same dependencies. - -How it's supposed to work: - -GitHub actions workflow -- The workflow is triggered on new issue comments, and proceeds if the issue title is “Lecture participation tracker 2024”. -- track_participation.py is run - -Python script (`track_participation.py`): -- Fetches all comments to the issue from the GitHub API -- If the author is a collaborator, or the comment is outside the commenting window (5 hours from the start of each lecture), the comment is ignored. -- Valid comments are stored in a dictionary, with keys for each student who has commented. -- The script generates a markdown table, similar to the one for tracking tasks, which displays the lectures each student has attended. -- The issue description is updated with this markdown table and a timestamp. - -I have tested that (in a copy of the repo): -- the workflow triggers correctly when a new comment is added to the tracker. -- comments made by collaborators are ignored as expected. -- comments made outside of the allowed window are not counted. -- valid comments update the participation tracker in the issue. -- timezones work as expected (don't quote me on this) - -I have not tested for more than two unique students/commenters, as would be the case in "production". - -Updating for newer years should only require changing the lecture dates constant in the Python code and the issue title in the YAML file. - -Closes #2459 - -**Relevance** - -This contribution sets up a CI job for a repository for a course in DevOps. From 71c9c9fe8c3338041c72ec90109dadda65936430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Thiberg?= Date: Thu, 12 Sep 2024 23:23:35 +0200 Subject: [PATCH 09/12] add required yearly updates to documentation --- tools/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/README.md b/tools/README.md index f2e9b6cc1b..7bb7ec39f3 100644 --- a/tools/README.md +++ b/tools/README.md @@ -36,6 +36,10 @@ This script is used to grade each student according to the number of task comple - argparse - requests +### Update yearly +- Lecture dates and start times in `/tools/track_participation_config.json` +- Lecture participation issue number in `.github/lecture_participation.yml` + ### Usage `python3 final_grade_exporter.py --course XXXX --token 88779~...` From ef44d53b1909a36ff8097a73e39560e934e1a975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Thiberg?= Date: Thu, 12 Sep 2024 23:31:04 +0200 Subject: [PATCH 10/12] separate commenting duration into lecture and leeway durations --- tools/track_participation.py | 6 ++++-- tools/track_participation_config.json | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/track_participation.py b/tools/track_participation.py index 2e0713a16f..1b8804e5e5 100644 --- a/tools/track_participation.py +++ b/tools/track_participation.py @@ -23,9 +23,11 @@ LECTURE_DATES_TO_NUMBER = config['LECTURE_DATES_TO_NUMBER'] LECTURE_DATES_TO_START_TIME = config['LECTURE_DATES_TO_START_TIME'] -COMMENTING_DURATION_HOURS = config['COMMENTING_DURATION_HOURS'] +LECTURE_DURATION_HOURS = config['LECTURE_DURATION_HOURS'] +COMMENTING_LEEWAY_HOURS = config['COMMENTING_LEEWAY_HOURS'] LECTURE_TIMEZONE = ZoneInfo(config['LECTURE_TIMEZONE']) +commenting_duration_hours = LECTURE_DURATION_HOURS + COMMENTING_LEEWAY_HOURS def main(): handle_args(sys.argv[1:]) @@ -109,7 +111,7 @@ def is_valid_lecture_time(comment_time): lecture_start_hour = LECTURE_DATES_TO_START_TIME[lecture_date_str] allowed_period_start = comment_time.replace(hour=lecture_start_hour, minute=0, second=0, microsecond=0) - allowed_period_end = allowed_period_start + timedelta(hours=COMMENTING_DURATION_HOURS) + allowed_period_end = allowed_period_start + timedelta(hours=commenting_duration_hours) # Check if the comment time falls within the valid window return allowed_period_start <= comment_time <= allowed_period_end diff --git a/tools/track_participation_config.json b/tools/track_participation_config.json index 24722b026b..2661c637d3 100644 --- a/tools/track_participation_config.json +++ b/tools/track_participation_config.json @@ -15,6 +15,7 @@ "2024-10-02": 13, "2024-10-09": 13 }, - "COMMENTING_DURATION_HOURS": 5, + "LECTURE_DURATION_HOURS": 4, + "COMMENTING_LEEWAY_HOURS": 1, "LECTURE_TIMEZONE": "Europe/Stockholm" } From 053b348aaf943d1ae8834c1ea1bc5b51d83b3caf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Thiberg?= Date: Fri, 13 Sep 2024 00:03:31 +0200 Subject: [PATCH 11/12] update workflow to run in tools dir, get config from current dir --- .github/workflows/lecture_participation.yml | 3 ++- tools/track_participation.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lecture_participation.yml b/.github/workflows/lecture_participation.yml index d91d5c392a..601d190bfd 100644 --- a/.github/workflows/lecture_participation.yml +++ b/.github/workflows/lecture_participation.yml @@ -25,9 +25,10 @@ jobs: if [ -f ./tools/requirements.txt ]; then pip install -r ./tools/requirements.txt; fi - name: Update participation tracker + working-directory: tools env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} REPO_FULLNAME: ${{ github.repository }} TRACKER_ISSUE_NUMBER: ${{ github.event.issue.number }} - run: python ./tools/track_participation.py --printMarkdown --publish + run: python track_participation.py --printMarkdown --publish diff --git a/tools/track_participation.py b/tools/track_participation.py index 1b8804e5e5..1229b536e8 100644 --- a/tools/track_participation.py +++ b/tools/track_participation.py @@ -19,7 +19,7 @@ REPO_FULLNAME = os.getenv("REPO_FULLNAME") ISSUE_NUMBER = os.getenv("TRACKER_ISSUE_NUMBER") -config = json.load(open("tools/track_participation_config.json")) +config = json.load(open("track_participation_config.json")) LECTURE_DATES_TO_NUMBER = config['LECTURE_DATES_TO_NUMBER'] LECTURE_DATES_TO_START_TIME = config['LECTURE_DATES_TO_START_TIME'] From 5c90115b36fe587ebc92017071e036e1fc114884 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Thiberg?= Date: Fri, 13 Sep 2024 00:12:54 +0200 Subject: [PATCH 12/12] fix: use timezone in "last changed" timestamps --- tools/track_participation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/track_participation.py b/tools/track_participation.py index 1229b536e8..6241564337 100644 --- a/tools/track_participation.py +++ b/tools/track_participation.py @@ -133,7 +133,7 @@ def get_participation_markdown(participation): """ Returns markdown table representation of participation. """ - current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + current_time = datetime.now(LECTURE_TIMEZONE).strftime("%Y-%m-%d %H:%M:%S") content = f"Here we track active participation in lectures.\n\n" content += ("To do this, you record as a comment the question you make to presentations or demos during the " @@ -158,7 +158,7 @@ def get_participation_text(participation): """ Returns plaintext table representation of participation. """ - current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + current_time = datetime.now(LECTURE_TIMEZONE).strftime("%Y-%m-%d %H:%M:%S") table = PrettyTable() table.field_names = ["Index", "Student Name", "Number of Lectures Attended", "Lecture(s) attended"]