fix: add packages write permission for ghcr push #7
Workflow file for this run
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: Release — Build & Publish Installers | |
| on: | |
| push: | |
| tags: | |
| - 'v*.*.*' # 正式版本:v1.2.0 | |
| - 'v*.*.*.*' # 子版本:v1.1.13.6 | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: "版本号(如 v1.2.0)" | |
| required: true | |
| type: string | |
| push_latest: | |
| description: "同时更新 latest 标签" | |
| required: false | |
| default: true | |
| type: boolean | |
| concurrency: | |
| group: release-${{ github.ref }} | |
| cancel-in-progress: false | |
| env: | |
| REGISTRY: registry.cn-hangzhou.aliyuncs.com/thingspanel | |
| jobs: | |
| # ── 确定版本号 ────────────────────────────────────────────────────────────── | |
| prepare: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| steps: | |
| - id: version | |
| name: Resolve version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| VERSION="${{ inputs.version }}" | |
| else | |
| VERSION="${GITHUB_REF_NAME}" | |
| fi | |
| echo "version=${VERSION}" >> $GITHUB_OUTPUT | |
| echo "Version: ${VERSION}" | |
| # ── 验证 docker-compose.yml 语法 ─────────────────────────────────────────── | |
| validate: | |
| runs-on: ubuntu-latest | |
| needs: prepare | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Create test .env | |
| run: | | |
| cat > .env << 'EOF' | |
| POSTGRES_PASSWORD=test_pg_pass | |
| REDIS_PASSWORD=test_redis_pass | |
| AUTH_SECRET=test_auth_secret_minimum_32_chars_long | |
| TP_VERSION=${{ needs.prepare.outputs.version }} | |
| TP_VUE_VERSION=${{ needs.prepare.outputs.version }} | |
| TP_BACKEND_VERSION=${{ needs.prepare.outputs.version }} | |
| TP_GMQTT_VERSION=v1.1.6 | |
| TP_REDIS_VERSION=6.2.7 | |
| TP_MODBUS_VERSION=v1.0.6.1 | |
| TP_HTTP_ADAPTER_VERSION=v1.0.0 | |
| TP_THINGSVIS_SERVER_VERSION=v1.0.4 | |
| TP_THINGSVIS_STUDIO_VERSION=v1.0.4 | |
| TP_TIMESCALEDB_VERSION=14 | |
| DATA_DIR=./data | |
| HTTP_PORT=8080 | |
| MQTT_PORT=1883 | |
| MODBUS_TCP_PORT=502 | |
| MODBUS_RTU_PORT=503 | |
| TZ=Asia/Shanghai | |
| TP_LOG_LEVEL=error | |
| EOF | |
| - name: Validate docker-compose syntax | |
| run: docker compose config --quiet | |
| - name: Check script syntax (bash) | |
| run: | | |
| bash -n install.sh | |
| bash -n upgrade.sh | |
| bash -n uninstall.sh | |
| # ── 构建 Windows 安装包 ───────────────────────────────────────────────────── | |
| # ── 镜像推送到 GHCR (可选) ────────────────────────────────────────────────── | |
| sync-ghcr: | |
| runs-on: ubuntu-latest | |
| needs: prepare | |
| permissions: | |
| packages: write | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Create .env | |
| run: | | |
| touch .env | |
| echo "TP_VERSION=${{ needs.prepare.outputs.version }}" >> .env | |
| echo "TP_VUE_VERSION=${{ needs.prepare.outputs.version }}" >> .env | |
| echo "TP_BACKEND_VERSION=${{ needs.prepare.outputs.version }}" >> .env | |
| echo "TP_GMQTT_VERSION=v1.1.6" >> .env | |
| echo "TP_REDIS_VERSION=6.2.7" >> .env | |
| echo "TP_MODBUS_VERSION=v1.0.6.1" >> .env | |
| echo "TP_HTTP_ADAPTER_VERSION=v1.0.0" >> .env | |
| echo "TP_THINGSVIS_SERVER_VERSION=v1.0.4" >> .env | |
| echo "TP_THINGSVIS_STUDIO_VERSION=v1.0.4" >> .env | |
| echo "TP_TIMESCALEDB_VERSION=14" >> .env | |
| echo "POSTGRES_PASSWORD=1" >> .env | |
| echo "REDIS_PASSWORD=1" >> .env | |
| echo "AUTH_SECRET=1" >> .env | |
| echo "DATA_DIR=./data" >> .env | |
| - name: Use Aliyun to list images | |
| run: | | |
| echo "DOCKER_REGISTRY=registry.cn-hangzhou.aliyuncs.com" >> .env | |
| docker compose config --images > images.txt | |
| - name: Log in to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Pull and Push | |
| run: | | |
| while read img; do | |
| docker pull $img | |
| ghcr_img=$(echo "$img" | sed 's/registry.cn-hangzhou.aliyuncs.com/ghcr.io/g') | |
| docker tag "$img" "$ghcr_img" | |
| docker push "$ghcr_img" | |
| done < images.txt | |
| build-windows: | |
| runs-on: windows-latest | |
| needs: [prepare, validate, sync-ghcr] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Inno Setup | |
| run: choco install innosetup --no-progress -y | |
| - name: Create placeholder icon (if not exists) | |
| shell: pwsh | |
| run: | | |
| $iconDir = "packaging\windows\assets" | |
| if (-not (Test-Path "$iconDir\thingspanel.ico")) { | |
| # 使用系统图标作为占位符(CI 环境) | |
| Copy-Item "$env:SystemRoot\System32\shell32.dll" "$iconDir\thingspanel.ico" -ErrorAction SilentlyContinue || true | |
| } | |
| if (-not (Test-Path "$iconDir\sidebar.bmp")) { | |
| # 创建最小占位 BMP | |
| [System.IO.File]::WriteAllBytes("$iconDir\sidebar.bmp", [byte[]]@(66,77,58,0,0,0,0,0,0,0,54,0,0,0,40,0,0,0,1,0,0,0,1,0,0,0,1,0,24,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0)) | |
| } | |
| - name: Download Docker images for offline bundle | |
| env: | |
| TP_VERSION: ${{ needs.prepare.outputs.version }} | |
| run: | | |
| echo "POSTGRES_PASSWORD=1" > .env | |
| echo "REDIS_PASSWORD=1" >> .env | |
| echo "AUTH_SECRET=1" >> .env | |
| echo "TP_VERSION=$TP_VERSION" >> .env | |
| echo "TP_VUE_VERSION=$TP_VERSION" >> .env | |
| echo "TP_BACKEND_VERSION=$TP_VERSION" >> .env | |
| echo "DOCKER_REGISTRY=registry.cn-hangzhou.aliyuncs.com" >> .env | |
| docker compose pull | |
| docker save $(docker compose config --images) -o images.tar | |
| shell: bash | |
| - name: Build Windows installer | |
| shell: cmd | |
| env: | |
| TP_VERSION: ${{ needs.prepare.outputs.version }} | |
| run: | | |
| mkdir dist\windows 2>nul || true | |
| "C:\Program Files (x86)\Inno Setup 6\ISCC.exe" /DTP_VERSION=%TP_VERSION% packaging\windows\ThingsPanel-Setup.iss | |
| - name: Upload Windows artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: windows-installer | |
| path: dist/windows/ThingsPanel-Setup-*.exe | |
| retention-days: 7 | |
| # ── 构建 macOS 安装包 ─────────────────────────────────────────────────────── | |
| build-macos: | |
| runs-on: macos-latest | |
| needs: [prepare, validate, sync-ghcr] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Create placeholder resources (if not exists) | |
| run: | | |
| mkdir -p packaging/macos/resources | |
| [ -f packaging/macos/resources/welcome.html ] || echo "<html><body><h2>欢迎安装 ThingsPanel</h2></body></html>" > packaging/macos/resources/welcome.html | |
| [ -f packaging/macos/resources/readme.html ] || echo "<html><body><h2>说明</h2><p>ThingsPanel 是一个开...</p></body></html>" > packaging/macos/resources/readme.html | |
| [ -f packaging/macos/resources/license.html ] || echo "<html><body><h2>许可证</h2><p>Apache 2.0</p></body></html>" > packaging/macos/resources/license.html | |
| [ -f packaging/macos/resources/conclusion.html ] || echo "<html><body><h2>安装完成</h2><p>访问 http://localhost:8080</p></body></html>" > packaging/macos/resources/conclusion.html | |
| # 生成一个 1x1 透明 PNG 占位,防止 productbuild 报错 | |
| [ -f packaging/macos/resources/background.png ] || echo "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=" | base64 -d > packaging/macos/resources/background.png | |
| - name: Make scripts executable | |
| run: | | |
| chmod +x packaging/macos/build.sh | |
| chmod +x packaging/macos/scripts/preinstall | |
| chmod +x packaging/macos/scripts/postinstall | |
| - name: Download Docker images for offline bundle | |
| env: | |
| TP_VERSION: ${{ needs.prepare.outputs.version }} | |
| run: | | |
| echo "POSTGRES_PASSWORD=1" > .env | |
| echo "REDIS_PASSWORD=1" >> .env | |
| echo "AUTH_SECRET=1" >> .env | |
| echo "TP_VERSION=$TP_VERSION" >> .env | |
| echo "TP_VUE_VERSION=$TP_VERSION" >> .env | |
| echo "TP_BACKEND_VERSION=$TP_VERSION" >> .env | |
| echo "DOCKER_REGISTRY=registry.cn-hangzhou.aliyuncs.com" >> .env | |
| docker compose pull | |
| docker save $(docker compose config --images) -o images.tar | |
| - name: Build macOS installer | |
| env: | |
| TP_VERSION: ${{ needs.prepare.outputs.version }} | |
| run: ./packaging/macos/build.sh | |
| - name: Upload macOS artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: macos-installer | |
| path: dist/macos/ThingsPanel-*.pkg | |
| retention-days: 7 | |
| # ── 发布 GitHub Release ───────────────────────────────────────────────────── | |
| release: | |
| runs-on: ubuntu-latest | |
| needs: [prepare, build-windows, build-macos] | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Download Windows installer | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: windows-installer | |
| path: dist/windows | |
| - name: Download macOS installer | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: macos-installer | |
| path: dist/macos | |
| - name: Generate SHA256 checksums | |
| run: | | |
| cd dist | |
| touch SHA256SUMS.txt | |
| find . -type f \( -name "*.exe" -o -name "*.pkg" \) | sort | while read f; do | |
| sha256sum "$f" >> SHA256SUMS.txt | |
| done | |
| cat SHA256SUMS.txt | |
| - name: Create Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ needs.prepare.outputs.version }} | |
| name: "ThingsPanel All-in-One ${{ needs.prepare.outputs.version }}" | |
| body: | | |
| ## ThingsPanel All-in-One ${{ needs.prepare.outputs.version }} | |
| ### 快速安装 | |
| **Linux / macOS(推荐)** | |
| ```bash | |
| curl -fsSL https://raw.githubusercontent.com/ThingsPanel/all-in-one-assembler/main/install.sh | sh | |
| ``` | |
| **Windows** | |
| 下载下方 `ThingsPanel-Setup-*.exe`,右键"以管理员身份运行"。 | |
| **macOS(图形界面)** | |
| 下载下方 `ThingsPanel-*.pkg`,双击安装。 | |
| ### 前置要求 | |
| - Docker Desktop(Windows / macOS)或 Docker Engine(Linux) | |
| - 内存 ≥ 2GB | |
| ### 文件说明 | |
| | 文件 | 平台 | 说明 | | |
| |------|------|------| | |
| | `ThingsPanel-Setup-*.exe` | Windows | Inno Setup 安装向导 | | |
| | `ThingsPanel-*.pkg` | macOS | macOS 安装包 | | |
| | `install.sh` | Linux/macOS | 一行命令安装脚本 | | |
| draft: false | |
| prerelease: ${{ contains(needs.prepare.outputs.version, 'rc') || contains(needs.prepare.outputs.version, 'beta') }} | |
| files: | | |
| dist/windows/*.exe | |
| dist/macos/*.pkg | |
| dist/SHA256SUMS.txt |