diff --git a/.github/scripts/build_assets/api_handler.py b/.github/scripts/build_assets/api_handler.py index fef1db575..042edb5ee 100644 --- a/.github/scripts/build_assets/api_handler.py +++ b/.github/scripts/build_assets/api_handler.py @@ -2,12 +2,13 @@ import sys import re from typing import List +from io import FileIO # our base url which leads to devicon base_url = "https://api.github.com/repos/devicons/devicon/" -def get_merged_pull_reqs_since_last_release(token): +def get_merged_pull_reqs_since_last_release(token, log_output: FileIO=sys.stdout): """ Get all the merged pull requests since the last release. """ @@ -16,9 +17,8 @@ def get_merged_pull_reqs_since_last_release(token): found_last_release = False page = 1 - print("Getting PRs since last release.") while not found_last_release: - data = get_merged_pull_reqs(token, page) + data = get_merged_pull_reqs(token, page, log_output) # assume we don't encounter it during the loop last_release_index = 101 @@ -34,7 +34,7 @@ def get_merged_pull_reqs_since_last_release(token): return pull_reqs -def get_merged_pull_reqs(token, page): +def get_merged_pull_reqs(token, page, log_output: FileIO=sys.stdout): """ Get the merged pull requests based on page. There are 100 results per page. See https://docs.github.com/en/rest/reference/pulls @@ -53,7 +53,7 @@ def get_merged_pull_reqs(token, page): "page": page } - print(f"Querying the GitHub API for requests page #{page}") + print(f"Querying the GitHub API for requests page #{page}", file=log_output) response = requests.get(url, headers=headers, params=params) if not response: print(f"Can't query the GitHub API. Status code is {response.status_code}. Message is {response.text}") diff --git a/.github/scripts/build_assets/filehandler.py b/.github/scripts/build_assets/filehandler.py index b50b0d271..dd54f190d 100644 --- a/.github/scripts/build_assets/filehandler.py +++ b/.github/scripts/build_assets/filehandler.py @@ -1,9 +1,10 @@ import json -from zipfile import ZipFile +from zipfile import ZipFile, is_zipfile from pathlib import Path from typing import List, Union import os import re +from io import FileIO def find_new_icons_in_devicon_json(devicon_json_path: str, icomoon_json_path: str): @@ -133,7 +134,7 @@ def is_alias(font_version: str, aliases: List[dict]): return False -def extract_files(zip_path: str, extract_path: str, delete=True): +def extract_files(zip_path: str, extract_path: str, logfile: FileIO, delete=True): """ Extract the style.css and font files from the devicon.zip folder. Must call the gulp task "get-icomoon-files" @@ -144,9 +145,11 @@ def extract_files(zip_path: str, extract_path: str, delete=True): will put the extracted files. :param delete, whether the function should delete the zip file when it's done. + :param logfile """ - print("Extracting zipped files...") - + print("Extracting zipped files...", file=logfile) + fixBadZipfile(zip_path, logfile) + print(f"it's zipped {is_zipfile(zip_path)}", file=logfile) icomoon_zip = ZipFile(zip_path) target_files = ('selection.json', 'fonts/', 'fonts/devicon.ttf', 'fonts/devicon.woff', 'fonts/devicon.eot', @@ -154,22 +157,40 @@ def extract_files(zip_path: str, extract_path: str, delete=True): for file in target_files: icomoon_zip.extract(file, extract_path) - print("Files extracted") + print("Files extracted", file=logfile) if delete: - print("Deleting devicon zip file...") + print("Deleting devicon zip file...", file=logfile) icomoon_zip.close() os.remove(zip_path) -def rename_extracted_files(extract_path: str): +def fixBadZipfile(zippath: str, logfile: FileIO): + """ + Fix a bad zipfile (one that causes zipfile.ZipFile to throw a BadZipfile Error). + Taken from https://stackoverflow.com/a/11385480/11683637. + """ + f = open(zippath, 'r+b') + data = f.read() + pos = data.find(b'\x50\x4b\x05\x06') # End of central directory signature + if (pos > 0): + # self._log("Trancating file at location " + str(pos + 22)+ ".") + f.seek(pos + 22) # size of 'ZIP end of central directory record' + f.truncate() + else: + print("Zipfile don't need to be fixed", file=logfile) + + f.close() + + +def rename_extracted_files(extract_path: str, logfile: FileIO): """ Rename the extracted files selection.json and style.css. :param extract_path, the location where the function can find the extracted files. :return: None. """ - print("Renaming files") + print("Renaming files", file=logfile) old_to_new_list = [ { "old": Path(extract_path, "selection.json"), @@ -184,7 +205,7 @@ def rename_extracted_files(extract_path: str): for dict_ in old_to_new_list: os.replace(dict_["old"], dict_["new"]) - print("Files renamed") + print("Files renamed", file=logfile) def create_screenshot_folder(dir, screenshot_name: str="screenshots/"): diff --git a/.github/scripts/build_assets/selenium_runner/BuildSeleniumRunner.py b/.github/scripts/build_assets/selenium_runner/BuildSeleniumRunner.py index 1550802b6..4cc81564a 100644 --- a/.github/scripts/build_assets/selenium_runner/BuildSeleniumRunner.py +++ b/.github/scripts/build_assets/selenium_runner/BuildSeleniumRunner.py @@ -27,7 +27,7 @@ def upload_icomoon(self, icomoon_json_path: str): :param icomoon_json_path: a path to the iconmoon.json. :raises TimeoutException: happens when elements are not found. """ - print("Uploading icomoon.json file...") + print("Uploading icomoon.json file...", file=self.log_output) # find the file input and enter the file path import_btn = self.driver.find_element_by_css_selector( @@ -44,7 +44,7 @@ def upload_icomoon(self, icomoon_json_path: str): raise Exception("Cannot find the confirm button when uploading the icomoon.json" \ "Ensure that the icomoon.json is in the correct format for Icomoon.io") - print("JSON file uploaded.") + print("JSON file uploaded.", file=self.log_output) def upload_svgs(self, svgs: List[str], screenshot_folder: str): """ @@ -52,7 +52,7 @@ def upload_svgs(self, svgs: List[str], screenshot_folder: str): :param svgs: a list of svg Paths that we'll upload to icomoon. :param screenshot_folder: the name of the screenshot_folder. """ - print("Uploading SVGs...") + print("Uploading SVGs...", file=self.log_output) import_btn = self.driver.find_element_by_css_selector( SeleniumRunner.SET_IMPORT_BUTTON_CSS @@ -63,7 +63,7 @@ def upload_svgs(self, svgs: List[str], screenshot_folder: str): err_messages = [] for i in range(len(svgs)): import_btn.send_keys(svgs[i]) - print(f"Uploading {svgs[i]}") + print(f"Uploading {svgs[i]}", file=self.log_output) # see if there are stroke messages or replacing icon message # there should be none of the second kind @@ -83,8 +83,9 @@ def upload_svgs(self, svgs: List[str], screenshot_folder: str): raise Exception(f"Unexpected alert found: {alert}") self.edit_svg() - print(f"Finished editing icon.") + print(f"Finished editing icon.", file=self.log_output) + print("Finished uploading all files.", file=self.log_output) if err_messages != []: message = "BuildSeleniumRunner - Issues found when uploading SVGs:\n" raise Exception(message + '\n'.join(err_messages)) @@ -94,9 +95,9 @@ def upload_svgs(self, svgs: List[str], screenshot_folder: str): self.switch_toolbar_option(IcomoonOptionState.SELECT) self.select_all_icons_in_top_set() new_svgs_path = str(Path(screenshot_folder, "new_svgs.png").resolve()) - self.driver.save_screenshot(new_svgs_path); + self.driver.save_screenshot(new_svgs_path) - print("Finished uploading the svgs...") + print("Finished uploading the svgs...", file=self.log_output) def take_icon_screenshot(self, screenshot_folder: str): """ @@ -105,7 +106,7 @@ def take_icon_screenshot(self, screenshot_folder: str): :param screenshot_folder: the name of the screenshot_folder. """ # take pictures - print("Taking screenshot of the new icons...") + print("Taking screenshot of the new icons...", file=self.log_output) self.go_to_generate_font_page() # take an overall screenshot of the icons that were just added @@ -113,8 +114,11 @@ def take_icon_screenshot(self, screenshot_folder: str): new_icons_path = str(Path(screenshot_folder, "new_icons.png").resolve()) main_content_xpath = "/html/body/div[4]/div[2]/div/div[1]" main_content = self.driver.find_element_by_xpath(main_content_xpath) + + # wait a bit for all the icons to load before we take a pic + time.sleep(SeleniumRunner.MED_WAIT_IN_SEC) main_content.screenshot(new_icons_path) - print("Saved screenshot of the new icons...") + print("Saved screenshot of the new icons...", file=self.log_output) def go_to_generate_font_page(self): """ @@ -137,7 +141,7 @@ def download_icomoon_fonts(self, zip_path: Path): what the icons look like. :param zip_path: the path to the zip file after it's downloaded. """ - print("Downloading Font files...") + print("Downloading Font files...", file=self.log_output) if self.current_page != IcomoonPage.SELECTION: self.go_to_page(IcomoonPage.SELECTION) @@ -149,7 +153,7 @@ def download_icomoon_fonts(self, zip_path: Path): ) download_btn.click() if self.wait_for_zip(zip_path): - print("Font files downloaded.") + print("Font files downloaded.", file=self.log_output) else: raise TimeoutError(f"Couldn't find {zip_path} after download button was clicked.") diff --git a/.github/scripts/build_assets/selenium_runner/PeekSeleniumRunner.py b/.github/scripts/build_assets/selenium_runner/PeekSeleniumRunner.py index 24ec717d4..eb1fa6441 100644 --- a/.github/scripts/build_assets/selenium_runner/PeekSeleniumRunner.py +++ b/.github/scripts/build_assets/selenium_runner/PeekSeleniumRunner.py @@ -28,7 +28,7 @@ def peek_svgs(self, svgs: List[str], screenshot_folder: str): :return an array of svgs with strokes as strings. These show which icon contains stroke. """ - print("Peeking SVGs...") + print("Peeking SVGs...", file=self.log_output) import_btn = self.driver.find_element_by_css_selector( SeleniumRunner.GENERAL_IMPORT_BUTTON_CSS @@ -37,13 +37,13 @@ def peek_svgs(self, svgs: List[str], screenshot_folder: str): svgs_with_strokes = [] for i in range(len(svgs)): import_btn.send_keys(svgs[i]) - print(f"Uploaded {svgs[i]}") + print(f"Uploaded {svgs[i]}", file=self.log_output) alert = self.test_for_possible_alert(self.SHORT_WAIT_IN_SEC) if alert == None: pass # all good elif alert == IcomoonAlerts.STROKES_GET_IGNORED_WARNING: - print(f"- This icon contains strokes: {svgs[i]}") + print(f"- This icon contains strokes: {svgs[i]}", file=self.log_output) svg = Path(svgs[i]) svgs_with_strokes.append(f"- {svg.name}") self.click_alert_button(self.ALERTS[alert]["buttons"]["DISMISS"]) @@ -57,9 +57,9 @@ def peek_svgs(self, svgs: List[str], screenshot_folder: str): new_svgs_path = str(Path(screenshot_folder, "new_svgs.png").resolve()) icon_set_xpath = "/html/body/div[4]/div[1]/div[2]/div[1]" icon_set = self.driver.find_element_by_xpath(icon_set_xpath) - icon_set.screenshot(new_svgs_path); + icon_set.screenshot(new_svgs_path) - print("Finished peeking the svgs...") + print("Finished peeking the svgs...", file=self.log_output) return svgs_with_strokes def peek_icons(self, screenshot_folder: str, icon_info: dict): @@ -68,7 +68,7 @@ def peek_icons(self, screenshot_folder: str, icon_info: dict): :param screenshot_folder: the name of the screenshot_folder. :param icon_info: a dictionary containing info on an icon. Taken from the devicon.json. """ - print("Begin peeking at the icons...") + print("Begin peeking at the icons...", file=self.log_output) # ensure all icons in the set is selected. self.select_all_icons_in_top_set() self.go_to_page(IcomoonPage.GENERATE_FONT) @@ -119,4 +119,4 @@ def peek_icons(self, screenshot_folder: str, icon_info: dict): i += 1 - print("Finished peeking the icons...") + print("Finished peeking the icons...", file=self.log_output) diff --git a/.github/scripts/build_assets/selenium_runner/SeleniumRunner.py b/.github/scripts/build_assets/selenium_runner/SeleniumRunner.py index 89da771e1..680344c78 100644 --- a/.github/scripts/build_assets/selenium_runner/SeleniumRunner.py +++ b/.github/scripts/build_assets/selenium_runner/SeleniumRunner.py @@ -1,5 +1,6 @@ from pathlib import Path -from selenium.webdriver.common import service +from io import FileIO +import sys from selenium.webdriver.firefox.webdriver import WebDriver from selenium.webdriver.firefox.service import Service @@ -8,6 +9,7 @@ from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as ec from selenium.common.exceptions import TimeoutException as SeleniumTimeoutException +from selenium.common.exceptions import ElementNotInteractableException from build_assets.selenium_runner.enums import IcomoonOptionState, IcomoonPage, IcomoonAlerts @@ -106,7 +108,7 @@ class SeleniumRunner: } def __init__(self, download_path: str, - geckodriver_path: str, headless: bool): + geckodriver_path: str, headless: bool, log_output: FileIO=sys.stdout): """ Create a SeleniumRunner object. :param download_path: the location where you want to download @@ -117,7 +119,16 @@ def __init__(self, download_path: str, self.driver = None # default values when we open Icomoon self.current_option_state = IcomoonOptionState.SELECT + """ + Track the current option in the tool bar. + """ + self.current_page = IcomoonPage.SELECTION + """Track the current page the driver is on.""" + + file=self.log_output = log_output + """The log output stream. Default is stdout.""" + self.set_browser_options(download_path, geckodriver_path, headless) def set_browser_options(self, download_path: str, geckodriver_path: str, @@ -145,7 +156,7 @@ def set_browser_options(self, download_path: str, geckodriver_path: str, options.set_preference("browser.download.dir", download_path) options.headless = headless - print("Activating browser client...") + print("Activating browser client...", file=self.log_output) self.driver = self.create_driver_instance(options, geckodriver_path) self.driver.get(self.ICOMOON_URL) @@ -153,7 +164,7 @@ def set_browser_options(self, download_path: str, geckodriver_path: str, WebDriverWait(self.driver, self.LONG_WAIT_IN_SEC).until( ec.element_to_be_clickable((By.XPATH, "(//i[@class='icon-menu'])[2]")) ) - print("Accessed icomoon.io") + print("Accessed icomoon.io", file=self.log_output) def create_driver_instance(self, options: Options, geckodriver_path: str): """ @@ -163,44 +174,37 @@ def create_driver_instance(self, options: Options, geckodriver_path: str): :param geckodriver_path: the path to the firefox executable. the icomoon.zip to. """ - retries = SeleniumRunner.MAX_RETRY - finished = False driver = None err_msgs = [] # keep for logging purposes - while not finished and retries > 0: + for i in range(SeleniumRunner.MAX_RETRY): try: - # order matters, don't change the lines below - finished = True # signal we are done in case we are actually done - # customize the local server service = None - # first retry: use 8080 + # first try: use 8080 # else: random - if retries == SeleniumRunner.MAX_RETRY: + if i == 0: service = Service(executable_path=geckodriver_path, port=8080) else: service = Service(executable_path=geckodriver_path) driver = WebDriver(options=options, service=service) - except SeleniumTimeoutException as e: - # retry. This is intended to catch "no connection could be made" error - retries -= 1 - finished = False # flip the var so we can retry - msg = f"Retry {retries}/{SeleniumRunner.MAX_RETRY} SeleniumTimeoutException: {e.msg}" - print(msg) - err_msgs.append(msg) except Exception as e: - # anything else: unsure if retry works. Just end the retry - msg = f"Retry {retries}/{SeleniumRunner.MAX_RETRY} Exception: {e}" + # retry. This is intended to catch "no connection could be made" error + # anything else: unsure if retry works. Still retry + msg = f"Retry {i + 1}/{SeleniumRunner.MAX_RETRY} Exception: {e}" err_msgs.append(msg) - print(msg) + print(msg, file=self.log_output) + else: + # works fine break + else: + # out of retries + # handle situation when we can't make a driver + err_msg_formatted = '\n'.join(reversed(err_msgs)) + msg = f"Unable to create WebDriver Instance:\n{err_msg_formatted}" + raise Exception(msg) - if driver is not None: - return driver + return driver - err_msg_formatted = '\n'.join(reversed(err_msgs)) - msg = f"Unable to create WebDriver Instance:\n{err_msg_formatted}" - raise Exception(msg) def switch_toolbar_option(self, option: IcomoonOptionState): """ @@ -311,7 +315,7 @@ def edit_svg(self, screenshot_folder: str=None, index: int=None): edit_screen = self.driver.find_element_by_css_selector( edit_screen_selector) edit_screen.screenshot(screenshot_path) - print("Took screenshot of svg and saved it at " + screenshot_path) + print("Took screenshot of svg and saved it at " + screenshot_path, file=self.log_output) close_btn = self.driver \ .find_element_by_css_selector("div.overlayWindow i.icon-close") @@ -334,11 +338,22 @@ def select_all_icons_in_top_set(self): """ Select all the svgs in the top most (latest) set. """ - self.click_hamburger_input() - select_all_button = WebDriverWait(self.driver, self.LONG_WAIT_IN_SEC).until( - ec.element_to_be_clickable((By.XPATH, "//button[text()='Select All']")) - ) - select_all_button.click() + tries = 3 + for i in range(tries): + try: + self.click_hamburger_input() + select_all_button = WebDriverWait(self.driver, self.SHORT_WAIT_IN_SEC).until( + ec.element_to_be_clickable((By.XPATH, "//button[text()='Select All']")) + ) + select_all_button.click() + except ElementNotInteractableException: + # retry until it works + pass + else: + break + else: + # after all tries and still can't click? Raise an error + raise ElementNotInteractableException("Can't click the 'Select All' button in the hamburger input.") def deselect_all_icons_in_top_set(self): """ @@ -366,5 +381,5 @@ def close(self): """ Close the SeleniumRunner instance. """ - print("Closing down SeleniumRunner...") + print("Closing down SeleniumRunner...", file=self.log_output) self.driver.quit() diff --git a/.github/scripts/build_assets/util.py b/.github/scripts/build_assets/util.py index 55ebb3219..a9f5a1093 100644 --- a/.github/scripts/build_assets/util.py +++ b/.github/scripts/build_assets/util.py @@ -4,13 +4,17 @@ import platform import sys import traceback +from io import FileIO -def exit_with_err(err: Exception): +def exit_with_err(err: Exception, logfile: FileIO=None): """ Exit the current step and display the err. :param: err, the error/exception encountered. """ - traceback.print_exc() + if logfile: + traceback.print_exc(file=logfile) + else: + traceback.print_exc() sys.exit(1) diff --git a/.github/scripts/icomoon_build.py b/.github/scripts/icomoon_build.py index 56f6544a9..3dafe3a68 100644 --- a/.github/scripts/icomoon_build.py +++ b/.github/scripts/icomoon_build.py @@ -5,6 +5,7 @@ import subprocess import json from typing import List, Dict +from io import FileIO # pycharm complains that build_assets is an unresolved ref @@ -18,63 +19,68 @@ def main(): Build the icons using Icomoon. Also optimize the svgs. """ runner = None + logfile = open("log.txt", "w") try: args = arg_getters.get_selenium_runner_args() - new_icons = get_icons_for_building(args.icomoon_json_path, args.devicon_json_path, args.token) + new_icons = get_icons_for_building(args.icomoon_json_path, args.devicon_json_path, args.token, logfile) if len(new_icons) == 0: sys.exit("No files need to be uploaded. Ending script...") - print(f"There are {len(new_icons)} icons to be build. Here are they:", *new_icons, sep = "\n") + print(f"There are {len(new_icons)} icons to be build. Here are they:", *new_icons, sep = "\n", file=logfile) - print("Begin optimizing files...") - optimize_svgs(new_icons, args.icons_folder_path) + print("Begin optimizing files...", file=logfile) + optimize_svgs(new_icons, args.icons_folder_path, logfile=logfile) - print("Updating the icomoon json...") - update_icomoon_json(new_icons, args.icomoon_json_path) + print("Updating the icomoon json...", file=logfile) + update_icomoon_json(new_icons, args.icomoon_json_path, logfile) - print("Start the building icons process...") + print("Start the building icons process...", file=logfile) icon_svgs = filehandler.get_svgs_paths( new_icons, args.icons_folder_path, icon_versions_only=True) zip_name = "devicon-v1.0.zip" zip_path = Path(args.download_path, zip_name) screenshot_folder = filehandler.create_screenshot_folder("./") + runner = BuildSeleniumRunner(args.download_path, - args.geckodriver_path, args.headless) + args.geckodriver_path, args.headless, log_output=logfile) runner.build_icons(args.icomoon_json_path, zip_path, icon_svgs, screenshot_folder) - filehandler.extract_files(str(zip_path), args.download_path) - filehandler.rename_extracted_files(args.download_path) + filehandler.extract_files(str(zip_path), args.download_path, logfile) + filehandler.rename_extracted_files(args.download_path, logfile) - print("Creating the release message by querying the GitHub API...") - get_release_message(args.token) + print("Creating the release message by querying the GitHub API...", file=logfile) + get_release_message(args.token, logfile) - print("Closing issues with the `in-develop` label.") + print("Closing issues with the `in-develop` label.", file=logfile) issues = api_handler.get_issues_by_labels(args.token, ["in-develop"]) issue_nums = [issue_num["number"] for issue_num in issues] api_handler.close_issues(args.token, issue_nums) - print("Task completed.") + print("Task completed.", file=logfile) except TimeoutException as e: - util.exit_with_err(Exception("Selenium Time Out Error: \n" + str(e))) + util.exit_with_err(Exception("Selenium Time Out Error: \n" + str(e)), logfile) except Exception as e: - util.exit_with_err(e) + util.exit_with_err(e, logfile) finally: + print("Exiting", file=logfile) if runner is not None: runner.close() + logfile.close() -def get_icons_for_building(icomoon_json_path: str, devicon_json_path: str, token: str): +def get_icons_for_building(icomoon_json_path: str, devicon_json_path: str, token: str, logfile: FileIO): """ Get the icons for building. :param icomoon_json_path - the path to the `icomoon.json`. :param devicon_json_path - the path to the `devicon.json`. :param token - the token to access the GitHub API. + :param logfile. :return a list of dict containing info on the icons. These are from the `devicon.json`. """ devicon_json = filehandler.get_json_file_content(devicon_json_path) - pull_reqs = api_handler.get_merged_pull_reqs_since_last_release(token) + pull_reqs = api_handler.get_merged_pull_reqs_since_last_release(token, logfile) new_icons = [] for pull_req in pull_reqs: @@ -95,22 +101,24 @@ def get_icons_for_building(icomoon_json_path: str, devicon_json_path: str, token return new_icons -def optimize_svgs(new_icons: List[dict], icons_folder_path: str): +def optimize_svgs(new_icons: List[str], icons_folder_path: str, logfile: FileIO): """ Optimize the newly added svgs. This is done in batches since the command line has a limit on characters allowed. :param new_icons - the new icons that need to be optimized. :param icons_folder_path - the path to the /icons folder. + :param logfile - the file obj to store logging info in. """ svgs = filehandler.get_svgs_paths(new_icons, icons_folder_path, icon_versions_only=False) start = 0 step = 10 for i in range(start, len(svgs), step): batch = svgs[i:i + step] + print(f"Optimizing these files\n{batch}", file=logfile) subprocess.run(["npm", "run", "optimize-svg", "--", f"--svgFiles={json.dumps(batch)}"], shell=True) -def update_icomoon_json(new_icons: List[str], icomoon_json_path: str): +def update_icomoon_json(new_icons: List[str], icomoon_json_path: str, logfile: FileIO): """ Update the `icomoon.json` if it contains any icons that needed to be updated. This will remove the icons @@ -127,7 +135,7 @@ def update_icomoon_json(new_icons: List[str], icomoon_json_path: str): icomoon_json["icons"] = list(icons_to_keep) new_len = len(icomoon_json["icons"]) - print(f"Update completed. Removed {cur_len - new_len} icons:", *messages, sep='\n') + print(f"Update completed. Removed {cur_len - new_len} icons:", *messages, sep='\n', file=logfile) filehandler.write_to_file(icomoon_json_path, json.dumps(icomoon_json)) @@ -149,18 +157,18 @@ def find_icomoon_icon_not_in_new_icons(icomoon_icon: Dict, new_icons: List, mess return True -def get_release_message(token): +def get_release_message(token, logfile: FileIO): """ Get the release message for the latest build and write the result in a file. :param token: the GitHub API token to access the API. """ # fetch first page by default - data = api_handler.get_merged_pull_reqs_since_last_release(token) + data = api_handler.get_merged_pull_reqs_since_last_release(token, logfile) newIcons = [] features = [] - print("Parsing through the pull requests...") + print("Parsing through the pull requests...", file=logfile) for pullData in data: authors = api_handler.find_all_authors(pullData, token) markdown = f"- [{pullData['title']}]({pullData['html_url']}) by {authors}." @@ -170,7 +178,7 @@ def get_release_message(token): else: features.append(markdown) - print("Constructing message...") + print("Constructing message...", file=logfile) thankYou = "A huge thanks to all our maintainers and contributors for making this release possible!" iconTitle = f"**{len(newIcons)} New Icons**" featureTitle = f"**{len(features)} New Features**" @@ -178,10 +186,10 @@ def get_release_message(token): iconTitle, "\n".join(newIcons), featureTitle, "\n".join(features)) - print("--------------Here is the build message--------------\n", finalString) + print("--------------Here is the build message--------------\n", finalString, file=logfile) release_message_path = "./release_message.txt" filehandler.write_to_file(release_message_path, finalString) - print("Script finished") + print("Script finished", file=logfile) if __name__ == "__main__": diff --git a/.github/workflows/build_icons.yml b/.github/workflows/build_icons.yml index 4747bd0bc..518540a4e 100644 --- a/.github/workflows/build_icons.yml +++ b/.github/workflows/build_icons.yml @@ -33,6 +33,13 @@ jobs: name: geckodriver-log path: ./geckodriver.log + - name: Upload log file for debugging purposes + uses: actions/upload-artifact@v2 + if: always() + with: + name: logfile + path: ./log.txt + - name: Build devicon.min.css if: success() run: npm run build-css diff --git a/gulpfile.js b/gulpfile.js index f6cc2fae5..80ecd5c4a 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -155,7 +155,6 @@ function cleanUp() { */ function optimizeSvg() { let svgGlob = JSON.parse(yargs.argv.svgFiles); - console.log("Optimizing these files: ", svgGlob); return gulp .src(svgGlob) .pipe(svgmin(configOptionCallback))