Skip to content

release: v0.3.2

release: v0.3.2 #44

Workflow file for this run

name: 构建
on:
push:
branches: [ 'main' ]
paths: [ 'version.txt' ]
workflow_dispatch: {}
permissions:
contents: write
env:
APP_NAME: openlistsync
DOCKER_USER: syscc
DOCKER_NAME: openlistsync
jobs:
get-version:
name: 获取版本号
runs-on: ubuntu-latest
outputs:
TAG_LIST: ${{ steps.getVersion.outputs.TAG_LIST }}
VERSION: ${{ steps.getVersion.outputs.VERSION }}
steps:
- name: 检出仓库代码
uses: actions/checkout@v4
- id: getVersion
name: 获取版本号
run: |
versions=$(head -n 1 version.txt)
tagList=""
IFS=',' read -ra versionList <<< "$versions"
cuVersion="${versionList[0]}"
for version in "${versionList[@]}"; do
tagList+="-t $DOCKER_USER/$DOCKER_NAME:$version "
done
echo "TAG_LIST=$tagList" >> "$GITHUB_OUTPUT"
echo "VERSION=$cuVersion" >> "$GITHUB_OUTPUT"
build-frontend:
name: 构建前端
runs-on: ubuntu-latest
needs: [ get-version ]
env:
VERSION: ${{ needs.get-version.outputs.VERSION }}
steps:
- name: 检出仓库代码
uses: actions/checkout@v4
- name: 安装Node.js 22.x
uses: actions/setup-node@v4
with:
node-version: "22.x"
cache: npm
cache-dependency-path: web/package-lock.json
- name: 安装依赖并构建前端
working-directory: web
run: |
sed -i "s/__version_placeholder__/$VERSION/g" src/locales/zh-CN.yaml src/locales/en.yaml
npm ci
npm run build
- name: 上传artifact
uses: actions/upload-artifact@v4
with:
name: web-dist
path: web/dist
retention-days: 1
build-docker:
name: 构建Docker与linux
runs-on: ubuntu-latest
needs: [ get-version, build-frontend ]
env:
VERSION: ${{ needs.get-version.outputs.VERSION }}
strategy:
matrix:
platform:
- linux/amd64
- linux/arm64
- linux/arm/v7
- linux/386
- linux/arm/v6
- linux/s390x
- linux/ppc64le
steps:
- name: 替换平台名称中的斜杠为横杠
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: 设置QEMU
uses: docker/setup-qemu-action@v3
- name: 设置Docker BuildX
uses: docker/setup-buildx-action@v3
- name: 登录到DockerHub
uses: docker/login-action@v3
with:
username: ${{ env.DOCKER_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: 检出仓库代码
uses: actions/checkout@v4
- name: 下载前端
uses: actions/download-artifact@v4
with:
name: web-dist
path: web/dist
- id: build-image
name: 构建docker镜像
uses: docker/build-push-action@v6
with:
context: .
platforms: ${{ matrix.platform }}
outputs: |
type=docker
type=image,name=${{ env.DOCKER_USER }}/${{ env.DOCKER_NAME }},push-by-digest=true,name-canonical=true,push=true
- name: 导出digest
run: |
mkdir -p /tmp/digests
digest="${{ steps.build-image.outputs.digest }}"
touch "/tmp/digests/${digest#sha256:}"
- name: 上传digest到artifact
uses: actions/upload-artifact@v4
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: /tmp/digests/*
retention-days: 1
- name: 从镜像中提取可执行文件
run: |
docker create --name tmp ${{ steps.build-image.outputs.imageid }} /bin/true
docker cp tmp:/app/${{ env.APP_NAME }} ${{ env.APP_NAME }}
tar czf "$APP_NAME-$VERSION-$PLATFORM_PAIR.tar.gz" ${{ env.APP_NAME }}
- name: 上传可执行文件到artifact
uses: actions/upload-artifact@v4
with:
name: dist-${{ env.PLATFORM_PAIR }}
path: ${{ env.APP_NAME }}-${{ env.VERSION }}-${{ env.PLATFORM_PAIR }}.tar.gz
retention-days: 1
merge-docker:
name: 合并Docker镜像
runs-on: ubuntu-latest
needs: [get-version, build-docker]
env:
TAG_LIST: ${{ needs.get-version.outputs.TAG_LIST }}
steps:
- name: 下载digest
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
merge-multiple: true
- name: 设置Docker BuildX
uses: docker/setup-buildx-action@v3
- name: 登录到DockerHub
uses: docker/login-action@v3
with:
username: ${{ env.DOCKER_USER }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: 创建清单并推送
working-directory: /tmp/digests
run: |
docker buildx imagetools create ${{ env.TAG_LIST }}$(printf '${{ env.DOCKER_USER }}/${{ env.DOCKER_NAME }}@sha256:%s ' *)
build-windows:
name: 构建windows
strategy:
matrix:
os:
- windows-latest
- windows-11-arm
runs-on: ${{ matrix.os }}
needs: [get-version, build-frontend]
env:
VERSION: ${{needs.get-version.outputs.VERSION}}
if: ${{ !contains(needs.get-version.outputs.VERSION, 'dev') }}
steps:
- name: 判断平台
run: |
$os = "${{ matrix.os }}"
if ($os -eq "windows-latest") {
$PLATFORM = "amd64"
} else {
$PLATFORM = "arm64"
}
"PLATFORM=$PLATFORM" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
- name: 检出仓库代码
uses: actions/checkout@v4
- name: 下载前端
uses: actions/download-artifact@v4
with:
name: web-dist
path: web/dist
- name: 设置python环境
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: 安装依赖并构建打包
run: |
python -m pip install 'pyinstaller>=6,<7'
python -m pip install -r requirements.txt
python -m PyInstaller ${{ env.APP_NAME }}.spec
cd dist
pwsh -Command "Compress-Archive -Path * -DestinationPath '${{ env.APP_NAME }}-${{ env.VERSION }}-windows-${{ env.PLATFORM }}.zip'"
- name: 上传artifact
uses: actions/upload-artifact@v4
with:
name: dist-windows-${{ env.PLATFORM }}
path: dist/*.zip
build-darwin:
name: 构建darwin
strategy:
matrix:
os:
- macos-15
- macos-15-intel
runs-on: ${{ matrix.os }}
needs: [get-version, build-frontend]
env:
VERSION: ${{needs.get-version.outputs.VERSION}}
if: ${{ !contains(needs.get-version.outputs.VERSION, 'dev') }}
steps:
- name: 判断平台
run: |
os=${{ matrix.os }}
if [ "$os" = "macos-15-intel" ]; then
PLATFORM="amd64"
else
PLATFORM="arm64"
fi
echo "PLATFORM=$PLATFORM" >> $GITHUB_ENV
- name: 检出仓库代码
uses: actions/checkout@v4
- name: 下载前端
uses: actions/download-artifact@v4
with:
name: web-dist
path: web/dist
- name: 设置python环境
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: 安装依赖并构建打包
run: |
python -m pip install 'pyinstaller>=6,<7'
python -m pip install -r requirements.txt
python -m PyInstaller "$APP_NAME.spec"
cd dist
tar czf "$APP_NAME-$VERSION-darwin-$PLATFORM.tar.gz" .
- name: 上传artifact
uses: actions/upload-artifact@v4
with:
name: dist-darwin-${{ env.PLATFORM }}
path: dist/*.tar.gz
retention-days: 1
build-staticx:
name: 构建Linux StaticX
runs-on: ubuntu-latest
needs: [get-version, build-frontend]
env:
VERSION: ${{ needs.get-version.outputs.VERSION }}
strategy:
matrix:
platform: ["amd64", "arm64", "arm32"]
steps:
- name: 检出仓库代码
uses: actions/checkout@v4
- name: 下载前端
uses: actions/download-artifact@v4
with:
name: web-dist
path: web/dist
- name: 设置QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: all
- name: 设置构建变量
run: |
case "${{ matrix.platform }}" in
amd64) echo "T_ARCH=amd64" >> "$GITHUB_ENV" ;;
arm64) echo "T_ARCH=arm64" >> "$GITHUB_ENV" ;;
arm32) echo "T_ARCH=arm/v7" >> "$GITHUB_ENV" ;;
esac
- name: 在Docker中进行静态打包
run: |
case "${{ matrix.platform }}" in
amd64) IMG="python:3.11-slim-bullseye"; LIB="/usr/lib/x86_64-linux-gnu" ;;
arm64) IMG="arm64v8/python:3.11-slim-bullseye"; LIB="/usr/lib/aarch64-linux-gnu" ;;
arm32) IMG="arm32v7/python:3.11-slim-bullseye"; LIB="/usr/lib/arm-linux-gnueabihf" ;;
esac
docker run --rm \
--platform "linux/${T_ARCH}" \
-v "$(pwd):/app" \
-w /app \
-e APP_NAME="${APP_NAME}" \
-e LIB_PATH="${LIB}" \
"${IMG}" \
sh -c '
set -e
apt-get update
apt-get install -y --no-install-recommends \
build-essential zlib1g-dev patchelf binutils zip
rm -rf /var/lib/apt/lists/*
python -m pip install --upgrade pip
python -m pip install setuptools wheel scons hatchling
python -m pip install --no-build-isolation "pyinstaller>=6,<7" staticx
python -m pip install -r requirements.txt
export LD_LIBRARY_PATH="/usr/local/lib:${LIB_PATH}"
python -m PyInstaller "${APP_NAME}.spec" \
--distpath "/app/dist/${{ matrix.platform }}" \
--workpath "/app/build/${{ matrix.platform }}" \
--noconfirm
staticx "/app/dist/${{ matrix.platform }}/${APP_NAME}" "/app/dist/${{ matrix.platform }}/${APP_NAME}_StaticX"
mv -f "/app/dist/${{ matrix.platform }}/${APP_NAME}_StaticX" "/app/dist/${{ matrix.platform }}/${APP_NAME}"
chmod 755 "/app/dist/${{ matrix.platform }}/${APP_NAME}"
'
- name: 压缩StaticX产物
run: |
cd "dist/${{ matrix.platform }}"
zip -r "../../${APP_NAME}-${VERSION}-linux-StaticX-${{ matrix.platform }}.zip" .
- name: 上传artifact
uses: actions/upload-artifact@v4
with:
name: dist-linux-staticx-${{ matrix.platform }}
path: ${{ env.APP_NAME }}-${{ env.VERSION }}-linux-StaticX-${{ matrix.platform }}.zip
retention-days: 1
build-android:
name: 构建Android
runs-on: ubuntu-latest
needs: [get-version, build-frontend]
env:
VERSION: ${{ needs.get-version.outputs.VERSION }}
BUILDOZER_SPEC: buildozer.spec
P4A_VERSION: 2024.01.21
CACHE_VERSION: v6
steps:
- name: 检出仓库代码
uses: actions/checkout@v4
- name: 下载前端
uses: actions/download-artifact@v4
with:
name: web-dist
path: web/dist
- name: 准备Android前端资源
run: |
rm -rf front
cp -r web/dist front
test -f front/index.html
test -f locales/zh_CN.yaml
- name: 设置python环境
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: 安装系统依赖
run: |
sudo apt-get update -y
sudo apt-get install -y --no-install-recommends \
autoconf automake libtool pkg-config \
zlib1g-dev libncurses5-dev libncursesw5-dev \
libffi-dev libssl-dev libsqlite3-dev libbz2-dev libreadline-dev \
libportaudio2 libportaudiocpp0 \
libltdl-dev libtool-bin \
ccache git wget unzip zip \
openjdk-17-jdk build-essential
sudo ln -sf "$(which python3)" /usr/bin/python
echo "ACLOCAL_PATH=/usr/share/aclocal" >> "$GITHUB_ENV"
- name: 配置Java环境变量
run: |
echo "JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64" >> "$GITHUB_ENV"
echo "/usr/lib/jvm/java-17-openjdk-amd64/bin" >> "$GITHUB_PATH"
- name: 安装Buildozer与python-for-android
run: |
python -m pip install --upgrade pip
python -m pip install "buildozer==1.5.0" "python-for-android==${P4A_VERSION}" "Cython==0.29.34" virtualenv
python -c "import pythonforandroid; print('p4a version:', pythonforandroid.__version__)"
- name: 缓存Buildozer目录
uses: actions/cache@v4
with:
path: |
~/.buildozer
~/.gradle
key: buildozer-${{ runner.os }}-${{ env.CACHE_VERSION }}-p4a${{ env.P4A_VERSION }}-py311-${{ hashFiles('buildozer.spec', 'requirements.txt') }}
restore-keys: |
buildozer-${{ runner.os }}-${{ env.CACHE_VERSION }}-p4a${{ env.P4A_VERSION }}-py311-
- name: 清理旧构建产物
run: |
rm -rf .buildozer bin .python-for-android
- name: 切换Android入口
run: |
test -f "$BUILDOZER_SPEC"
test -f main_android.py
cp main_android.py main.py
- name: 注入Android版本号
run: |
ver_num="${VERSION#v}"
sed -i "s/^version = .*/version = $ver_num/" "$BUILDOZER_SPEC"
IFS='.' read -r major minor patch <<< "$ver_num"
major="${major%%[!0-9]*}"; major="${major:-0}"
minor="${minor%%[!0-9]*}"; minor="${minor:-0}"
patch="${patch%%[!0-9]*}"; patch="${patch:-0}"
numeric_version=$(( major*10000 + minor*100 + patch ))
sed -i "/^android.numeric_version[[:space:]]*=/d" "$BUILDOZER_SPEC"
sed -i "/^version[[:space:]]*=/a android.numeric_version = $numeric_version" "$BUILDOZER_SPEC"
grep -E "^(version|android.numeric_version)" "$BUILDOZER_SPEC"
- name: 编译Android Debug APK
run: PYTHONWARNINGS="ignore:Unable to find acceptable character detection:UserWarning" buildozer -v android debug
- name: 整理Android产物
run: |
mkdir -p dist
apk_path=$(find bin -maxdepth 1 -name '*.apk' -print -quit)
if [ -z "$apk_path" ]; then
echo "::error::未找到编译产物 APK"
exit 1
fi
cp "$apk_path" "dist/${APP_NAME}-${VERSION}-android-debug.apk"
- name: 上传artifact
uses: actions/upload-artifact@v4
with:
name: dist-android
path: dist/*.apk
if-no-files-found: error
retention-days: 1
compression-level: 0
create-release:
name: 发布release
runs-on: ubuntu-latest
needs: [get-version, build-windows, build-darwin, build-docker, build-staticx, build-android]
env:
VERSION: ${{needs.get-version.outputs.VERSION}}
if: ${{ !contains(needs.get-version.outputs.VERSION, 'dev') }}
steps:
- name: 检出仓库代码
uses: actions/checkout@v4
- name: 下载构建结果
uses: actions/download-artifact@v4
with:
pattern: dist-*
path: dist
merge-multiple: true
- name: 检查Android发布产物
run: |
apk_path=$(find dist -maxdepth 1 -type f -name "${APP_NAME}-${VERSION}-android-*.apk" -print -quit)
if [ -z "$apk_path" ]; then
echo "::error::Release 中缺少 Android APK"
exit 1
fi
echo "Android APK: $apk_path"
- name: 没有版本日志文件自动创建
run: |
version_first=$(echo $VERSION | cut -d'-' -f1)
LOG_FILE="doc/changelog/$version_first.md"
if [ ! -f "$LOG_FILE" ]; then
mkdir -p "$(dirname "$LOG_FILE")"
touch "$LOG_FILE"
echo "$VERSION" > "$LOG_FILE"
fi
echo "LOG_FILE=$LOG_FILE" >> "$GITHUB_ENV"
- name: 创建release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.VERSION }}
files: dist/*
body_path: ${{ env.LOG_FILE }}
prerelease: ${{ contains(env.VERSION, 'dev') || contains(env.VERSION, 'pre') || contains(env.VERSION, 'beta') }}