From 8788144260ce33eb59f6f53ab9b800675c6666a1 Mon Sep 17 00:00:00 2001 From: Elaine Krauss Date: Wed, 16 Sep 2026 16:06:15 -0400 Subject: [PATCH 1/9] Updates commit hash patcher - testing --- bin/patch-repos-with-validator-commit-hash.py | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/bin/patch-repos-with-validator-commit-hash.py b/bin/patch-repos-with-validator-commit-hash.py index f574f39b7..e06a26caa 100644 --- a/bin/patch-repos-with-validator-commit-hash.py +++ b/bin/patch-repos-with-validator-commit-hash.py @@ -2,6 +2,7 @@ import sys import time import pkg_resources +import json from inspect import getsourcefile FRONT_END_ROOT_DIR = "fecfile-web-app" @@ -44,21 +45,24 @@ def patch_app(commit_hash): print("Patching package.json...") sleep(0.5) - packages = open("package.json", "r") - package_lines = "" - for line in packages: - if "fecfile-validate" in line: - key, value = line.split(": ") - url = value.split("#")[0] - new_line = key+": "+url+"#"+commit_hash+'",\n' - package_lines += new_line + package_manifest = json.load("package.json") + + package_manifest["dependencies"]["fecfile-validate"] = ( + f"https://github.com/fecgov/fecfile-validate#{commit_hash}" + ) + + allowedScripts = package_manifest["allowScripts"].keys() + + newAllowedScripts = {} + for allowedScript in allowedScripts: + if "fecfile-validate" in allowedScript: + scriptName = f"github:fecgov/fecfile-validate#{commit_hash}" + newAllowedScripts[scriptName] = package_manifest["allowScripts"][allowedScript] else: - package_lines += line + newAllowedScripts[allowedScript] = package_manifest["allowScripts"][allowedScript] - packages.close() - new_packages = open("package.json", "w") - new_packages.write(package_lines) - new_packages.close() + package_manifest["allowScripts"] = newAllowedScripts + json.dump(package_manifest, "test-package.json") print("Done!\n") sleep(0.5) From 7313be3e747e8296ec089179f00c8b69020f86b9 Mon Sep 17 00:00:00 2001 From: Elaine Krauss Date: Wed, 16 Sep 2026 16:14:09 -0400 Subject: [PATCH 2/9] Fixes the new json read/write strategy --- bin/patch-repos-with-validator-commit-hash.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/bin/patch-repos-with-validator-commit-hash.py b/bin/patch-repos-with-validator-commit-hash.py index e06a26caa..874aa6ac7 100644 --- a/bin/patch-repos-with-validator-commit-hash.py +++ b/bin/patch-repos-with-validator-commit-hash.py @@ -45,7 +45,9 @@ def patch_app(commit_hash): print("Patching package.json...") sleep(0.5) - package_manifest = json.load("package.json") + package = open("package.json", "r") + package_manifest = json.load(package) + package.close() package_manifest["dependencies"]["fecfile-validate"] = ( f"https://github.com/fecgov/fecfile-validate#{commit_hash}" @@ -62,7 +64,15 @@ def patch_app(commit_hash): newAllowedScripts[allowedScript] = package_manifest["allowScripts"][allowedScript] package_manifest["allowScripts"] = newAllowedScripts - json.dump(package_manifest, "test-package.json") + + package = open("package.json", "w") + json.dump( + package_manifest, + package, + indent=2, + ) + package.write("\n") + package.close() print("Done!\n") sleep(0.5) From 62aab1b762265e8a95eed77ffd6e840dfae8024e Mon Sep 17 00:00:00 2001 From: Elaine Krauss Date: Wed, 16 Sep 2026 17:09:32 -0400 Subject: [PATCH 3/9] Strips out spin-down, image pruning, and cache clearing. Implements manual fallback when gitpython is not installed. Adds verification of automatically retrieved hashes. --- bin/patch-repos-with-validator-commit-hash.py | 80 +++++++++---------- 1 file changed, 36 insertions(+), 44 deletions(-) diff --git a/bin/patch-repos-with-validator-commit-hash.py b/bin/patch-repos-with-validator-commit-hash.py index 874aa6ac7..8c7efdf7e 100644 --- a/bin/patch-repos-with-validator-commit-hash.py +++ b/bin/patch-repos-with-validator-commit-hash.py @@ -1,10 +1,10 @@ import os import sys import time -import pkg_resources import json from inspect import getsourcefile + FRONT_END_ROOT_DIR = "fecfile-web-app" BACK_END_ROOT_DIR = "fecfile-web-api" VALIDATOR_ROOT_DIR = "fecfile-validate" @@ -14,27 +14,46 @@ YES_TO_ALL = False -def gitpython_is_installed(): - installed_packages = pkg_resources.working_set - for package in installed_packages: - if package.key == "gitpython": - return True - return False - - -def get_commit_hash(): +def get_commit_hash_automatic(): import git os.chdir(BASE_DIR) os.chdir(VALIDATOR_ROOT_DIR) repo = git.Repo() - commit_hash = repo.head.object.hexsha + return repo.head.object.hexsha - print("\nValidator Commit Hash:", commit_hash+"\n") - sleep(1) - return commit_hash +def get_commit_hash_manual(skip_gitpython_install_recommendation=True): + if not skip_gitpython_install_recommendation: + print( + "\n\n" + "This script can optionally use the gitpython module to automatically\n" + "retrieve the most recent commit hash of your validate repo's active branch" + "\n\n" + "You can install it with: python -m pip install gitpython\n" + "\n\n" + "Alternatively:" + ) + + return input("Please input the commit hash: ") + + +def get_commit_hash(): + try: + print("\n\nAttempting to automatically retrieve commit hash...") + commit_hash = get_commit_hash_automatic() + + sleep(1) + print("\nValidator Commit Hash:", commit_hash+"\n") + correct = ask_true_false("Is this correct?") + if correct: + return commit_hash + else: + return get_commit_hash_manual(True) + except: + print("Failed to automatically retrieve commit hash") + return get_commit_hash_manual(YES_TO_ALL) def patch_app(commit_hash): @@ -118,17 +137,13 @@ def delete_app_cache(): sleep(0.5) -def delete_api_docker_images(docker_images): - print("Deleting .angular & node_modules...") +def spin_down_docker(): + print("Spinning down Docker...") os.chdir(BASE_DIR) os.chdir(BACK_END_ROOT_DIR) - print("Spinning down Docker...") os.system("docker-compose down") - for image in docker_images: - print("Removing", image, "...") - os.system("docker rmi "+image) - print("Done!\nBe sure to run `docker-compose up`") + print("Done!\nBe sure to run `docker-compose build --no-cache`") sleep(0.5) @@ -178,11 +193,6 @@ def main(): global YES_TO_ALL YES_TO_ALL = True - if not gitpython_is_installed(): - print("Please install gitpython!") - print("python -m pip install gitpython") - return - if not check_user_is_ready(): return @@ -190,24 +200,6 @@ def main(): patch_app(commit_hash) patch_api(commit_hash) - if ask_true_false( - "Would you like to delete the .angular and node_modules directories within " + - FRONT_END_ROOT_DIR - ): - delete_app_cache() - - docker_images = [ - "fecfile-db", - "fecfile-api", - "fecfile-celery-worker", - "redis:6.2-alpine" - ] - if ask_true_false( - "Would you like to delete the following docker images?\n" + - "\n".join(docker_images)+"\n" - ): - delete_api_docker_images(docker_images) - if __name__ == "__main__": main() From b504da2b1c20d52e4028a36dee0570ca03aca74e Mon Sep 17 00:00:00 2001 From: Elaine Krauss <104506225+Elaine-Krauss-TCG@users.noreply.github.com> Date: Wed, 16 Sep 2026 17:34:11 -0400 Subject: [PATCH 4/9] updates help message --- bin/patch-repos-with-validator-commit-hash.py | 36 ++++--------------- 1 file changed, 6 insertions(+), 30 deletions(-) diff --git a/bin/patch-repos-with-validator-commit-hash.py b/bin/patch-repos-with-validator-commit-hash.py index 8c7efdf7e..30a774fde 100644 --- a/bin/patch-repos-with-validator-commit-hash.py +++ b/bin/patch-repos-with-validator-commit-hash.py @@ -124,29 +124,6 @@ def patch_api(commit_hash): sleep(0.5) -def delete_app_cache(): - print("Deleting .angular & node_modules...") - - os.chdir(BASE_DIR) - os.chdir(FRONT_END_ROOT_DIR) - os.chdir("front-end") - os.system("rm -r .angular") - os.system("rm -r node_modules") - - print("Done!\nBe sure to run `npm install`\n") - sleep(0.5) - - -def spin_down_docker(): - print("Spinning down Docker...") - os.chdir(BASE_DIR) - os.chdir(BACK_END_ROOT_DIR) - os.system("docker-compose down") - - print("Done!\nBe sure to run `docker-compose build --no-cache`") - sleep(0.5) - - def sleep(t): if "-q" not in sys.argv: time.sleep(t) @@ -172,16 +149,15 @@ def check_user_is_ready(): def help(): help_string = """ - This script uses the active branch of your fecfile-validate repo to - update the validator commit hashes of your local app and api repos. - Optionally, it also deletes the .angular and node_modules directories - as well as the relevant docker images. - - For this script to work, it needs to be placed in the directory - wherein each of the three repos can be found. + This script updates the validator commit hash in fecfile-web-api's requirements.txt file + and in fecfile-web-app's package.json file. If the gitpython module is installed, this + script will automatically retrieve the commit hash for the most recent commit on the + working branch of your fecfile-validate repo. Alternatively, you can manually enter the + commit hash. Command line arguments: -y or --yes | auto-confirm all options + -q | skip all sleep() calls """ print(help_string) From a9555f288ec02a556d9a24f51e77d79ae89b83be Mon Sep 17 00:00:00 2001 From: Elaine Krauss Date: Wed, 16 Sep 2026 18:45:01 -0400 Subject: [PATCH 5/9] Switches to argparse; no more blank Except --- bin/patch-repos-with-validator-commit-hash.py | 60 ++++++++++++------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/bin/patch-repos-with-validator-commit-hash.py b/bin/patch-repos-with-validator-commit-hash.py index 30a774fde..a76a7341a 100644 --- a/bin/patch-repos-with-validator-commit-hash.py +++ b/bin/patch-repos-with-validator-commit-hash.py @@ -2,6 +2,7 @@ import sys import time import json +import argparse from inspect import getsourcefile @@ -12,6 +13,7 @@ # Get the directory three steps above the directory containing this file BASE_DIR = "/".join(FILE_PATH.split("/")[:-3]) YES_TO_ALL = False +QUICK = False def get_commit_hash_automatic(): @@ -24,7 +26,7 @@ def get_commit_hash_automatic(): return repo.head.object.hexsha -def get_commit_hash_manual(skip_gitpython_install_recommendation=True): +def get_commit_hash_manual(skip_gitpython_install_recommendation): if not skip_gitpython_install_recommendation: print( "\n\n" @@ -51,7 +53,7 @@ def get_commit_hash(): return commit_hash else: return get_commit_hash_manual(True) - except: + except ModuleNotFoundError: print("Failed to automatically retrieve commit hash") return get_commit_hash_manual(YES_TO_ALL) @@ -125,7 +127,7 @@ def patch_api(commit_hash): def sleep(t): - if "-q" not in sys.argv: + if not QUICK: time.sleep(t) @@ -139,7 +141,7 @@ def ask_true_false(question): return True -def check_user_is_ready(): +def check_directories_are_correct(): print("This script acts upon the active branches of the following repos:") for repo in [FRONT_END_ROOT_DIR, BACK_END_ROOT_DIR, VALIDATOR_ROOT_DIR]: padded_repo = repo+" "*(48-len(repo)) @@ -147,29 +149,45 @@ def check_user_is_ready(): return ask_true_false("\nAre these directories correct?") -def help(): - help_string = """ - This script updates the validator commit hash in fecfile-web-api's requirements.txt file - and in fecfile-web-app's package.json file. If the gitpython module is installed, this - script will automatically retrieve the commit hash for the most recent commit on the - working branch of your fecfile-validate repo. Alternatively, you can manually enter the - commit hash. +def main(): + description = ( + "This script updates the validator commit hash in fecfile-web-api's\n" + "requirements.txt file and in fecfile-web-app's package.json file.\n\n" + "If the gitpython module is installed, this script will automatically\n" + "retrieve the commit hash for the most recent commit on the working\n" + "branch of your fecfile-validate repo. Alternatively, you can enter\n" + "the commit hash manually." + ) - Command line arguments: - -y or --yes | auto-confirm all options - -q | skip all sleep() calls - """ - print(help_string) + parser = argparse.ArgumentParser( + prog="patch-repos-with-validator-commit-hash", + description=description, + ) + parser.add_argument( + '-y', + '--yes', + action="store_true", + default=False, + help="auto-confirm all y/n prompts" + ) + parser.add_argument( + '-q', + '--quick', + action="store_true", + default=False, + help="Skip all sleep() calls" + ) -def main(): - if "-h" in sys.argv or "--help" in sys.argv: - return help() - if "-y" in sys.argv or "--yes" in sys.argv: + args = parser.parse_args() + if args.yes: global YES_TO_ALL YES_TO_ALL = True + if args.quick: + global QUICK + QUICK = True - if not check_user_is_ready(): + if not check_directories_are_correct(): return commit_hash = get_commit_hash() From b325ebaa84d442b378bda2196f4e81ebeead723d Mon Sep 17 00:00:00 2001 From: Elaine Krauss Date: Wed, 16 Sep 2026 18:48:39 -0400 Subject: [PATCH 6/9] Fixes line length issue --- bin/patch-repos-with-validator-commit-hash.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/bin/patch-repos-with-validator-commit-hash.py b/bin/patch-repos-with-validator-commit-hash.py index a76a7341a..3038448dc 100644 --- a/bin/patch-repos-with-validator-commit-hash.py +++ b/bin/patch-repos-with-validator-commit-hash.py @@ -74,15 +74,16 @@ def patch_app(commit_hash): f"https://github.com/fecgov/fecfile-validate#{commit_hash}" ) - allowedScripts = package_manifest["allowScripts"].keys() + allowScripts = package_manifest["allowScripts"] + allowScriptKeys = allowScripts.keys() newAllowedScripts = {} - for allowedScript in allowedScripts: - if "fecfile-validate" in allowedScript: + for allowScriptKey in allowScriptKeys: + if "fecfile-validate" in allowScriptKey: scriptName = f"github:fecgov/fecfile-validate#{commit_hash}" - newAllowedScripts[scriptName] = package_manifest["allowScripts"][allowedScript] + newAllowedScripts[scriptName] = allowScripts[allowScriptKey] else: - newAllowedScripts[allowedScript] = package_manifest["allowScripts"][allowedScript] + newAllowedScripts[allowScriptKey] = allowScripts[allowScriptKey] package_manifest["allowScripts"] = newAllowedScripts From 39c08100f27e4191b6cc0dd3840ed3f8c0850e9e Mon Sep 17 00:00:00 2001 From: Elaine Krauss Date: Wed, 16 Sep 2026 18:51:12 -0400 Subject: [PATCH 7/9] Updates variable names for consistent naming_scheme --- bin/patch-repos-with-validator-commit-hash.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/bin/patch-repos-with-validator-commit-hash.py b/bin/patch-repos-with-validator-commit-hash.py index 3038448dc..b2f9dcaf1 100644 --- a/bin/patch-repos-with-validator-commit-hash.py +++ b/bin/patch-repos-with-validator-commit-hash.py @@ -74,18 +74,18 @@ def patch_app(commit_hash): f"https://github.com/fecgov/fecfile-validate#{commit_hash}" ) - allowScripts = package_manifest["allowScripts"] - allowScriptKeys = allowScripts.keys() + allow_scripts = package_manifest["allowScripts"] + allow_script_keys = allow_scripts.keys() - newAllowedScripts = {} - for allowScriptKey in allowScriptKeys: + new_allowed_scripts = {} + for allowScriptKey in allow_script_keys: if "fecfile-validate" in allowScriptKey: - scriptName = f"github:fecgov/fecfile-validate#{commit_hash}" - newAllowedScripts[scriptName] = allowScripts[allowScriptKey] + script_name = f"github:fecgov/fecfile-validate#{commit_hash}" + new_allowed_scripts[script_name] = allow_scripts[allowScriptKey] else: - newAllowedScripts[allowScriptKey] = allowScripts[allowScriptKey] + new_allowed_scripts[allowScriptKey] = allow_scripts[allowScriptKey] - package_manifest["allowScripts"] = newAllowedScripts + package_manifest["allowScripts"] = new_allowed_scripts package = open("package.json", "w") json.dump( From 1f5ca4826f52e7f58fc19f57212ff9df1e50e782 Mon Sep 17 00:00:00 2001 From: Elaine Krauss Date: Wed, 16 Sep 2026 18:52:36 -0400 Subject: [PATCH 8/9] Removes unused import; one more variable rename --- bin/patch-repos-with-validator-commit-hash.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bin/patch-repos-with-validator-commit-hash.py b/bin/patch-repos-with-validator-commit-hash.py index b2f9dcaf1..8e30b256a 100644 --- a/bin/patch-repos-with-validator-commit-hash.py +++ b/bin/patch-repos-with-validator-commit-hash.py @@ -1,5 +1,4 @@ import os -import sys import time import json import argparse @@ -78,12 +77,12 @@ def patch_app(commit_hash): allow_script_keys = allow_scripts.keys() new_allowed_scripts = {} - for allowScriptKey in allow_script_keys: - if "fecfile-validate" in allowScriptKey: + for allow_script_key in allow_script_keys: + if "fecfile-validate" in allow_script_key: script_name = f"github:fecgov/fecfile-validate#{commit_hash}" - new_allowed_scripts[script_name] = allow_scripts[allowScriptKey] + new_allowed_scripts[script_name] = allow_scripts[allow_script_key] else: - new_allowed_scripts[allowScriptKey] = allow_scripts[allowScriptKey] + new_allowed_scripts[allow_script_key] = allow_scripts[allow_script_key] package_manifest["allowScripts"] = new_allowed_scripts From 8920bd30919cb27abea9575be957b4b015fd6531 Mon Sep 17 00:00:00 2001 From: Elaine Krauss Date: Wed, 16 Sep 2026 18:59:45 -0400 Subject: [PATCH 9/9] Separates argument parsing into its own function for clarity --- bin/patch-repos-with-validator-commit-hash.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bin/patch-repos-with-validator-commit-hash.py b/bin/patch-repos-with-validator-commit-hash.py index 8e30b256a..8a711b171 100644 --- a/bin/patch-repos-with-validator-commit-hash.py +++ b/bin/patch-repos-with-validator-commit-hash.py @@ -149,7 +149,7 @@ def check_directories_are_correct(): return ask_true_false("\nAre these directories correct?") -def main(): +def parse_args(): description = ( "This script updates the validator commit hash in fecfile-web-api's\n" "requirements.txt file and in fecfile-web-app's package.json file.\n\n" @@ -187,6 +187,10 @@ def main(): global QUICK QUICK = True + +def main(): + parse_args() + if not check_directories_are_correct(): return