Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing github action for build automatisation (using python) #268

Merged
merged 52 commits into from
Sep 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
bffbac0
Moved css into its own folders
Thomas-Boi Apr 25, 2020
864e08a
Merge branch 'master' of https://github.com/konpa/devicon
Thomas-Boi Jul 28, 2020
effdb96
Added files to upgrade devicon.json and a simple github workflow
Thomas-Boi Aug 17, 2020
330c994
Added workflow for building the repo
Thomas-Boi Aug 18, 2020
d3ef847
Workflow now takes path to geckodriver instead of manually adding it …
Thomas-Boi Aug 21, 2020
7fafae1
Added action to commit built file
Thomas-Boi Aug 21, 2020
9a33742
Added checks to see if devicon zip file is downloaded
Thomas-Boi Aug 25, 2020
24efc9a
Built new icons, icomoon.json and devicon.css
Thomas-Boi Aug 25, 2020
7d8b3cb
Update .github/workflows/build_icons.yml
Thomas-Boi Sep 1, 2020
a34da1b
merge master with build-integrate branch
amacado Sep 1, 2020
5ac2c58
Merge remote-tracking branch 'origin/master' into merge/build-integra…
amacado Sep 1, 2020
83378fa
Merge pull request #276 from devicons/merge/build-integrate/master
Thomas-Boi Sep 2, 2020
33b0722
Added __pycache__ to gitignore. Documented geckodriver. Invalid path …
Thomas-Boi Sep 2, 2020
72a6dbf
Add checks for when there are no files to commit. Also fix a bug with…
Thomas-Boi Sep 2, 2020
5aa1708
Removed .pyc files and add them to gitignore
Thomas-Boi Sep 2, 2020
0a71b13
Fixed a bug where workflow trigger got reverted back to push
Thomas-Boi Sep 2, 2020
2fb0918
Fix a bug where the SeleniumRunner doesn't run properly
Thomas-Boi Sep 2, 2020
00b2996
download_path commandline arg doesn't have to exist for script to fun…
Thomas-Boi Sep 2, 2020
ecf1012
Build script now look for devicon-*.zip pattern instead of const string
Thomas-Boi Sep 2, 2020
c6848be
Fix a bug with the workflow
Thomas-Boi Sep 3, 2020
52d729a
Fix a bug for the ref error in the workflow
Thomas-Boi Sep 3, 2020
2aa03e2
Added a fix to the workflow commit bug
Thomas-Boi Sep 4, 2020
96fb237
Downgrade geckodriver to v0.26
Thomas-Boi Sep 4, 2020
dcdcc60
Revert "Downgrade geckodriver to v0.26"
Thomas-Boi Sep 4, 2020
a7619e2
Add try-except in icomoon_upload. Workflow will also upload geckodriv…
Thomas-Boi Sep 4, 2020
77460c3
Built new icons, icomoon.json and devicon.css
Thomas-Boi Sep 4, 2020
75a9195
remove icons with typo (as in 493ebf3c0b94849323b333e1f19eb3dd1f7e3582)
amacado Sep 6, 2020
220c3d8
enhance readme about geckodriver
amacado Sep 6, 2020
fd24c48
Merge pull request #1 from amacado/build-integrate
amacado Sep 6, 2020
668c10a
remove built_files dir
amacado Sep 6, 2020
3a49809
Built new icons, icomoon.json and devicon.css
amacado Sep 6, 2020
138798f
Merge pull request #2 from amacado/build-integrate
amacado Sep 6, 2020
2d3abe9
readd amazonwebservices in devicon.json
amacado Sep 6, 2020
edf42fe
Merge remote-tracking branch 'origin/build-integrate' into build-inte…
amacado Sep 6, 2020
bd20509
Built new icons, icomoon.json and devicon.css
amacado Sep 6, 2020
112532c
Merge pull request #3 from amacado/build-integrate
amacado Sep 6, 2020
45c7bfb
remove branch from action
amacado Sep 6, 2020
e8c2839
Build new icons, icomoon.json and devicon.css
amacado Sep 6, 2020
2187e82
Merge remote-tracking branch 'origin/master' into build-integrate
amacado Sep 6, 2020
ee24132
Merge remote-tracking branch 'origin/build-integrate' into build-inte…
amacado Sep 6, 2020
17bf149
Build new icons, icomoon.json and devicon.css
amacado Sep 6, 2020
a24e3aa
Merge pull request #4 from amacado/build-integrate
amacado Sep 6, 2020
dedf8c7
add name for geckodriver log build artifact
amacado Sep 6, 2020
5627a92
Build new icons, icomoon.json and devicon.css
amacado Sep 6, 2020
8dbd464
Merge pull request #5 from amacado/build-integrate
amacado Sep 6, 2020
a818e3e
Build new icons, icomoon.json and devicon.css
amacado Sep 6, 2020
e9d110b
add handling for no given aliases
amacado Sep 6, 2020
047ab67
Build new icons, icomoon.json and devicon.css
amacado Sep 6, 2020
e6a5f9c
add gulp action for building devicon.min.css
amacado Sep 6, 2020
3788400
Build new icons, icomoon.json and devicon.css
amacado Sep 6, 2020
377c739
Merge pull request #281 from amacado/master
Thomas-Boi Sep 7, 2020
a2a1720
Build new icons, icomoon.json and devicon.css
Thomas-Boi Sep 7, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/scripts/build_assets/PathResolverAction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import argparse
from pathlib import Path


class PathResolverAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
path = Path(values).resolve()
if not path.exists():
raise ValueError(f"{path} doesn't exist.")

if self.dest == "icons_folder_path":
if not path.is_dir():
raise ValueError("icons_folder_path must be a directory")

elif self.dest == "download_path":
if not path.is_dir():
raise ValueError("download_path must be a directory")

setattr(namespace, self.dest, str(path))
264 changes: 264 additions & 0 deletions .github/scripts/build_assets/SeleniumRunner.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
from typing import List
from pathlib import Path
import time

from selenium.webdriver.firefox.webdriver import WebDriver
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from selenium.common.exceptions import TimeoutException as SeleniumTimeoutException


class SeleniumRunner:
"""
A runner that upload and download Icomoon resources using Selenium.
The WebDriver will use Firefox.
"""

"""
The long wait time for the driver in seconds.
"""
LONG_WAIT_IN_SEC = 25

"""
The medium wait time for the driver in seconds.
"""
MED_WAIT_IN_SEC = 6

"""
The short wait time for the driver in seconds.
"""
SHORT_WAIT_IN_SEC = 0.6

"""
The Icomoon Url.
"""
ICOMOON_URL = "https://icomoon.io/app/#/select"

def __init__(self, icomoon_json_path: str, download_path: str,
geckodriver_path: str, headless):
"""
Create a SeleniumRunner object.
:param icomoon_json_path: a path to the iconmoon.json.
:param download_path: the location where you want to download
the icomoon.zip to.
:param geckodriver_path: the path to the firefox executable.
:param headless: whether to run browser in headless (no UI) mode.
"""
self.icomoon_json_path = icomoon_json_path
self.download_path = download_path
self.driver = None
self.set_options(geckodriver_path, headless)

def set_options(self, geckodriver_path: str, headless: bool):
"""
Build the WebDriver with Firefox Options allowing downloads and
set download to download_path.
:param geckodriver_path: the path to the firefox executable.
:param headless: whether to run browser in headless (no UI) mode.

:raises AssertionError: if the page title does not contain
"IcoMoon App".
"""
options = Options()
allowed_mime_types = "application/zip, application/gzip, application/octet-stream"
# disable prompt to download from Firefox
options.set_preference("browser.helperApps.neverAsk.saveToDisk", allowed_mime_types)
options.set_preference("browser.helperApps.neverAsk.openFile", allowed_mime_types)

# set the default download path to downloadPath
options.set_preference("browser.download.folderList", 2)
options.set_preference("browser.download.dir", self.download_path)
options.headless = headless

self.driver = WebDriver(options=options, executable_path=geckodriver_path)
self.driver.get(self.ICOMOON_URL)
assert "IcoMoon App" in self.driver.title

def upload_icomoon(self):
"""
Upload the icomoon.json to icomoon.io.
:raises TimeoutException: happens when elements are not found.
"""
print("Uploading icomoon.json file...")
try:
# find the file input and enter the file path
import_btn = WebDriverWait(self.driver, SeleniumRunner.LONG_WAIT_IN_SEC).until(
ec.presence_of_element_located((By.CSS_SELECTOR, "div#file input"))
)
import_btn.send_keys(self.icomoon_json_path)
except Exception as e:
self.close()
raise e

try:
confirm_btn = WebDriverWait(self.driver, SeleniumRunner.MED_WAIT_IN_SEC).until(
ec.element_to_be_clickable((By.XPATH, "//div[@class='overlay']//button[text()='Yes']"))
)
confirm_btn.click()
except SeleniumTimeoutException as e:
print(e.stacktrace)
print("Cannot find the confirm button when uploading the icomoon.json",
"Ensure that the icomoon.json is in the correct format for Icomoon.io",
sep='\n')
self.close()

