-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7d9cc85
commit 6126e42
Showing
34 changed files
with
2,585 additions
and
1,735 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{ | ||
"repoOwner": "agritheory", | ||
"repoName": "cloud_storage", | ||
"targetBranchChoices": ["version-14", "version-15"], | ||
"targetBranches": ["version-14", "version-15"], | ||
"autoMerge": true, | ||
"autoMergeMethod": "squash", | ||
"branchLabelMapping": { | ||
"^auto-backport-to-(.+)$": "$1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
cloud_storage/public/js/lib/* | ||
cloud_storage/templates/includes/* | ||
cloud_storage/www/website_script.js |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
{ | ||
"env": { | ||
"browser": true, | ||
"node": true, | ||
"es2022": true | ||
}, | ||
"parserOptions": { | ||
"sourceType": "module" | ||
}, | ||
"extends": "eslint:recommended", | ||
"rules": { | ||
"indent": "off", | ||
"brace-style": "off", | ||
"no-mixed-spaces-and-tabs": "off", | ||
"no-useless-escape": "off", | ||
"space-unary-ops": ["error", { "words": true }], | ||
"linebreak-style": "off", | ||
"quotes": ["off"], | ||
"semi": "off", | ||
"camelcase": "off", | ||
"no-unused-vars": "off", | ||
"no-console": ["warn"], | ||
"no-extra-boolean-cast": ["off"], | ||
"no-control-regex": ["off"] | ||
}, | ||
"root": true, | ||
"globals": { | ||
"frappe": true, | ||
"Vue": true, | ||
"SetVueGlobals": true, | ||
"__": true, | ||
"repl": true, | ||
"Class": true, | ||
"locals": true, | ||
"cint": true, | ||
"cstr": true, | ||
"cur_frm": true, | ||
"cur_dialog": true, | ||
"cur_page": true, | ||
"cur_list": true, | ||
"cur_tree": true, | ||
"msg_dialog": true, | ||
"is_null": true, | ||
"in_list": true, | ||
"has_common": true, | ||
"posthog": true, | ||
"has_words": true, | ||
"validate_email": true, | ||
"open_web_template_values_editor": true, | ||
"validate_name": true, | ||
"validate_phone": true, | ||
"validate_url": true, | ||
"get_number_format": true, | ||
"format_number": true, | ||
"format_currency": true, | ||
"comment_when": true, | ||
"open_url_post": true, | ||
"toTitle": true, | ||
"lstrip": true, | ||
"rstrip": true, | ||
"strip": true, | ||
"strip_html": true, | ||
"replace_all": true, | ||
"flt": true, | ||
"precision": true, | ||
"CREATE": true, | ||
"AMEND": true, | ||
"CANCEL": true, | ||
"copy_dict": true, | ||
"get_number_format_info": true, | ||
"strip_number_groups": true, | ||
"print_table": true, | ||
"Layout": true, | ||
"web_form_settings": true, | ||
"$c": true, | ||
"$a": true, | ||
"$i": true, | ||
"$bg": true, | ||
"$y": true, | ||
"$c_obj": true, | ||
"refresh_many": true, | ||
"refresh_field": true, | ||
"toggle_field": true, | ||
"get_field_obj": true, | ||
"get_query_params": true, | ||
"unhide_field": true, | ||
"hide_field": true, | ||
"set_field_options": true, | ||
"getCookie": true, | ||
"getCookies": true, | ||
"get_url_arg": true, | ||
"md5": true, | ||
"$": true, | ||
"jQuery": true, | ||
"moment": true, | ||
"hljs": true, | ||
"Awesomplete": true, | ||
"Sortable": true, | ||
"Showdown": true, | ||
"Taggle": true, | ||
"Gantt": true, | ||
"Slick": true, | ||
"Webcam": true, | ||
"PhotoSwipe": true, | ||
"PhotoSwipeUI_Default": true, | ||
"io": true, | ||
"JsBarcode": true, | ||
"L": true, | ||
"Chart": true, | ||
"DataTable": true, | ||
"Cypress": true, | ||
"cy": true, | ||
"it": true, | ||
"describe": true, | ||
"expect": true, | ||
"context": true, | ||
"before": true, | ||
"beforeEach": true, | ||
"after": true, | ||
"qz": true, | ||
"localforage": true, | ||
"extend_cscript": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -69,6 +69,7 @@ ignore = | |
F841, | ||
E713, | ||
E712, | ||
B028, | ||
|
||
max-line-length = 200 | ||
exclude=,test_*.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#!/bin/bash | ||
|
||
set -e | ||
|
||
cd ~ || exit | ||
|
||
sudo apt update | ||
sudo apt remove mysql-server mysql-client | ||
sudo apt install libcups2-dev redis-server mariadb-client-10.6 | ||
|
||
pip install frappe-bench | ||
|
||
bench init --skip-redis-config-generation --skip-assets --python "$(which python)" --frappe-branch version-15 frappe-bench | ||
|
||
mkdir ~/frappe-bench/sites/test_site | ||
cp -r "${GITHUB_WORKSPACE}/.github/helper/site_config.json" ~/frappe-bench/sites/test_site/ | ||
|
||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL character_set_server = 'utf8mb4'" | ||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'" | ||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'" | ||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "CREATE DATABASE test_frappe" | ||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'" | ||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "FLUSH PRIVILEGES" | ||
|
||
install_whktml() { | ||
wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz | ||
tar -xf /tmp/wkhtmltox.tar.xz -C /tmp | ||
sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf | ||
sudo chmod o+x /usr/local/bin/wkhtmltopdf | ||
} | ||
install_whktml & | ||
|
||
cd ~/frappe-bench || exit | ||
|
||
sed -i 's/watch:/# watch:/g' Procfile | ||
sed -i 's/schedule:/# schedule:/g' Procfile | ||
sed -i 's/socketio:/# socketio:/g' Procfile | ||
sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile | ||
|
||
bench get-app erpnext --branch "version-15" --resolve-deps | ||
bench get-app cloud_storage "${GITHUB_WORKSPACE}" | ||
bench setup requirements --dev | ||
|
||
bench start &> bench_run_logs.txt & | ||
CI=Yes bench build --app frappe & | ||
|
||
bench --site test_site reinstall --yes | ||
bench --site test_site install-app cloud_storage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"db_host": "127.0.0.1", | ||
"db_port": 3306, | ||
"db_name": "test_frappe", | ||
"db_password": "test_frappe", | ||
"allow_tests": true, | ||
"db_type": "mariadb", | ||
"auto_email_id": "[email protected]", | ||
"mail_server": "localhost", | ||
"mail_port": 2525, | ||
"mail_login": "[email protected]", | ||
"mail_password": "test", | ||
"admin_password": "admin", | ||
"root_login": "root", | ||
"root_password": "root", | ||
"host_name": "http://test_site:8000", | ||
"monitor": 1, | ||
"server_script_enabled": true | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
import json | ||
import pathlib | ||
import sys | ||
|
||
|
||
def scrub(txt: str) -> str: | ||
return txt.replace(" ", "_").replace("-", "_").lower() | ||
|
||
|
||
def unscrub(txt: str) -> str: | ||
return txt.replace("_", " ").replace("-", " ").title() | ||
|
||
|
||
def get_customized_doctypes(): | ||
apps_dir = pathlib.Path(__file__).resolve().parent.parent.parent | ||
apps_order = pathlib.Path(__file__).resolve().parent.parent.parent.parent / "sites" / "apps.txt" | ||
apps_order = apps_order.read_text().split("\n") | ||
customized_doctypes = {} | ||
for _app_dir in apps_order: | ||
app_dir = (apps_dir / _app_dir).resolve() | ||
if not app_dir.is_dir(): | ||
continue | ||
modules = (app_dir / _app_dir / "modules.txt").read_text().split("\n") | ||
for module in modules: | ||
if not (app_dir / _app_dir / scrub(module) / "custom").exists(): | ||
continue | ||
for custom_file in list((app_dir / _app_dir / scrub(module) / "custom").glob("**/*.json")): | ||
if custom_file.stem in customized_doctypes: | ||
customized_doctypes[custom_file.stem].append(custom_file.resolve()) | ||
else: | ||
customized_doctypes[custom_file.stem] = [custom_file.resolve()] | ||
|
||
return dict(sorted(customized_doctypes.items())) | ||
|
||
|
||
def validate_module(customized_doctypes, set_module=False): | ||
exceptions = [] | ||
app_dir = pathlib.Path(__file__).resolve().parent.parent | ||
this_app = app_dir.stem | ||
for doctype, customize_files in customized_doctypes.items(): | ||
for customize_file in customize_files: | ||
if not this_app in str(customize_file): | ||
continue | ||
module = customize_file.parent.parent.stem | ||
file_contents = json.loads(customize_file.read_text()) | ||
if file_contents.get("custom_fields"): | ||
for custom_field in file_contents.get("custom_fields"): | ||
if set_module: | ||
custom_field["module"] = unscrub(module) | ||
continue | ||
if not custom_field.get("module"): | ||
exceptions.append( | ||
f"Custom Field for {custom_field.get('dt')} in {this_app} '{custom_field.get('fieldname')}' does not have a module key" | ||
) | ||
continue | ||
elif custom_field.get("module") != unscrub(module): | ||
exceptions.append( | ||
f"Custom Field for {custom_field.get('dt')} in {this_app} '{custom_field.get('fieldname')}' has module key ({custom_field.get('module')}) associated with another app" | ||
) | ||
continue | ||
if file_contents.get("property_setters"): | ||
for ps in file_contents.get("property_setters"): | ||
if set_module: | ||
ps["module"] = unscrub(module) | ||
continue | ||
if not ps.get("module"): | ||
exceptions.append( | ||
f"Property Setter for {ps.get('doc_type')} in {this_app} '{ps.get('property')}' on {ps.get('field_name')} does not have a module key" | ||
) | ||
continue | ||
elif ps.get("module") != unscrub(module): | ||
exceptions.append( | ||
f"Property Setter for {ps.get('doc_type')} in {this_app} '{ps.get('property')}' on {ps.get('field_name')} has module key ({ps.get('module')}) associated with another app" | ||
) | ||
continue | ||
if set_module: | ||
with customize_file.open("w", encoding="UTF-8") as target: | ||
json.dump(file_contents, target, sort_keys=True, indent=2) | ||
|
||
return exceptions | ||
|
||
|
||
def validate_no_custom_perms(customized_doctypes): | ||
exceptions = [] | ||
this_app = pathlib.Path(__file__).resolve().parent.parent.stem | ||
for doctype, customize_files in customized_doctypes.items(): | ||
for customize_file in customize_files: | ||
if not this_app in str(customize_file): | ||
continue | ||
file_contents = json.loads(customize_file.read_text()) | ||
if file_contents.get("custom_perms"): | ||
exceptions.append(f"Customization for {doctype} in {this_app} contains custom permissions") | ||
return exceptions | ||
|
||
|
||
def validate_duplicate_customizations(customized_doctypes): | ||
exceptions = [] | ||
common_fields = {} | ||
common_property_setters = {} | ||
app_dir = pathlib.Path(__file__).resolve().parent.parent | ||
this_app = app_dir.stem | ||
for doctype, customize_files in customized_doctypes.items(): | ||
if len(customize_files) == 1: | ||
continue | ||
common_fields[doctype] = {} | ||
common_property_setters[doctype] = {} | ||
for customize_file in customize_files: | ||
module = customize_file.parent.parent.stem | ||
app = customize_file.parent.parent.parent.parent.stem | ||
file_contents = json.loads(customize_file.read_text()) | ||
if file_contents.get("custom_fields"): | ||
fields = [cf.get("fieldname") for cf in file_contents.get("custom_fields")] | ||
common_fields[doctype][module] = fields | ||
if file_contents.get("property_setters"): | ||
ps = [ps.get("name") for ps in file_contents.get("property_setters")] | ||
common_property_setters[doctype][module] = ps | ||
|
||
for doctype, module_and_fields in common_fields.items(): | ||
if this_app not in module_and_fields.keys(): | ||
continue | ||
this_modules_fields = module_and_fields.pop(this_app) | ||
for module, fields in module_and_fields.items(): | ||
for field in fields: | ||
if field in this_modules_fields: | ||
exceptions.append( | ||
f"Custom Field for {unscrub(doctype)} in {this_app} '{field}' also appears in customizations for {module}" | ||
) | ||
|
||
for doctype, module_and_ps in common_property_setters.items(): | ||
if this_app not in module_and_ps.keys(): | ||
continue | ||
this_modules_ps = module_and_ps.pop(this_app) | ||
for module, ps in module_and_ps.items(): | ||
for p in ps: | ||
if p in this_modules_ps: | ||
exceptions.append( | ||
f"Property Setter for {unscrub(doctype)} in {this_app} on '{p}' also appears in customizations for {module}" | ||
) | ||
|
||
return exceptions | ||
|
||
|
||
def validate_customizations(set_module): | ||
customized_doctypes = get_customized_doctypes() | ||
exceptions = validate_no_custom_perms(customized_doctypes) | ||
exceptions += validate_module(customized_doctypes, set_module) | ||
exceptions += validate_duplicate_customizations(customized_doctypes) | ||
|
||
return exceptions | ||
|
||
|
||
if __name__ == "__main__": | ||
exceptions = [] | ||
set_module = False | ||
for arg in sys.argv: | ||
if arg == "--set-module": | ||
set_module = True | ||
exceptions.append(validate_customizations(set_module)) | ||
|
||
if exceptions: | ||
for exception in exceptions: | ||
[print(e) for e in exception] # TODO: colorize | ||
|
||
sys.exit(1) if all(exceptions) else sys.exit(0) |
Oops, something went wrong.