Skip to content

Commit 5869cb5

Browse files
authored
Refactor GitHub Actions workflow for Windows installer
1 parent 965ff2f commit 5869cb5

File tree

1 file changed

+136
-136
lines changed

1 file changed

+136
-136
lines changed
Lines changed: 136 additions & 136 deletions
Original file line numberDiff line numberDiff line change
@@ -1,203 +1,203 @@
1-
name: Test streamlit executable for Windows with embeddable python
2-
on:
1+
name: Build Streamlit Windows Installer (Multi-CAB, Embeddable Python)
2+
3+
on:
34
push:
45
branches: [ "main" ]
56
workflow_dispatch:
67

78
jobs:
8-
build-win-executable-with-embeddable-python:
9+
build-win-installer:
910
runs-on: windows-2022
1011

1112
env:
1213
PYTHON_VERSION: 3.10.0
13-
APP_UpgradeCode: 4abc2e23-3ba5-40e4-95c9-09e6cb8ecaeb
1414
APP_NAME: OpenMS-NuXLApp-Test
15+
APP_UpgradeCode: 4abc2e23-3ba5-40e4-95c9-09e6cb8ecaeb
1516

1617
steps:
17-
- name: Checkout code
18+
- name: Checkout repository
1819
uses: actions/checkout@v4
1920

