diff --git a/.github/scripts/build_assets/api_handler.py b/.github/scripts/build_assets/api_handler.py index f75a20ccd..002221126 100644 --- a/.github/scripts/build_assets/api_handler.py +++ b/.github/scripts/build_assets/api_handler.py @@ -1,8 +1,14 @@ import requests import sys import re +from typing import List +# our base url which leads to devicon +# base_url = "https://api.github.com/repos/devicons/devicon/" +# testing url +base_url = "https://api.github.com/repos/Thomas-Boi/devicon/" + def get_merged_pull_reqs_since_last_release(token): """ Get all the merged pull requests since the last release. @@ -38,7 +44,7 @@ def get_merged_pull_reqs(token, page): :param token, a GitHub API token. :param page, the page number. """ - queryPath = "https://api.github.com/repos/devicons/devicon/pulls" + url = base_url + "pulls" headers = { "Authorization": f"token {token}" } @@ -50,7 +56,7 @@ def get_merged_pull_reqs(token, page): } print(f"Querying the GitHub API for requests page #{page}") - response = requests.get(queryPath, headers=headers, params=params) + 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}") sys.exit(1) @@ -99,3 +105,80 @@ def find_all_authors(pull_req_data, token): authors.add(commit["commit"]["author"]["name"]) print(f"This URL didn't have an `author` attribute: {pull_req_data['commits_url']}") return ", ".join(["@" + author for author in list(authors)]) + + +def label_issues(token: str, repo: str, issues: List[str], labels: List[str]): + """ + Label the issues specified with the label specified. + :param token: the GitHub API token. + :param issues: the issue numbers (as str) that we are labelling. + :param labels: the labels that we are labelling. + """ + headers = { + "Authorization": f"token {token}", + "accept": "application/vnd.github.v3+json" + } + url = base_url + "issues/{}/labels" + for issue in issues: + body = { + "labels": labels + } + response = requests.post(url.format(repo, issue), headers=headers, json=body) + if not response: + raise Exception(f"Can't label the Issue provided. Issue: {issue}, labels: {labels}, API response: " + response.text) + else: + print(f"Successfully labelled issue {issue}") + + +def close_issues(token: str, issues: List[str]): + """ + Close issues. + :param token: the GitHub API token. + :param issues: the issue numbers (as str) that we are labelling. + """ + headers = { + "Authorization": f"token {token}", + "accept": "application/vnd.github.v3+json" + } + url = base_url + "issues/{}" + body = { + "state": "closed" + } + for issue in issues: + response = requests.patch(url.format(issue), headers=headers, json=body) + if not response: + raise Exception(f"Can't close Issue provided. Issue: {issue}, API response: " + response.text) + else: + print(f"Successfully closed issue {issue}") + + +def get_issues_by_labels(token: str, labels: List[str]): + """ + Get a list of issues based on their labels. + :param token: the GitHub API token. + :param labels: the labels that we are labelling. + """ + url = base_url + "issues?per_page=100&labels={}&page={}" + headers = { + "Authorization": f"token {token}", + "accept": "application/vnd.github.v3+json" + } + issues = [] + done = False + page_num = 1 + while not done: + response = requests.get(url.format(",".join(labels), page_num), headers=headers) + if not response: + raise Exception(f"Can't access API. Can't get issues for labels: {labels}, API response: " + response.text) + else: + results = response.json() + if len(results) < 100: + done = True # we are done + else: + page_num += 1 # page is full => might need to check another page + + # GitHub API also returns PRs for issues queries => have to check + issues_only = [issue for issue in results if issue.get("pull_request") is None] + issues.extend(issues_only) + + return issues diff --git a/.github/scripts/build_assets/arg_getters.py b/.github/scripts/build_assets/arg_getters.py index 80b88d3c2..dcfb53fe2 100644 --- a/.github/scripts/build_assets/arg_getters.py +++ b/.github/scripts/build_assets/arg_getters.py @@ -34,28 +34,32 @@ def get_selenium_runner_args(peek_mode=False): action=PathResolverAction) if peek_mode: - parser.add_argument("--pr_title", + parser.add_argument("pr_title", help="The title of the PR that we are peeking at") else: parser.add_argument("token", - help="The GitHub token to access the GitHub REST API.", - type=str) + help="The GitHub token to access the GitHub REST API.") return parser.parse_args() -def get_check_svgs_on_pr_args(): +def get_check_icon_pr_args(): """ - Get the commandline arguments for the check_svgs_on_pr.py. + Get the commandline arguments for the check_icon_pr.py. """ parser = ArgumentParser(description="Check the SVGs to ensure their attributes are correct. Run whenever a PR is opened") - parser.add_argument("files_added_json_path", - help="The path to the files_added.json created by the gh-action-get-changed-files@2.1.4", + + 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) - parser.add_argument("files_modified_json_path", - help="The path to the files_modified.json created by the gh-action-get-changed-files@2.1.4", + parser.add_argument("devicon_json_path", + help="The path to the devicon.json", action=PathResolverAction) + return parser.parse_args() @@ -64,7 +68,25 @@ def get_release_message_args(): Get the commandline arguments for get_release_message.py. """ parser = ArgumentParser(description="Create a text containing the icons and features added since last release.") + parser.add_argument("token", + help="The GitHub token to access the GitHub REST API.") + return parser.parse_args() + + +def get_in_develop_labeler_args(): + """ + Get the commandline arguments for in_develop_labeler.py. + """ + parser = ArgumentParser(description="Parse the PR body to find the issue(s) we are labelling.") parser.add_argument("token", help="The GitHub token to access the GitHub REST API.", type=str) + + parser.add_argument("body", + help="The PR's initial comment by the author AKA the `body` attribute of the `pull_request` API object.", + type=str) + + parser.add_argument("repo", + help="The owner and repo name. Ex: devicons/devicon", + type=str) return parser.parse_args() diff --git a/.github/scripts/build_assets/filehandler.py b/.github/scripts/build_assets/filehandler.py index 054431cd2..1e24045db 100644 --- a/.github/scripts/build_assets/filehandler.py +++ b/.github/scripts/build_assets/filehandler.py @@ -68,7 +68,7 @@ def get_svgs_paths(new_icons: List[dict], icons_folder_path: str, folder_path = Path(icons_folder_path, icon_info['name']) if not folder_path.is_dir(): - raise ValueError(f"Invalid path. This is not a directory: {folder_path}.") + raise ValueError(f"Invalid path. This is not a directory: '{folder_path}'.") if icon_versions_only: get_icon_svgs_paths(folder_path, icon_info, file_paths, as_str) @@ -100,7 +100,7 @@ def get_icon_svgs_paths(folder_path: Path, icon_info: dict, if path.exists(): file_paths.append(str(path) if as_str else path) else: - raise ValueError(f"This path doesn't exist: {path}") + raise ValueError(f"This path doesn't exist: '{path}'") def get_all_svgs_paths(folder_path: Path, icon_info: dict, @@ -119,7 +119,7 @@ def get_all_svgs_paths(folder_path: Path, icon_info: dict, if path.exists(): file_paths.append(str(path) if as_str else path) else: - raise ValueError(f"This path doesn't exist: {path}") + raise ValueError(f"This path doesn't exist: '{path}'") def is_alias(font_version: str, aliases: List[dict]): @@ -207,6 +207,14 @@ def create_screenshot_folder(dir, screenshot_name: str="screenshots/"): finally: return str(screenshot_folder) +def write_to_file(path: str, value: any): + """ + Write the value to a file. + """ + with open(path, "w") as file: + file.write(value) + +# --- NOT USED CURRENTLY --- def get_added_modified_svgs(files_added_json_path: str, files_modified_json_path: str): """ @@ -231,10 +239,3 @@ def get_added_modified_svgs(files_added_json_path: str, return svgs - -def write_to_file(path: str, value: any): - """ - Write the value to a file. - """ - with open(path, "w") as file: - file.write(value) diff --git a/.github/scripts/build_assets/util.py b/.github/scripts/build_assets/util.py index 9ecbc8075..f8fe55c11 100644 --- a/.github/scripts/build_assets/util.py +++ b/.github/scripts/build_assets/util.py @@ -5,6 +5,11 @@ import sys import traceback +# patterns for versions +valid_versions = "(original|plain|line)(-wordmark)?" +valid_versions_pattern = re.compile(f"^{valid_versions}$") +valid_svg_filename_pattern = re.compile(r"^\w+-" + valid_versions + r"\.svg$") + def exit_with_err(err: Exception): """ @@ -66,3 +71,20 @@ def find_object_added_in_pr(icons: List[dict], pr_title: str): 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) + + +def is_version_name_valid(version: str): + """ + Check whether the version name is valid. + :param version: the version name. + :return bool, whether the version is valid (match our standards) + """ + return valid_versions_pattern.search(version) is not None + +def is_svg_name_valid(filename: str): + """ + Check whether the svg filename is valid. + :param version: the version name. + :return bool, whether the version is valid (match our standards) + """ + return valid_svg_filename_pattern.search(filename) is not None diff --git a/.github/scripts/check_icon_pr.py b/.github/scripts/check_icon_pr.py new file mode 100644 index 000000000..2c62f9ac7 --- /dev/null +++ b/.github/scripts/check_icon_pr.py @@ -0,0 +1,165 @@ +from typing import List +import xml.etree.ElementTree as et +from pathlib import Path + + +# pycharm complains that build_assets is an unresolved ref +# don't worry about it, the script still runs +from build_assets import filehandler, arg_getters, util + + +def main(): + """ + Check the quality of the svgs IF this is an icon PR. Else, does nothing. + If any svg error is found, create a json file called 'svg_err_messages.json' + in the root folder that will contains the error messages. + """ + args = arg_getters.get_check_icon_pr_args() + try: + all_icons = filehandler.get_json_file_content(args.devicon_json_path) + + # 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) + devicon_err_msg = 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) + + err_msg = [] + if devicon_err_msg != "": + err_msg.append(devicon_err_msg) + + if filename_err_msg != "": + err_msg.append(filename_err_msg) + + if svg_err_msg != "": + err_msg.append(svg_err_msg) + + filehandler.write_to_file("./err_messages.txt", "\n\n".join(err_msg)) + print("Task completed.") + except Exception as e: + filehandler.write_to_file("./err_messages.txt", str(e)) + util.exit_with_err(e) + + +def check_devicon_object(icon: dict): + """ + Check that the devicon object added is up to standard. + :return a string containing the error messages if any. + """ + err_msgs = [] + try: + for tag in icon["tags"]: + if type(tag) != str: + raise TypeError() + except TypeError: + err_msgs.append("- 'tags' must be an array of strings, not: " + str(icon["tags"])) + except KeyError: + err_msgs.append("- missing key: 'tags'.") + + try: + if type(icon["versions"]) != dict: + err_msgs.append("- 'versions' must be an object.") + except KeyError: + err_msgs.append("- missing key: 'versions'.") + + try: + if type(icon["versions"]["svg"]) != list or len(icon["versions"]["svg"]) == 0: + err_msgs.append("- must contain at least 1 svg version in a list.") + + for version in icon["versions"]["svg"]: + if not util.is_version_name_valid(version): + 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.") + + for version in icon["versions"]["font"]: + if not util.is_version_name_valid(version): + err_msgs.append(f"- Invalid version name in versions['font']: '{version}'. Must match regexp: (original|plain|line)(-wordmark)?") + except KeyError: + err_msgs.append("- missing key: 'font' in 'versions'.") + + try: + if type(icon["color"]) != str or "#" not in icon["color"]: + err_msgs.append("- 'color' must be a string in the format '#abcdef'") + except KeyError: + err_msgs.append("- missing key: 'color'.") + + try: + if type(icon["aliases"]) != list: + err_msgs.append("- 'aliases' must be an array.") + except KeyError: + err_msgs.append("- missing key: 'aliases'.") + + if len(err_msgs) > 0: + message = "Error found in 'devicon.json' for '{}' entry: \n{}".format(icon["name"], "\n".join(err_msgs)) + return message + return "" + + +def check_svgs(svg_file_paths: List[Path]): + """ + Check the width, height, viewBox and style of each svgs passed in. + The viewBox must be '0 0 128 128'. + The style must not contain any 'stroke' declarations. + If any error is found, they will be thrown. + :param: svg_file_paths, the file paths to the svg to check for. + :return: None if there no errors. If there is, return a JSON.stringified + list with the error messages in it. + """ + # batch err messages together so user can fix everything at once + err_msgs = [] + for svg_path in svg_file_paths: + try: + err_msg = [f"SVG Error in '{svg_path.name}':"] + + # name check + if not util.is_svg_name_valid(svg_path.name): + err_msg.append("- SVG file name didn't match our pattern of `name-(original|plain|line)(-wordmark)?.svg`") + + # svg check + tree = et.parse(svg_path) + root = tree.getroot() + namespace = "{http://www.w3.org/2000/svg}" + + if root.tag != f"{namespace}svg": + err_msg.append(f"- root is '{root.tag}'. Root must be an 'svg' element") + + if root.get("viewBox") != "0 0 128 128": + err_msg.append("- 'viewBox' is not '0 0 128 128' -> Set it or scale the file using https://www.iloveimg.com/resize-image/resize-svg.") + + # goes through all elems and check for strokes + for child in tree.iter(): + if child.get("stroke") != None: + err_msg.append("- SVG contains `stroke` property. This will get ignored by Icomoon. Please convert them to fills.") + break + + if len(err_msg) > 1: + err_msgs.append("\n".join(err_msg)) + except et.ParseError as e: + raise Exception(f"SVG Error in file: {svg_path}. Full Error: \n" + str(e)) + + if len(err_msgs) > 0: + return "\n\n".join(err_msgs) + return "" + + +if __name__ == "__main__": + main() diff --git a/.github/scripts/check_svgs_on_pr.py b/.github/scripts/check_svgs_on_pr.py deleted file mode 100644 index d6a725654..000000000 --- a/.github/scripts/check_svgs_on_pr.py +++ /dev/null @@ -1,89 +0,0 @@ -from enum import Enum -from typing import List -import xml.etree.ElementTree as et -from pathlib import Path - - -# pycharm complains that build_assets is an unresolved ref -# don't worry about it, the script still runs -from build_assets import filehandler, arg_getters -from build_assets import util - - -class SVG_STATUS_CODE(Enum): - """ - The status codes to check for in post_check_svgs_comment.yml - """ - NO_SVG = 0 # action: do nothing - SVG_OK = 1 # action: let user know their svgs are fine - - -def main(): - """ - Check the quality of the svgs. - If any svg error is found, create a json file called 'svg_err_messages.json' - in the root folder that will contains the error messages. - """ - args = arg_getters.get_check_svgs_on_pr_args() - try: - # check the svgs - svgs = filehandler.get_added_modified_svgs(args.files_added_json_path, - args.files_modified_json_path) - print("SVGs to check: ", *svgs, sep='\n') - - if len(svgs) == 0: - print("No SVGs to check, ending script.") - err_messages = SVG_STATUS_CODE.NO_SVG.value - else: - err_messages = check_svgs(svgs) - - filehandler.write_to_file("./svg_err_messages.txt", str(err_messages)) - print("Task completed.") - except Exception as e: - util.exit_with_err(e) - - -def check_svgs(svg_file_paths: List[Path]): - """ - Check the width, height, viewBox and style of each svgs passed in. - The viewBox must be '0 0 128 128'. - If the svg has a width and height attr, ensure it's '128px'. - The style must not contain any 'fill' declarations. - If any error is found, they will be thrown. - :param: svg_file_paths, the file paths to the svg to check for. - :return: None if there no errors. If there is, return a JSON.stringified - list with the error messages in it. - """ - # batch err messages together so user can fix everything at once - err_msgs = [] - for svg_path in svg_file_paths: - try: - tree = et.parse(svg_path) - root = tree.getroot() - namespace = "{http://www.w3.org/2000/svg}" - err_msg = [f"{svg_path}:"] - - if root.tag != f"{namespace}svg": - err_msg.append(f"-root is '{root.tag}'. Root must be an 'svg' element") - - if root.get("viewBox") != "0 0 128 128": - err_msg.append("-'viewBox' is not '0 0 128 128' -> Set it or scale the file using https://www.iloveimg.com/resize-image/resize-svg.") - - if root.get("x") is not None: - err_msg.append("-unneccessary 'x' attribute in svg root element -> Remove it") - - if root.get("y") is not None: - err_msg.append("-unneccessary 'y' attribute in svg root element -> Remove it") - - if len(err_msg) > 1: - err_msgs.append("\n".join(err_msg)) - except et.ParseError as e: - raise Exception(f"SVG Error in file: {svg_path}. Full Error: \n" + str(e)) - - if len(err_msgs) > 0: - return "\n\n".join(err_msgs) - return SVG_STATUS_CODE.SVG_OK.value - - -if __name__ == "__main__": - main() diff --git a/.github/scripts/icomoon_build.py b/.github/scripts/icomoon_build.py index 1a362c697..f59f5414c 100644 --- a/.github/scripts/icomoon_build.py +++ b/.github/scripts/icomoon_build.py @@ -20,34 +20,39 @@ def main(): runner = None try: args = arg_getters.get_selenium_runner_args() - new_icons = get_icons_for_building(args.icomoon_json_path, args.devicon_json_path, args.token) - 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("Begin optimizing files...") - optimize_svgs(new_icons, args.icons_folder_path) - - print("Updating the icomoon json...") - update_icomoon_json(new_icons, args.icomoon_json_path) - - print("Start the building icons process...") - 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) - 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) - - print("Creating the release message by querying the GitHub API...") - get_release_message(args.token) + # new_icons = get_icons_for_building(args.icomoon_json_path, args.devicon_json_path, args.token) + # 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("Begin optimizing files...") + # optimize_svgs(new_icons, args.icons_folder_path) + + # print("Updating the icomoon json...") + # update_icomoon_json(new_icons, args.icomoon_json_path) + + # print("Start the building icons process...") + # 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) + # 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) + + # print("Creating the release message by querying the GitHub API...") + # get_release_message(args.token) + + print("Closing the issues with the label of `in-develop`.") + 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.") except TimeoutException as e: diff --git a/.github/scripts/icomoon_peek.py b/.github/scripts/icomoon_peek.py index 900f1aae4..fe53ad482 100644 --- a/.github/scripts/icomoon_peek.py +++ b/.github/scripts/icomoon_peek.py @@ -1,6 +1,5 @@ from build_assets.selenium_runner.PeekSeleniumRunner import PeekSeleniumRunner -from build_assets import filehandler, arg_getters -from build_assets import util +from build_assets import filehandler, arg_getters, util def main(): diff --git a/.github/scripts/in_develop_labeler.py b/.github/scripts/in_develop_labeler.py new file mode 100644 index 000000000..9d4917796 --- /dev/null +++ b/.github/scripts/in_develop_labeler.py @@ -0,0 +1,20 @@ +import re +from build_assets import arg_getters, api_handler + +def main(): + args = arg_getters.get_in_develop_labeler_args() + try: + # find the issue closing line + issue_line = [line for line in args.body.split("\n") if line.startswith("**This PR closes")][0] + + print("Issue Line is " + issue_line) + issue_pattern = re.compile(r"\d+") + issues_numbers = issue_pattern.findall(issue_line) + print("Labelling issues: " + str(issues_numbers)) + api_handler.label_issues(args.token, args.repo, issues_numbers, ["in-develop"]) + except IndexError: # if can't find the issue line + print("The PR body doesn't contain `**This PR closes` keywords. Ending workflow.") + return + +if __name__ == "__main__": + main() diff --git a/.github/workflows/build_icons.yml b/.github/workflows/build_icons.yml index 2d1d68e62..4747bd0bc 100644 --- a/.github/workflows/build_icons.yml +++ b/.github/workflows/build_icons.yml @@ -23,7 +23,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: > python ./.github/scripts/icomoon_build.py - ./.github/scripts/build_assets/geckodriver-v0.29.1-win64/geckodriver.exe ./icomoon.json + ./.github/scripts/build_assets/geckodriver-v0.30.0-win64/geckodriver.exe ./icomoon.json ./devicon.json ./icons ./ %GITHUB_TOKEN% --headless - name: Upload geckodriver.log for debugging purposes diff --git a/.github/workflows/check_svgs_on_pr.yml b/.github/workflows/check_icon_pr.yml similarity index 56% rename from .github/workflows/check_svgs_on_pr.yml rename to .github/workflows/check_icon_pr.yml index 70dd42446..1247ed8ae 100644 --- a/.github/workflows/check_svgs_on_pr.yml +++ b/.github/workflows/check_icon_pr.yml @@ -1,9 +1,10 @@ -name: Check SVGs On PR +name: Check Icon PR on: pull_request jobs: check: - name: Check the SVGs' quality + name: Check the `devicon.json` and the SVGs' quality runs-on: ubuntu-18.04 + if: startsWith(github.event.pull_request.title, 'new icon') # only checks icon PR steps: - uses: actions/checkout@v2 @@ -11,24 +12,17 @@ jobs: with: python-version: 3.8 - - name: Install dependencies - run: python -m pip install --upgrade pip - - - name: Get Changed Files and generate files_added.json & files_modified.json - uses: lots0logs/gh-action-get-changed-files@2.1.4 - with: - token: ${{ secrets.GITHUB_TOKEN }} - - name: Run the check_svg script - run: > - python ./.github/scripts/check_svgs_on_pr.py $HOME/files_added.json $HOME/files_modified.json + env: + PR_TITLE: ${{ github.event.pull_request.title }} + run: python ./.github/scripts/check_icon_pr.py "$PR_TITLE" ./icons ./devicon.json - name: Upload the err messages uses: actions/upload-artifact@v2 if: success() with: - name: svg_err_messages - path: ./svg_err_messages.txt + name: err_messages + path: ./err_messages.txt - name: Save the pr num in an artifact shell: bash diff --git a/.github/workflows/in_develop_labeler.yml b/.github/workflows/in_develop_labeler.yml new file mode 100644 index 000000000..22ce676ed --- /dev/null +++ b/.github/workflows/in_develop_labeler.yml @@ -0,0 +1,27 @@ +name: Label Issue In Develop +on: + pull_request: + types: [closed] +jobs: + label: + name: Label Issue In Develop + runs-on: ubuntu-18.04 + if: github.event.pull_request.merged == true + steps: + - uses: actions/checkout@v2 + + - name: Setup Python v3.8 + uses: actions/setup-python@v2 + with: + python-version: 3.8 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r ./.github/scripts/requirements.txt + + - name: Run in_develop_labeler.py + env: + TOKEN: ${{ secrets.GITHUB_TOKEN }} + BODY: ${{ github.event.pull_request.body }} + run: python ./.github/scripts/in_develop_labeler.py $TOKEN "$BODY" $GITHUB_REPOSITORY diff --git a/.github/workflows/post_check_svgs_comment.yml b/.github/workflows/post_check_icon_pr_comment.yml similarity index 78% rename from .github/workflows/post_check_svgs_comment.yml rename to .github/workflows/post_check_icon_pr_comment.yml index 5ac89d3aa..716ca752b 100644 --- a/.github/workflows/post_check_svgs_comment.yml +++ b/.github/workflows/post_check_icon_pr_comment.yml @@ -1,7 +1,7 @@ -name: Post the result of a SVG Check into its PR. +name: Post the result of the check_icon_pr workflow into its PR. on: workflow_run: - workflows: ['Check SVGs On PR'] + workflows: ['Check Icon PR'] types: - completed jobs: @@ -18,7 +18,7 @@ jobs: if: success() with: github_token: ${{ secrets.GITHUB_TOKEN }} - workflow: peek_icons.yml + workflow: check_icon_pr.yml run_id: ${{ github.event.workflow_run.id }} - name: Read the pr_num file @@ -33,30 +33,27 @@ jobs: id: err_message_reader uses: juliangruber/read-file-action@v1.0.0 with: - path: ./svg_err_messages/svg_err_messages.txt + path: ./err_messages/err_messages.txt - name: Comment on the PR about the result - SVG Error uses: jungwinter/comment@v1 # let us comment on a specific PR - if: success() && (steps.err_message_reader.outputs.content != '0' && steps.err_message_reader.outputs.content != '1') + if: success() && (steps.err_message_reader.outputs.content != '') env: MESSAGE: | Hi! - I'm Devicons' SVG-Checker Bot and it seems we have some issues with your SVGs. + I'm the `check-bot` and we have some issues with your PR: - Here is what went wrong: ``` {0} ``` - For more reference on why these are errors, check out our [CONTRIBUTING guide](https://github.com/devicons/devicon/blob/develop/CONTRIBUTING.md#svgStandards) + Check our [CONTRIBUTING guide](https://github.com/devicons/devicon/blob/develop/CONTRIBUTING.md#svgStandards) for more details regarding these errors. Please address these issues. When you update this PR, I will check your SVGs again. Thanks for your help, SVG-Checker Bot :smile: - - PS. One day, I will be smart enough to fix these errors for you :persevere:. Until then, I can only point them out. with: type: create issue_number: ${{ steps.pr_num_reader.outputs.content }} diff --git a/devicon.json b/devicon.json index d9a40c776..ccd0fb913 100644 --- a/devicon.json +++ b/devicon.json @@ -92,6 +92,26 @@ "color": "#A4C439", "aliases": [] }, + { + "name": "testingicon", + "tags": [ + "architecture", + "programming", + "language", + "ARM" + ], + "versions": { + "svg": [ + "original", + "plain" + ], + "font": [ + "plain" + ] + }, + "color": "#16358C", + "aliases": [] + }, { "name": "aarch64", "tags": [ diff --git a/err_messages.txt b/err_messages.txt new file mode 100644 index 000000000..b6c9c6986 --- /dev/null +++ b/err_messages.txt @@ -0,0 +1,3 @@ +SVG Error in 'testingicon-original.svg': +- 'viewBox' is not '0 0 128 128' -> Set it or scale the file using https://www.iloveimg.com/resize-image/resize-svg. +- SVG contains `stroke` property. This will get ignored by Icomoon. Please convert them to fills. \ No newline at end of file diff --git a/gulpfile.js b/gulpfile.js index 9a7c74344..f6cc2fae5 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -187,6 +187,12 @@ function configOptionCallback(file) { }, { removeDimensions: true // remove height and width + }, + { + name: "removeAttrs", + params: { + attrs: "svg:(x|y)" + } } ] }; diff --git a/icons/testingicon/testingicon-origi.svg b/icons/testingicon/testingicon-origi.svg new file mode 100644 index 000000000..66009d4d3 --- /dev/null +++ b/icons/testingicon/testingicon-origi.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/testingicon/testingicon-original.svg b/icons/testingicon/testingicon-original.svg new file mode 100644 index 000000000..66009d4d3 --- /dev/null +++ b/icons/testingicon/testingicon-original.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/icons/testingicon/testingicon-plain.svg b/icons/testingicon/testingicon-plain.svg new file mode 100644 index 000000000..10774d41a --- /dev/null +++ b/icons/testingicon/testingicon-plain.svg @@ -0,0 +1 @@ + \ No newline at end of file