From 57f543b49c339ebeef3aece06f4b4a1f239fd995 Mon Sep 17 00:00:00 2001 From: Rithvik Doshi Date: Fri, 17 Oct 2025 16:10:58 -0400 Subject: [PATCH 01/17] feat: ci workflow to check compilation val --- .../scripts/validate-semoss-compilation.py | 401 ++++++++++++++++++ .github/workflows/semoss-validation.yml | 61 +++ 2 files changed, 462 insertions(+) create mode 100644 .github/scripts/validate-semoss-compilation.py create mode 100644 .github/workflows/semoss-validation.yml diff --git a/.github/scripts/validate-semoss-compilation.py b/.github/scripts/validate-semoss-compilation.py new file mode 100644 index 0000000..e9fc13d --- /dev/null +++ b/.github/scripts/validate-semoss-compilation.py @@ -0,0 +1,401 @@ +#!/usr/bin/env python3 +""" +Script to validate Java reactor compilation in SEMOSS +Creates temporary project, uploads code, compiles, then cleans up +@author: Patel, Parth +""" + +import zipfile +import os +import requests +import base64 +from datetime import datetime + +def print_step_header(step_name): + """Print formatted step header""" + print("=" * 60) + print(f"STEP: {step_name}") + print("=" * 60) + +def print_section_divider(title): + """Print section divider""" + print("=" * 60) + print(title) + print("=" * 60) + +def print_pixel_output(result, show_detailed=False): + """Print pixel execution output in a consistent format""" + if not result: + print("[WARN] No result returned") + return + + if isinstance(result, dict) and 'pixelReturn' in result: + pixel_return = result['pixelReturn'][0] if result['pixelReturn'] else {} + output = pixel_return.get('output', 'No output') + + if show_detailed: + # For compilation results - show with line numbers (no separate section) + if isinstance(output, list): + for i, line in enumerate(output, 1): + print(f"{i:3d}: {line}") + else: + print(f"Output: {output}") + else: + # For other pixels - just print the output + if isinstance(output, list): + for line in output: + print(f"[INFO] {line}") + else: + print(f"[INFO] {output}") + else: + print(f"[INFO] {result}") + +def run_pixel_with_logging(server_connection, pixel, full_response=False, show_output=True): + """Run pixel with logging and optional output display""" + print(f"Running pixel: {pixel}") + result = server_connection.run_pixel(pixel, full_response=full_response) + + if show_output: + print_pixel_output(result) + + return result + +def create_zip(): + """Create zip file with py, portals, java, client folders""" + print_step_header("Creating Project Zip File") + + folders_to_zip = ['py', 'portals', 'java', 'client'] + + timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') + zip_filename = f"project_{timestamp}.zip" + + print(f"[INFO] Creating zip file: {zip_filename}") + + with zipfile.ZipFile(zip_filename, 'w', zipfile.ZIP_DEFLATED) as zipf: + for folder in folders_to_zip: + if os.path.exists(folder): + print(f"[INFO] Adding folder: {folder}") + for root, dirs, files in os.walk(folder): + for file in files: + file_path = os.path.join(root, file) + zipf.write(file_path) + else: + print(f"[WARN] Folder '{folder}' not found") + + print(f"[SUCCESS] Zip file created: {zip_filename}") + return zip_filename + +def setup_ai_server(): + """Setup AI Server connection""" + print_step_header("Connecting to AI Server") + + try: + from ai_server import ServerClient + + server_url = os.getenv('AI_SERVER_URL') + access_key = os.getenv('ACCESS_KEY') + secret_key = os.getenv('SECRET_KEY') + + if not all([server_url, access_key, secret_key]): + print("[ERROR] Missing environment variables:") + print(" AI_SERVER_URL, ACCESS_KEY, SECRET_KEY") + return None + + print("[INFO] Connecting to AI Server...") + server_connection = ServerClient( + base=server_url, + access_key=access_key, + secret_key=secret_key + ) + + print("[SUCCESS] Connected to AI Server") + return server_connection + + except ImportError: + print("[ERROR] ai-server-sdk not installed") + return None + except Exception as e: + print(f"[ERROR] Failed to connect to AI Server: {e}") + return None + +def get_current_insight(server_connection): + """ + Get current insight ID from server connection + No pixel needed - uses existing connection insight + Why: Need insight ID for all subsequent operations + """ + print_step_header("Getting Current Insight") + + try: + insight_id = server_connection.cur_insight + print(f"[SUCCESS] Using insight: {insight_id}") + return insight_id + except Exception as e: + print(f"[ERROR] Failed to get insight ID: {e}") + return None + +def create_temporary_project(server_connection): + """ + Pixel: CreateProject(project=["Test-project-sep17"], portal=[true], projectType=["CODE"]) + Why: Create temporary project to test compilation without affecting existing projects + """ + print_step_header("Creating Temporary Project") + + try: + project_name = f"Test-project-{datetime.now().strftime('%b%d').lower()}" + create_project_pixel = f'CreateProject(project=["{project_name}"], portal=[true], projectType=["CODE"]);' + + result = run_pixel_with_logging(server_connection, create_project_pixel, full_response=True) + + # Extract project ID from result + if result and 'pixelReturn' in result: + pixel_result = result['pixelReturn'][0] + if 'output' in pixel_result and 'project_id' in pixel_result['output']: + project_id = pixel_result['output']['project_id'] + print(f"[SUCCESS] Temporary project created: {project_id}") + return project_id + + print("[ERROR] Could not extract project ID from CreateProject result") + return None + + except Exception as e: + print(f"[ERROR] Failed to create project: {e}") + return None + +def delete_existing_assets(server_connection, project_id): + """ + Pixel: DeleteAsset(filePath=["version/assets/"], space=["project_id"]) + Why: Clear any existing assets before uploading new code + """ + print_step_header("Deleting Existing Assets") + + try: + delete_pixel = f'DeleteAsset(filePath=["version/assets/"], space=["{project_id}"]);' + run_pixel_with_logging(server_connection, delete_pixel) + print("[SUCCESS] Assets deletion completed") + return True + except Exception as e: + print(f"[ERROR] Failed to delete assets: {e}") + return False + +def upload_zip_file(server_connection, zip_filename, project_id): + """ + HTTP Upload: /uploadFile/baseUpload + Why: Upload project files to SEMOSS for compilation testing + """ + print_step_header("Uploading Project Files") + + try: + server_url = os.getenv('AI_SERVER_URL') + access_key = os.getenv('ACCESS_KEY') + secret_key = os.getenv('SECRET_KEY') + insight_id = server_connection.cur_insight + + if not all([server_url, access_key, secret_key, insight_id]): + print("[ERROR] Missing required connection details for upload") + return False + + upload_url = f"{server_url}/uploadFile/baseUpload?insightId={insight_id}&projectId={project_id}&path=version/assets/" + print(f"[INFO] Uploading to: {upload_url}") + + # Use access_key:secret_key for basic auth + encoded = base64.b64encode(f"{access_key}:{secret_key}".encode()).decode() + + with open(zip_filename, 'rb') as f: + files = {'file': f} + headers = {'Authorization': f'Basic {encoded}'} + + response = requests.post(upload_url, files=files, headers=headers, timeout=60) + + response.raise_for_status() + upload_result = response.json() + + if upload_result and upload_result[0] and upload_result[0].get('fileLocation'): + print("[SUCCESS] Upload completed") + return True + else: + print("[ERROR] Upload failed: Invalid response") + return False + + except Exception as e: + print(f"[ERROR] Upload failed: {e}") + return False + +def unzip_main_project(server_connection, zip_filename, project_id): + """ + Pixel: UnzipFile(filePath=["version/assets/project_timestamp.zip"], space=["project_id"]) + Why: Extract uploaded project files including java.zip + """ + print_step_header("Unzipping Main Project File") + + try: + file_location = f"version/assets/{os.path.basename(zip_filename)}" + unzip_pixel = f'UnzipFile(filePath=["{file_location}"], space=["{project_id}"]);' + run_pixel_with_logging(server_connection, unzip_pixel) + print("[SUCCESS] Main project file unzipped") + return True + except Exception as e: + print(f"[ERROR] Failed to unzip main project: {e}") + return False + +def compile_reactors(server_connection): + """ + Pixel: CompileAppReactors() + Why: Compile Java reactors and validate no compilation errors exist + """ + print_step_header("Compiling App Reactors") + + try: + compile_pixel = "CompileAppReactors();" + result = run_pixel_with_logging(server_connection, compile_pixel, full_response=True, show_output=False) + + # Show detailed compilation output + print_pixel_output(result, show_detailed=True) + + # Analyze results for errors + if result and 'pixelReturn' in result: + pixel_result = result['pixelReturn'][0] + if 'output' in pixel_result: + output = pixel_result['output'] + + # Check for actual errors (not warnings) + if isinstance(output, list): + error_found = False + warning_count = 0 + mandatory_warning_count = 0 + + for line in output: + if isinstance(line, str): + # Count warnings + if '[MANDATORY_WARNING]' in line: + mandatory_warning_count += 1 + elif '[WARNING]' in line: + warning_count += 1 + # Look for actual errors (not warnings) + elif 'ERROR' in line.upper() and 'WARNING' not in line.upper(): + print(f"[ERROR] Compilation error found: {line}") + error_found = True + + print(f"[INFO] Summary: {mandatory_warning_count} mandatory warnings, {warning_count} warnings") + + if not error_found: + print("[SUCCESS] No compilation errors found") + return True + else: + print("[ERROR] Compilation errors detected") + return False + else: + print("[SUCCESS] Compilation completed") + return True + else: + print("[WARN] No compilation output returned") + return False + + except Exception as e: + print(f"[ERROR] Compilation failed: {e}") + return False + +def cleanup_project(server_connection, project_id): + """ + Pixel: DeleteProject(project=["project_id"]) + Why: Remove temporary project to avoid cluttering SEMOSS instance + """ + print_step_header("Cleaning Up Temporary Project") + + if not project_id: + print("[INFO] No project to clean up") + return True + + try: + delete_project_pixel = f'DeleteProject(project=["{project_id}"]);' + run_pixel_with_logging(server_connection, delete_project_pixel) + print("[SUCCESS] Temporary project deleted") + return True + except Exception as cleanup_error: + print(f"[WARN] Could not delete project: {cleanup_error}") + return False + +def cleanup_local_files(zip_filename): + """Remove local zip file""" + try: + os.remove(zip_filename) + print(f"[SUCCESS] Cleaned up local file: {zip_filename}") + except: + print(f"[WARN] Could not clean up: {zip_filename}") + +def run_validation_workflow(): + """Execute the main validation workflow steps""" + zip_filename = None + project_id = None + server_connection = None + + try: + # Step 1: Create project zip + zip_filename = create_zip() + if not zip_filename: + raise Exception("Failed to create zip file") + + # Step 2: Setup AI Server connection + server_connection = setup_ai_server() + if not server_connection: + raise Exception("Failed to connect to AI Server") + + # Step 3: Get current insight + insight_id = get_current_insight(server_connection) + if not insight_id: + raise Exception("Failed to get insight ID") + + # Step 4: Create temporary project + project_id = create_temporary_project(server_connection) + if not project_id: + raise Exception("Failed to create temporary project") + + # Step 5: Delete existing assets + if not delete_existing_assets(server_connection, project_id): + raise Exception("Failed to delete existing assets") + + # Step 6: Upload zip file + if not upload_zip_file(server_connection, zip_filename, project_id): + raise Exception("Failed to upload zip file") + + # Step 7: Unzip main project + if not unzip_main_project(server_connection, zip_filename, project_id): + raise Exception("Failed to unzip main project") + + # Step 8: Compile reactors + compilation_success = compile_reactors(server_connection) + if not compilation_success: + raise Exception("Compilation failed") + + return True + + except Exception as e: + print(f"[ERROR] {e}") + return False + + finally: + # Always cleanup + if server_connection and project_id: + cleanup_project(server_connection, project_id) + if zip_filename: + cleanup_local_files(zip_filename) + +def main(): + """Main compilation validation workflow""" + print("[INFO] Starting compilation validation workflow") + print("=" * 50) + + success = run_validation_workflow() + + print("=" * 50) + if success: + print("[SUCCESS] Compilation validation completed successfully") + print("[INFO] All Java reactors compiled without errors") + else: + print("[ERROR] Compilation validation failed") + + return success + +if __name__ == "__main__": + success = main() + exit(0 if success else 1) \ No newline at end of file diff --git a/.github/workflows/semoss-validation.yml b/.github/workflows/semoss-validation.yml new file mode 100644 index 0000000..97266f5 --- /dev/null +++ b/.github/workflows/semoss-validation.yml @@ -0,0 +1,61 @@ +name: SEMOSS Compilation Validation +authors: [ 'Patel, Parth' ] + +on: + push: + branches: [ default-app ] + pull_request: + branches: [ default-app ] + types: [ closed ] + +jobs: + validate-compilation: + # Only run on push to main OR when PR is merged (not just closed) + if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.merged == true) + + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 1 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: '3.12' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install ai-server-sdk[full] requests + + - name: Validate project structure + run: | + echo "[INFO] Checking project structure..." + for folder in py portals java client; do + if [ -d "$folder" ]; then + echo "[SUCCESS] Found folder: $folder" + else + echo "[WARN] Missing folder: $folder" + fi + done + + - name: Run SEMOSS compilation validation + env: + AI_SERVER_URL: ${{ secrets.AI_SERVER_URL }} + ACCESS_KEY: ${{ secrets.ACCESS_KEY }} + SECRET_KEY: ${{ secrets.SECRET_KEY }} + run: | + echo "[INFO] Starting SEMOSS compilation validation..." + python .github/scripts/validate-semoss-compilation.py + + - name: Upload validation logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: validation-logs-${{ github.sha }} + path: | + *.log + retention-days: 7 \ No newline at end of file From 4ca2c122632d9922aa3cfca08f29951cff8c3086 Mon Sep 17 00:00:00 2001 From: rithvik-doshi <81876806+rithvik-doshi@users.noreply.github.com> Date: Fri, 17 Oct 2025 16:11:35 -0400 Subject: [PATCH 02/17] Update semoss-validation.yml --- .github/workflows/semoss-validation.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/semoss-validation.yml b/.github/workflows/semoss-validation.yml index 97266f5..c52f193 100644 --- a/.github/workflows/semoss-validation.yml +++ b/.github/workflows/semoss-validation.yml @@ -6,7 +6,6 @@ on: branches: [ default-app ] pull_request: branches: [ default-app ] - types: [ closed ] jobs: validate-compilation: @@ -58,4 +57,4 @@ jobs: name: validation-logs-${{ github.sha }} path: | *.log - retention-days: 7 \ No newline at end of file + retention-days: 7 From d4a44032d2a47d2ecfa35692f7ec19741e5ac5ea Mon Sep 17 00:00:00 2001 From: Rithvik Doshi Date: Fri, 17 Oct 2025 16:12:40 -0400 Subject: [PATCH 03/17] fix: oops --- .github/workflows/semoss-validation.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/semoss-validation.yml b/.github/workflows/semoss-validation.yml index 97266f5..b9ef5c8 100644 --- a/.github/workflows/semoss-validation.yml +++ b/.github/workflows/semoss-validation.yml @@ -1,5 +1,4 @@ name: SEMOSS Compilation Validation -authors: [ 'Patel, Parth' ] on: push: From 3fcfea23c279a4c0f81d394a5d298b63f5b05b97 Mon Sep 17 00:00:00 2001 From: rithvik-doshi <81876806+rithvik-doshi@users.noreply.github.com> Date: Fri, 17 Oct 2025 16:14:41 -0400 Subject: [PATCH 04/17] Update validation job condition with TODO comment Commented out the conditional for job execution and added a TODO note for future fix. --- .github/workflows/semoss-validation.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/semoss-validation.yml b/.github/workflows/semoss-validation.yml index 90c6241..24a44e7 100644 --- a/.github/workflows/semoss-validation.yml +++ b/.github/workflows/semoss-validation.yml @@ -8,8 +8,8 @@ on: jobs: validate-compilation: - # Only run on push to main OR when PR is merged (not just closed) - if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.merged == true) + # TODO: fix this later. Only run on push to main OR when PR is merged (not just closed) + # if: github.event_name == 'push' || (github.event_name == 'pull_request' && github.event.pull_request.merged == true) runs-on: ubuntu-latest From 5fe45a77b7937f4cc099e65a98743bae963d64c0 Mon Sep 17 00:00:00 2001 From: Rithvik Doshi Date: Mon, 20 Oct 2025 10:53:41 -0400 Subject: [PATCH 05/17] feat: step numbers --- .github/scripts/run-val-locally.sh | 10 ++++ .../scripts/validate-semoss-compilation.py | 54 +++++++++++++------ .gitignore | 4 +- 3 files changed, 50 insertions(+), 18 deletions(-) create mode 100755 .github/scripts/run-val-locally.sh diff --git a/.github/scripts/run-val-locally.sh b/.github/scripts/run-val-locally.sh new file mode 100755 index 0000000..f2d6ea0 --- /dev/null +++ b/.github/scripts/run-val-locally.sh @@ -0,0 +1,10 @@ +# !/bin/bash +# Make sure you have a .env file with the required variables. Something as such: + +# AI_SERVER_URL="http://localhost:9090/Monolith/api" # This should point to your local SEMOSS server +# ACCESS_KEY="your_access_key" +# SECRET_KEY="your_secret_key" + +# Then run the script as follows (if in windows, use git bash or wsl): + +set -a; . .github/scripts/.env; set +a; python3 .github/scripts/validate-semoss-compilation.py \ No newline at end of file diff --git a/.github/scripts/validate-semoss-compilation.py b/.github/scripts/validate-semoss-compilation.py index e9fc13d..e7c64f9 100644 --- a/.github/scripts/validate-semoss-compilation.py +++ b/.github/scripts/validate-semoss-compilation.py @@ -11,10 +11,30 @@ import base64 from datetime import datetime -def print_step_header(step_name): - """Print formatted step header""" +# Total number of primary workflow steps (display-only constant) +TOTAL_STEPS = 8 + +def print_step_header(step_name, step_number=None, total_steps=None): + """Print formatted step header with optional numbering. + + Args: + step_name (str): Descriptive name of the step. + step_number (int, optional): The ordinal position of the step. + Positive numbers indicate workflow steps. + Negative numbers indicate cleanup/teardown steps. + total_steps (int, optional): Total number of steps for context. + """ print("=" * 60) - print(f"STEP: {step_name}") + if step_number is not None: + if step_number < 0: + # Cleanup/teardown step + print(f"CLEANUP: {step_name}") + elif total_steps is not None: + print(f"STEP {step_number}/{total_steps}: {step_name}") + else: + print(f"STEP {step_number}: {step_name}") + else: + print(f"STEP: {step_name}") print("=" * 60) def print_section_divider(title): @@ -61,8 +81,8 @@ def run_pixel_with_logging(server_connection, pixel, full_response=False, show_o return result def create_zip(): - """Create zip file with py, portals, java, client folders""" - print_step_header("Creating Project Zip File") + """Create zip file with py, portals, java, client folders (Step 1).""" + print_step_header("Creating Project Zip File", step_number=1, total_steps=TOTAL_STEPS) folders_to_zip = ['py', 'portals', 'java', 'client'] @@ -86,8 +106,8 @@ def create_zip(): return zip_filename def setup_ai_server(): - """Setup AI Server connection""" - print_step_header("Connecting to AI Server") + """Setup AI Server connection (Step 2).""" + print_step_header("Connecting to AI Server", step_number=2, total_steps=TOTAL_STEPS) try: from ai_server import ServerClient @@ -124,7 +144,7 @@ def get_current_insight(server_connection): No pixel needed - uses existing connection insight Why: Need insight ID for all subsequent operations """ - print_step_header("Getting Current Insight") + print_step_header("Getting Current Insight", step_number=3, total_steps=TOTAL_STEPS) try: insight_id = server_connection.cur_insight @@ -139,7 +159,7 @@ def create_temporary_project(server_connection): Pixel: CreateProject(project=["Test-project-sep17"], portal=[true], projectType=["CODE"]) Why: Create temporary project to test compilation without affecting existing projects """ - print_step_header("Creating Temporary Project") + print_step_header("Creating Temporary Project", step_number=4, total_steps=TOTAL_STEPS) try: project_name = f"Test-project-{datetime.now().strftime('%b%d').lower()}" @@ -167,7 +187,7 @@ def delete_existing_assets(server_connection, project_id): Pixel: DeleteAsset(filePath=["version/assets/"], space=["project_id"]) Why: Clear any existing assets before uploading new code """ - print_step_header("Deleting Existing Assets") + print_step_header("Deleting Existing Assets", step_number=5, total_steps=TOTAL_STEPS) try: delete_pixel = f'DeleteAsset(filePath=["version/assets/"], space=["{project_id}"]);' @@ -183,7 +203,7 @@ def upload_zip_file(server_connection, zip_filename, project_id): HTTP Upload: /uploadFile/baseUpload Why: Upload project files to SEMOSS for compilation testing """ - print_step_header("Uploading Project Files") + print_step_header("Uploading Project Files", step_number=6, total_steps=TOTAL_STEPS) try: server_url = os.getenv('AI_SERVER_URL') @@ -226,7 +246,7 @@ def unzip_main_project(server_connection, zip_filename, project_id): Pixel: UnzipFile(filePath=["version/assets/project_timestamp.zip"], space=["project_id"]) Why: Extract uploaded project files including java.zip """ - print_step_header("Unzipping Main Project File") + print_step_header("Unzipping Main Project File", step_number=7, total_steps=TOTAL_STEPS) try: file_location = f"version/assets/{os.path.basename(zip_filename)}" @@ -243,7 +263,7 @@ def compile_reactors(server_connection): Pixel: CompileAppReactors() Why: Compile Java reactors and validate no compilation errors exist """ - print_step_header("Compiling App Reactors") + print_step_header("Compiling App Reactors", step_number=8, total_steps=TOTAL_STEPS) try: compile_pixel = "CompileAppReactors();" @@ -300,7 +320,7 @@ def cleanup_project(server_connection, project_id): Pixel: DeleteProject(project=["project_id"]) Why: Remove temporary project to avoid cluttering SEMOSS instance """ - print_step_header("Cleaning Up Temporary Project") + print_step_header("Cleaning Up Temporary Project", step_number=-1) if not project_id: print("[INFO] No project to clean up") @@ -366,13 +386,13 @@ def run_validation_workflow(): compilation_success = compile_reactors(server_connection) if not compilation_success: raise Exception("Compilation failed") - + return True - + except Exception as e: print(f"[ERROR] {e}") return False - + finally: # Always cleanup if server_connection and project_id: diff --git a/.gitignore b/.gitignore index 2c4bd69..9114481 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,6 @@ java/project.properties .vscode/ .classpath .project -.settings/ \ No newline at end of file +.settings/ +**/.env +!client/.env \ No newline at end of file From eb6fc587a4332a90e077a31457b778ca0f453dbd Mon Sep 17 00:00:00 2001 From: Rithvik Doshi Date: Mon, 20 Oct 2025 11:20:37 -0400 Subject: [PATCH 06/17] fix: remove full package --- .github/workflows/semoss-validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/semoss-validation.yml b/.github/workflows/semoss-validation.yml index 24a44e7..793dd05 100644 --- a/.github/workflows/semoss-validation.yml +++ b/.github/workflows/semoss-validation.yml @@ -27,7 +27,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install ai-server-sdk[full] requests + pip install ai-server-sdk requests - name: Validate project structure run: | From 5c2c659dfd371b5a40d222103f31998badca1399 Mon Sep 17 00:00:00 2001 From: Rithvik Doshi Date: Mon, 20 Oct 2025 11:34:12 -0400 Subject: [PATCH 07/17] feat: switch to uv --- .github/workflows/semoss-validation.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/semoss-validation.yml b/.github/workflows/semoss-validation.yml index 793dd05..f58fed5 100644 --- a/.github/workflows/semoss-validation.yml +++ b/.github/workflows/semoss-validation.yml @@ -24,10 +24,11 @@ jobs: with: python-version: '3.12' + - name: Install uv + uses: astral-sh/setup-uv@v3 + - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install ai-server-sdk requests + run: uv pip install --system ai-server-sdk requests - name: Validate project structure run: | From a658d5a352eb19c966a95124cfccb9741417092e Mon Sep 17 00:00:00 2001 From: Rithvik Doshi Date: Mon, 20 Oct 2025 14:42:42 -0400 Subject: [PATCH 08/17] check response --- .github/scripts/validate-semoss-compilation.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/scripts/validate-semoss-compilation.py b/.github/scripts/validate-semoss-compilation.py index e7c64f9..fd69473 100644 --- a/.github/scripts/validate-semoss-compilation.py +++ b/.github/scripts/validate-semoss-compilation.py @@ -226,9 +226,12 @@ def upload_zip_file(server_connection, zip_filename, project_id): headers = {'Authorization': f'Basic {encoded}'} response = requests.post(upload_url, files=files, headers=headers, timeout=60) + print("the response should be here:") + print(response) response.raise_for_status() upload_result = response.json() + if upload_result and upload_result[0] and upload_result[0].get('fileLocation'): print("[SUCCESS] Upload completed") From f7a78e5c70a1c0c6ff906fa9ec672ee79b7125a6 Mon Sep 17 00:00:00 2001 From: Rithvik Doshi Date: Mon, 20 Oct 2025 15:29:08 -0400 Subject: [PATCH 09/17] remove --- .github/scripts/validate-semoss-compilation.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/scripts/validate-semoss-compilation.py b/.github/scripts/validate-semoss-compilation.py index fd69473..627803d 100644 --- a/.github/scripts/validate-semoss-compilation.py +++ b/.github/scripts/validate-semoss-compilation.py @@ -226,8 +226,6 @@ def upload_zip_file(server_connection, zip_filename, project_id): headers = {'Authorization': f'Basic {encoded}'} response = requests.post(upload_url, files=files, headers=headers, timeout=60) - print("the response should be here:") - print(response) response.raise_for_status() upload_result = response.json() From 58f4f328391b58d6e486b205021b1e1549877afb Mon Sep 17 00:00:00 2001 From: Rithvik Doshi Date: Mon, 20 Oct 2025 16:29:02 -0400 Subject: [PATCH 10/17] fix: deprecated method --- .github/scripts/validate-semoss-compilation.py | 2 ++ java/src/reactors/AbstractProjectReactor.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/scripts/validate-semoss-compilation.py b/.github/scripts/validate-semoss-compilation.py index 627803d..035f1ca 100644 --- a/.github/scripts/validate-semoss-compilation.py +++ b/.github/scripts/validate-semoss-compilation.py @@ -226,6 +226,8 @@ def upload_zip_file(server_connection, zip_filename, project_id): headers = {'Authorization': f'Basic {encoded}'} response = requests.post(upload_url, files=files, headers=headers, timeout=60) + + print(response.json()) response.raise_for_status() upload_result = response.json() diff --git a/java/src/reactors/AbstractProjectReactor.java b/java/src/reactors/AbstractProjectReactor.java index 3d46933..f7b08fa 100644 --- a/java/src/reactors/AbstractProjectReactor.java +++ b/java/src/reactors/AbstractProjectReactor.java @@ -116,7 +116,7 @@ protected void preExecute() { */ @SuppressWarnings("unchecked") protected Map getMap(String paramName) { - GenRowStruct mapGrs = this.store.getNoun(paramName); + GenRowStruct mapGrs = this.store.getGenRowStruct(paramName); if (mapGrs != null && !mapGrs.isEmpty()) { List mapInputs = mapGrs.getNounsOfType(PixelDataType.MAP); if (mapInputs != null && !mapInputs.isEmpty()) { From 93011ecac6f728da2c950af3c3119102c4d7f37f Mon Sep 17 00:00:00 2001 From: Rithvik Doshi Date: Wed, 22 Oct 2025 13:58:40 -0400 Subject: [PATCH 11/17] ci: todos --- .github/scripts/validate-semoss-compilation.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/scripts/validate-semoss-compilation.py b/.github/scripts/validate-semoss-compilation.py index 035f1ca..bb7a840 100644 --- a/.github/scripts/validate-semoss-compilation.py +++ b/.github/scripts/validate-semoss-compilation.py @@ -3,6 +3,16 @@ Script to validate Java reactor compilation in SEMOSS Creates temporary project, uploads code, compiles, then cleans up @author: Patel, Parth + +TODOS: +- Print the zip size +- Skip adding node modules to zip (or other things) +- Build portals if not present +- Retry potentially? Error with invalid session + - Log errors for sure +- Potentially - on merge to deployment/default branch, have a cd action to just build the zip (can also have action to run manually) +- Make python version an env var +- Semantic versioning - work on this """ import zipfile @@ -210,6 +220,8 @@ def upload_zip_file(server_connection, zip_filename, project_id): access_key = os.getenv('ACCESS_KEY') secret_key = os.getenv('SECRET_KEY') insight_id = server_connection.cur_insight + + print(insight_id) if not all([server_url, access_key, secret_key, insight_id]): print("[ERROR] Missing required connection details for upload") From 4d7f1039bc91bc34262e850d19b665362aaa7e15 Mon Sep 17 00:00:00 2001 From: Rithvik Doshi Date: Wed, 22 Oct 2025 15:02:09 -0400 Subject: [PATCH 12/17] ci(feat): build portals --- .../scripts/validate-semoss-compilation.py | 70 ++++++++++++++++++- .github/workflows/semoss-validation.yml | 10 +++ 2 files changed, 77 insertions(+), 3 deletions(-) diff --git a/.github/scripts/validate-semoss-compilation.py b/.github/scripts/validate-semoss-compilation.py index bb7a840..4e6a2be 100644 --- a/.github/scripts/validate-semoss-compilation.py +++ b/.github/scripts/validate-semoss-compilation.py @@ -5,9 +5,6 @@ @author: Patel, Parth TODOS: -- Print the zip size -- Skip adding node modules to zip (or other things) -- Build portals if not present - Retry potentially? Error with invalid session - Log errors for sure - Potentially - on merge to deployment/default branch, have a cd action to just build the zip (can also have action to run manually) @@ -19,6 +16,7 @@ import os import requests import base64 +import subprocess from datetime import datetime # Total number of primary workflow steps (display-only constant) @@ -90,10 +88,66 @@ def run_pixel_with_logging(server_connection, pixel, full_response=False, show_o return result +def build_portals_if_needed(): + """Build portals using pnpm build in client folder if portals doesn't exist""" + if not os.path.exists('portals'): + print("[INFO] Portals folder not found, building from client...") + + if not os.path.exists('client'): + print("[ERROR] Client folder not found - cannot build portals") + return False + + try: + # Run pnpm install first to ensure dependencies are installed + print("[INFO] Running 'pnpm install' in client directory...") + install_result = subprocess.run( + ['pnpm', 'install'], + cwd='client', + timeout=300 # 5 minute timeout + ) + + if install_result.returncode != 0: + print(f"[ERROR] pnpm install failed with return code {install_result.returncode}") + return False + + print("[SUCCESS] Dependencies installed successfully") + + # Run pnpm build in client directory with live output + print("[INFO] Running 'pnpm build' in client directory...") + build_result = subprocess.run( + ['pnpm', 'build'], + cwd='client', + timeout=300 # 5 minute timeout + ) + + if build_result.returncode == 0: + print("[SUCCESS] Portals built successfully") + return True + else: + print(f"[ERROR] pnpm build failed with return code {build_result.returncode}") + return False + + except subprocess.TimeoutExpired: + print("[ERROR] pnpm build timed out after 5 minutes") + return False + except FileNotFoundError: + print("[ERROR] pnpm command not found - make sure pnpm is installed") + return False + except Exception as e: + print(f"[ERROR] Failed to build portals: {e}") + return False + else: + print("[INFO] Portals folder already exists") + return True + def create_zip(): """Create zip file with py, portals, java, client folders (Step 1).""" print_step_header("Creating Project Zip File", step_number=1, total_steps=TOTAL_STEPS) + # Build portals if not present + if not build_portals_if_needed(): + print("[ERROR] Failed to build portals - continuing without it") + folders_to_zip = ['py', 'portals', 'java', 'client'] timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') @@ -106,12 +160,22 @@ def create_zip(): if os.path.exists(folder): print(f"[INFO] Adding folder: {folder}") for root, dirs, files in os.walk(folder): + # Skip node_modules directories + if 'node_modules' in dirs: + dirs.remove('node_modules') + print(f"[INFO] Skipping node_modules in {root}") + for file in files: file_path = os.path.join(root, file) zipf.write(file_path) else: print(f"[WARN] Folder '{folder}' not found") + # Get and print zip file size + zip_size_bytes = os.path.getsize(zip_filename) + zip_size_mb = zip_size_bytes / (1024 * 1024) + print(f"[INFO] Zip file size: {zip_size_bytes:,} bytes ({zip_size_mb:.2f} MB)") + print(f"[SUCCESS] Zip file created: {zip_filename}") return zip_filename diff --git a/.github/workflows/semoss-validation.yml b/.github/workflows/semoss-validation.yml index f58fed5..9276fae 100644 --- a/.github/workflows/semoss-validation.yml +++ b/.github/workflows/semoss-validation.yml @@ -24,6 +24,16 @@ jobs: with: python-version: '3.12' + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '24' + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + - name: Install uv uses: astral-sh/setup-uv@v3 From b30098dd450ab98d66d9c1e55acffc9270ed24c2 Mon Sep 17 00:00:00 2001 From: Rithvik Doshi Date: Fri, 24 Oct 2025 15:00:47 -0400 Subject: [PATCH 13/17] fix(ci): project id and enhanced error tracking --- .../scripts/validate-semoss-compilation.py | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/.github/scripts/validate-semoss-compilation.py b/.github/scripts/validate-semoss-compilation.py index 4e6a2be..58ef4e6 100644 --- a/.github/scripts/validate-semoss-compilation.py +++ b/.github/scripts/validate-semoss-compilation.py @@ -337,7 +337,7 @@ def unzip_main_project(server_connection, zip_filename, project_id): print(f"[ERROR] Failed to unzip main project: {e}") return False -def compile_reactors(server_connection): +def compile_reactors(server_connection, project_id): """ Pixel: CompileAppReactors() Why: Compile Java reactors and validate no compilation errors exist @@ -345,12 +345,9 @@ def compile_reactors(server_connection): print_step_header("Compiling App Reactors", step_number=8, total_steps=TOTAL_STEPS) try: - compile_pixel = "CompileAppReactors();" + compile_pixel = f"CompileAppReactors(project=\"{project_id}\");" result = run_pixel_with_logging(server_connection, compile_pixel, full_response=True, show_output=False) - # Show detailed compilation output - print_pixel_output(result, show_detailed=True) - # Analyze results for errors if result and 'pixelReturn' in result: pixel_result = result['pixelReturn'][0] @@ -359,29 +356,35 @@ def compile_reactors(server_connection): # Check for actual errors (not warnings) if isinstance(output, list): - error_found = False + error_count = 0 warning_count = 0 mandatory_warning_count = 0 - for line in output: - if isinstance(line, str): + # Flatten all lines by splitting on \n + all_lines = [] + for item in output: + if isinstance(item, str): + all_lines.extend(item.split('\n')) + + for line in all_lines: + if isinstance(line, str) and line.strip(): # Skip empty lines # Count warnings if '[MANDATORY_WARNING]' in line: mandatory_warning_count += 1 elif '[WARNING]' in line: warning_count += 1 # Look for actual errors (not warnings) - elif 'ERROR' in line.upper() and 'WARNING' not in line.upper(): + elif '[ERROR]' in line: print(f"[ERROR] Compilation error found: {line}") - error_found = True + error_count += 1 - print(f"[INFO] Summary: {mandatory_warning_count} mandatory warnings, {warning_count} warnings") + print(f"[INFO] Summary: {error_count} errors, {mandatory_warning_count} mandatory warnings, {warning_count} warnings") - if not error_found: + if error_count == 0: print("[SUCCESS] No compilation errors found") return True else: - print("[ERROR] Compilation errors detected") + print(f"[ERROR] {error_count} compilation errors detected") return False else: print("[SUCCESS] Compilation completed") @@ -462,7 +465,7 @@ def run_validation_workflow(): raise Exception("Failed to unzip main project") # Step 8: Compile reactors - compilation_success = compile_reactors(server_connection) + compilation_success = compile_reactors(server_connection, project_id) if not compilation_success: raise Exception("Compilation failed") From b3153dfd4386e86111558b99f66bee42cf1225da Mon Sep 17 00:00:00 2001 From: Rithvik Doshi Date: Fri, 24 Oct 2025 15:26:28 -0400 Subject: [PATCH 14/17] fix(ci): colors --- .../scripts/validate-semoss-compilation.py | 56 +++++++++++++------ 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/.github/scripts/validate-semoss-compilation.py b/.github/scripts/validate-semoss-compilation.py index 58ef4e6..0fcdc02 100644 --- a/.github/scripts/validate-semoss-compilation.py +++ b/.github/scripts/validate-semoss-compilation.py @@ -19,6 +19,28 @@ import subprocess from datetime import datetime +# ANSI color wrapper +def cprint(message: str, color: str = None): + """Print a message with optional ANSI color. + + Args: + message (str): Text to print + color (str): One of 'green','red','yellow','blue','magenta','cyan','reset', or None + """ + colors = { + 'green': '\033[92m', + 'red': '\033[91m', + 'yellow': '\033[93m', + 'blue': '\033[94m', + 'magenta': '\033[95m', + 'cyan': '\033[96m', + 'reset': '\033[0m' + } + if color in colors: + print(f"{colors[color]}{message}{colors['reset']}") + else: + print(message) + # Total number of primary workflow steps (display-only constant) TOTAL_STEPS = 8 @@ -110,7 +132,7 @@ def build_portals_if_needed(): print(f"[ERROR] pnpm install failed with return code {install_result.returncode}") return False - print("[SUCCESS] Dependencies installed successfully") + cprint("[SUCCESS] Dependencies installed successfully", "green") # Run pnpm build in client directory with live output print("[INFO] Running 'pnpm build' in client directory...") @@ -121,7 +143,7 @@ def build_portals_if_needed(): ) if build_result.returncode == 0: - print("[SUCCESS] Portals built successfully") + cprint("[SUCCESS] Portals built successfully", "green") return True else: print(f"[ERROR] pnpm build failed with return code {build_result.returncode}") @@ -176,7 +198,7 @@ def create_zip(): zip_size_mb = zip_size_bytes / (1024 * 1024) print(f"[INFO] Zip file size: {zip_size_bytes:,} bytes ({zip_size_mb:.2f} MB)") - print(f"[SUCCESS] Zip file created: {zip_filename}") + cprint(f"[SUCCESS] Zip file created: {zip_filename}", "green") return zip_filename def setup_ai_server(): @@ -202,7 +224,7 @@ def setup_ai_server(): secret_key=secret_key ) - print("[SUCCESS] Connected to AI Server") + cprint("[SUCCESS] Connected to AI Server", "green") return server_connection except ImportError: @@ -222,7 +244,7 @@ def get_current_insight(server_connection): try: insight_id = server_connection.cur_insight - print(f"[SUCCESS] Using insight: {insight_id}") + cprint(f"[SUCCESS] Using insight: {insight_id}", "green") return insight_id except Exception as e: print(f"[ERROR] Failed to get insight ID: {e}") @@ -246,7 +268,7 @@ def create_temporary_project(server_connection): pixel_result = result['pixelReturn'][0] if 'output' in pixel_result and 'project_id' in pixel_result['output']: project_id = pixel_result['output']['project_id'] - print(f"[SUCCESS] Temporary project created: {project_id}") + cprint(f"[SUCCESS] Temporary project created: {project_id}", "green") return project_id print("[ERROR] Could not extract project ID from CreateProject result") @@ -266,7 +288,7 @@ def delete_existing_assets(server_connection, project_id): try: delete_pixel = f'DeleteAsset(filePath=["version/assets/"], space=["{project_id}"]);' run_pixel_with_logging(server_connection, delete_pixel) - print("[SUCCESS] Assets deletion completed") + cprint("[SUCCESS] Assets deletion completed", "green") return True except Exception as e: print(f"[ERROR] Failed to delete assets: {e}") @@ -310,7 +332,7 @@ def upload_zip_file(server_connection, zip_filename, project_id): if upload_result and upload_result[0] and upload_result[0].get('fileLocation'): - print("[SUCCESS] Upload completed") + cprint("[SUCCESS] Upload completed", "green") return True else: print("[ERROR] Upload failed: Invalid response") @@ -331,7 +353,7 @@ def unzip_main_project(server_connection, zip_filename, project_id): file_location = f"version/assets/{os.path.basename(zip_filename)}" unzip_pixel = f'UnzipFile(filePath=["{file_location}"], space=["{project_id}"]);' run_pixel_with_logging(server_connection, unzip_pixel) - print("[SUCCESS] Main project file unzipped") + cprint("[SUCCESS] Main project file unzipped", "green") return True except Exception as e: print(f"[ERROR] Failed to unzip main project: {e}") @@ -370,24 +392,26 @@ def compile_reactors(server_connection, project_id): if isinstance(line, str) and line.strip(): # Skip empty lines # Count warnings if '[MANDATORY_WARNING]' in line: + cprint(line, "yellow") mandatory_warning_count += 1 elif '[WARNING]' in line: + cprint(line, "blue") warning_count += 1 # Look for actual errors (not warnings) elif '[ERROR]' in line: - print(f"[ERROR] Compilation error found: {line}") + cprint(line, "red") error_count += 1 print(f"[INFO] Summary: {error_count} errors, {mandatory_warning_count} mandatory warnings, {warning_count} warnings") if error_count == 0: - print("[SUCCESS] No compilation errors found") + cprint("[SUCCESS] No compilation errors found", "green") return True else: - print(f"[ERROR] {error_count} compilation errors detected") + cprint(f"[ERROR] {error_count} compilation errors detected", "red") return False else: - print("[SUCCESS] Compilation completed") + cprint("[SUCCESS] Compilation completed", "green") return True else: print("[WARN] No compilation output returned") @@ -411,7 +435,7 @@ def cleanup_project(server_connection, project_id): try: delete_project_pixel = f'DeleteProject(project=["{project_id}"]);' run_pixel_with_logging(server_connection, delete_project_pixel) - print("[SUCCESS] Temporary project deleted") + cprint("[SUCCESS] Temporary project deleted", "green") return True except Exception as cleanup_error: print(f"[WARN] Could not delete project: {cleanup_error}") @@ -421,7 +445,7 @@ def cleanup_local_files(zip_filename): """Remove local zip file""" try: os.remove(zip_filename) - print(f"[SUCCESS] Cleaned up local file: {zip_filename}") + cprint(f"[SUCCESS] Cleaned up local file: {zip_filename}", "green") except: print(f"[WARN] Could not clean up: {zip_filename}") @@ -491,7 +515,7 @@ def main(): print("=" * 50) if success: - print("[SUCCESS] Compilation validation completed successfully") + cprint("[SUCCESS] Compilation validation completed successfully", "green") print("[INFO] All Java reactors compiled without errors") else: print("[ERROR] Compilation validation failed") From 248a33a04645b5941e846dc82473a689fc0729df Mon Sep 17 00:00:00 2001 From: Rithvik Doshi Date: Fri, 24 Oct 2025 15:52:19 -0400 Subject: [PATCH 15/17] ci: more colors and retry once --- .../scripts/validate-semoss-compilation.py | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/.github/scripts/validate-semoss-compilation.py b/.github/scripts/validate-semoss-compilation.py index 0fcdc02..e83bcde 100644 --- a/.github/scripts/validate-semoss-compilation.py +++ b/.github/scripts/validate-semoss-compilation.py @@ -438,7 +438,7 @@ def cleanup_project(server_connection, project_id): cprint("[SUCCESS] Temporary project deleted", "green") return True except Exception as cleanup_error: - print(f"[WARN] Could not delete project: {cleanup_error}") + cprint(f"[WARN] Could not delete project: {cleanup_error}", 'yellow') return False def cleanup_local_files(zip_filename): @@ -446,8 +446,8 @@ def cleanup_local_files(zip_filename): try: os.remove(zip_filename) cprint(f"[SUCCESS] Cleaned up local file: {zip_filename}", "green") - except: - print(f"[WARN] Could not clean up: {zip_filename}") + except Exception as e: + cprint(f"[WARN] Could not clean up {zip_filename}: {e}", 'yellow') def run_validation_workflow(): """Execute the main validation workflow steps""" @@ -496,7 +496,7 @@ def run_validation_workflow(): return True except Exception as e: - print(f"[ERROR] {e}") + cprint(f"[ERROR] {e}", 'red') return False finally: @@ -508,17 +508,29 @@ def run_validation_workflow(): def main(): """Main compilation validation workflow""" - print("[INFO] Starting compilation validation workflow") - print("=" * 50) - - success = run_validation_workflow() - - print("=" * 50) - if success: - cprint("[SUCCESS] Compilation validation completed successfully", "green") - print("[INFO] All Java reactors compiled without errors") - else: - print("[ERROR] Compilation validation failed") + + tries = 2 # Retry once + success = False + + while tries > 0: + print("[INFO] Starting compilation validation workflow") + print("=" * 50) + + success = run_validation_workflow() + + print("=" * 50) + if success: + cprint("[SUCCESS] Compilation validation completed successfully", "green") + cprint("[INFO] All Java reactors compiled without errors", 'blue') + else: + cprint("[ERROR] Compilation validation failed", 'red') + + if success: + break + tries -= 1 + + if tries > 0: + cprint("Retrying...", 'yellow') return success From cae18baee67dddee6bd0f2e8e55174ac41c86c63 Mon Sep 17 00:00:00 2001 From: Rithvik Doshi Date: Fri, 24 Oct 2025 16:01:35 -0400 Subject: [PATCH 16/17] ci: uuid on project name --- .github/scripts/validate-semoss-compilation.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/scripts/validate-semoss-compilation.py b/.github/scripts/validate-semoss-compilation.py index e83bcde..6390d1e 100644 --- a/.github/scripts/validate-semoss-compilation.py +++ b/.github/scripts/validate-semoss-compilation.py @@ -2,11 +2,9 @@ """ Script to validate Java reactor compilation in SEMOSS Creates temporary project, uploads code, compiles, then cleans up -@author: Patel, Parth +@author: Patel, Parth; Doshi, Rithvik TODOS: -- Retry potentially? Error with invalid session - - Log errors for sure - Potentially - on merge to deployment/default branch, have a cd action to just build the zip (can also have action to run manually) - Make python version an env var - Semantic versioning - work on this @@ -18,6 +16,7 @@ import base64 import subprocess from datetime import datetime +import uuid # ANSI color wrapper def cprint(message: str, color: str = None): @@ -258,7 +257,7 @@ def create_temporary_project(server_connection): print_step_header("Creating Temporary Project", step_number=4, total_steps=TOTAL_STEPS) try: - project_name = f"Test-project-{datetime.now().strftime('%b%d').lower()}" + project_name = f"Test-project-{datetime.now().strftime('%b%d').lower()}-{uuid.uuid1()}" create_project_pixel = f'CreateProject(project=["{project_name}"], portal=[true], projectType=["CODE"]);' result = run_pixel_with_logging(server_connection, create_project_pixel, full_response=True) From c1cc2980d007162cbcb12f9adade565a0759ab6d Mon Sep 17 00:00:00 2001 From: Rithvik Doshi Date: Fri, 24 Oct 2025 16:27:33 -0400 Subject: [PATCH 17/17] ci: try increasing retries --- .github/scripts/validate-semoss-compilation.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/scripts/validate-semoss-compilation.py b/.github/scripts/validate-semoss-compilation.py index 6390d1e..d5b92b2 100644 --- a/.github/scripts/validate-semoss-compilation.py +++ b/.github/scripts/validate-semoss-compilation.py @@ -5,7 +5,6 @@ @author: Patel, Parth; Doshi, Rithvik TODOS: -- Potentially - on merge to deployment/default branch, have a cd action to just build the zip (can also have action to run manually) - Make python version an env var - Semantic versioning - work on this """ @@ -508,7 +507,7 @@ def run_validation_workflow(): def main(): """Main compilation validation workflow""" - tries = 2 # Retry once + tries = 5 # number of retries success = False while tries > 0: @@ -529,7 +528,7 @@ def main(): tries -= 1 if tries > 0: - cprint("Retrying...", 'yellow') + cprint(f"Retrying... ({tries} left)", 'yellow') return success