initial refactor of ci-cd pipeline
This commit is contained in:
@@ -7,7 +7,7 @@ import sys
|
||||
import re
|
||||
from pathlib import Path
|
||||
from enum import Enum
|
||||
from typing import List
|
||||
from typing import List, TypedDict
|
||||
|
||||
|
||||
class DistroType(Enum):
|
||||
@@ -16,7 +16,19 @@ class DistroType(Enum):
|
||||
RHEL = "rhel"
|
||||
|
||||
|
||||
def run_command(cmd: list[str], check: bool = True, working_dir: str | None = None) -> subprocess.CompletedProcess:
|
||||
class DistroConfigDict(TypedDict):
|
||||
"""Type definition for distro configuration."""
|
||||
|
||||
name: str
|
||||
bin_path: str
|
||||
pkg_suffix: str
|
||||
spec_file: str
|
||||
pkg_type: str
|
||||
architecture: str
|
||||
postinstall: str | None
|
||||
|
||||
|
||||
def run_command(cmd: list[str], check: bool = True, working_dir: str | None = None) -> subprocess.CompletedProcess[bytes]:
|
||||
"""Run command and handle errors."""
|
||||
print(f"Running: {' '.join(cmd)}")
|
||||
try:
|
||||
@@ -29,9 +41,9 @@ def run_command(cmd: list[str], check: bool = True, working_dir: str | None = No
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def get_distro_config(distro_type: DistroType) -> dict:
|
||||
def get_distro_config(distro_type: DistroType) -> DistroConfigDict:
|
||||
"""Get configuration for specific distro type."""
|
||||
configs = {
|
||||
configs: dict[DistroType, DistroConfigDict] = {
|
||||
DistroType.DEBIAN: {
|
||||
"name": "Debian",
|
||||
"bin_path": "usr/local/bin",
|
||||
@@ -131,10 +143,11 @@ def package_with_fpm(distro_type: DistroType, version: str, project_root: Path)
|
||||
# Add distro-specific options
|
||||
if distro_type == DistroType.DEBIAN:
|
||||
output_file = dist_dir / f"android-file-handler_{version}_{config['architecture']}.deb"
|
||||
postinstall = config["postinstall"]
|
||||
fpm_cmd.extend([
|
||||
"--deb-user", "root",
|
||||
"--deb-group", "root",
|
||||
"--after-install", config["postinstall"],
|
||||
*(["--after-install", postinstall] if postinstall else []),
|
||||
"-p", str(output_file)
|
||||
])
|
||||
elif distro_type == DistroType.ARCH:
|
||||
@@ -144,9 +157,9 @@ def package_with_fpm(distro_type: DistroType, version: str, project_root: Path)
|
||||
])
|
||||
elif distro_type == DistroType.RHEL:
|
||||
output_file = dist_dir / f"android-file-handler-{version}.{config['architecture']}.rpm"
|
||||
postinstall = config["postinstall"]
|
||||
fpm_cmd.extend([
|
||||
"--prefix", "/usr/bin",
|
||||
"--after-install", config["postinstall"],
|
||||
*(["--after-install", postinstall] if postinstall else []),
|
||||
"-p", str(output_file)
|
||||
])
|
||||
|
||||
|
||||
+29
-20
@@ -1,52 +1,57 @@
|
||||
# Docker Build Environment
|
||||
# Container Build Environment
|
||||
|
||||
This directory contains Dockerfiles for building the Android File Handler on different Linux distributions. These images match exactly the images used in the CI/CD pipeline.
|
||||
This directory contains OCI-compatible Containerfiles (Dockerfiles) for building the Android File Handler on different Linux distributions. These images match exactly the images used in the CI/CD pipeline.
|
||||
|
||||
The project uses **Podman** as the container runtime. All commands below use Podman; if you have Docker installed, the Dockerfiles are OCI-compatible and will work with Docker as well.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Using Docker Compose (Recommended)
|
||||
### Using Podman Compose (Recommended)
|
||||
|
||||
Build for all distributions:
|
||||
```bash
|
||||
docker-compose up --build
|
||||
podman-compose up --build
|
||||
```
|
||||
|
||||
Build for a specific distribution:
|
||||
```bash
|
||||
docker-compose up --build debian
|
||||
docker-compose up --build arch
|
||||
docker-compose up --build rhel
|
||||
podman-compose up --build debian
|
||||
podman-compose up --build arch
|
||||
podman-compose up --build rhel
|
||||
```
|
||||
|
||||
Build all distributions in parallel:
|
||||
### Using Prefect + Dagger (CI Pipeline Locally)
|
||||
|
||||
The CI/CD pipeline uses Prefect and Dagger to orchestrate builds. You can run it locally:
|
||||
```bash
|
||||
docker-compose up --build --parallel
|
||||
poetry install --with ci
|
||||
poetry run python -m ci.prefect_flow build-linux
|
||||
```
|
||||
|
||||
### Manual Docker Build
|
||||
### Manual Podman Build
|
||||
|
||||
Build the image:
|
||||
```bash
|
||||
# Debian
|
||||
docker build -f scripts/docker/Dockerfile.debian -t android-file-handler-debian-builder .
|
||||
podman build -f scripts/docker/Dockerfile.debian -t android-file-handler-debian-builder .
|
||||
|
||||
# Arch
|
||||
docker build -f scripts/docker/Dockerfile.arch -t android-file-handler-arch-builder .
|
||||
podman build -f scripts/docker/Dockerfile.arch -t android-file-handler-arch-builder .
|
||||
|
||||
# RHEL/Fedora
|
||||
docker build -f scripts/docker/Dockerfile.rhel -t android-file-handler-rhel-builder .
|
||||
podman build -f scripts/docker/Dockerfile.rhel -t android-file-handler-rhel-builder .
|
||||
```
|
||||
|
||||
Run the build:
|
||||
```bash
|
||||
# Debian
|
||||
docker run --rm -v $(pwd):/workspace -w /workspace android-file-handler-debian-builder
|
||||
podman run --rm -v $(pwd):/workspace:Z -w /workspace android-file-handler-debian-builder
|
||||
|
||||
# Arch
|
||||
docker run --rm -v $(pwd):/workspace -w /workspace android-file-handler-arch-builder
|
||||
podman run --rm -v $(pwd):/workspace:Z -w /workspace android-file-handler-arch-builder
|
||||
|
||||
# RHEL/Fedora
|
||||
docker run --rm -v $(pwd):/workspace -w /workspace android-file-handler-rhel-builder
|
||||
podman run --rm -v $(pwd):/workspace:Z -w /workspace android-file-handler-rhel-builder
|
||||
```
|
||||
|
||||
## Output
|
||||
@@ -81,9 +86,13 @@ After building, you'll find:
|
||||
|
||||
### Virtualenv Conflicts
|
||||
|
||||
The Docker Compose configuration automatically excludes the host's `.venv` directory to prevent conflicts between the host Python environment and the container Python environment. Each container creates its own virtualenv in `/tmp/poetry-cache`.
|
||||
The Podman Compose configuration automatically excludes the host's `.venv` directory to prevent conflicts between the host Python environment and the container Python environment. Each container creates its own virtualenv in `/tmp/poetry-cache`.
|
||||
|
||||
If you encounter virtualenv-related errors, ensure you're using the latest docker-compose.yml configuration.
|
||||
If you encounter virtualenv-related errors, ensure you're using the latest podman-compose.yml configuration.
|
||||
|
||||
### SELinux (Fedora/RHEL hosts)
|
||||
|
||||
Volume mounts use the `:Z` suffix to apply the correct SELinux labels automatically. If you encounter permission errors, ensure the `:Z` suffix is present on volume mounts.
|
||||
|
||||
## Cleaning Up
|
||||
|
||||
@@ -92,9 +101,9 @@ Remove build artifacts:
|
||||
rm -rf dist pkg_dist_* dist_*
|
||||
```
|
||||
|
||||
Remove Docker volumes and containers:
|
||||
Remove Podman containers and volumes:
|
||||
```bash
|
||||
docker compose down -v
|
||||
podman-compose down -v
|
||||
```
|
||||
|
||||
## Customization
|
||||
|
||||
@@ -19,7 +19,7 @@ if command -v gtk-update-icon-cache >/dev/null 2>&1; then
|
||||
fi
|
||||
|
||||
# Ensure installed binary is executable
|
||||
if [ -f /usr/local/bin/android-file-handler ]; then
|
||||
if [ -f /usr/bin/android-file-handler ]; then
|
||||
chmod 0755 /usr/bin/android-file-handler || true
|
||||
fi
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ a = Analysis(
|
||||
pathex=['../..'],
|
||||
binaries=[],
|
||||
datas=[
|
||||
('../../src/gui', 'gui'),
|
||||
('../windows/first_run_install.ps1', 'scripts/windows')
|
||||
('../../src/gui', 'gui'),
|
||||
],
|
||||
hiddenimports=[
|
||||
# GUI modules
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
; Inno Setup script for Android File Handler
|
||||
; Compiles a Windows installer from the PyInstaller one-file executable.
|
||||
;
|
||||
; Usage (CI):
|
||||
; iscc scripts\windows\android-file-handler-setup.iss /DMyAppVersion=1.2.3
|
||||
;
|
||||
; Usage (local, from repo root):
|
||||
; "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" scripts\windows\android-file-handler-setup.iss
|
||||
|
||||
#ifndef MyAppVersion
|
||||
#define MyAppVersion "0.1.1"
|
||||
#endif
|
||||
|
||||
#define MyAppName "Android File Handler"
|
||||
#define MyAppPublisher "Jason Ross"
|
||||
#define MyAppURL "https://github.com/JMR-dev/android-file-handler"
|
||||
#define MyAppExeName "android-file-handler-windows.exe"
|
||||
|
||||
[Setup]
|
||||
AppId={{8F2B3A7E-4D1C-4E8F-9A2B-6C7D8E9F0A1B}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion}
|
||||
AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}
|
||||
AppUpdatesURL={#MyAppURL}
|
||||
DefaultDirName={autopf}\{#MyAppName}
|
||||
DefaultGroupName={#MyAppName}
|
||||
LicenseFile=..\..\LICENSE.txt
|
||||
OutputDir=..\..\dist
|
||||
OutputBaseFilename=android-file-handler-setup
|
||||
SetupIconFile=..\..\icon_media\robot_files_256.ico
|
||||
UninstallDisplayIcon={app}\{#MyAppExeName}
|
||||
Compression=lzma2/ultra64
|
||||
SolidCompression=yes
|
||||
WizardStyle=modern
|
||||
ArchitecturesInstallIn64BitMode=x64compatible
|
||||
PrivilegesRequired=admin
|
||||
MinVersion=10.0
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
|
||||
[Tasks]
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||
|
||||
[Files]
|
||||
Source: "..\..\dist\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
|
||||
|
||||
[Icons]
|
||||
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
|
||||
Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
|
||||
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
|
||||
@@ -1,51 +0,0 @@
|
||||
param(
|
||||
[string]$ExePath = "$PSScriptRoot\..\..\dist\android-file-handler.exe",
|
||||
[string]$IconPath = "$PSScriptRoot\..\..\assets\icons\android-file-handler.ico",
|
||||
[string]$AppName = "Android File Handler"
|
||||
)
|
||||
|
||||
function Ensure-Elevated {
|
||||
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
|
||||
# Relaunch the script with elevation
|
||||
$psi = New-Object System.Diagnostics.ProcessStartInfo
|
||||
$psi.FileName = "powershell.exe"
|
||||
$psi.Arguments = "-ExecutionPolicy Bypass -File `"$PSCommandPath`""
|
||||
$psi.Verb = "runas"
|
||||
try {
|
||||
[System.Diagnostics.Process]::Start($psi) | Out-Null
|
||||
Exit 0
|
||||
} catch {
|
||||
Write-Error "Elevation required to install to Program Files."
|
||||
Exit 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ensure-Elevated
|
||||
|
||||
$destDir = Join-Path ${env:ProgramFiles} $AppName
|
||||
if (-not (Test-Path $destDir)) { New-Item -ItemType Directory -Path $destDir | Out-Null }
|
||||
|
||||
$resolvedExe = Resolve-Path -Path $ExePath -ErrorAction SilentlyContinue
|
||||
if (-not $resolvedExe) {
|
||||
Write-Error "Application executable not found at $ExePath"
|
||||
Exit 1
|
||||
}
|
||||
|
||||
Copy-Item -Path $resolvedExe -Destination (Join-Path $destDir (Split-Path $resolvedExe -Leaf)) -Force
|
||||
|
||||
# Create Start Menu shortcut
|
||||
$programs = Join-Path $env:APPDATA 'Microsoft\Windows\Start Menu\Programs'
|
||||
$appFolder = Join-Path $programs $AppName
|
||||
if (-not (Test-Path $appFolder)) { New-Item -ItemType Directory -Path $appFolder | Out-Null }
|
||||
|
||||
$shortcutPath = Join-Path $appFolder "$AppName.lnk"
|
||||
$wsh = New-Object -ComObject WScript.Shell
|
||||
$sc = $wsh.CreateShortcut($shortcutPath)
|
||||
$sc.TargetPath = (Join-Path $destDir (Split-Path $resolvedExe -Leaf))
|
||||
$sc.WorkingDirectory = $destDir
|
||||
if (Test-Path $IconPath) { $sc.IconLocation = Resolve-Path $IconPath }
|
||||
$sc.Save()
|
||||
|
||||
Write-Output "Installed $AppName to $destDir and created Start Menu shortcut."
|
||||
Exit 0
|
||||
Reference in New Issue
Block a user