From 88b0d54bb983cc15272086a7265892ce27d67f54 Mon Sep 17 00:00:00 2001 From: nicolasbisurgi Date: Fri, 14 Nov 2025 11:41:22 -0300 Subject: [PATCH] - Updated GitHub Actions workflow to dynamically generate PyInstaller spec file during build - Configured workflow to automatically attach Windows executable to 'latest' release on master merges - Added label property to ExecutionMode enum for cleaner display formatting - Refactored results.py to use mode.label property, removing LABEL_MAP circular import - Enhanced .gitignore to exclude build artifacts, spec files, results, and log files --- .github/workflows/build.yml | 75 ++++++++++++++++++++++++++++++++----- .gitignore | 10 ++++- execution_mode.py | 10 +++++ optimuspy.py | 1 - results.py | 6 +-- 5 files changed, 85 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bfae127..758e45d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,6 +9,8 @@ jobs: build-windows: name: Build on Windows runs-on: windows-latest + permissions: + contents: write steps: - name: Checkout code uses: actions/checkout@v4 @@ -24,19 +26,72 @@ jobs: pip install pyinstaller pip install -r requirements.txt - - name: Build executable + - name: Generate PyInstaller spec file run: | - pyinstaller --onefile ` - --name "optimuspy" ` - --add-data "execution_mode.py;." ` - --add-data "executors.py;." ` - --add-data "results.py;." ` - --hidden-import "seaborn" ` - --console optimuspy.py + $specContent = @" + # -*- mode: python ; coding: utf-8 -*- + + a = Analysis( + ['optimuspy.py'], + pathex=[], + binaries=[], + datas=[('execution_mode.py', '.'), ('executors.py', '.'), ('results.py', '.')], + hiddenimports=['seaborn', 'execution_mode', 'executors', 'results','win32timezone'], + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, + ) + pyz = PYZ(a.pure) + + exe = EXE( + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='optimuspy', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=True, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, + ) + "@ + Set-Content -Path "optimuspy.spec" -Value $specContent + + - name: Build executable + run: pyinstaller optimuspy.spec - name: Upload executable artifact uses: actions/upload-artifact@v4 with: - name: optimuspy-winOS + name: optimuspy-windows path: dist/optimuspy.exe - retention-days: 180 \ No newline at end of file + retention-days: 180 + + - name: Attach to latest release + uses: softprops/action-gh-release@v2 + with: + files: dist/optimuspy.exe + tag_name: latest + name: Latest Build + body: | + Latest Windows executable build from master branch. + + **Download:** optimuspy.exe + + This executable is automatically built and updated on every merge to master. + draft: false + prerelease: false + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 485dee6..b1a6178 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,9 @@ -.idea +.idea/ +dist/ +.venv/ +build/ +__pycache__/ +*.pyc +*.spec +results/ +*.log diff --git a/execution_mode.py b/execution_mode.py index 9555041..0b6ed95 100644 --- a/execution_mode.py +++ b/execution_mode.py @@ -13,3 +13,13 @@ def _missing_(cls, value): return member # default return cls.ALL + + @property + def label(self) -> str: + """Return human-readable label for the execution mode.""" + labels = { + ExecutionMode.ORIGINAL_ORDER: "Original Order", + ExecutionMode.ITERATIONS: "Iterations", + ExecutionMode.RESULT: "Result", + } + return labels.get(self, self.name) diff --git a/optimuspy.py b/optimuspy.py index 9ba0212..d2214fa 100644 --- a/optimuspy.py +++ b/optimuspy.py @@ -41,7 +41,6 @@ def set_current_directory(): os.chdir(directory) return directory - def configure_logging(): logging.basicConfig( filename=LOGFILE, diff --git a/results.py b/results.py index 6c12e4a..5c3a727 100644 --- a/results.py +++ b/results.py @@ -93,14 +93,12 @@ def build_csv_header(self) -> str: return SEPARATOR.join(self.build_header()) + "\n" def to_row(self, view_name: str, process_name: str, original_order_result: 'PermutationResult') -> List[str]: - from optimuspy import LABEL_MAP - median_query_time = float(self.median_query_time(view_name)) original_median_query_time = float(original_order_result.median_query_time(view_name)) query_time_ratio = median_query_time / original_median_query_time - 1 row = [ str(self.permutation_id), - LABEL_MAP[self.mode], + self.mode.label, str(self.is_best), median_query_time, query_time_ratio] @@ -250,8 +248,6 @@ def to_png(self, view_name: str, process_name: str, file_name: str): @property def original_order_result(self) -> PermutationResult: - from optimuspy import ExecutionMode - for result in self.permutation_results: if result.mode == ExecutionMode.ORIGINAL_ORDER: return result