name: Build & Publish All-in-One on: push: branches: [main, dev] tags: [v*] workflow_dispatch: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} BOT_TOKEN: ${{ secrets.LITEYUKIFLOW_TOKEN }} BIN_NAME: spage BIN_NAME_AGENT: spage-agent BIN_OUT: build FRONTEND_DIR: web-src # for container build CONTAINER_PLATFORMS: linux/amd64,linux/arm64,linux/386,linux/arm REG_GHCR: ghcr.io REG_DOCKERHUB: docker.io REG_LCR: reg.liteyuki.org NAMESPACE_GHCR: liteyukistudio NAMESPACE_DOCKERHUB: liteyukistudio NAMESPACE_LCR: spage ARCH_MAP: | amd64:amd64-v1 arm64:arm64 arm:armv7 386:386-sse2 ppc64le:ppc64le s390x:s390x concurrency: group: "build-aio" cancel-in-progress: true permissions: contents: write packages: write jobs: frontend: name: Build Frontend runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Cache pnpm store uses: actions/cache@v4 with: path: | ~/.pnpm-store ${{ env.FRONTEND_DIR }}/node_modules key: ${{ runner.os }}-pnpm-${{ hashFiles('${{ env.FRONTEND_DIR }}/pnpm-lock.yaml') }} restore-keys: | ${{ runner.os }}-pnpm- pnpm- - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 20 - name: Build frontend run: | npm install pnpm -g make web - name: Upload frontend artifact uses: actions/upload-artifact@v4 with: name: web path: ${{ env.FRONTEND_DIR }}/out retention-days: 30 backend: name: Build Backend needs: frontend runs-on: ubuntu-latest outputs: version: ${{ steps.version.outputs.version }} tag: ${{ steps.version.outputs.tag }} nightly: ${{ steps.version.outputs.nightly }} strategy: matrix: include: [ { goos: "darwin", goarch: "amd64", goamd64: "v1", output: "amd64-v1" }, { goos: "darwin", goarch: "amd64", goamd64: "v3", output: "amd64-v3" }, { goos: "darwin", goarch: "arm64", output: "arm64" }, { goos: "freebsd", goarch: "amd64", goamd64: "v1", output: "amd64-v1" }, { goos: "freebsd", goarch: "amd64", goamd64: "v3", output: "amd64-v3" }, { goos: "freebsd", goarch: "arm64", output: "arm64" }, { goos: "linux", goarch: "amd64", goamd64: "v1", output: "amd64-v1" }, { goos: "linux", goarch: "amd64", goamd64: "v3", output: "amd64-v3" }, { goos: "linux", goarch: "arm64", output: "arm64" }, { goos: "linux", goarch: "386", go386: "sse2", output: "386-sse2" }, { goos: "linux", goarch: "arm", goarm: "7", output: "armv7" }, { goos: "linux", goarch: "arm", goarm: "6", output: "armv6" }, { goos: "linux", goarch: "arm", goarm: "5", output: "armv5" }, { goos: "windows", goarch: "amd64", goamd64: "v1", output: "amd64-v1" }, { goos: "windows", goarch: "amd64", goamd64: "v3", output: "amd64-v3" }, { goos: "windows", goarch: "arm64", output: "arm64" }, ] steps: - name: Checkout code uses: actions/checkout@v4 - name: Cache Go modules uses: actions/cache@v4 with: path: | ~/.cache/go-build ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} restore-keys: | ${{ runner.os }}-go- - name: Setup Go uses: actions/setup-go@v5 - name: Set version/tag id: version run: | if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then VERSION="${GITHUB_REF#refs/tags/}" TAG="${VERSION}" NIGHTLY="false" else VERSION="${GITHUB_SHA}" TAG="nightly" NIGHTLY="true" fi echo "version=${VERSION}" >> $GITHUB_OUTPUT echo "tag=${TAG}" >> $GITHUB_OUTPUT echo "nightly=${NIGHTLY}" >> $GITHUB_OUTPUT - name: Download frontend artifact uses: actions/download-artifact@v4 with: name: web path: static/dist/ - name: Build Go Server binary env: GOOS: ${{ matrix.goos }} GOARCH: ${{ matrix.goarch }} GOAMD64: ${{ matrix.goamd64 }} GOARM: ${{ matrix.goarm }} GO386: ${{ matrix.go386 }} run: | make ${{ env.BIN_NAME }} GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} GOAMD64=${{ matrix.goamd64 }} GOARM=${{ matrix.goarm }} GO386=${{ matrix.go386 }} make ${{ env.BIN_NAME_AGENT }} GOOS=${{ matrix.goos }} GOARCH=${{ matrix.goarch }} GOAMD64=${{ matrix.goamd64 }} GOARM=${{ matrix.goarm }} GO386=${{ matrix.go386 }} - name: List build dir run: ls -lh build/ - name: Prepare main arch binaries for Docker buildx env: ARCH_MAP: ${{ env.ARCH_MAP }} run: | # Process both binaries for binary in "${{ env.BIN_NAME }}" "${{ env.BIN_NAME_AGENT }}"; do echo "Processing $binary..." for line in $(echo "${ARCH_MAP}"); do short=$(echo "$line" | cut -d: -f1) long=$(echo "$line" | cut -d: -f2) src="build/${binary}-linux-$long" dst="build/${binary}-linux-$short" if [ -f "$src" ]; then cp "$src" "$dst" || true echo "Copied $src -> $dst" else echo "Warning: $src not found, skip $short for $binary" fi done done ls -lhR build/ - name: Upload artifact uses: actions/upload-artifact@v4 with: name: binaries-${{ matrix.goos }}-${{ matrix.output }} path: build/* retention-days: 30 container: name: Build & Publish Container Images runs-on: ubuntu-latest needs: backend steps: - name: Checkout code uses: actions/checkout@v4 - name: Download all linux artifacts for docker uses: actions/download-artifact@v4 with: pattern: binaries-linux-* # 更新模式以匹配新的工件名称 path: build/ merge-multiple: true - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Login to GHCR uses: docker/login-action@v3 with: registry: ${{ env.REG_GHCR }} username: ${{ secrets.GHCR_USER }} password: ${{ secrets.GHCR_TOKEN }} - name: Login to DockerHub uses: docker/login-action@v3 with: registry: ${{ env.REG_DOCKERHUB }} username: ${{ secrets.DOCKERHUB_USER }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Login to LCR uses: docker/login-action@v3 with: registry: ${{ env.REG_LCR }} username: ${{ secrets.LITEYUKIREG_USER }} password: ${{ secrets.LITEYUKIREG_TOKEN }} - name: Build & Push Docker Images ${{ env.BIN_NAME }} (tag & latest) if: ${{ needs.backend.outputs.nightly == 'false' }} uses: docker/build-push-action@v6 with: context: . file: Dockerfile.spage push: true tags: | ${{ env.NAMESPACE_DOCKERHUB }}/${{ env.BIN_NAME }}:${{ needs.backend.outputs.tag }} ${{ env.NAMESPACE_DOCKERHUB }}/${{ env.BIN_NAME }}:latest ${{ env.NAMESPACE_DOCKERHUB }}/${{ env.BIN_NAME }}:nightly ${{ env.REG_GHCR }}/${{ env.NAMESPACE_GHCR }}/${{ env.BIN_NAME }}:${{ needs.backend.outputs.tag }} ${{ env.REG_GHCR }}/${{ env.NAMESPACE_GHCR }}/${{ env.BIN_NAME }}:latest ${{ env.REG_GHCR }}/${{ env.NAMESPACE_GHCR }}/${{ env.BIN_NAME }}:nightly ${{ env.REG_LCR }}/${{ env.NAMESPACE_LCR }}/${{ env.BIN_NAME }}:${{ needs.backend.outputs.tag }} ${{ env.REG_LCR }}/${{ env.NAMESPACE_LCR }}/${{ env.BIN_NAME }}:latest ${{ env.REG_LCR }}/${{ env.NAMESPACE_LCR }}/${{ env.BIN_NAME }}:nightly platforms: ${{ env.CONTAINER_PLATFORMS }} - name: Build & Push Docker Images ${{ env.BIN_NAME_AGENT }} (tag & latest) if: ${{ needs.backend.outputs.nightly == 'false' }} uses: docker/build-push-action@v6 with: context: . file: Dockerfile.spage-agent push: true tags: | ${{ env.NAMESPACE_DOCKERHUB }}/${{ env.BIN_NAME_AGENT }}:${{ needs.backend.outputs.tag }} ${{ env.NAMESPACE_DOCKERHUB }}/${{ env.BIN_NAME_AGENT }}:latest ${{ env.NAMESPACE_DOCKERHUB }}/${{ env.BIN_NAME_AGENT }}:nightly ${{ env.REG_GHCR }}/${{ env.NAMESPACE_GHCR }}/${{ env.BIN_NAME_AGENT }}:${{ needs.backend.outputs.tag }} ${{ env.REG_GHCR }}/${{ env.NAMESPACE_GHCR }}/${{ env.BIN_NAME_AGENT }}:latest ${{ env.REG_GHCR }}/${{ env.NAMESPACE_GHCR }}/${{ env.BIN_NAME_AGENT }}:nightly ${{ env.REG_LCR }}/${{ env.NAMESPACE_LCR }}/${{ env.BIN_NAME_AGENT }}:${{ needs.backend.outputs.tag }} ${{ env.REG_LCR }}/${{ env.NAMESPACE_LCR }}/${{ env.BIN_NAME_AGENT }}:latest ${{ env.REG_LCR }}/${{ env.NAMESPACE_LCR }}/${{ env.BIN_NAME_AGENT }}:nightly platforms: ${{ env.CONTAINER_PLATFORMS }} - name: Build & Push Docker Images ${{ env.BIN_NAME }} (nightly only) if: ${{ needs.backend.outputs.nightly == 'true' }} uses: docker/build-push-action@v6 with: context: . file: Dockerfile.spage push: true tags: | ${{ env.NAMESPACE_DOCKERHUB }}/${{ env.BIN_NAME }}:nightly ${{ env.REG_GHCR }}/${{ env.NAMESPACE_GHCR }}/${{ env.BIN_NAME }}:nightly ${{ env.REG_LCR }}/${{ env.NAMESPACE_LCR }}/${{ env.BIN_NAME }}:nightly platforms: ${{ env.CONTAINER_PLATFORMS }} - name: Build & Push Docker Images ${{ env.BIN_NAME_AGENT }} (nightly only) if: ${{ needs.backend.outputs.nightly == 'true' }} uses: docker/build-push-action@v6 with: context: . file: Dockerfile.spage-agent push: true tags: | ${{ env.NAMESPACE_DOCKERHUB }}/${{ env.BIN_NAME_AGENT }}:nightly ${{ env.NAMESPACE_GHCR }}/${{ env.BIN_NAME_AGENT }}:nightly ${{ env.NAMESPACE_LCR }}/${{ env.BIN_NAME_AGENT }}:nightly platforms: ${{ env.CONTAINER_PLATFORMS }} release: name: Publish GitHub Release runs-on: ubuntu-latest needs: backend steps: - name: Download all linux artifacts for docker uses: actions/download-artifact@v4 with: pattern: binaries-* # 更新模式以匹配新的工件名称 path: build/ merge-multiple: true - name: Publish GitHub Release(tag & latest) if: ${{ needs.backend.outputs.nightly == 'false' }} uses: ncipollo/release-action@v1 with: tag: ${{ needs.backend.outputs.tag }} artifacts: build/* name: "Release ${{ needs.backend.outputs.tag }}" generateReleaseNotes: true allowUpdates: true token: ${{ env.BOT_TOKEN }} - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Edit Changelog run: | npx changelogithub || true env: GITHUB_TOKEN: ${{ env.BOT_TOKEN }}