Skip to content

Commit fc615c1

Browse files
ci: allow multi submission
1 parent df4e8bd commit fc615c1

File tree

6 files changed

+95
-95
lines changed

6 files changed

+95
-95
lines changed

.github/scripts/build_assets/arg_getters.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
def get_selenium_runner_args(has_token=True, peek_mode=False):
66
"""
7-
Get the commandline arguments for the icomoon_peek.py and
7+
Get the commandline arguments for the icomoon_peek.py and
88
icomoon_build.py.
99
"""
1010
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):
4040
parser.add_argument("token",
4141
help="The GitHub token to access the GitHub REST API.")
4242

43+
parser.add_argument("changed_files",
44+
help="List of SVG files changed since the last release/tag",
45+
nargs="+")
46+
4347
return parser.parse_args()
4448

4549

@@ -49,9 +53,6 @@ def get_check_icon_pr_args():
4953
"""
5054
parser = ArgumentParser(description="Check the SVGs to ensure their attributes are correct. Run whenever a PR is opened")
5155

52-
parser.add_argument("pr_title",
53-
help="The title of the PR that we are peeking at")
54-
5556
parser.add_argument("icons_folder_path",
5657
help="The path to the icons folder",
5758
action=PathResolverAction)
@@ -60,6 +61,10 @@ def get_check_icon_pr_args():
6061
help="The path to the devicon.json",
6162
action=PathResolverAction)
6263

64+
parser.add_argument("changed_files",
65+
help="List of SVG files changed in the PR",
66+
nargs="+")
67+
6368
return parser.parse_args()
6469

6570

.github/scripts/build_assets/util.py

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,29 +50,24 @@ def set_env_var(key: str, value: str, delimiter: str='~'):
5050
raise Exception("This function doesn't support this platform: " + platform.system())
5151

5252

53-
def find_object_added_in_pr(icons: List[dict], pr_title: str):
53+
def find_changed_icons(icons: List[dict], changed_files: List[str]) -> List[dict]:
5454
"""
55-
Find the icon name from the PR title.
55+
Find the changed icons in the PR.
5656
:param icons, a list of the font objects found in the devicon.json.
57-
:pr_title, the title of the PR that this workflow was called on.
58-
:return a dictionary with the "name"
59-
entry's value matching the name in the pr_title.
60-
:raise If no object can be found, raise an Exception.
57+
:changed_files, SVG files changed in this PR.
58+
:return a list of dictionaries with the "name"
59+
entry values matching the name of changed icons.
6160
"""
62-
try:
63-
pattern = re.compile(r"(?<=^new icon: )\w+ (?=\(.+\))|(?<=^update icon: )\w+ (?=\(.+\))", re.I)
64-
icon_name_index = 0
65-
icon_name = pattern.findall(pr_title)[icon_name_index].lower().strip() # should only have one match
66-
icon = [icon for icon in icons if icon["name"] == icon_name][0]
67-
return icon
68-
except IndexError as e: # there are no match in the findall()
69-
print(e)
70-
message = "util.find_object_added_in_pr: Couldn't find an icon matching the name in the PR title.\n" \
71-
f"PR title is: '{pr_title}'"
72-
raise Exception(message)
61+
filtered_icons = []
62+
for file in changed_files:
63+
icon_name = Path(file).parent.name
64+
icon = [icon for icon in icons if icon["name"] == icon_name]
65+
if len(icon) > 0:
66+
filtered_icons.extend(icon)
67+
return filtered_icons
7368

7469

75-
def is_svg_in_font_attribute(svg_file_path: Path, devicon_object: dict):
70+
def is_svg_in_font_attribute(svg_file_path: Path, devicon_object: dict):
7671
"""
7772
Check if svg is in devicon.json's font attribute.
7873
:param svg_file_path, the path to a single svg icon

.github/scripts/check_icon_pr.py

Lines changed: 37 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,42 +18,45 @@ def main():
1818
try:
1919
all_icons = filehandler.get_json_file_content(args.devicon_json_path)
2020

