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>
133 lines
4.9 KiB
YAML
133 lines
4.9 KiB
YAML
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
|