name: Build and Push Images env: VERSION: "2.0.7-beta" # 分支推送时使用的默认版本 REGISTRY: ghcr.io on: push: tags: - '[0-9]*' # 匹配 2.0.8, 2.0.8-beta 等格式 jobs: check-version: name: Check Version and Decide Build runs-on: ubuntu-latest outputs: version: ${{ steps.version.outputs.version }} should_build: ${{ steps.version.outputs.should_build }} should_build_gost: ${{ steps.version.outputs.should_build_gost }} is_tag: ${{ steps.version.outputs.is_tag }} image_owner: ${{ steps.version.outputs.image_owner }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Determine version and build strategy id: version run: | # 镜像 owner 需要小写 IMAGE_OWNER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') echo "image_owner=$IMAGE_OWNER" >> $GITHUB_OUTPUT if [[ "${{ github.ref_type }}" == "tag" ]]; then # Tag 触发:直接使用 tag 名作为版本,全量构建 VERSION="${{ github.ref_name }}" echo "🏷️ Tag trigger detected: $VERSION" echo "version=$VERSION" >> $GITHUB_OUTPUT echo "is_tag=true" >> $GITHUB_OUTPUT echo "should_build=true" >> $GITHUB_OUTPUT echo "should_build_gost=true" >> $GITHUB_OUTPUT else # 分支触发:使用 env.VERSION,检查是否需要构建 VERSION="${{ env.VERSION }}" echo "🌿 Branch trigger detected, using version: $VERSION" echo "version=$VERSION" >> $GITHUB_OUTPUT echo "is_tag=false" >> $GITHUB_OUTPUT # 检查 tag 是否已存在 if git rev-parse "$VERSION" >/dev/null 2>&1; then echo "Tag $VERSION already exists" echo "should_build=false" >> $GITHUB_OUTPUT # 检查 go-gost 目录是否有变化 TAG_COMMIT=$(git rev-list -n 1 "$VERSION") if git diff --quiet --ignore-all-space --ignore-blank-lines $TAG_COMMIT HEAD -- go-gost/ 2>/dev/null; then echo "✅ GOST files unchanged since tag" echo "should_build_gost=false" >> $GITHUB_OUTPUT else echo "🔄 Detected changes in go-gost directory" git diff --stat $TAG_COMMIT HEAD -- go-gost/ || true echo "should_build_gost=true" >> $GITHUB_OUTPUT fi else echo "Tag $VERSION does not exist, will build all components" echo "should_build=true" >> $GITHUB_OUTPUT echo "should_build_gost=true" >> $GITHUB_OUTPUT fi fi build-gost: name: Build & Compress GOST Binary needs: check-version if: needs.check-version.outputs.should_build_gost == 'true' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v5 with: go-version: '1.23' - name: Cache Go modules uses: actions/cache@v4 with: path: | ~/.cache/go-build ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('go-gost/go.sum') }} restore-keys: | ${{ runner.os }}-go- - name: Install UPX run: | wget -q https://github.com/upx/upx/releases/download/v4.2.1/upx-4.2.1-amd64_linux.tar.xz tar -xf upx-4.2.1-amd64_linux.tar.xz sudo mv upx-4.2.1-amd64_linux/upx /usr/local/bin/ rm -rf upx-4.2.1-amd64_linux* - name: Build GOST binary (AMD64) working-directory: ./go-gost run: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w -X main.version=${{ needs.check-version.outputs.version }}" -o gost-amd64 - name: Build GOST binary (ARM64) working-directory: ./go-gost run: CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build -ldflags="-s -w -X main.version=${{ needs.check-version.outputs.version }}" -o gost-arm64 - name: Compress with UPX working-directory: ./go-gost run: | upx --best --lzma gost-amd64 upx --best --lzma gost-arm64 - name: Generate SHA256 checksums working-directory: ./go-gost run: | sha256sum gost-amd64 > gost-amd64.sha256 sha256sum gost-arm64 > gost-arm64.sha256 - name: Upload GOST AMD64 artifact uses: actions/upload-artifact@v4 with: name: gost-binary-amd64 path: ./go-gost/gost-amd64 - name: Upload GOST ARM64 artifact uses: actions/upload-artifact@v4 with: name: gost-binary-arm64 path: ./go-gost/gost-arm64 - name: Upload GOST AMD64 checksum artifact uses: actions/upload-artifact@v4 with: name: gost-checksum-amd64 path: ./go-gost/gost-amd64.sha256 - name: Upload GOST ARM64 checksum artifact uses: actions/upload-artifact@v4 with: name: gost-checksum-arm64 path: ./go-gost/gost-arm64.sha256 build-vite: name: Build & Push Vite Frontend needs: check-version if: needs.check-version.outputs.should_build == 'true' runs-on: ubuntu-latest permissions: contents: read packages: write steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Prepare build args run: | VERSION="${{ needs.check-version.outputs.version }}" { echo "VITE_GITHUB_REPO=https://github.com/${{ github.repository }}" echo "VITE_APP_VERSION=$VERSION" } > ./vite-frontend/.env.production - name: Build and push Vite Docker images run: | VERSION="${{ needs.check-version.outputs.version }}" OWNER="${{ needs.check-version.outputs.image_owner }}" docker buildx build \ --platform linux/amd64,linux/arm64 \ --push \ -t ${{ env.REGISTRY }}/${OWNER}/vite-frontend:latest \ -t ${{ env.REGISTRY }}/${OWNER}/vite-frontend:${VERSION} \ ./vite-frontend build-go-backend: name: Build & Push Go Backend needs: check-version if: needs.check-version.outputs.should_build == 'true' runs-on: ubuntu-latest permissions: contents: read packages: write steps: - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v5 with: go-version: '1.23' - name: Cache Go dependencies uses: actions/cache@v4 with: path: | ~/.cache/go-build ~/go/pkg/mod key: ${{ runner.os }}-go-backend-${{ hashFiles('go-backend/go.sum') }} restore-keys: ${{ runner.os }}-go-backend- - name: Download dependencies working-directory: ./go-backend run: go mod download - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push Go backend Docker images run: | VERSION="${{ needs.check-version.outputs.version }}" OWNER="${{ needs.check-version.outputs.image_owner }}" docker buildx build \ --platform linux/amd64,linux/arm64 \ --push \ -t ${{ env.REGISTRY }}/${OWNER}/flux-panel-backend:latest \ -t ${{ env.REGISTRY }}/${OWNER}/flux-panel-backend:${VERSION} \ ./go-backend create-release: name: Create Release (Tag Only) needs: [check-version, build-gost, build-vite, build-go-backend] if: needs.check-version.outputs.is_tag == 'true' runs-on: ubuntu-latest permissions: contents: write steps: - uses: actions/checkout@v4 - name: Download GOST AMD64 binary uses: actions/download-artifact@v4 with: name: gost-binary-amd64 path: ./artifacts/amd64 - name: Download GOST ARM64 binary uses: actions/download-artifact@v4 with: name: gost-binary-arm64 path: ./artifacts/arm64 - name: Download GOST AMD64 checksum uses: actions/download-artifact@v4 with: name: gost-checksum-amd64 path: ./artifacts/ - name: Download GOST ARM64 checksum uses: actions/download-artifact@v4 with: name: gost-checksum-arm64 path: ./artifacts/ - name: Prepare release files run: | VERSION="${{ needs.check-version.outputs.version }}" OWNER="${{ needs.check-version.outputs.image_owner }}" REPO="${{ github.repository }}" # 移动二进制文件 mv ./artifacts/amd64/gost-amd64 ./artifacts/gost-amd64 mv ./artifacts/arm64/gost-arm64 ./artifacts/gost-arm64 # 复制并修改 docker-compose 文件 cp docker-compose-v4.yml ./artifacts/docker-compose-v4.yml cp docker-compose-v6.yml ./artifacts/docker-compose-v6.yml # 替换镜像地址为 GHCR sed -i "s|image: .*flux-panel-backend:[^[:space:]]*|image: ${{ env.REGISTRY }}/${OWNER}/flux-panel-backend:${VERSION}|g" ./artifacts/docker-compose-v4.yml sed -i "s|image: .*vite-frontend:[^[:space:]]*|image: ${{ env.REGISTRY }}/${OWNER}/vite-frontend:${VERSION}|g" ./artifacts/docker-compose-v4.yml sed -i "s|image: .*flux-panel-backend:[^[:space:]]*|image: ${{ env.REGISTRY }}/${OWNER}/flux-panel-backend:${VERSION}|g" ./artifacts/docker-compose-v6.yml sed -i "s|image: .*vite-frontend:[^[:space:]]*|image: ${{ env.REGISTRY }}/${OWNER}/vite-frontend:${VERSION}|g" ./artifacts/docker-compose-v6.yml # 复制并修改安装脚本 cp install.sh ./artifacts/install.sh cp panel_install.sh ./artifacts/panel_install.sh # 替换仓库地址和版本号 sed -i "s|bqlpfy/flux-panel|${REPO}|g" ./artifacts/install.sh sed -i "s|bqlpfy/flux-panel|${REPO}|g" ./artifacts/panel_install.sh sed -i "s|2.0.7-beta|${VERSION}|g" ./artifacts/install.sh sed -i "s|2.0.7-beta|${VERSION}|g" ./artifacts/panel_install.sh # 注入固定版本号,使从 Release 页下载的脚本只安装该版本 sed -i "s|^PINNED_VERSION=\"\"|PINNED_VERSION=\"${VERSION}\"|" ./artifacts/install.sh sed -i "s|^PINNED_VERSION=\"\"|PINNED_VERSION=\"${VERSION}\"|" ./artifacts/panel_install.sh - name: Create Release env: GH_TOKEN: ${{ github.token }} run: | VERSION="${{ needs.check-version.outputs.version }}" OWNER="${{ needs.check-version.outputs.image_owner }}" # 获取 commit 信息 COMMIT_MSG=$(git log -1 --pretty=format:"%s") COMMIT_AUTHOR=$(git log -1 --pretty=format:"%an") COMMIT_DATE=$(git log -1 --pretty=format:"%ai") # 创建 release gh release create "${VERSION}" \ --title "Release ${VERSION}" \ --notes "## 📝 Release Information - **Version**: ${VERSION} - **Commit**: [\`${GITHUB_SHA:0:7}\`](https://github.com/${{ github.repository }}/commit/${{ github.sha }}) - **Author**: ${COMMIT_AUTHOR} - **Date**: ${COMMIT_DATE} - **Message**: ${COMMIT_MSG} ## 📦 Docker Images \`\`\`bash # Backend docker pull ${{ env.REGISTRY }}/${OWNER}/flux-panel-backend:${VERSION} # Frontend docker pull ${{ env.REGISTRY }}/${OWNER}/vite-frontend:${VERSION} \`\`\` ## 🚀 Quick Install **Panel (安装此版本 ${VERSION}):** \`\`\`bash curl -L https://github.com/${{ github.repository }}/releases/download/${VERSION}/panel_install.sh -o panel_install.sh && chmod +x panel_install.sh && ./panel_install.sh \`\`\` **Node (安装此版本 ${VERSION}):** \`\`\`bash curl -L https://github.com/${{ github.repository }}/releases/download/${VERSION}/install.sh -o install.sh && chmod +x install.sh && ./install.sh \`\`\` **安装最新版:** \`\`\`bash # 面板端 curl -L https://raw.githubusercontent.com/${{ github.repository }}/main/panel_install.sh -o panel_install.sh && chmod +x panel_install.sh && ./panel_install.sh # 节点端 curl -L https://raw.githubusercontent.com/${{ github.repository }}/main/install.sh -o install.sh && chmod +x install.sh && ./install.sh \`\`\`" \ --repo ${{ github.repository }} # 上传所有文件到 release echo "📤 上传 GOST 二进制文件..." gh release upload "${VERSION}" ./artifacts/gost-amd64 --clobber gh release upload "${VERSION}" ./artifacts/gost-arm64 --clobber echo "📤 上传 GOST 校验文件..." gh release upload "${VERSION}" ./artifacts/gost-amd64.sha256 --clobber gh release upload "${VERSION}" ./artifacts/gost-arm64.sha256 --clobber echo "📤 上传安装脚本..." gh release upload "${VERSION}" ./artifacts/install.sh --clobber gh release upload "${VERSION}" ./artifacts/panel_install.sh --clobber echo "📤 上传 Docker Compose 配置文件..." gh release upload "${VERSION}" ./artifacts/docker-compose-v4.yml --clobber gh release upload "${VERSION}" ./artifacts/docker-compose-v6.yml --clobber echo "✅ Release ${VERSION} 创建完成" update-release-gost: name: Update GOST Binaries in Release needs: [check-version, build-gost] if: needs.check-version.outputs.is_tag == 'false' && needs.check-version.outputs.should_build == 'false' && needs.check-version.outputs.should_build_gost == 'true' runs-on: ubuntu-latest permissions: contents: write steps: - uses: actions/checkout@v4 - name: Download GOST AMD64 binary uses: actions/download-artifact@v4 with: name: gost-binary-amd64 path: ./artifacts/amd64 - name: Download GOST ARM64 binary uses: actions/download-artifact@v4 with: name: gost-binary-arm64 path: ./artifacts/arm64 - name: Download GOST AMD64 checksum uses: actions/download-artifact@v4 with: name: gost-checksum-amd64 path: ./artifacts/ - name: Download GOST ARM64 checksum uses: actions/download-artifact@v4 with: name: gost-checksum-arm64 path: ./artifacts/ - name: Rename binaries run: | mv ./artifacts/amd64/gost-amd64 ./artifacts/gost-amd64 mv ./artifacts/arm64/gost-arm64 ./artifacts/gost-arm64 - name: Update GOST binaries in Release env: GH_TOKEN: ${{ github.token }} run: | VERSION="${{ needs.check-version.outputs.version }}" echo "🔄 更新 Release ${VERSION} 中的 GOST 二进制文件..." gh release upload "${VERSION}" ./artifacts/gost-amd64 --clobber gh release upload "${VERSION}" ./artifacts/gost-arm64 --clobber echo "📤 上传 GOST 校验文件..." gh release upload "${VERSION}" ./artifacts/gost-amd64.sha256 --clobber gh release upload "${VERSION}" ./artifacts/gost-arm64.sha256 --clobber echo "✅ GOST 二进制文件更新完成"