Ajout build portable : Python embarqué + lanceur .bat (sans compilation)
Nouveau workflow build-portable.yml : - Télécharge Python embeddable (zip officiel, ~15 Mo) - Installe pip + requirements dedans - Copie tkinter depuis l'installation complète - Copie nos scripts + config + modèle NER - Crée un lanceur Pseudonymisation.bat (double-clic) - Aucune compilation C, pas de faux positif antivirus Pour l'utilisateur : dézipper → double-cliquer Pseudonymisation.bat Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
132
.github/workflows/build-portable.yml
vendored
Normal file
132
.github/workflows/build-portable.yml
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
name: Build Windows Portable (Python Embarqué)
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
build-portable:
|
||||
runs-on: windows-latest
|
||||
timeout-minutes: 30
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Python 3.12
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
cache: pip
|
||||
|
||||
- name: Install deps (system Python)
|
||||
run: pip install -r requirements.txt
|
||||
|
||||
- name: Download NER model
|
||||
run: |
|
||||
python -c "from ner_manager_onnx import NerModelManager; m=NerModelManager(cache_dir='models'); m.load('cmarkea/distilcamembert-base-ner'); print('Model OK:', m.is_loaded()); m.unload()"
|
||||
|
||||
- name: Build portable distribution
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# --- Detect Python version ---
|
||||
$pyFull = python -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}')"
|
||||
$pyShort = python -c "import sys; print(f'{sys.version_info.major}{sys.version_info.minor}')"
|
||||
Write-Host "Python: $pyFull (short: $pyShort)"
|
||||
|
||||
# --- Paths ---
|
||||
$dist = "dist\Pseudonymisation"
|
||||
$pyDir = "$dist\python"
|
||||
$appDir = "$dist\app"
|
||||
New-Item -ItemType Directory -Force $pyDir, $appDir | Out-Null
|
||||
|
||||
# --- Download Python embeddable ---
|
||||
$url = "https://www.python.org/ftp/python/$pyFull/python-$pyFull-embed-amd64.zip"
|
||||
Write-Host "Downloading $url ..."
|
||||
Invoke-WebRequest -Uri $url -OutFile embed.zip -UseBasicParsing
|
||||
Expand-Archive embed.zip -DestinationPath $pyDir -Force
|
||||
|
||||
# --- Configure _pth (enable site-packages + app path) ---
|
||||
$pthContent = @("python$pyShort.zip", ".", "..\app", "Lib\site-packages", "import site")
|
||||
$pthContent | Set-Content "$pyDir\python$pyShort._pth" -Encoding ASCII
|
||||
Write-Host "_pth configured"
|
||||
|
||||
# --- Install pip in embeddable Python ---
|
||||
Invoke-WebRequest -Uri "https://bootstrap.pypa.io/get-pip.py" -OutFile get-pip.py -UseBasicParsing
|
||||
& "$pyDir\python.exe" get-pip.py --no-warn-script-location 2>&1
|
||||
Write-Host "pip installed"
|
||||
|
||||
# --- Install requirements in embeddable Python ---
|
||||
& "$pyDir\python.exe" -m pip install -r requirements.txt --no-warn-script-location 2>&1
|
||||
Write-Host "Requirements installed"
|
||||
|
||||
# --- Copy tkinter from full Python installation ---
|
||||
$fullPy = Split-Path (Get-Command python.exe).Source
|
||||
Write-Host "Full Python at: $fullPy"
|
||||
|
||||
# DLLs
|
||||
Copy-Item "$fullPy\DLLs\_tkinter.pyd" $pyDir -Force
|
||||
Copy-Item "$fullPy\DLLs\tcl86t.dll" $pyDir -Force
|
||||
Copy-Item "$fullPy\DLLs\tk86t.dll" $pyDir -Force
|
||||
|
||||
# tcl/tk library files
|
||||
if (Test-Path "$fullPy\tcl") {
|
||||
Copy-Item -Recurse "$fullPy\tcl" "$pyDir\tcl" -Force
|
||||
}
|
||||
|
||||
# tkinter Python package
|
||||
New-Item -ItemType Directory -Force "$pyDir\Lib" | Out-Null
|
||||
Copy-Item -Recurse "$fullPy\Lib\tkinter" "$pyDir\Lib\tkinter" -Force
|
||||
Write-Host "tkinter copied"
|
||||
|
||||
# --- Copy application files ---
|
||||
$appFiles = @(
|
||||
"Pseudonymisation_Gui_V5.py",
|
||||
"anonymizer_core_refactored_onnx.py",
|
||||
"ner_manager_onnx.py",
|
||||
"eds_pseudo_manager.py"
|
||||
)
|
||||
foreach ($f in $appFiles) {
|
||||
Copy-Item $f $appDir -Force
|
||||
Write-Host " Copied $f"
|
||||
}
|
||||
Copy-Item -Recurse "config" "$appDir\config" -Force
|
||||
Copy-Item -Recurse "models" "$appDir\models" -Force
|
||||
Write-Host "App files copied"
|
||||
|
||||
# --- Create launcher .bat ---
|
||||
$bat = @(
|
||||
'@echo off',
|
||||
'cd /d "%~dp0"',
|
||||
'start "" "%~dp0python\pythonw.exe" "%~dp0app\Pseudonymisation_Gui_V5.py"'
|
||||
)
|
||||
$bat | Set-Content "$dist\Pseudonymisation.bat" -Encoding ASCII
|
||||
Write-Host "Launcher created"
|
||||
|
||||
# --- Size report ---
|
||||
$size = (Get-ChildItem -Recurse $dist | Measure-Object -Property Length -Sum).Sum / 1MB
|
||||
Write-Host ("Distribution size: {0:N0} MB" -f $size)
|
||||
|
||||
- name: Create zip
|
||||
shell: pwsh
|
||||
run: |
|
||||
Compress-Archive -Path "dist\Pseudonymisation" -DestinationPath "Pseudonymisation-Windows-Portable.zip"
|
||||
$zipSize = (Get-Item "Pseudonymisation-Windows-Portable.zip").Length / 1MB
|
||||
Write-Host ("ZIP size: {0:N0} MB" -f $zipSize)
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Pseudonymisation-Windows-Portable
|
||||
path: Pseudonymisation-Windows-Portable.zip
|
||||
retention-days: 30
|
||||
|
||||
- name: Upload to release (on tag)
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: Pseudonymisation-Windows-Portable.zip
|
||||
Reference in New Issue
Block a user