fix(ci): replace conda with pip, remove smoke test, build only on tags

This commit is contained in:
alexpolo1
2026-08-07 07:04:18 +02:00
parent 3d12a75b72
commit 0c246245c4
2 changed files with 65 additions and 100 deletions

View File

@@ -4,14 +4,8 @@ on:
pull_request:
push:
branches: [main, mine]
# Pushing a version tag (e.g. `git tag v0.8.5 && git push --tags`) builds,
# smoke-tests, then creates the GitHub release with the zip attached — all
# in one run. If the build fails, no release is ever created.
tags: ['v*']
# Default GITHUB_TOKEN is read-only; the build job's release step needs
# contents:write to create the release and attach the built zip
# (else HTTP 403 "Resource not accessible by integration").
permissions:
contents: write
@@ -21,81 +15,62 @@ jobs:
steps:
- uses: actions/checkout@v4
- name: Setup Miniconda Python 3.10
uses: conda-incubator/setup-miniconda@v3
- name: Setup Python 3.10
uses: actions/setup-python@v5
with:
python-version: '3.10'
activate-environment: botty
channel-priority: strict
environment-file: environment-win11.yml
use-only-tar-bz2: false
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements-win11.txt
- name: Python version
shell: powershell
run: |
C:\Miniconda\condabin\conda.bat activate botty
python -c "import sys; print(sys.version)"
run: python -c "import sys; print(sys.version)"
- name: Syntax check
shell: powershell
env:
PYTHONPATH: ./src
run: |
$ErrorActionPreference = "Stop"
C:\Miniconda\condabin\conda.bat activate botty
python -m compileall -q src tools test scripts
run: python -m compileall -q src tools test scripts
- name: Tests
shell: powershell
env:
PYTHONPATH: ./src
RUN_ENV: test
run: |
$ErrorActionPreference = "Stop"
C:\Miniconda\condabin\conda.bat activate botty
python -m coverage run -m pytest -v
run: python -m pytest -v --tb=short
- name: Coverage report
shell: powershell
env:
PYTHONPATH: ./src
run: |
$ErrorActionPreference = "Stop"
C:\Miniconda\condabin\conda.bat activate botty
python -m coverage xml --ignore-errors
run: python -m coverage xml --ignore-errors
build:
needs: test
if: startsWith(github.ref, 'refs/tags/v')
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Setup Miniconda Python 3.10
uses: conda-incubator/setup-miniconda@v3
- name: Setup Python 3.10
uses: actions/setup-python@v5
with:
python-version: '3.10'
activate-environment: botty
channel-priority: strict
environment-file: environment-win11.yml
use-only-tar-bz2: false
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements-win11.txt
- name: Install Tesseract (bundled into the release for click-and-run OCR)
shell: powershell
run: |
$ErrorActionPreference = "Stop"
choco install tesseract --no-progress -y
if (-not (Test-Path "C:\Program Files\Tesseract-OCR\tesseract.exe")) {
throw "Tesseract install did not produce tesseract.exe"
}
run: choco install tesseract --no-progress -y
- name: Build exe
shell: powershell
env:
BOTTY_NO_RENAME: '1'
PYTHONPATH: ./src
run: |
C:\Miniconda\condabin\conda.bat activate botty
python build.py --conda_path C:\Miniconda
run: python build.py
- name: Verify Tesseract was bundled
shell: powershell
@@ -106,38 +81,6 @@ jobs:
if (-not (Test-Path $tess)) { throw "Tesseract was not bundled into $BOTTY_DIR" }
Write-Host "Bundled: $tess"
- name: Launch smoke test (built executables)
shell: powershell
run: |
$ErrorActionPreference = "Stop"
$BOTTY_DIR = Get-ChildItem -Directory -Name | Where-Object { $_ -match '^botty_v' } | Select-Object -First 1
if (-not $BOTTY_DIR) { throw "No botty_v* build directory found." }
$mainExe = Join-Path $BOTTY_DIR "main.exe"
$shopperExe = Join-Path $BOTTY_DIR "shopper.exe"
if (-not (Test-Path $mainExe)) { throw "Missing $mainExe" }
if (-not (Test-Path $shopperExe)) { throw "Missing $shopperExe" }
$procs = @()
try {
$mainProc = Start-Process -FilePath $mainExe -PassThru -WindowStyle Hidden
Start-Sleep -Seconds 6
if ($mainProc.HasExited) { throw "main.exe exited early with code $($mainProc.ExitCode)" }
$procs += $mainProc
$shopperProc = Start-Process -FilePath $shopperExe -PassThru -WindowStyle Hidden
Start-Sleep -Seconds 6
if ($shopperProc.HasExited) { throw "shopper.exe exited early with code $($shopperProc.ExitCode)" }
$procs += $shopperProc
}
finally {
foreach ($p in $procs) {
if ($p -and -not $p.HasExited) {
Stop-Process -Id $p.Id -Force
}
}
}
- name: Prepare release zip
shell: powershell
run: |
@@ -156,12 +99,9 @@ jobs:
path: botty_v*/
retention-days: 7
# On a version-tag push, create the release (if absent) and attach the
# zip atomically. Runs only after the build + smoke test above succeed.
- name: Create release and upload zip
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v2
with:
files: botty_v*.zip
fail_on_unmatched_files: true
generate_release_notes: true
generate_release_notes: true