21-
devicon_err_msg = []
21+
err_msg = []
2222
#First check if devicon.json is sorted
2323
if sorted(all_icons, key=lambda d: d['name']) != all_icons:
24-
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")
24+
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")
2525

2626
# get only the icon object that has the name matching the pr title
27-
filtered_icon = util.find_object_added_in_pr(all_icons, args.pr_title)
28-
print("Checking devicon.json object: " + str(filtered_icon))
29-
devicon_err_msg.append(check_devicon_object(filtered_icon))
30-
31-
# check the file names
32-
filename_err_msg = ""
33-
svgs = None
34-
try:
35-
svgs = filehandler.get_svgs_paths([filtered_icon], args.icons_folder_path, as_str=False)
36-
print("SVGs to check: ", *svgs, sep='\n')
37-
except ValueError as e:
38-
filename_err_msg = "Error found regarding filenames:\n- " + e.args[0]
39-
40-
# check the svgs
41-
if svgs is None or len(svgs) == 0:
42-
print("No SVGs to check, ending script.")
43-
svg_err_msg = "Error checking SVGs: no SVGs to check. Might be caused by above issues."
44-
else:
45-
svg_err_msg = check_svgs(svgs, filtered_icon)
46-
47-
err_msg = []
48-
if devicon_err_msg != []:
49-
err_msg.extend(devicon_err_msg)
50-
51-
if filename_err_msg != "":
52-
err_msg.append(filename_err_msg)
53-
54-
if svg_err_msg != "":
55-
err_msg.append(svg_err_msg)
56-
27+
filtered_icons = util.find_changed_icons(all_icons, args.changed_files)
28+
for filtered_icon in filtered_icons:
29+
devicon_err_msg = []
30+
print("Checking devicon.json object: " + str(filtered_icon))
31+
devicon_err_msg.append(check_devicon_object(filtered_icon))
32+
33+
# check the file names
34+
filename_err_msg = ""
35+
svgs = None
36+
try:
37+
svgs = filehandler.get_svgs_paths([filtered_icon], args.icons_folder_path, as_str=False)
38+
print("SVGs to check: ", *svgs, sep='\n')
39+
except ValueError as e:
40+
filename_err_msg = "Error found regarding filenames:\n- " + e.args[0]
41+
42+
# check the svgs
43+
if svgs is None or len(svgs) == 0:
44+
print("No SVGs to check for this icon.")
45+
svg_err_msg = "Error checking SVGs: no SVGs to check. Might be caused by above issues."
46+
else:
47+
svg_err_msg = check_svgs(svgs, filtered_icon)
48+
49+
if devicon_err_msg:
50+
err_msg.extend(devicon_err_msg)
51+
52+
if filename_err_msg:
53+
err_msg.append(filename_err_msg)
54+
55+
if svg_err_msg:
56+
err_msg.append(svg_err_msg)
57+
58+
err_msg = list(filter(None, err_msg)) # remove empty strings from err_msg
59+
print("Error messages: ", err_msg)
5760
filehandler.write_to_file("./err_messages.txt", "\n\n".join(err_msg))
5861
print("Task completed.")
5962
except Exception as e:
@@ -109,7 +112,7 @@ def check_devicon_object(icon: dict):
109112
err_msgs.append(f"- Invalid version name in versions['svg']: '{version}'. Must match regexp: (original|plain|line)(-wordmark)?")
110113
except KeyError:
111114
err_msgs.append("- missing key: 'svg' in 'versions'.")
112-
115+
113116
try:
114117
if type(icon["versions"]["font"]) != list or len(icon["versions"]["svg"]) == 0:
115118
err_msgs.append("- must contain at least 1 font version in a list.")
@@ -160,7 +163,7 @@ def check_devicon_object(icon: dict):
160163
if len(err_msgs) > 0:
161164
message = "Error found in \"devicon.json\" for \"{}\" entry: \n{}".format(icon["name"], "\n".join(err_msgs))
162165
return message
163-
return ""
166+
return ""
164167

165168

166169
def check_svgs(svg_file_paths: List[Path], devicon_object: dict):