20-
- name: Download python embeddable version
21+
# ----------------------------------------------------------------------
22+
# Download embeddable Python
23+
# ----------------------------------------------------------------------
24+
- name: Download Python embeddable
25+
shell: bash
2126
run: |
22-
mkdir python-${{ env.PYTHON_VERSION }}
23-
curl -O https://www.python.org/ftp/python/${{ env.PYTHON_VERSION }}/python-${{ env.PYTHON_VERSION }}-embed-amd64.zip
24-
unzip python-${{ env.PYTHON_VERSION }}-embed-amd64.zip -d python-${{ env.PYTHON_VERSION }}
25-
rm python-${{ env.PYTHON_VERSION }}-embed-amd64.zip
27+
mkdir python-${PYTHON_VERSION}
28+
curl -LO https://www.python.org/ftp/python/${PYTHON_VERSION}/python-${PYTHON_VERSION}-embed-amd64.zip
29+
unzip python-${PYTHON_VERSION}-embed-amd64.zip -d python-${PYTHON_VERSION}
30+
rm python-${PYTHON_VERSION}-embed-amd64.zip
2631
27-
- name: Install pip
32+
- name: Install pip into embeddable Python
33+
shell: bash
2834
run: |
29-
curl -O https://bootstrap.pypa.io/get-pip.py
30-
./python-${{ env.PYTHON_VERSION }}/python get-pip.py --no-warn-script-location
35+
curl -LO https://bootstrap.pypa.io/get-pip.py
36+
./python-${PYTHON_VERSION}/python get-pip.py --no-warn-script-location
3137
rm get-pip.py
32-
33-
- name: Uncomment 'import site' in python310._pth file
38+
39+
- name: Enable site-packages (import site)
40+
shell: bash
3441
run: |
35-
sed -i 's/#import site/import site/' python-${{ env.PYTHON_VERSION }}/python310._pth
36-
37-
- name: Print content of python310._pth file
42+
sed -i 's/#import site/import site/' python-${PYTHON_VERSION}/python310._pth
43+
44+
- name: Install Python requirements
3845
run: |
39-
cat python-${{ env.PYTHON_VERSION }}/python310._pth
46+
.\python-${{ env.PYTHON_VERSION }}\python -m pip install -r requirements.txt --no-warn-script-location
4047
41-
- name: Install Required Packages
42-
run: .\python-${{ env.PYTHON_VERSION }}\python -m pip install -r requirements.txt --no-warn-script-location
43-
44-
- name: Create .bat file
48+
# ----------------------------------------------------------------------
49+
# Build portable application directory
50+
# ----------------------------------------------------------------------
51+
- name: Create launcher batch file
52+
shell: bash
4553
run: |
46-
echo " start /min .\python-${{ env.PYTHON_VERSION }}\python -m streamlit run app.py local" > ${{ env.APP_NAME }}.bat
47-
48-
- name: Create All-in-one executable folder
54+
echo "start /min python-${PYTHON_VERSION}\\python -m streamlit run app.py local" > ${APP_NAME}.bat
55+
56+
- name: Assemble portable app folder
4957
run: |
58+
Remove-Item -Recurse -Force streamlit_exe -ErrorAction SilentlyContinue
5059
mkdir streamlit_exe
5160
mv python-${{ env.PYTHON_VERSION }} streamlit_exe
5261
cp -r src streamlit_exe
5362
cp -r content streamlit_exe
54-
cp -r docs streamlit_exe
5563
cp -r assets streamlit_exe
5664
cp -r example-data streamlit_exe
5765
cp -r .streamlit streamlit_exe
5866
cp app.py streamlit_exe
5967
cp settings.json streamlit_exe
60-
cp default-parameters.json streamlit_exe
6168
cp ${{ env.APP_NAME }}.bat streamlit_exe
62-
63-
- name: Generate Readme.txt
64-
shell: bash
69+
70+
# Optional but strongly recommended: reduce file count
71+
- name: Remove Python caches and tests
6572
run: |
66-
cat <<EOF > streamlit_exe/Readme.txt
67-
Welcome to ${{ env.APP_NAME }} app!
68-
69-
To launch the application:
70-
1. Navigate to the installation directory.
71-
2. Double-click on the file: ${{ env.APP_NAME }}.bat or ${{ env.APP_NAME }} shortcut.
72-
73-
Additional Information:
74-
- If multiple Streamlit apps are running, you can change the port in the .streamlit/config.toml file.
75-
Example:
76-
[server]
77-
port = 8502
78-
79-
Reach out to us:
80-
- Join our Discord server for support and community discussions: https://discord.com/invite/4TAGhqJ7s5
81-
- Contribute or stay updated with the latest OpenMS web app developments on GitHub: https://github.com/OpenMS/streamlit-template
82-
- Visit our website for more information: https://openms.de/
83-
84-
Thank you for using ${{ env.APP_NAME }}!
85-
EOF
86-
87-
- name: Install WiX Toolset
73+
Get-ChildItem streamlit_exe -Recurse -Directory -Filter "__pycache__" | Remove-Item -Recurse -Force
74+
Get-ChildItem streamlit_exe -Recurse -Directory -Match "test","tests" | Remove-Item -Recurse -Force
75+
76+
# ----------------------------------------------------------------------
77+
# Install WiX Toolset 3.11
78+
# ----------------------------------------------------------------------
79+
- name: Install WiX
80+
shell: bash
8881
run: |
8982
curl -LO https://github.com/wixtoolset/wix3/releases/download/wix3111rtm/wix311-binaries.zip
9083
unzip wix311-binaries.zip -d wix
9184
rm wix311-binaries.zip
92-
93-
- name: Build .wxs for streamlit_exe folder
85+
86+
# ----------------------------------------------------------------------
87+
# Split harvesting (CRITICAL PART)
88+
# ----------------------------------------------------------------------
89+
- name: Harvest application files (no Python)
90+
run: |
91+
./wix/heat.exe dir streamlit_exe `
92+
-gg -sfrag -sreg -srd `
93+
-template component `
94+
-cg AppFiles `
95+
-dr AppSubFolder `
96+
-x streamlit_exe/python-${{ env.PYTHON_VERSION }} `
97+
-out app_files.wxs
98+
99+
- name: Harvest Python runtime (no site-packages)
94100
run: |
95-
./wix/heat.exe dir streamlit_exe -gg -sfrag -sreg -srd -template component -cg StreamlitExeFiles -dr AppSubFolder -out streamlit_exe_files.wxs
96-
97-
- name: Generate VBScript file
101+
./wix/heat.exe dir streamlit_exe/python-${{ env.PYTHON_VERSION }} `
102+
-gg -sfrag -sreg -srd `
103+
-template component `
104+
-cg PythonRuntime `
105+
-dr AppSubFolder `
106+
-x streamlit_exe/python-${{ env.PYTHON_VERSION }}/Lib/site-packages `
107+
-out python_runtime.wxs
108+
109+
- name: Harvest Python site-packages
110+
run: |
111+
./wix/heat.exe dir streamlit_exe/python-${{ env.PYTHON_VERSION }}/Lib/site-packages `
112+
-gg -sfrag -sreg -srd `
113+
-template component `
114+
-cg PythonPackages `
115+
-dr AppSubFolder `
116+
-out python_packages.wxs
117+
118+
# ----------------------------------------------------------------------
119+
# Assign DiskId to avoid CAB overflow
120+
# ----------------------------------------------------------------------
121+
- name: Assign DiskId per harvest
98122
shell: bash
99123
run: |
100-
cat <<EOF > ShowSuccessMessage.vbs
101-
MsgBox " The ${{ env.APP_NAME }} application is successfully installed.", vbInformation, "Installation Complete"
102-
EOF
124+
sed -i 's/<File /<File DiskId="1" /' app_files.wxs
125+
sed -i 's/<File /<File DiskId="2" /' python_runtime.wxs
126+
sed -i 's/<File /<File DiskId="3" /' python_packages.wxs
103127
128+
# ----------------------------------------------------------------------
129+
# Prepare SourceDir
130+
# ----------------------------------------------------------------------
104131
- name: Prepare SourceDir
105132
run: |
106133
mkdir SourceDir
107134
mv streamlit_exe/* SourceDir
108-
cp ShowSuccessMessage.vbs SourceDir
109135
cp assets/openms_license.rtf SourceDir
110-
# Logo of app
111136
cp assets/openms.ico SourceDir
112-
113-
- name: Generate WiX XML file
137+
138+
# ----------------------------------------------------------------------
139+
# Main WiX product file
140+
# ----------------------------------------------------------------------
141+
- name: Generate main WiX file
114142
shell: bash
115143
run: |
116-
cat <<EOF > streamlit_exe.wxs
144+
cat <<EOF > installer.wxs
117145
<?xml version="1.0"?>
118146
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
119-
<Product Id="*" Name="${{ env.APP_NAME }}" Language="1033" Version="1.0.0.0" Codepage="1252" Manufacturer="OpenMS Developer Team" UpgradeCode="${{ env.APP_UpgradeCode }}">
120-
<Package Id="*" InstallerVersion="300" Compressed="yes" InstallPrivileges="elevated" Platform="x64" />
121-
<Media Id="1" Cabinet="streamlit.cab" EmbedCab="yes" />
122-
123-
<!-- Folder structure -->
124-
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
147+
<Product Id="*" Name="${APP_NAME}" Language="1033"
148+
Version="1.0.0.0"
149+
Manufacturer="OpenMS Developer Team"
150+
UpgradeCode="${APP_UpgradeCode}">
151+
<Package InstallerVersion="300" Compressed="yes" Platform="x64"/>
152+
153+
<Media Id="1" Cabinet="app.cab" EmbedCab="yes"/>
154+
<Media Id="2" Cabinet="python.cab" EmbedCab="yes"/>
155+
<Media Id="3" Cabinet="packages.cab" EmbedCab="yes"/>
156+
125157
<Directory Id="TARGETDIR" Name="SourceDir">
126-
<Directory Id="ProgramFilesFolder">
127-
<Directory Id="INSTALLFOLDER" Name="${{ env.APP_NAME }}">
128-
<Directory Id="AppSubFolder" Name="${{ env.APP_NAME }}" />
129-
<Component Id="CreateAppFolder" Guid="95dbfa06-d36a-427f-995c-e87769ac2e59">
130-
<CreateFolder>
131-
<Permission User="Everyone" GenericAll="yes" />
132-
</CreateFolder>
133-
</Component>
158+
<Directory Id="ProgramFilesFolder">
159+
<Directory Id="INSTALLFOLDER" Name="${APP_NAME}">
160+
<Directory Id="AppSubFolder" Name="${APP_NAME}"/>
134161
</Directory>
135162
</Directory>
136-
<Directory Id="DesktopFolder" />
163+
<Directory Id="DesktopFolder"/>
137164
</Directory>
138-
139-
<!-- Add components -->
140-
<Feature Id="MainFeature" Title="Main Application" Level="1">
141-
<ComponentGroupRef Id="StreamlitExeFiles" />
142-
<ComponentRef Id="CreateAppFolder" />
143-
<ComponentRef Id="DesktopShortcutComponent" />
144-
<ComponentRef Id="InstallDirShortcutComponent" />
165+
166+
<Feature Id="MainFeature" Level="1">
167+
<ComponentGroupRef Id="AppFiles"/>
168+
<ComponentGroupRef Id="PythonRuntime"/>
169+
<ComponentGroupRef Id="PythonPackages"/>
145170
</Feature>
146-
147-
<!-- Create shortcut for running app on desktop -->
148-
<Component Id="DesktopShortcutComponent" Guid="3597b243-9180-4d0b-b105-30d8b0d1a334" Directory="DesktopFolder">
149-
<Shortcut Id="DesktopShortcut" Name="${{ env.APP_NAME }}" Description="Launch ${{ env.APP_NAME }}" Target="[AppSubFolder]${{ env.APP_NAME }}.bat" WorkingDirectory="AppSubFolder" Icon="AppIcon" />
150-
<RegistryValue Root="HKCU" Key="Software\\OpenMS\\${{ env.APP_NAME }}" Name="DesktopShortcut" Type="integer" Value="1" KeyPath="yes" />
151-
</Component>
152-
153-
<!-- Create shortcut for running app in installer folder -->
154-
<Component Id="InstallDirShortcutComponent" Guid="c2df9472-3b45-4558-a56d-6034cf7c8b72" Directory="AppSubFolder">
155-
<Shortcut Id="InstallDirShortcut" Name="${{ env.APP_NAME }}" Description="Launch ${{ env.APP_NAME }}" Target="[AppSubFolder]${{ env.APP_NAME }}.bat" WorkingDirectory="AppSubFolder" Icon="AppIcon" />
156-
<RegistryValue Root="HKCU" Key="Software\\OpenMS\\${{ env.APP_NAME }}" Name="InstallFolderShortcut" Type="integer" Value="1" KeyPath="yes" />
157-
</Component>
158-
159-
<!-- Provide icon here; it should exist in the SourceDir folder -->
160-
<Icon Id="AppIcon" SourceFile="SourceDir/openms.ico" />
161-
162-
<!-- Run app directly after installation -->
163-
<!-- <CustomAction Id="RunApp" Directory="AppSubFolder" Execute="deferred" Return="asyncNoWait" Impersonate="no"
164-
ExeCommand="cmd.exe /c &quot;[AppSubFolder]${{ env.APP_NAME }}.bat&quot;" /> -->
165-
166-
<!-- Custom Action to Show Success Message -->
167-
<Binary Id="ShowMessageScript" SourceFile="SourceDir/ShowSuccessMessage.vbs" />
168-
<CustomAction Id="ShowSuccessMessage" BinaryKey="ShowMessageScript" VBScriptCall="" Execute="immediate" Return="check" />
169-
170-
<!-- Add all Custom Actions -->
171-
<InstallExecuteSequence>
172-
<!-- Custom action display success message -->
173-
<Custom Action="ShowSuccessMessage" After="InstallFinalize">NOT Installed</Custom>
174-
<!-- Run app directly after installation -->
175-
<!-- <Custom Action="RunApp" Before="InstallFinalize">NOT REMOVE</Custom> -->
176-
</InstallExecuteSequence>
177-
178-
<!-- Interface options -->
171+
172+
<Icon Id="AppIcon" SourceFile="SourceDir/openms.ico"/>
173+
<WixVariable Id="WixUILicenseRtf" Value="SourceDir/openms_license.rtf"/>
174+
179175
<UI>
180-
<UIRef Id="WixUI_InstallDir" />
181-
<UIRef Id="WixUI_ErrorProgressText" />
182-
</UI>
183-
184-
<!-- Provide license; it should exist in the SourceDir folder -->
185-
<WixVariable Id="WixUILicenseRtf" Value="SourceDir/openms_license.rtf" />
176+
<UIRef Id="WixUI_InstallDir"/>
177+
<UIRef Id="WixUI_ErrorProgressText"/>
178+
</UI>
186179
</Product>
187180
</Wix>
188181
EOF
189182
190-
- name: Build .wixobj file with candle.exe
183+
# ----------------------------------------------------------------------
184+
# Build MSI
185+
# ----------------------------------------------------------------------
186+
- name: Compile WiX sources
191187
run: |
192-
./wix/candle.exe streamlit_exe.wxs streamlit_exe_files.wxs
193-
194-
- name: Link .wixobj file into .msi with light.exe
188+
./wix/candle.exe installer.wxs app_files.wxs python_runtime.wxs python_packages.wxs
189+
190+
- name: Link MSI
195191
run: |
196-
./wix/light.exe -ext WixUIExtension -sice:ICE60 -o ${{ env.APP_NAME }}.msi streamlit_exe_files.wixobj streamlit_exe.wixobj
192+
./wix/light.exe -ext WixUIExtension `
193+
-o ${APP_NAME}.msi `
194+
installer.wixobj app_files.wixobj python_runtime.wixobj python_packages.wixobj
197195
198-
- name: Archive build artifacts
196+
# ----------------------------------------------------------------------
197+
# Upload artifact
198+
# ----------------------------------------------------------------------
199+
- name: Upload MSI
199200
uses: actions/upload-artifact@v4
200201
with:
201-
name: OpenMS-App-Test
202-
path: |
203-
${{ env.APP_NAME }}.msi
202+
name: OpenMS-Windows-MSI
203+
path: ${{ env.APP_NAME }}.msi

0 commit comments

Comments
 (0)