Skip to content

Build and Release

Build and Release #24

Workflow file for this run

name: Build and Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
build_windows:
description: 'Build Windows x64 executable'
required: true
default: true
type: boolean
build_linux:
description: 'Build Linux x64 deb package'
required: true
default: true
type: boolean
create_release:
description: 'Create GitHub Release'
required: true
default: false
type: boolean
env:
APP_NAME: assignsticker
APP_VERSION: "1.3.0"
jobs:
build-windows:
runs-on: windows-latest
if: github.event_name != 'workflow_dispatch' || inputs.build_windows
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Set up Python
run: uv python install 3.13
- name: Install dependencies
run: |
uv sync
uv pip install pyinstaller
- name: Build
run: uv run python build.py
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: AssignSticker-windows-x64
path: dist/AssignSticker.exe
build-linux:
runs-on: ubuntu-latest
if: github.event_name != 'workflow_dispatch' || inputs.build_linux
steps:
- uses: actions/checkout@v4
- name: Get version from tag
if: startsWith(github.ref, 'refs/tags/v')
run: echo "APP_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
- name: Install uv
uses: astral-sh/setup-uv@v5
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
python3-dev \
pkg-config \
libcairo2-dev \
libgirepository-2.0-dev \
gir1.2-girepository-2.0 \
gir1.2-gtk-3.0 \
gir1.2-webkit2-4.1 \
gir1.2-ayatanaappindicator3-0.1 \
dpkg-dev
- name: Build with PyInstaller
run: |
# 安装依赖和 pyinstaller
uv sync
uv add --dev pyinstaller
# 创建 pyinstaller spec 文件
cat > assignsticker.spec << 'SPECEOF'
# -*- mode: python ; coding: utf-8 -*-
import sys
from PyInstaller.building.build_main import Analysis, PYZ, EXE, COLLECT
block_cipher = None
# 数据文件
datas = [
('htmls', 'htmls'),
('icons', 'icons'),
('saying', 'saying'),
('desktop_widgets', 'desktop_widgets'),
('font.ttf', '.'),
('icon.ico', '.'),
('introduce', '.'),
('banner.png', '.'),
]
# 隐藏导入(Linux 特有)
hiddenimports = [
'gi',
'gi.repository',
'gi.repository.Gtk',
'gi.repository.Gdk',
'gi.repository.GObject',
'gi.repository.GLib',
'gi.repository.Gio',
'gi.repository.AyatanaAppIndicator3',
'cairo',
'webview',
'webview.platforms.gtk',
'pystray',
'pystray._appindicator',
'PIL',
'PIL._imagingtk',
'PIL._tkinter_finder',
]
a = Analysis(
['main.py'],
pathex=[],
binaries=[],
datas=datas,
hiddenimports=hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='assignsticker',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon='icon.ico',
)
SPECEOF
# 使用 pyinstaller 打包
uv run pyinstaller assignsticker.spec
- name: Build DEB package
run: |
set -e
PKG="build/deb/${APP_NAME}"
# 创建 deb 包目录结构
mkdir -p "${PKG}/opt/${APP_NAME}"
mkdir -p "${PKG}/usr/bin"
mkdir -p "${PKG}/usr/share/applications"
mkdir -p "${PKG}/DEBIAN"
# 复制 PyInstaller 输出
cp -r dist/assignsticker/* "${PKG}/opt/${APP_NAME}/"
# 创建启动脚本
cat > "${PKG}/usr/bin/${APP_NAME}" <<'EOF'
#!/bin/bash
export GI_TYPELIB_PATH=/usr/lib/x86_64-linux-gnu/girepository-1.0
exec /opt/assignsticker/assignsticker "$@"
EOF
chmod +x "${PKG}/usr/bin/${APP_NAME}"
# 创建 Desktop Entry
cat > "${PKG}/usr/share/applications/${APP_NAME}.desktop" <<EOF
[Desktop Entry]
Name=AssignSticker
Comment=Homework Kanban Application
Exec=${APP_NAME}
Icon=/opt/${APP_NAME}/icon.ico
Type=Application
Categories=Education;Office;
Terminal=false
StartupWMClass=assignsticker
EOF
# 计算大小并创建 control 文件
SIZE=$(du -sk "${PKG}" | cut -f1)
cat > "${PKG}/DEBIAN/control" <<EOF
Package: ${APP_NAME}
Version: ${APP_VERSION}
Section: education
Priority: optional
Architecture: amd64
Installed-Size: ${SIZE}
Depends: gir1.2-gtk-3.0,
gir1.2-webkit2-4.1,
gir1.2-ayatanaappindicator3-0.1,
libcairo2,
libgtk-3-0,
libwebkit2gtk-4.1-0,
libgirepository-2.0-0
gir1.2-girepository-2.0
Maintainer: SECTL <sectl@example.com>
Homepage: https://github.com/sectl/AssignSticker
Description: Homework Showboard Application
AssignSticker is a homework management and display
application for classroom use.
EOF
# 打包
dpkg-deb --root-owner-group --build "${PKG}"
mv "build/deb/${APP_NAME}.deb" "AssignSticker-${APP_VERSION}-amd64.deb"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: AssignSticker-linux-amd64
path: "*.deb"
release:
needs: [build-windows, build-linux]
runs-on: ubuntu-latest
if: |
always() &&
(startsWith(github.ref, 'refs/tags/v') ||
(github.event_name == 'workflow_dispatch' && inputs.create_release))
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
merge-multiple: true
- name: List files
run: find artifacts -type f
- name: Create Release
uses: softprops/action-gh-release@v2
with:
files: artifacts/*
draft: false
prerelease: false
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}