From f911fe01cd89ae4a4b77e04eeccb9ff3c7390356 Mon Sep 17 00:00:00 2001 From: Jaeseok Kang <123261952+ziesski@users.noreply.github.com> Date: Wed, 26 Jun 2024 14:37:38 -0400 Subject: [PATCH] [Feature:RainbowGrades] Display RainbowGrades version (#56) This update allows all users of RainbowGrades (i.e. instructors and students) to see the build version at the bottom of the RainbowGrades page. This version info is vital as it allows instructors to know which version they are currently using. Having this version information readily available will enable instructors to provide accurate details when reporting any issues or errors they encounter. In turn, developers can use this version information to identify any potential discrepancies caused by outdated versions and assist instructors more efficiently in resolving their concerns. [Instructor view] ![Screen Shot 2023-07-28 at 11 49 10 AM](https://github.com/Submitty/RainbowGrades/assets/123261952/81ce995a-0086-4ead-9f0b-0d3686017d77) [student view] ![Screen Shot 2023-07-28 at 1 39 52 PM](https://github.com/Submitty/RainbowGrades/assets/123261952/0776a2e8-6f9d-4567-bf6a-e38c6142300f) --------- Co-authored-by: William Powe <116031952+powe97@users.noreply.github.com> Co-authored-by: Barb Cutler Co-authored-by: Barb Cutler --- MakefileHelper | 11 ++++++--- main.cpp | 3 ++- output.cpp | 31 +++++++++++++++++++++++ track_Rainbow_version.py | 53 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 track_Rainbow_version.py diff --git a/MakefileHelper b/MakefileHelper index 5b573a7..7cdb6c7 100644 --- a/MakefileHelper +++ b/MakefileHelper @@ -1,4 +1,4 @@ -.PHONY: default pull push all compile overall section lab hw test quiz final zone clean src_clean remove_json_comments +.PHONY: default pull push all compile overall section lab hw test quiz final zone clean src_clean remove_json_comments version default: overall @@ -26,6 +26,9 @@ endif nlohmann_json_dir=${RAINBOW_GRADES_DIRECTORY}/../vendor/nlohmann/json +export RAINBOW_GRADES_DIRECTORY +export REPORTS_DIRECTORY + ${nlohmann_json_dir}: mkdir -p ${nlohmann_json_dir} wget https://github.com/nlohmann/json/releases/download/v3.1.2/include.zip -O ${RAINBOW_GRADES_DIRECTORY}/../vendor/nlohmann_json.zip @@ -75,6 +78,8 @@ endif json_include = -I${nlohmann_json_dir}/include/ +version: + python3 ${RAINBOW_GRADES_DIRECTORY}/track_Rainbow_version.py remove_json_comments: customization.json cpp -xc++ $< | sed -e '/^#/d' > customization_no_comments.json @@ -93,12 +98,12 @@ process_grades.out: \ individual_summary_html all_students_summary_csv all_students_summary_html: mkdir -p $@ -compile: remove_json_comments process_grades.out individual_summary_html all_students_summary_html all_students_summary_csv +compile: remove_json_comments version process_grades.out individual_summary_html all_students_summary_html all_students_summary_csv clean: rm -rf *~ *.dSYM rm -f process_grades.out - rm -f customization_no_comments.json files_json.txt + rm -f customization_no_comments.json files_json.txt RG_version.json src_clean: clean rm -f ${json_syntax_checker.py} diff --git a/main.cpp b/main.cpp index eb33b3d..00e0989 100644 --- a/main.cpp +++ b/main.cpp @@ -37,11 +37,12 @@ std::vector OMIT_SECTION_FROM_STATS; std::string OUTPUT_FILE = "./output.html"; std::string OUTPUT_CSV_FILE = "./output.csv"; std::string CUSTOMIZATION_FILE = "./customization_no_comments.json"; +std::string RG_VERSION_FILE = "./RG_version.json"; std::string RAW_DATA_DIRECTORY = "./raw_data/all_grades/"; std::string INDIVIDUAL_FILES_OUTPUT_DIRECTORY = "./individual_summary_html/"; std::string ALL_STUDENTS_OUTPUT_DIRECTORY = "./all_students_summary_html/"; -std::string ALL_STUDENTS_OUTPUT_DIRECTORY_CSV = "./all_students_summary_csv/"; +std::string ALL_STUDENTS_OUTPUT_DIRECTORY_CSV = "./all_students_summary_csv/"; nlohmann::json GLOBAL_CUSTOMIZATION_JSON; diff --git a/output.cpp b/output.cpp index 56760fd..57b037d 100644 --- a/output.cpp +++ b/output.cpp @@ -24,6 +24,8 @@ extern std::string OUTPUT_FILE; extern std::string OUTPUT_CSV_FILE; +extern std::string RG_VERSION_FILE; + extern std::string ALL_STUDENTS_OUTPUT_DIRECTORY; extern std::string ALL_STUDENTS_OUTPUT_DIRECTORY_CSV; @@ -1389,5 +1391,34 @@ void end_table(std::ofstream &ostr, bool for_instructor, Student *s) { } + // RAINBOW GRADE VERSION DISPLAY + std::ifstream istr(RG_VERSION_FILE.c_str()); + assert (istr.good()); + nlohmann::json j = nlohmann::json::parse(istr); + // current_commit_hash_rg (Full hash) is not used, parsing just for possible future use + nlohmann::json current_commit_hash_rg = j["installed_commit_rg"]; + nlohmann::json current_short_commit_hash_rg = j["short_installed_commit_rg"]; + nlohmann::json current_git_tag_rg = j["most_recent_git_tag_rg"]; + + // Remove double quotation + std::string rainbow_short_hash = current_short_commit_hash_rg; + std::string rainbow_git_tag = current_git_tag_rg; + rainbow_git_tag.erase(std::remove(rainbow_git_tag.begin(), rainbow_git_tag.end(), '\"'), rainbow_git_tag.end()); + rainbow_short_hash.erase(std::remove(rainbow_short_hash.begin(), rainbow_short_hash.end(), '\"'), rainbow_short_hash.end()); + + std::time_t currentTime = std::time(nullptr); + // Convert the time to the local time struct + std::tm* localTime = std::localtime(¤tTime); + // Extract the current year from the local time struct + int currentYear = localTime->tm_year + 1900; + + + ostr << "

© " << currentYear << " Submitty/RainbowGrades " << rainbow_git_tag << "

" << std::endl; + + + + ostr.close(); } diff --git a/track_Rainbow_version.py b/track_Rainbow_version.py new file mode 100644 index 0000000..5d848f6 --- /dev/null +++ b/track_Rainbow_version.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 + +import os +import json +import subprocess + +CURRENT_PATH = os.path.dirname(os.path.realpath(__file__)) +RG_DIR = os.environ.get('RAINBOW_GRADES_DIRECTORY') +REPORT_DIR = os.environ.get('REPORTS_DIRECTORY') +WORKING_DIRECTORY = "." + +if __name__ == "__main__": + + json_dir = os.path.join(WORKING_DIRECTORY, "RG_version.json") + output_dict = {} + current_commit_hash_rg = 'unknown' + current_short_commit_hash_rg = 'unknown' + current_git_tag_rg = 'unknown' + + try: + #run the command 'git rev-parse HEAD' from the RainbowGrades repository directory + current_commit_hash_rg = subprocess.check_output(['git', 'rev-parse', 'HEAD'], cwd=RG_DIR) + current_commit_hash_rg = current_commit_hash_rg.decode('ascii').strip() + current_short_commit_hash_rg = subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'], cwd=RG_DIR) + current_short_commit_hash_rg = current_short_commit_hash_rg.decode('ascii').strip() + print("Commit {0} is currently installed on this system.".format(current_commit_hash_rg)) + except: + print("ERROR: could not determine commit hash.") + current_commit_hash_rg = 'unknown' + + try: + #run the command 'git describe --tag --abbrev=0' from the RainbowGrades repository directory + current_git_tag_rg = subprocess.check_output(['git', 'describe', '--tag', '--abbrev=0'], cwd=RG_DIR) + current_git_tag_rg = current_git_tag_rg.decode('ascii').strip() + print("Tag {0} is the most recent git tag.".format(current_git_tag_rg)) + except: + print("ERROR: could not determine current git tag.") + current_git_tag_rg = 'unknown' + + + #remove newline at the end of the hash and tag and convert them from bytes to ascii. + + output_dict["installed_commit_rg"] = current_commit_hash_rg + output_dict["short_installed_commit_rg"] = current_short_commit_hash_rg + output_dict["most_recent_git_tag_rg"] = current_git_tag_rg + + + try: + #Update rainbow_grades/RG_version.json to reflect the current commit hash. + with open(json_dir, 'w') as outfile: + json.dump(output_dict, outfile, indent=2) + except: + print("ERROR: could not write to {0}".format(json_dir))