From 548200f20d50c0ba9b28d474df1bba33f544361b Mon Sep 17 00:00:00 2001 From: bitkeeper Date: Thu, 19 Dec 2024 11:08:18 +0100 Subject: [PATCH 1/2] Update project to distribute self containing executable Instead of distributing the source an executable is build with pyinstaller. Git workflow is update to: * use a virtual env * build the executable * sign the exectutable before packed with the installer. --- .github/workflows/release.yml | 26 +++++++++++++++++++++----- requirements.dev.txt | 4 ++++ src/LPM.cmd | 1 - utils/BuildExecutable.bat | 2 ++ utils/Setup.iss | 23 +++-------------------- 5 files changed, 30 insertions(+), 26 deletions(-) create mode 100644 requirements.dev.txt delete mode 100644 src/LPM.cmd create mode 100644 utils/BuildExecutable.bat diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1b4ece5..1b0a8cb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,10 +27,6 @@ jobs: - name: Install Inno Setup silently run: .\is.exe /verysilent /dir="C:\Program Files\InnoSetup" - - name: Create the EXE Installer - working-directory: ./utils - run: ./BuildInstaller.bat - - name: Code Signing Setup - Setup Certificate shell: bash run: echo "${{secrets.SM_CLIENT_CERT_FILE_B64 }}" | base64 --decode > /d/Certificate_pkcs12.p12 @@ -52,7 +48,27 @@ jobs: C:\Windows\System32\certutil.exe -csp "DigiCert Signing Manager KSP" -key -user smksp_cert_sync.exe - - name: Code Signing Setup - Sign using Signtool + - name: Setup python virtual environment + run: | + python -m venv .venv + .venv\Scripts\Activate + pip install -r requirements.dev.txt + + - name: Create the EXE Installer + working-directory: ./utils + run: + ./BuildExecutable.bat + + - name: Code Signing Setup - Sign Executable using Signtool + run: | + signtool.exe sign /sha1 ${{ secrets.SM_CODE_SIGNING_CERT_SHA1_HASH }} /tr http://timestamp.digicert.com /td SHA256 /fd SHA256 "./dist/LPM.exe" + signtool.exe verify /v /pa "./dist/LPM.exe" + + - name: Create the EXE Installer + working-directory: ./utils + run: ./BuildInstaller.bat + + - name: Code Signing Setup - Sign Installer using Signtool run: | signtool.exe sign /sha1 ${{ secrets.SM_CODE_SIGNING_CERT_SHA1_HASH }} /tr http://timestamp.digicert.com /td SHA256 /fd SHA256 "./build/LPM-Setup.exe" signtool.exe verify /v /pa "./build/LPM-Setup.exe" diff --git a/requirements.dev.txt b/requirements.dev.txt new file mode 100644 index 0000000..d29ac86 --- /dev/null +++ b/requirements.dev.txt @@ -0,0 +1,4 @@ +pytest==8.3.4 +pyinstaller==6.11.1 + +. requirements.txt diff --git a/src/LPM.cmd b/src/LPM.cmd deleted file mode 100644 index 989ecfe..0000000 --- a/src/LPM.cmd +++ /dev/null @@ -1 +0,0 @@ -@python "%~dp0\LPM.py" %* diff --git a/utils/BuildExecutable.bat b/utils/BuildExecutable.bat new file mode 100644 index 0000000..0b392f1 --- /dev/null +++ b/utils/BuildExecutable.bat @@ -0,0 +1,2 @@ +cd .. +pyinstaller --onefile --clean --add-data src\version.json:. --icon=files\favicon.ico src\LPM.py diff --git a/utils/Setup.iss b/utils/Setup.iss index d3f8373..48ea264 100644 --- a/utils/Setup.iss +++ b/utils/Setup.iss @@ -5,7 +5,7 @@ #define MyAppVersion "1.0.6" #define MyAppPublisher "Loupe" #define MyAppURL "https://loupe.team/" -#define MyAppExeName "LPM.cmd" +#define MyAppExeName "LPM.exe" [Setup] ; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications. @@ -39,33 +39,16 @@ AlwaysRestart=yes Name: "english"; MessagesFile: "compiler:Default.isl" [Files] -Source: "..\src\*.py"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs -Source: "..\src\LPM.cmd"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\src\version.json"; DestDir: "{app}"; Flags: ignoreversion -Source: "..\requirements.txt"; DestDir: "{app}"; Flags: ignoreversion -; NOTE: Don't use "Flags: ignoreversion" on any shared system files +Source: "..\dist\LPM.exe"; DestDir: "{app}"; Flags: ignoreversion [Registry] Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}"; [Run] Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait skipifsilent -Filename: "{cmd}"; Parameters: "/C pip install -r ""{app}\requirements.txt"""; Description: "Installing Python dependencies..."; StatusMsg: "Installing dependencies..."; Check: PythonAndPipExist() [Code] -{ ///////////////////////////////////////////////////////////////////// } -function PythonAndPipExist(): Boolean; -var - ErrorCode: Integer; -begin - if Exec('python', '--version', '', SW_HIDE, ewWaitUntilTerminated, ErrorCode) and - Exec('pip', '--version', '', SW_HIDE, ewWaitUntilTerminated, ErrorCode) then - Result := True - else - Result := False; -end; - { ///////////////////////////////////////////////////////////////////// } function GetUninstallString(): String; var @@ -123,4 +106,4 @@ begin UnInstallOldVersion(); end; end; -end; \ No newline at end of file +end; From b81003ec1c57f09243e8f8153ab0f77d4e8ab280 Mon Sep 17 00:00:00 2001 From: bitkeeper Date: Fri, 10 Jan 2025 08:51:51 +0100 Subject: [PATCH 2/2] Add version resource to executable BY using a window resource for version you can inspect the version of an executable. --- utils/BuildExecutable.bat | 2 +- version.txt | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 version.txt diff --git a/utils/BuildExecutable.bat b/utils/BuildExecutable.bat index 0b392f1..435f692 100644 --- a/utils/BuildExecutable.bat +++ b/utils/BuildExecutable.bat @@ -1,2 +1,2 @@ cd .. -pyinstaller --onefile --clean --add-data src\version.json:. --icon=files\favicon.ico src\LPM.py +pyinstaller --onefile --clean --add-data src\version.json:. --version-file="version.txt" --icon=files\favicon.ico src\LPM.py diff --git a/version.txt b/version.txt new file mode 100644 index 0000000..fc8aa1c --- /dev/null +++ b/version.txt @@ -0,0 +1,33 @@ +# UTF-8 +VSVersionInfo( + ffi=FixedFileInfo( + filevers=(1, 0, 6, 1), + prodvers=(1, 0, 6, 1), + mask=0x3f, + flags=0x0, + OS=0x4, + fileType=0x1, + subtype=0x0, + date=(0, 0) + ), + kids=[ + StringFileInfo( + [ + StringTable( + u'040904B0', + [ + StringStruct(u'CompanyName', u'Loupe'), + StringStruct(u'FileDescription', u'LPM is the Loupe Package Manager voor B&R Automation Studio'), + StringStruct(u'FileVersion', u'1.0.6'), + StringStruct(u'InternalName', u'LPM'), + StringStruct(u'LegalCopyright', u'Copyright (C) 2023 Loupe, All rights reserved.'), + StringStruct(u'ProductName', u'LPM'), + StringStruct(u'ProductVersion', u'1.0.0'), + StringStruct(u'ApplicationName', u'LPM.exe') + ] + ) + ] + ), + VarFileInfo([VarStruct(u'Translation', [1033, 1200])]) + ] +)