From fc615c16e161a548211f0f5fcca57b6f7aaf7087 Mon Sep 17 00:00:00 2001 From: ReenigneArcher <42013603+ReenigneArcher@users.noreply.github.com> Date: Mon, 4 Nov 2024 19:55:39 -0500 Subject: [PATCH] ci: allow multi submission --- .github/scripts/build_assets/arg_getters.py | 13 ++-- .github/scripts/build_assets/util.py | 31 ++++----- .github/scripts/check_icon_pr.py | 71 +++++++++++---------- .github/scripts/icomoon_build.py | 38 ++++------- .github/workflows/build_icons.yml | 24 ++++--- .github/workflows/check_icon_pr.yml | 13 ++-- 6 files changed, 95 insertions(+), 95 deletions(-) diff --git a/.github/scripts/build_assets/arg_getters.py b/.github/scripts/build_assets/arg_getters.py index 8f82f0e6d..ddb5a6ae9 100644 --- a/.github/scripts/build_assets/arg_getters.py +++ b/.github/scripts/build_assets/arg_getters.py @@ -4,7 +4,7 @@ def get_selenium_runner_args(has_token=True, peek_mode=False): """ - Get the commandline arguments for the icomoon_peek.py and + Get the commandline arguments for the icomoon_peek.py and icomoon_build.py. """ parser = ArgumentParser(description="Upload svgs to Icomoon to create icon files.") @@ -40,6 +40,10 @@ def get_selenium_runner_args(has_token=True, peek_mode=False): parser.add_argument("token", help="The GitHub token to access the GitHub REST API.") + parser.add_argument("changed_files", + help="List of SVG files changed since the last release/tag", + nargs="+") + return parser.parse_args() @@ -49,9 +53,6 @@ def get_check_icon_pr_args(): """ parser = ArgumentParser(description="Check the SVGs to ensure their attributes are correct. Run whenever a PR is opened") - parser.add_argument("pr_title", - help="The title of the PR that we are peeking at") - parser.add_argument("icons_folder_path", help="The path to the icons folder", action=PathResolverAction) @@ -60,6 +61,10 @@ def get_check_icon_pr_args(): help="The path to the devicon.json", action=PathResolverAction) + parser.add_argument("changed_files", + help="List of SVG files changed in the PR", + nargs="+") + return parser.parse_args() diff --git a/.github/scripts/build_assets/util.py b/.github/scripts/build_assets/util.py index e98b2a900..60ba6ac6d 100644 --- a/.github/scripts/build_assets/util.py +++ b/.github/scripts/build_assets/util.py @@ -50,29 +50,24 @@ def set_env_var(key: str, value: str, delimiter: str='~'): raise Exception("This function doesn't support this platform: " + platform.system()) -def find_object_added_in_pr(icons: List[dict], pr_title: str): +def find_changed_icons(icons: List[dict], changed_files: List[str]) -> List[dict]: """ - Find the icon name from the PR title. + Find the changed icons in the PR. :param icons, a list of the font objects found in the devicon.json. - :pr_title, the title of the PR that this workflow was called on. - :return a dictionary with the "name" - entry's value matching the name in the pr_title. - :raise If no object can be found, raise an Exception. + :changed_files, SVG files changed in this PR. + :return a list of dictionaries with the "name" + entry values matching the name of changed icons. """ - try: - pattern = re.compile(r"(?<=^new icon: )\w+ (?=\(.+\))|(?<=^update icon: )\w+ (?=\(.+\))", re.I) - icon_name_index = 0 - icon_name = pattern.findall(pr_title)[icon_name_index].lower().strip() # should only have one match - icon = [icon for icon in icons if icon["name"] == icon_name][0] - return icon - except IndexError as e: # there are no match in the findall() - print(e) - message = "util.find_object_added_in_pr: Couldn't find an icon matching the name in the PR title.\n" \ - f"PR title is: '{pr_title}'" - raise Exception(message) + filtered_icons = [] + for file in changed_files: + icon_name = Path(file).parent.name + icon = [icon for icon in icons if icon["name"] == icon_name] + if len(icon) > 0: + filtered_icons.extend(icon) + return filtered_icons -def is_svg_in_font_attribute(svg_file_path: Path, devicon_object: dict): +def is_svg_in_font_attribute(svg_file_path: Path, devicon_object: dict): """ Check if svg is in devicon.json's font attribute. :param svg_file_path, the path to a single svg icon diff --git a/.github/scripts/check_icon_pr.py b/.github/scripts/check_icon_pr.py index dc5eec771..423c057cd 100644 --- a/.github/scripts/check_icon_pr.py +++ b/.github/scripts/check_icon_pr.py @@ -18,42 +18,45 @@ def main(): try: all_icons = filehandler.get_json_file_content(args.devicon_json_path) - devicon_err_msg = [] + err_msg = [] #First check if devicon.json is sorted if sorted(all_icons, key=lambda d: d['name']) != all_icons: - devicon_err_msg.append(f"devicon.json is not sorted correctly.\nPlease make sure that your icon is added in the `devicon.json` file at the correct alphabetic position\nas seen here: https://github.com/devicons/devicon/wiki/Updating-%60devicon.json%60") + err_msg.append(f"devicon.json is not sorted correctly.\nPlease make sure that your icon is added in the `devicon.json` file at the correct alphabetic position\nas seen here: https://github.com/devicons/devicon/wiki/Updating-%60devicon.json%60") # get only the icon object that has the name matching the pr title - filtered_icon = util.find_object_added_in_pr(all_icons, args.pr_title) - print("Checking devicon.json object: " + str(filtered_icon)) - devicon_err_msg.append(check_devicon_object(filtered_icon)) - - # check the file names - filename_err_msg = "" - svgs = None - try: - svgs = filehandler.get_svgs_paths([filtered_icon], args.icons_folder_path, as_str=False) - print("SVGs to check: ", *svgs, sep='\n') - except ValueError as e: - filename_err_msg = "Error found regarding filenames:\n- " + e.args[0] - - # check the svgs - if svgs is None or len(svgs) == 0: - print("No SVGs to check, ending script.") - svg_err_msg = "Error checking SVGs: no SVGs to check. Might be caused by above issues." - else: - svg_err_msg = check_svgs(svgs, filtered_icon) - - err_msg = [] - if devicon_err_msg != []: - err_msg.extend(devicon_err_msg) - - if filename_err_msg != "": - err_msg.append(filename_err_msg) - - if svg_err_msg != "": - err_msg.append(svg_err_msg) - + filtered_icons = util.find_changed_icons(all_icons, args.changed_files) + for filtered_icon in filtered_icons: + devicon_err_msg = [] + print("Checking devicon.json object: " + str(filtered_icon)) + devicon_err_msg.append(check_devicon_object(filtered_icon)) + + # check the file names + filename_err_msg = "" + svgs = None + try: + svgs = filehandler.get_svgs_paths([filtered_icon], args.icons_folder_path, as_str=False) + print("SVGs to check: ", *svgs, sep='\n') + except ValueError as e: + filename_err_msg = "Error found regarding filenames:\n- " + e.args[0] + + # check the svgs + if svgs is None or len(svgs) == 0: + print("No SVGs to check for this icon.") + svg_err_msg = "Error checking SVGs: no SVGs to check. Might be caused by above issues." + else: + svg_err_msg = check_svgs(svgs, filtered_icon) + + if devicon_err_msg: + err_msg.extend(devicon_err_msg) + + if filename_err_msg: + err_msg.append(filename_err_msg) + + if svg_err_msg: + err_msg.append(svg_err_msg) + + err_msg = list(filter(None, err_msg)) # remove empty strings from err_msg + print("Error messages: ", err_msg) filehandler.write_to_file("./err_messages.txt", "\n\n".join(err_msg)) print("Task completed.") except Exception as e: @@ -109,7 +112,7 @@ def check_devicon_object(icon: dict): err_msgs.append(f"- Invalid version name in versions['svg']: '{version}'. Must match regexp: (original|plain|line)(-wordmark)?") except KeyError: err_msgs.append("- missing key: 'svg' in 'versions'.") - + try: if type(icon["versions"]["font"]) != list or len(icon["versions"]["svg"]) == 0: err_msgs.append("- must contain at least 1 font version in a list.") @@ -160,7 +163,7 @@ def check_devicon_object(icon: dict): if len(err_msgs) > 0: message = "Error found in \"devicon.json\" for \"{}\" entry: \n{}".format(icon["name"], "\n".join(err_msgs)) return message - return "" + return "" def check_svgs(svg_file_paths: List[Path], devicon_object: dict): diff --git a/.github/scripts/icomoon_build.py b/.github/scripts/icomoon_build.py index 3dafe3a68..890a969db 100644 --- a/.github/scripts/icomoon_build.py +++ b/.github/scripts/icomoon_build.py @@ -22,7 +22,7 @@ def main(): 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, logfile) + new_icons = get_icons_for_building(args.devicon_json_path, args.changed_files) if len(new_icons) == 0: sys.exit("No files need to be uploaded. Ending script...") @@ -39,7 +39,7 @@ def main(): 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("./") + screenshot_folder = filehandler.create_screenshot_folder("./") runner = BuildSeleniumRunner(args.download_path, args.geckodriver_path, args.headless, log_output=logfile) @@ -65,38 +65,26 @@ def main(): finally: print("Exiting", file=logfile) if runner is not None: - runner.close() + runner.close() logfile.close() -def get_icons_for_building(icomoon_json_path: str, devicon_json_path: str, token: str, logfile: FileIO): +def get_icons_for_building(devicon_json_path: str, changed_files: List[str]): """ 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 + :param changed_files - the list of changed files since the last release/tag. + + :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, logfile) new_icons = [] - for pull_req in pull_reqs: - if api_handler.is_feature_icon(pull_req): - filtered_icon = util.find_object_added_in_pr(devicon_json, pull_req["title"]) - if filtered_icon not in new_icons: - new_icons.append(filtered_icon) - - # get any icons that might not have been found by the API - # sometimes happen due to the PR being opened before the latest build release - new_icons_from_devicon_json = filehandler.find_new_icons_in_devicon_json( - devicon_json_path, icomoon_json_path) + filtered_icons = util.find_changed_icons(devicon_json, changed_files) - for icon in new_icons_from_devicon_json: - if icon not in new_icons: - new_icons.append(icon) + # add the filtered icons to the new_icons list only if they are not already there + new_icons.extend([icon for icon in filtered_icons if icon not in new_icons]) return new_icons @@ -137,7 +125,7 @@ def update_icomoon_json(new_icons: List[str], icomoon_json_path: str, logfile: F new_len = len(icomoon_json["icons"]) 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)) - + def find_icomoon_icon_not_in_new_icons(icomoon_icon: Dict, new_icons: List, messages: List): """ @@ -145,7 +133,7 @@ def find_icomoon_icon_not_in_new_icons(icomoon_icon: Dict, new_icons: List, mess This also add logging for which icons were removed. :param icomoon_icon - a dict object from the icomoon.json's `icons` attribute. :param new_icons - a list of new icons. Each element is an object from the `devicon.json`. - :param messages - an empty list where the function can attach logging on which + :param messages - an empty list where the function can attach logging on which icon were removed. """ for new_icon in new_icons: @@ -182,7 +170,7 @@ def get_release_message(token, logfile: FileIO): 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**" - finalString = "{0}\n\n {1}\n{2}\n\n {3}\n{4}".format(thankYou, + finalString = "{0}\n\n {1}\n{2}\n\n {3}\n{4}".format(thankYou, iconTitle, "\n".join(newIcons), featureTitle, "\n".join(features)) diff --git a/.github/workflows/build_icons.yml b/.github/workflows/build_icons.yml index d9156e234..0062388f7 100644 --- a/.github/workflows/build_icons.yml +++ b/.github/workflows/build_icons.yml @@ -7,7 +7,7 @@ jobs: steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 - with: + with: python-version: '3.10' - name: Install dependencies (python, pip, npm) @@ -20,10 +20,18 @@ jobs: shell: bash env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: > - python ./.github/scripts/icomoon_build.py - ./.github/scripts/build_assets/geckodriver-v0.32.2-linux64/geckodriver ./icomoon.json - ./devicon.json ./icons ./ $GITHUB_TOKEN --headless + run: | + git fetch --tags + CHANGED_ICONS=$(git diff --name-only $(git describe --tags --abbrev=0)..HEAD | grep -E 'icons/.*\.svg') + python ./.github/scripts/icomoon_build.py \ + ./.github/scripts/build_assets/geckodriver-v0.32.2-linux64/geckodriver + ./icomoon.json \ + ./devicon.json \ + ./icons \ + ./ \ + $GITHUB_TOKEN \ + ${CHANGED_ICONS} \ + --headless - name: Upload geckodriver.log for debugging purposes uses: actions/upload-artifact@v2 @@ -40,7 +48,7 @@ jobs: path: ./log.txt - name: Build devicon.min.css - if: success() + if: success() run: npm run build-css # - name: Upload screenshot of the newly made icons @@ -58,10 +66,10 @@ jobs: uses: juliangruber/read-file-action@v1.0.0 with: # taken from icomoon_build.py's get_release_message() - path: ./release_message.txt + path: ./release_message.txt - name: Create Pull Request - if: success() + if: success() uses: peter-evans/create-pull-request@v3 env: MESSAGE: | diff --git a/.github/workflows/check_icon_pr.yml b/.github/workflows/check_icon_pr.yml index 3054a6f84..45555fb71 100644 --- a/.github/workflows/check_icon_pr.yml +++ b/.github/workflows/check_icon_pr.yml @@ -6,17 +6,17 @@ jobs: runs-on: ubuntu-latest if: startsWith(github.event.pull_request.title, 'new icon') || startsWith(github.event.pull_request.title, 'update icon') # only checks icon PR steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Check if PR is develop if: ${{ github.base_ref != 'develop' }} run: | echo -e "The PR's base branch is \`${{ github.base_ref }}\`, but should be \`develop\`\nPlease change the PR so that it's based on, and merged into \`develop\`" > ./err_messages.txt echo "wrong_branch=true" >> $GITHUB_ENV - + - uses: actions/setup-python@v4 if: ${{ !env.wrong_branch }} - with: + with: python-version: 3.8 - name: Install dependencies @@ -27,9 +27,10 @@ jobs: - name: Run the check_svg script if: ${{ !env.wrong_branch }} - env: - PR_TITLE: ${{ github.event.pull_request.title }} - run: python ./.github/scripts/check_icon_pr.py "$PR_TITLE" ./icons ./devicon.json + run: | + git fetch origin ${{ github.base_ref }} + CHANGED_ICONS=$(git diff --name-only origin/${{ github.base_ref }} ${{ github.sha }} | grep -E 'icons/.*\.svg') + python ./.github/scripts/check_icon_pr.py ./icons ./devicon.json ${CHANGED_ICONS} - name: Upload the err messages uses: actions/upload-artifact@v3