diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 8d5df76..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -github: alireza0 diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index ef05880..cc1812c 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -9,71 +9,21 @@ on: default: "v1.4.1" type: string +permissions: + contents: read + packages: write + +env: + IMAGE_NAME: ghcr.io/${{ github.repository }} + jobs: - frontend-build: - runs-on: ubuntu-24.04 - steps: - - name: 检出仓库 - uses: actions/checkout@v6.0.2 - with: - ref: ${{ inputs.tag }} - submodules: recursive - - - name: 设置 Node.js - uses: actions/setup-node@v6 - with: - node-version: 25 - - - name: 安装依赖并构建前端 - run: | - cd frontend - npm install - npm run build - - - name: 上传前端构建产物 - uses: actions/upload-artifact@v7 - with: - name: frontend-dist - path: frontend/dist/ - build: - needs: frontend-build - strategy: - fail-fast: false - matrix: - include: - - { platform: linux/amd64 } - - { platform: linux/386 } - - { platform: linux/arm64/v8 } - - { platform: linux/arm/v7 } - - { platform: linux/arm/v6 } runs-on: ubuntu-24.04 steps: - name: 检出仓库 uses: actions/checkout@v6.0.2 with: - ref: ${{ inputs.tag }} - - - name: 下载前端构建产物 - uses: actions/download-artifact@v8 - with: - name: frontend-dist - path: frontend_dist - - - name: 准备 - run: | - platform="${{ matrix.platform }}" - echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV - - - name: Docker 元数据 - id: meta - uses: docker/metadata-action@v6 - with: - images: | - alireza7/s-ui - ghcr.io/alireza0/s-ui - tags: | - type=raw,value=${{ inputs.tag }} + submodules: recursive - name: 设置 QEMU uses: docker/setup-qemu-action@v4 @@ -81,101 +31,20 @@ jobs: - name: 设置 Docker Buildx uses: docker/setup-buildx-action@v4 - - name: 缓存 Docker 层 - uses: actions/cache@v5 - with: - path: /tmp/.buildx-cache - key: ${{ runner.os }}-buildx-${{ matrix.platform }}-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-buildx-${{ matrix.platform }}- - - - name: 登录 Docker Hub - uses: docker/login-action@v4 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - name: 登录 GHCR uses: docker/login-action@v4 with: registry: ghcr.io - username: ${{ github.repository_owner }} + username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: 按摘要构建并推送 - id: build + - name: 构建并推送 Docker 镜像 uses: docker/build-push-action@v7 with: context: . - file: Dockerfile.frontend-artifact - platforms: ${{ matrix.platform }} - labels: ${{ steps.meta.outputs.labels }} + file: Dockerfile + platforms: linux/amd64,linux/386,linux/arm64/v8,linux/arm/v7,linux/arm/v6 + push: true tags: | - alireza7/s-ui - ghcr.io/alireza0/s-ui - cache-from: type=local,src=/tmp/.buildx-cache - cache-to: type=local,dest=/tmp/.buildx-cache,mode=max - outputs: type=image,push-by-digest=true,name-canonical=true,push=true - - - name: 导出摘要 - run: | - mkdir -p ${{ runner.temp }}/digests - digest="${{ steps.build.outputs.digest }}" - echo "${digest#sha256:}" > "${{ runner.temp }}/digests/${digest#sha256:}" - - - name: 上传摘要 - uses: actions/upload-artifact@v7 - with: - name: digests-${{ env.PLATFORM_PAIR }} - path: ${{ runner.temp }}/digests/* - if-no-files-found: error - retention-days: 1 - - merge: - needs: build - runs-on: ubuntu-24.04 - steps: - - name: 下载摘要 - uses: actions/download-artifact@v8 - with: - path: ${{ runner.temp }}/digests - pattern: digests-* - merge-multiple: true - - - name: 登录 Docker Hub - uses: docker/login-action@v4 - with: - username: ${{ secrets.DOCKER_HUB_USERNAME }} - password: ${{ secrets.DOCKER_HUB_TOKEN }} - - - name: 登录 GHCR - uses: docker/login-action@v4 - with: - registry: ghcr.io - username: ${{ github.repository_owner }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: 设置 Docker Buildx - uses: docker/setup-buildx-action@v4 - - - name: Docker 元数据 - id: meta - uses: docker/metadata-action@v6 - with: - images: | - alireza7/s-ui - ghcr.io/alireza0/s-ui - tags: | - type=raw,value=${{ inputs.tag }} - - - name: 创建清单列表并推送 - env: - DOCKER_METADATA_OUTPUT_JSON: ${{ steps.meta.outputs.json }} - working-directory: ${{ runner.temp }}/digests - run: | - set -e - for img in alireza7/s-ui ghcr.io/alireza0/s-ui; do - TAGS_ARGS=$(echo "$DOCKER_METADATA_OUTPUT_JSON" | jq -cr --arg img "$img" '.tags | map(select(startswith($img))) | map("-t " + .) | join(" ")') - DIGEST_REFS=$(for f in *; do echo -n "${img}@sha256:$(cat "$f") "; done) - docker buildx imagetools create $TAGS_ARGS $DIGEST_REFS - done + ${{ env.IMAGE_NAME }}:${{ inputs.tag }} + ${{ env.IMAGE_NAME }}:latest diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 36b8017..0c73760 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,6 +9,9 @@ on: default: "v1.4.1" type: string +permissions: + contents: write + env: NODE_VERSION: "25" CRONET_GO_VERSION: "2fef65f9dba90ddb89a87d00a6eb6165487c10c1" @@ -19,10 +22,9 @@ jobs: build-frontend: runs-on: ubuntu-latest steps: - - name: 检出仓库(仅前端) + - name: 检出仓库 uses: actions/checkout@v6.0.2 with: - ref: ${{ inputs.tag }} submodules: recursive fetch-depth: 1 @@ -30,7 +32,7 @@ jobs: uses: actions/setup-node@v6 with: node-version: ${{ env.NODE_VERSION }} - cache: 'npm' + cache: "npm" cache-dependency-path: frontend/package-lock.json - name: 构建前端 @@ -38,13 +40,13 @@ jobs: cd frontend npm install npm run build - cd .. - - name: 上传前端 dist + - name: 上传前端构建产物 uses: actions/upload-artifact@v7 with: name: frontend-dist path: frontend/dist/ + retention-days: 1 build-linux: name: 构建-${{ matrix.platform }} @@ -64,10 +66,8 @@ jobs: steps: - name: 检出仓库 uses: actions/checkout@v6.0.2 - with: - ref: ${{ inputs.tag }} - - name: 下载前端 dist + - name: 下载前端构建产物 uses: actions/download-artifact@v8 with: name: frontend-dist @@ -79,8 +79,7 @@ jobs: cache: false go-version-file: go.mod - # Naive 平台:仅使用 cronet 工具链(不使用 Bootlin)。 - - name: 克隆 cronet-go(naive 使用的 cronet 工具链) + - name: 克隆 cronet-go(naive 平台) if: matrix.naive run: | set -e @@ -98,19 +97,7 @@ jobs: cd ~/cronet-go GPG_TTY=/dev/null ./naiveproxy/src/build/linux/sysroot_scripts/generate_keyring.sh - - name: 缓存 Chromium 工具链 - if: matrix.naive - id: cache-chromium-toolchain - uses: actions/cache@v5 - with: - path: | - ~/cronet-go/naiveproxy/src/third_party/llvm-build/ - ~/cronet-go/naiveproxy/src/gn/out/ - ~/cronet-go/naiveproxy/src/chrome/build/pgo_profiles/ - ~/cronet-go/naiveproxy/src/out/sysroot-build/ - key: chromium-toolchain-${{ matrix.platform }}-musl-${{ env.CRONET_GO_VERSION }} - - - name: 构建 cronet 库并设置工具链环境(CC、CXX、CGO_LDFLAGS、PATH) + - name: 构建 cronet 库并设置工具链环境 if: matrix.naive run: | set -e @@ -122,15 +109,14 @@ jobs: echo "$line" >> $GITHUB_ENV done - - name: 设置 Go 构建环境(所有平台) + - name: 设置 Go 构建环境 run: | echo "CGO_ENABLED=1" >> $GITHUB_ENV echo "GOOS=linux" >> $GITHUB_ENV echo "GOARCH=${{ matrix.arch }}" >> $GITHUB_ENV if [ -n "${{ matrix.goarm }}" ]; then echo "GOARM=${{ matrix.goarm }}" >> $GITHUB_ENV; fi - # 仅非 naive 平台:Bootlin musl(armv5、s390x)。 - - name: 设置 Bootlin musl(armv5、s390x) + - name: 设置 Bootlin musl(非 naive 平台) if: ${{ matrix.naive != true }} run: | set -e @@ -180,14 +166,26 @@ jobs: with: name: s-ui-linux-${{ matrix.platform }} path: ./s-ui-linux-${{ matrix.platform }}.tar.gz - retention-days: 30 + retention-days: 1 - - name: 上传到 Release - uses: svenstaro/upload-release-action@v2 + publish-linux: + name: 发布 Linux 产物 + needs: build-linux + runs-on: ubuntu-latest + steps: + - name: 下载 Linux 构建产物 + uses: actions/download-artifact@v8 with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - tag: ${{ inputs.tag }} - file: s-ui-linux-${{ matrix.platform }}.tar.gz - asset_name: s-ui-linux-${{ matrix.platform }}.tar.gz + pattern: s-ui-linux-* + path: release-assets + merge-multiple: true + + - name: 发布到当前仓库 Release + uses: softprops/action-gh-release@v3 + with: + tag_name: ${{ inputs.tag }} + name: S-UI ${{ inputs.tag }} + target_commitish: ${{ github.sha }} prerelease: true - overwrite: true + fail_on_unmatched_files: true + files: release-assets/* diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index e189281..6b18c22 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -9,6 +9,9 @@ on: default: "v1.4.1" type: string +permissions: + contents: write + env: NODE_VERSION: "25" TAGS: "with_quic,with_grpc,with_utls,with_acme,with_gvisor,with_naive_outbound,with_purego,badlinkname,tfogo_checklinkname0,with_tailscale" @@ -21,7 +24,6 @@ jobs: - name: 检出仓库 uses: actions/checkout@v6.0.2 with: - ref: ${{ inputs.tag }} submodules: recursive fetch-depth: 1 @@ -29,14 +31,15 @@ jobs: uses: actions/setup-node@v6 with: node-version: ${{ env.NODE_VERSION }} - registry-url: 'https://registry.npmjs.org' + registry-url: "https://registry.npmjs.org" + cache: "npm" + cache-dependency-path: frontend/package-lock.json - name: 构建前端 run: | cd frontend npm install npm run build - cd .. - name: 上传前端构建产物 uses: actions/upload-artifact@v7 @@ -58,8 +61,6 @@ jobs: steps: - name: 检出仓库 uses: actions/checkout@v6.0.2 - with: - ref: ${{ inputs.tag }} - name: 下载前端构建产物 uses: actions/download-artifact@v8 @@ -77,13 +78,11 @@ jobs: if: matrix.arch == 'amd64' shell: powershell run: | - # 如果 Chocolatey 不可用,则安装 Chocolatey if (!(Get-Command choco -ErrorAction SilentlyContinue)) { Set-ExecutionPolicy Bypass -Scope Process -Force [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) } - # 安装 zip choco install zip -y - name: 构建 s-ui @@ -114,19 +113,31 @@ jobs: run: | zip -r "s-ui-windows-${{ matrix.arch }}.zip" s-ui-windows - - name: 上传文件到构建产物 + - name: 上传构建产物 uses: actions/upload-artifact@v7 with: name: s-ui-windows-${{ matrix.arch }} path: ./s-ui-windows-${{ matrix.arch }}.zip - retention-days: 30 + retention-days: 1 - - name: 上传到 Release - uses: svenstaro/upload-release-action@v2 + publish-windows: + name: 发布 Windows 产物 + needs: build-windows + runs-on: ubuntu-latest + steps: + - name: 下载 Windows 构建产物 + uses: actions/download-artifact@v8 with: - repo_token: ${{ secrets.GITHUB_TOKEN }} - tag: ${{ inputs.tag }} - file: s-ui-windows-${{ matrix.arch }}.zip - asset_name: s-ui-windows-${{ matrix.arch }}.zip + pattern: s-ui-windows-* + path: release-assets + merge-multiple: true + + - name: 发布到当前仓库 Release + uses: softprops/action-gh-release@v3 + with: + tag_name: ${{ inputs.tag }} + name: S-UI ${{ inputs.tag }} + target_commitish: ${{ github.sha }} prerelease: true - overwrite: true + fail_on_unmatched_files: true + files: release-assets/* diff --git a/Dockerfile.frontend-artifact b/Dockerfile.frontend-artifact deleted file mode 100644 index e7395d0..0000000 --- a/Dockerfile.frontend-artifact +++ /dev/null @@ -1,43 +0,0 @@ -FROM golang:1.25-alpine AS backend-builder -WORKDIR /app -ARG TARGETARCH -ARG TARGETVARIANT -ENV CGO_ENABLED=1 -ENV CGO_CFLAGS="-D_LARGEFILE64_SOURCE" -ENV GOARCH=$TARGETARCH - -RUN apk update && apk add --no-cache \ - gcc \ - musl-dev \ - libc-dev \ - make \ - git \ - wget \ - unzip \ - bash \ - curl - -ENV CC=gcc - -RUN CRONET_ARCH="$TARGETARCH" && \ - CRONET_URL="https://github.com/SagerNet/cronet-go/releases/latest/download/libcronet-linux-${CRONET_ARCH}.so"; \ - echo "Downloading $CRONET_URL" && \ - wget -q -O ./libcronet.so "$CRONET_URL" && \ - chmod 755 ./libcronet.so - -COPY . . -COPY frontend_dist/ /app/web/html/ - -RUN if [ "$TARGETARCH" = "arm" ]; then export GOARM=7; [ "$TARGETVARIANT" = "v6" ] && export GOARM=6; fi; \ - go build -ldflags="-w -s" \ - -tags "with_quic,with_grpc,with_utls,with_acme,with_gvisor,with_naive_outbound,with_purego,with_tailscale" \ - -o sui main.go - -FROM alpine -LABEL org.opencontainers.image.authors="alireza7@gmail.com" -ENV TZ=Asia/Tehran -WORKDIR /app -RUN set -ex && apk add --no-cache --upgrade bash tzdata ca-certificates nftables -COPY --from=backend-builder /app/sui /app/libcronet.so /app/ -COPY entrypoint.sh /app/ -ENTRYPOINT [ "./entrypoint.sh" ] \ No newline at end of file diff --git a/README.md b/README.md index 1164b8b..691edb7 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,6 @@ | Windows | amd64, 386, arm64 | 支持 | | macOS | amd64, arm64 | 实验性支持 | -## 截图 - -!["主界面"](https://github.com/admin8800/s-ui-frontend/raw/main/media/main.png) - ## API 文档 [API 文档 Wiki](https://github.com/admin8800/s-ui/wiki/API-Documentation) @@ -125,7 +121,7 @@ docker run -itd \ -v $PWD/db/:/app/db/ \ -v $PWD/cert/:/root/cert/ \ --name s-ui --restart=unless-stopped \ - alireza7/s-ui:latest + ghcr.io/admin8800/s-ui:latest ``` > 自行构建镜像 diff --git a/docker-build-test.sh b/docker-build-test.sh index f761a1c..9337c16 100644 --- a/docker-build-test.sh +++ b/docker-build-test.sh @@ -1,29 +1,15 @@ -#!/usr/bin/env bash -# Test Docker multi-platform build (linux/amd64, 386, arm64, arm/v7, arm/v6) -# Requires: frontend_dist/ (run from repo root after building frontend) - -set -e -cd "$(dirname "$0")/.." - -echo "==> Preparing frontend_dist..." -if [ ! -d "frontend_dist" ] || [ -z "$(ls -A frontend_dist 2>/dev/null)" ]; then - echo "Building frontend..." - (cd frontend && npm install --prefer-offline --no-audit && npm run build) - rm -rf frontend_dist - mkdir -p frontend_dist - cp -R frontend/dist/* frontend_dist/ - echo "frontend_dist ready." -else - echo "frontend_dist exists, skipping frontend build." -fi - -PLATFORMS="linux/amd64,linux/386,linux/arm64/v8,linux/arm/v7,linux/arm/v6" -echo "==> Testing Docker build for: $PLATFORMS" -docker buildx build \ - --platform "$PLATFORMS" \ - -f Dockerfile.frontend-artifact \ - --build-arg CRONET_RELEASE=latest \ - --progress=plain \ - . 2>&1 | tee docker-build-test.log - -echo "==> Done. Check docker-build-test.log for full output." +#!/usr/bin/env bash +# 测试 Docker 多平台构建(linux/amd64、386、arm64、arm/v7、arm/v6) + +set -e +cd "$(dirname "$0")" + +PLATFORMS="linux/amd64,linux/386,linux/arm64/v8,linux/arm/v7,linux/arm/v6" +echo "==> 正在测试 Docker 构建平台:$PLATFORMS" +docker buildx build \ + --platform "$PLATFORMS" \ + -f Dockerfile \ + --progress=plain \ + . 2>&1 | tee docker-build-test.log + +echo "==> 完成。完整输出请查看 docker-build-test.log。" diff --git a/docker-compose.yml b/docker-compose.yml index a0fa863..4f1b9a1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: s-ui: - image: admin8800/s-ui + image: ghcr.io/admin8800/s-ui:latest container_name: s-ui hostname: "s-ui" volumes: @@ -14,4 +14,3 @@ services: networks: - s-ui entrypoint: "./entrypoint.sh" - \ No newline at end of file