.github/scripts/icomoon_build.py

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def main():
2222
logfile = open("log.txt", "w")
2323
try:
2424
args = arg_getters.get_selenium_runner_args()
25-
new_icons = get_icons_for_building(args.icomoon_json_path, args.devicon_json_path, args.token, logfile)
25+
new_icons = get_icons_for_building(args.devicon_json_path, args.changed_files)
2626
if len(new_icons) == 0:
2727
sys.exit("No files need to be uploaded. Ending script...")
2828

@@ -39,7 +39,7 @@ def main():
3939
new_icons, args.icons_folder_path, icon_versions_only=True)
4040
zip_name = "devicon-v1.0.zip"
4141
zip_path = Path(args.download_path, zip_name)
42-
screenshot_folder = filehandler.create_screenshot_folder("./")
42+
screenshot_folder = filehandler.create_screenshot_folder("./")
4343

4444
runner = BuildSeleniumRunner(args.download_path,
4545
args.geckodriver_path, args.headless, log_output=logfile)
@@ -65,38 +65,26 @@ def main():
6565
finally:
6666
print("Exiting", file=logfile)
6767
if runner is not None:
68-
runner.close()
68+
runner.close()
6969
logfile.close()
7070

7171

72-
def get_icons_for_building(icomoon_json_path: str, devicon_json_path: str, token: str, logfile: FileIO):
72+
def get_icons_for_building(devicon_json_path: str, changed_files: List[str]):
7373
"""
7474
Get the icons for building.
75-
:param icomoon_json_path - the path to the `icomoon.json`.
7675
:param devicon_json_path - the path to the `devicon.json`.
77-
:param token - the token to access the GitHub API.
78-
:param logfile.
79-
:return a list of dict containing info on the icons. These are
76+
:param changed_files - the list of changed files since the last release/tag.
77+
78+
:return a list of dict containing info on the icons. These are
8079
from the `devicon.json`.
8180
"""
8281
devicon_json = filehandler.get_json_file_content(devicon_json_path)
83-
pull_reqs = api_handler.get_merged_pull_reqs_since_last_release(token, logfile)
8482
new_icons = []
8583

86-
for pull_req in pull_reqs:
87-
if api_handler.is_feature_icon(pull_req):
88-
filtered_icon = util.find_object_added_in_pr(devicon_json, pull_req["title"])
89-
if filtered_icon not in new_icons:
90-
new_icons.append(filtered_icon)
91-
92-
# get any icons that might not have been found by the API
93-
# sometimes happen due to the PR being opened before the latest build release
94-
new_icons_from_devicon_json = filehandler.find_new_icons_in_devicon_json(
95-
devicon_json_path, icomoon_json_path)
84+
filtered_icons = util.find_changed_icons(devicon_json, changed_files)
9685

97-
for icon in new_icons_from_devicon_json:
98-
if icon not in new_icons:
99-
new_icons.append(icon)
86+
# add the filtered icons to the new_icons list only if they are not already there
87+
new_icons.extend([icon for icon in filtered_icons if icon not in new_icons])
10088

10189
return new_icons
10290