print("JSON file uploaded.")

def upload_svgs(self, svgs: List[str]):
"""
Upload the SVGs provided in folder_info
:param svgs: a list of svg Paths that we'll upload to icomoon.
"""
try:
print("Uploading SVGs...")

edit_mode_btn = self.driver.find_element_by_css_selector(
"div.btnBar button i.icon-edit"
)
edit_mode_btn.click()

self.click_hamburger_input()

for svg in svgs:
import_btn = self.driver.find_element_by_css_selector(
"li.file input[type=file]"
)
import_btn.send_keys(svg)
print(f"Uploaded {svg}")
self.test_for_possible_alert(self.SHORT_WAIT_IN_SEC, "Dismiss")
self.remove_color_from_icon()

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()
except Exception as e:
self.close()
raise e

def click_hamburger_input(self):
"""
Click the hamburger input until the pop up menu appears. This
method is needed because sometimes, we need to click the hamburger
input two times before the menu appears.
:return: None.
"""
try:
hamburger_input = self.driver.find_element_by_css_selector(
"button.btn5.lh-def.transparent i.icon-menu"
)

menu_appear_callback = ec.element_to_be_clickable(
(By.CSS_SELECTOR, "h1#setH2 ul")
)

while not menu_appear_callback(self.driver):
hamburger_input.click()
except Exception as e:
self.close()
raise e

def test_for_possible_alert(self, wait_period: float, btn_text: str):
"""
Test for the possible alert when we upload the svgs.
:param wait_period: the wait period for the possible alert
in seconds.
:param btn_text: the text that the alert's button will have.
:return: None.
"""
try:
dismiss_btn = WebDriverWait(self.driver, wait_period, 0.15).until(
ec.element_to_be_clickable(
(By.XPATH, f"//div[@class='overlay']//button[text()='{btn_text}']"))
)
dismiss_btn.click()
except SeleniumTimeoutException:
pass

def remove_color_from_icon(self):
"""
Remove the color from the most recent uploaded icon.
:return: None.
"""
try:
recently_uploaded_icon = WebDriverWait(self.driver, self.LONG_WAIT_IN_SEC).until(
ec.element_to_be_clickable((By.XPATH, "//div[@id='set0']//mi-box[1]//div"))
)
recently_uploaded_icon.click()
except Exception as e:
self.close()
raise e

try:
color_tab = WebDriverWait(self.driver, self.SHORT_WAIT_IN_SEC).until(
ec.element_to_be_clickable((By.CSS_SELECTOR, "div.overlayWindow i.icon-droplet"))
)
color_tab.click()

remove_color_btn = self.driver \
.find_element_by_css_selector("div.overlayWindow i.icon-droplet-cross")
remove_color_btn.click()
except SeleniumTimeoutException:
pass
except Exception as e:
self.close()
raise e

try:
close_btn = self.driver \
.find_element_by_css_selector("div.overlayWindow i.icon-close")
close_btn.click()
except Exception as e:
self.close()
raise e

def download_icomoon_fonts(self, zip_path: Path):
"""
Download the icomoon.zip from icomoon.io.
:param zip_path: the path to the zip file after it's downloaded.
"""
try:
print("Downloading Font files...")
self.driver.find_element_by_css_selector(
"a[href='#/select/font']"
).click()

self.test_for_possible_alert(self.MED_WAIT_IN_SEC, "Continue")
download_btn = WebDriverWait(self.driver, SeleniumRunner.LONG_WAIT_IN_SEC).until(
ec.presence_of_element_located((By.CSS_SELECTOR, "button.btn4 span"))
)
download_btn.click()
if self.wait_for_zip(zip_path):
print("Font files downloaded.")
else:
raise TimeoutError(f"Couldn't find {zip_path} after download button was clicked.")
except Exception as e:
self.close()
raise e

def wait_for_zip(self, zip_path: Path) -> bool:
"""
Wait for the zip file to be downloaded by checking for its existence
in the download path. Wait time is self.LONG_WAIT_IN_SEC and check time
is 1 sec.
:param zip_path: the path to the zip file after it's
downloaded.
:return: True if the file is found within the allotted time, else
False.
"""
end_time = time.time() + self.LONG_WAIT_IN_SEC
while time.time() <= end_time:
if zip_path.exists():
return True
time.sleep(1)
return False

def close(self):
"""
Close the SeleniumRunner instance.
"""
print("Closing down SeleniumRunner...")
self.driver.quit()
Loading