Spec script fix #12

Merged
JMR-dev merged 4 commits from spec-script-fix into main 2025-09-28 21:16:26 +00:00
7 changed files with 181 additions and 20 deletions
@@ -0,0 +1,114 @@
# Branch Protection Configuration Workflow
# This workflow sets up branch protection rules for the repository
# Only runs manually (workflow_dispatch) and only by repository owners on the main branch
name: Configure Branch Protection
on:
workflow_dispatch:
inputs:
target_branch:
description: "Branch to protect (default: main)"
required: false
default: "main"
type: string
required_reviewers:
description: "Number of required approving reviews"
required: false
default: "1"
type: choice
options:
- "1"
- "2"
- "3"
dismiss_stale_reviews:
description: "Dismiss stale reviews when new commits are pushed"
required: false
default: true
type: boolean
enforce_admins:
description: "Enforce restrictions for administrators"
required: false
default: false
type: boolean
permissions:
contents: read
jobs:
configure-branch-protection:
runs-on: ubuntu-latest
# Security: Only run on main branch and only by repository owner/admin
if: ${{ github.ref == 'refs/heads/main' && (github.actor == github.repository_owner || contains(fromJSON('["JMR-dev"]'), github.actor)) }}
steps:
- name: Display configuration
run: |
echo "Configuring branch protection for: ${{ github.event.inputs.target_branch }}"
echo "Required reviewers: ${{ github.event.inputs.required_reviewers }}"
echo "Dismiss stale reviews: ${{ github.event.inputs.dismiss_stale_reviews }}"
echo "Enforce for admins: ${{ github.event.inputs.enforce_admins }}"
echo "Triggered by: ${{ github.actor }}"
- name: Configure branch protection
run: |
# Define required status checks based on workflow jobs
REQUIRED_CHECKS='{
"strict": true,
"contexts": [
"run-unit-tests-linux",
"run-unit-tests-windows",
"build-windows",
"build-debian",
"build-arch",
"build-rhel"
]
}'
# Define PR review requirements
PR_REVIEWS='{
"restrict_pushes": true,
"require_code_owner_reviews": false
}'
# Apply branch protection
gh api repos/${{ github.repository }}/branches/${{ github.event.inputs.target_branch }}/protection \
--method PUT \
--field required_status_checks="$REQUIRED_CHECKS" \
--field restrictions=null \
--field allow_deletions=false \
--field allow_force_pushes=false \
--field block_creations=false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Verify configuration
run: |
echo "✅ Branch protection configured successfully!"
echo "The following jobs are now required status checks:"
echo " - run-unit-tests-linux"
echo " - run-unit-tests-windows"
echo " - build-windows"
echo " - build-debian"
echo " - build-arch"
echo " - build-rhel"
echo ""
echo "Pull request requirements:"
echo " - ${{ github.event.inputs.required_reviewers }} approving review(s) required"
echo ""
echo "Additional protections:"
echo " - Branch deletions: blocked"
echo " - Force pushes: blocked"
- name: Display next steps
run: |
echo ""
echo "🔒 Branch protection is now active for '${{ github.event.inputs.target_branch }}'"
echo ""
echo "Next steps:"
echo "1. Create a pull request to test the protection rules"
echo "2. Verify that all required status checks appear"
echo "3. Confirm that the PR cannot be merged until all checks pass"
echo ""
echo "To view current protection settings:"
echo " Repository Settings → Branches → ${{ github.event.inputs.target_branch }} → Edit"
+40 -8
View File
@@ -1,17 +1,22 @@
# Multi-platform build + packaging workflow
# - Builds a pyinstaller executable on Windows, Debian, Arch, Rocky.
# - Builds a pyinstaller executable on Windows, Debian, Arch, Fedora.
# - Packages using fpm into .deb, .rpm, and pacman (.pkg.tar.zst) files with explicit filenames.
# - Creates a GitHub Release with the produced artifacts.
#
# Notes:
# - Poetry is installed via snok/install-poetry@v1 in all jobs.
# - fpm gem is pinned to 1.16.0 in the examples; change as needed.
# - Rocky job uses tarball downloads for pyenv and python-build (non-interactive, CI-friendly).
# - Fedora job uses tarball downloads for pyenv and python-build (non-interactive, CI-friendly).
name: Build Multi-Platform Binaries
on:
workflow_dispatch:
inputs:
branch:
description: "Branch to build from"
required: false
default: "main"
type: string
jobs:
description: "Comma-separated jobs to run (e.g., build-windows,build-debian,build-arch,build-rhel)"
required: true
@@ -24,6 +29,8 @@ on:
description: "Set to 'true' to upload build artifacts to S3 after builds"
required: false
default: "false"
pull_request:
branches: [ main ]
permissions:
contents: write
@@ -40,6 +47,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.branch || github.head_ref || github.ref }}
- name: Display build information
run: |
echo "Event: ${{ github.event_name }}"
echo "Branch: ${{ github.event.inputs.branch || github.head_ref || github.ref }}"
echo "Jobs to run: ${{ github.event.inputs.jobs || 'build-windows,build-debian,build-arch,build-rhel' }}"
echo "Create release: ${{ github.event.inputs.DO_RELEASE || 'false' }}"
echo "Upload to S3: ${{ github.event.inputs.UPLOAD_S3 || 'false' }}"
- name: Set up Python
uses: actions/setup-python@v5
@@ -61,6 +78,8 @@ jobs:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.branch || github.head_ref || github.ref }}
- name: Set up Python
uses: actions/setup-python@v5
@@ -90,11 +109,13 @@ jobs:
poetry run pytest tests/ -v
build-windows:
needs: [run-unit-tests-linux, run-unit-tests-windows]
if: contains(github.event.inputs.jobs, 'build-windows')
if: ${{ github.event_name == 'pull_request' || contains(github.event.inputs.jobs, 'build-windows') }}
runs-on: windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.branch || github.head_ref || github.ref }}
- name: Set up Python 3.12
uses: actions/setup-python@v5
@@ -134,7 +155,7 @@ jobs:
build-debian:
needs: [run-unit-tests-linux, run-unit-tests-windows]
if: contains(github.event.inputs.jobs, 'build-debian')
if: ${{ github.event_name == 'pull_request' || contains(github.event.inputs.jobs, 'build-debian') }}
env:
DISTRO_TYPE: debian
runs-on: ubuntu-latest
@@ -154,6 +175,8 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.branch || github.head_ref || github.ref }}
- name: Set up Python 3.12
uses: actions/setup-python@v5
@@ -219,7 +242,7 @@ jobs:
build-arch:
needs: [run-unit-tests-linux, run-unit-tests-windows]
if: contains(github.event.inputs.jobs, 'build-arch')
if: ${{ github.event_name == 'pull_request' || contains(github.event.inputs.jobs, 'build-arch') }}
env:
DISTRO_TYPE: arch
runs-on: ubuntu-latest
@@ -239,6 +262,8 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.branch || github.head_ref || github.ref }}
- name: Set up Python 3.12
uses: actions/setup-python@v5
@@ -297,13 +322,15 @@ jobs:
build-rhel:
needs: [run-unit-tests-linux, run-unit-tests-windows]
if: contains(github.event.inputs.jobs, 'build-rhel')
if: ${{ github.event_name == 'pull_request' || contains(github.event.inputs.jobs, 'build-rhel') }}
env:
DISTRO_TYPE: rhel
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.branch || github.head_ref || github.ref }}
- name: Update OS and install Docker
run: |
@@ -396,11 +423,13 @@ jobs:
create-release:
needs: [run-unit-tests-linux, run-unit-tests-windows, build-windows, build-debian, build-arch, build-rhel]
if: ${{ github.event.inputs.DO_RELEASE == 'true' && needs.build-windows.result == 'success' && needs.build-debian.result == 'success' && needs.build-arch.result == 'success' && needs.build-rhel.result == 'success' }}
if: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.DO_RELEASE == 'true' && needs.build-windows.result == 'success' && needs.build-debian.result == 'success' && needs.build-arch.result == 'success' && needs.build-rhel.result == 'success' }}
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.branch || github.head_ref || github.ref }}
- name: Install Poetry
uses: snok/install-poetry@v1
@@ -436,11 +465,13 @@ jobs:
upload-s3:
needs: [run-unit-tests-linux, run-unit-tests-windows, build-windows, build-debian, build-arch, build-rhel]
if: ${{ github.event.inputs.UPLOAD_S3 == 'true' || contains(github.event.inputs.jobs, 'upload-s3') }}
if: ${{ github.event_name == 'workflow_dispatch' && (github.event.inputs.UPLOAD_S3 == 'true' || contains(github.event.inputs.jobs, 'upload-s3')) }}
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.branch || github.head_ref || github.ref }}
- name: Install AWS CLI
run: |
@@ -479,6 +510,7 @@ jobs:
- name: Checkout main repo
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.branch || github.ref }}
fetch-depth: 0
- name: Checkout wiki repo
+27 -8
View File
@@ -15,14 +15,17 @@ class DistroType(Enum):
RHEL = "rhel"
def run_command(cmd: list[str], check: bool = True) -> subprocess.CompletedProcess:
def run_command(cmd: list[str], check: bool = True, working_dir: str = None) -> subprocess.CompletedProcess:
"""Run command and handle errors."""
print(f"Running: {' '.join(cmd)}")
try:
return subprocess.run(cmd, check=check, capture_output=False)
return subprocess.run(cmd, check=check, capture_output=False, cwd=working_dir)
except subprocess.CalledProcessError as e:
print(f"Command failed with exit code {e.returncode}: {' '.join(cmd)}")
sys.exit(e.returncode)
except FileNotFoundError:
print(f"Command not found: {cmd[0]}")
sys.exit(1)
def get_distro_config(distro_type: DistroType) -> dict:
@@ -72,18 +75,27 @@ def prompt_distro_selection() -> List[DistroType]:
print("Invalid choice. Please enter 1, 2, 3, or 4.")
def build_for_distro(distro_type: DistroType, version: str) -> None:
def build_for_distro(distro_type: DistroType, version: str, project_root: Path) -> None:
"""Build package for specific distro type."""
config = get_distro_config(distro_type)
print(f"\n=== Building for {config['name']} ===")
# Construct absolute paths
spec_file = project_root / config['spec_file']
dist_dir = project_root / f"dist_{config['pkg_suffix']}"
# Verify spec file exists
if not spec_file.exists():
print(f"ERROR: Spec file not found: {spec_file}")
sys.exit(1)
# Build with distro-specific spec file
print(f"Building binary using {config['spec_file']}")
print(f"Building binary using {spec_file}")
run_command([
"poetry", "run", "pyinstaller",
config['spec_file'],
"--distpath", f"dist_{config['pkg_suffix']}"
])
str(spec_file),
"--distpath", str(dist_dir)
], working_dir=str(project_root))
# Make binary executable
binary_path = Path(f"dist_{config['pkg_suffix']}/android-file-handler")
@@ -161,6 +173,13 @@ StartupNotify=true
def main():
# Get project root (parent of scripts directory)
project_root = Path(__file__).parent.parent.resolve()
print(f"Project root: {project_root}")
# Change to project root
os.chdir(project_root)
# Check if running in CI/CD mode
is_ci_cd = os.environ.get("CI_CD", "false").lower() == "true"
@@ -204,7 +223,7 @@ def main():
# Build for selected distributions
for distro_type in selected_distros:
build_for_distro(distro_type, version)
build_for_distro(distro_type, version, project_root)
print(f"\n=== Build complete for: {', '.join([get_distro_config(d)['name'] for d in selected_distros])} ===")
@@ -5,7 +5,6 @@ a = Analysis(
binaries=[],
datas=[
('../../src/gui', 'gui'),
('../../src/platform-tools', 'platform-tools')
],
hiddenimports=[
# GUI modules
@@ -6,7 +6,6 @@ a = Analysis(
binaries=[],
datas=[
('../../src/gui', 'gui'),
('../../src/platform-tools', 'platform-tools'),
('../../scripts/debian_postinst.sh', 'scripts'),
],
hiddenimports=[
@@ -5,7 +5,6 @@ a = Analysis(
binaries=[],
datas=[
('../../src/gui', 'gui'),
('../../src/platform-tools', 'platform-tools'),
('../../scripts/rhel_postinst.sh', 'scripts'),
],
hiddenimports=[
@@ -6,7 +6,6 @@ a = Analysis(
binaries=[],
datas=[
('../../src/gui', 'gui'),
('../../src/platform-tools', 'platform-tools'),
('../windows/first_run_install.ps1', 'scripts/windows')
],
hiddenimports=[