@@ -137,15 +125,15 @@ def update_icomoon_json(new_icons: List[str], icomoon_json_path: str, logfile: F
137125
new_len = len(icomoon_json["icons"])
138126
print(f"Update completed. Removed {cur_len - new_len} icons:", *messages, sep='\n', file=logfile)
139127
filehandler.write_to_file(icomoon_json_path, json.dumps(icomoon_json))
140-
128+
141129

142130
def find_icomoon_icon_not_in_new_icons(icomoon_icon: Dict, new_icons: List, messages: List):
143131
"""
144132
Find all the icomoon icons that are not listed in the new icons.
145133
This also add logging for which icons were removed.
146134
:param icomoon_icon - a dict object from the icomoon.json's `icons` attribute.
147135
:param new_icons - a list of new icons. Each element is an object from the `devicon.json`.
148-
:param messages - an empty list where the function can attach logging on which
136+
:param messages - an empty list where the function can attach logging on which
149137
icon were removed.
150138
"""
151139
for new_icon in new_icons:
@@ -182,7 +170,7 @@ def get_release_message(token, logfile: FileIO):
182170
thankYou = "A huge thanks to all our maintainers and contributors for making this release possible!"
183171
iconTitle = f"**{len(newIcons)} New Icons**"
184172
featureTitle = f"**{len(features)} New Features**"
185-
finalString = "{0}\n\n {1}\n{2}\n\n {3}\n{4}".format(thankYou,
173+
finalString = "{0}\n\n {1}\n{2}\n\n {3}\n{4}".format(thankYou,
186174
iconTitle, "\n".join(newIcons),
187175
featureTitle, "\n".join(features))
188176

.github/workflows/build_icons.yml

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77
steps:
88
- uses: actions/checkout@v3
99
- uses: actions/setup-python@v4
10-
with:
10+
with:
1111
python-version: '3.10'
1212

1313
- name: Install dependencies (python, pip, npm)
@@ -20,10 +20,18 @@ jobs:
2020
shell: bash
2121
env:
2222
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
23-
run: >
24-
python ./.github/scripts/icomoon_build.py
25-
./.github/scripts/build_assets/geckodriver-v0.32.2-linux64/geckodriver ./icomoon.json
26-
./devicon.json ./icons ./ $GITHUB_TOKEN --headless
23+
run: |
24+
git fetch --tags
25+
CHANGED_ICONS=$(git diff --name-only $(git describe --tags --abbrev=0)..HEAD | grep -E 'icons/.*\.svg')
26+
python ./.github/scripts/icomoon_build.py \
27+
./.github/scripts/build_assets/geckodriver-v0.32.2-linux64/geckodriver
28+
./icomoon.json \
29+
./devicon.json \
30+
./icons \
31+
./ \
32+
$GITHUB_TOKEN \
33+
${CHANGED_ICONS} \
34+
--headless
2735
2836
- name: Upload geckodriver.log for debugging purposes
2937
uses: actions/upload-artifact@v2
@@ -40,7 +48,7 @@ jobs:
4048
path: ./log.txt
4149

4250
- name: Build devicon.min.css
43-
if: success()
51+
if: success()
4452
run: npm run build-css
4553

4654
# - name: Upload screenshot of the newly made icons
@@ -58,10 +66,10 @@ jobs:
5866
uses: juliangruber/[email protected]
5967
with:
6068
# taken from icomoon_build.py's get_release_message()
61-
path: ./release_message.txt
69+
path: ./release_message.txt
6270

6371
- name: Create Pull Request
64-
if: success()
72+
if: success()
6573
uses: peter-evans/create-pull-request@v3
6674
env:
6775
MESSAGE: |

.github/workflows/check_icon_pr.yml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ jobs:
66
runs-on: ubuntu-latest
77
if: startsWith(github.event.pull_request.title, 'new icon') || startsWith(github.event.pull_request.title, 'update icon') # only checks icon PR
88
steps:
9-
- uses: actions/checkout@v3
9+
- uses: actions/checkout@v4
1010

1111
- name: Check if PR is develop
1212
if: ${{ github.base_ref != 'develop' }}
1313
run: |
1414
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
1515
echo "wrong_branch=true" >> $GITHUB_ENV
16-
16+
1717
- uses: actions/setup-python@v4
1818
if: ${{ !env.wrong_branch }}
19-
with:
19+
with:
2020
python-version: 3.8
2121

2222
- name: Install dependencies
@@ -27,9 +27,10 @@ jobs:
2727
2828
- name: Run the check_svg script
2929
if: ${{ !env.wrong_branch }}
30-
env:
31-
PR_TITLE: ${{ github.event.pull_request.title }}
32-
run: python ./.github/scripts/check_icon_pr.py "$PR_TITLE" ./icons ./devicon.json
30+
run: |
31+
git fetch origin ${{ github.base_ref }}
32+
CHANGED_ICONS=$(git diff --name-only origin/${{ github.base_ref }} ${{ github.sha }} | grep -E 'icons/.*\.svg')
33+
python ./.github/scripts/check_icon_pr.py ./icons ./devicon.json ${CHANGED_ICONS}
3334
3435
- name: Upload the err messages
3536
uses: actions/upload-artifact@v3

0 commit comments

Comments
 (0)