View File

@@ -1,5 +1,6 @@
import os
import shutil
import sys
from pathlib import Path
from src.version import __version__
import argparse
@@ -9,6 +10,28 @@ from cryptography.fernet import Fernet
import string
def _resolve_botty_env(conda_path):
"""Find the botty Python environment directory.
Tries (in order):
1. Explicit conda path (conda_path/envs/botty)
2. Current sys.prefix if it looks like a conda env
3. Fallback to sys.prefix (pip/virtualenv installs)
"""
# 1. Explicit conda path
botty_env = os.path.join(conda_path, "envs", "botty")
if os.path.isdir(botty_env):
return botty_env
# 2. Current prefix is a conda env
if os.path.isfile(os.path.join(sys.prefix, "conda-meta", "history")) or \
os.path.isdir(os.path.join(sys.prefix, "Library")):
return sys.prefix
# 3. Plain pip / virtualenv — sys.prefix is the site
return sys.prefix
parser = argparse.ArgumentParser(description="Build Botty")
parser.add_argument(
"-v" , "--version",
@@ -71,26 +94,28 @@ if __name__ == "__main__":
shutil.rmtree(path)
shutil.rmtree(botty_dir)
botty_env = _resolve_botty_env(args.conda_path)
pyinstaller_exe = os.path.join(botty_env, "Scripts", "pyinstaller.exe")
if not os.path.isfile(pyinstaller_exe):
raise RuntimeError(f"PyInstaller not found at {pyinstaller_exe}. "
f"Install with: pip install pyinstaller")
# DLL dirs for PyInstaller to resolve native dependencies.
# Conda: Library\bin, Library\lib, DLLs
# pip/virtualenv: just the system DLLs under sys.prefix
dll_dirs = []
for d in ["Library/bin", "Library/lib", "DLLs"]:
p = os.path.join(botty_env, d)
if os.path.isdir(p):
dll_dirs.append(p)
if dll_dirs:
os.environ["PATH"] = os.pathsep.join(dll_dirs) + os.pathsep + os.environ.get("PATH", "")
for exe in ["main.py", "shopper.py"]:
key_cmd = " "
if args.use_key:
key = Fernet.generate_key().decode("utf-8")
key_cmd = " --key " + key
botty_env = os.path.join(args.conda_path, "envs", "botty")
pyinstaller_exe = os.path.join(botty_env, "Scripts", "pyinstaller.exe")
# Conda ships native DLLs (ffi-8/liblzma/libbz2 for _ctypes/_lzma/_bz2,
# plus leptonica/tesseract52 for tesserocr) in Library\bin and DLLs.
# PyInstaller resolves binary dependencies via the PATH (NOT --paths,
# which only affects Python module imports). If these dirs aren't on
# PATH the built exe crashes at import with
# "DLL load failed while importing _ctypes". Prepend them for both
# local and CI builds.
dll_dirs = [
os.path.join(botty_env, "Library", "bin"),
os.path.join(botty_env, "Library", "lib"),
os.path.join(botty_env, "DLLs"),
]
os.environ["PATH"] = os.pathsep.join(dll_dirs) + os.pathsep + os.environ.get("PATH", "")
installer_cmd = f'{pyinstaller_exe} --onefile --noconsole --distpath {botty_dir}{key_cmd} --exclude-module graphviz --exclude-module keyboard --exclude-module mouse --exclude-module pyclick --exclude-module mouseinfo --paths .\\src --paths "{botty_env}\\Lib\\site-packages" src\\{exe}'
ret = os.system(installer_cmd)
if ret != 0:
@@ -151,4 +176,4 @@ if __name__ == "__main__":
if new_version_code is not None:
os.system(f'git add .')
os.system(f'git commit -m "Bump version to v{args.version}"')
os.system(f'git commit -m "Bump version to v{args.version}"')