diff --git a/.github/workflows/deploy-pypi.yml b/.github/workflows/deploy-pypi.yml index 258a9de..c6e7795 100644 --- a/.github/workflows/deploy-pypi.yml +++ b/.github/workflows/deploy-pypi.yml @@ -123,6 +123,7 @@ jobs: sudo apt update sudo apt install -y libxcb-cursor0 qt6-base-dev patchelf ccache zlib1g-dev sudo apt install -y flatpak flatpak-builder elfutils patchelf + sudo apt install -y rpm echo "QMAKE=$(which qmake6)" >> $GITHUB_ENV flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo flatpak update @@ -225,6 +226,7 @@ jobs: Furious-*.AppImage Furious-*.deb Furious-*.flatpak + Furious-*.rpm github-release: name: Upload to GitHub Release diff --git a/.gitignore b/.gitignore index 6b65e63..e70d35c 100644 --- a/.gitignore +++ b/.gitignore @@ -174,6 +174,8 @@ AppDir/ debian/ # Linux flatpak dir flatpak/ +# Linux rpmbuild dir +rpmbuild/ # zip files *.zip @@ -185,3 +187,5 @@ flatpak/ *.deb # flatpak files *.flatpak +# rpm files +*.rpm diff --git a/Deploy.py b/Deploy.py index 8da35d6..bde2102 100644 --- a/Deploy.py +++ b/Deploy.py @@ -22,8 +22,11 @@ from Furious.Frozenlib import * import os import re import sys +import glob import shutil import logging +import tarfile +import pathlib import argparse import datetime import subprocess @@ -179,6 +182,9 @@ elif PLATFORM == 'Linux': LINUX_FLATPAK_DIR = ROOT_DIR / 'flatpak' LINUX_FLATPAK_FILENAME = f'{ARTIFACT_NAME}.flatpak' + + LINUX_RPM_DIR = ROOT_DIR / 'rpmbuild' + LINUX_RPM_FILENAME = f'{ARTIFACT_NAME}.rpm' else: # Deploy: Not implemented ARTIFACT_NAME = '' @@ -400,6 +406,37 @@ def cleanup(): logger.error(f'remove flatpak dir failed: {ex}') else: logger.info(f'remove flatpak dir success') + + # Cleanup rpm environment + try: + # Remove artifact + os.remove(ROOT_DIR / LINUX_RPM_FILENAME) + except Exception as ex: + # Any non-exit exceptions + + logger.error(f'remove artifact failed: {ex}') + else: + logger.info(f'remove artifact success') + + try: + # Remove rpm folder + shutil.rmtree(LINUX_RPM_DIR) + except Exception as ex: + # Any non-exit exceptions + + logger.error(f'remove rpm dir failed: {ex}') + else: + logger.info(f'remove rpm dir success') + + try: + # Remove home rpmbuild folder + shutil.rmtree(pathlib.Path.home() / 'rpmbuild') + except Exception as ex: + # Any non-exit exceptions + + logger.error(f'remove home rpmbuild failed: {ex}') + else: + logger.info(f'remove home rpmbuild success') else: # Deploy: Not implemented pass @@ -959,6 +996,132 @@ def main(): raise finally: os.chdir(cwd) + + # Create .rpm package + logger.info('generating rpm') + + # Prepare package layout + try: + os.makedirs( + LINUX_RPM_DIR / f'{APPLICATION_NAME}-{APPLICATION_VERSION}', + exist_ok=True, + ) + + for name in ['BUILD', 'RPMS', 'SOURCES', 'SPECS', 'SRPMS']: + os.makedirs( + pathlib.Path.home() / 'rpmbuild' / name, + exist_ok=True, + ) + except Exception: + # Any non-exit exceptions + + raise + + # Copy output + shutil.copytree( + ROOT_DIR / DEPLOY_DIR_NAME / f'{APPLICATION_NAME}.dist', + LINUX_RPM_DIR / f'{APPLICATION_NAME}-{APPLICATION_VERSION}', + dirs_exist_ok=True, + ) + shutil.copy( + ROOT_DIR / 'Icons' / 'png' / f'{iconbase}.png', + LINUX_RPM_DIR / f'{APPLICATION_NAME}-{APPLICATION_VERSION}', + ) + + with tarfile.open(LINUX_RPM_DIR / f'{ARTIFACT_NAME}.tar.gz', 'w:gz') as tar: + tar.add( + LINUX_RPM_DIR / f'{APPLICATION_NAME}-{APPLICATION_VERSION}', + arcname=f'{APPLICATION_NAME}-{APPLICATION_VERSION}', + ) + + shutil.move( + LINUX_RPM_DIR / f'{ARTIFACT_NAME}.tar.gz', + pathlib.Path.home() / 'rpmbuild' / 'SOURCES', + ) + + # Create rpm manifest file + try: + with open( + pathlib.Path.home() / 'rpmbuild' / 'SPECS' / f'{APPLICATION_NAME}.spec', + 'w', + encoding='utf-8', + ) as file: + file.write( + f'Name: {APPLICATION_NAME}\n' + f'Version: {APPLICATION_VERSION}\n' + f'Release: 1%{{?dist}}\n' + f'Summary: A GUI proxy client based on PySide6. Support Xray-core & hysteria\n' + f'\n' + f'License: GPLv3\n' + f'URL: {APPLICATION_ABOUT_PAGE}\n' + f'Source0: {ARTIFACT_NAME}.tar.gz\n' + f'\n' + f'BuildArch: {PLATFORM_MACHINE_LOWER}\n' + f'\n' + f'%description\n' + f'A GUI proxy client based on PySide6. Support Xray-core & hysteria\n' + f'\n' + f'%prep\n' + f'%autosetup\n' + f'\n' + f'%install\n' + f'rm -rf %{{buildroot}}\n' + f'\n' + f'# App directory\n' + f'mkdir -p %{{buildroot}}/opt/{APPLICATION_NAME}\n' + f'cp -a * %{{buildroot}}/opt/{APPLICATION_NAME}/\n' + f'\n' + f'# Binary symlink\n' + f'mkdir -p %{{buildroot}}/usr/bin\n' + f'ln -s /opt/{APPLICATION_NAME}/Furious.bin %{{buildroot}}/usr/bin/{APPLICATION_NAME}\n' + f'\n' + f'# Desktop entry\n' + f'mkdir -p %{{buildroot}}/usr/share/applications\n' + f'cat > %{{buildroot}}/usr/share/applications/{APPLICATION_NAME}.desktop <