release: v0.3.2 #44
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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') }} |