diff --git a/.github/workflows/docker-build-push.yml b/.github/workflows/docker-build-push.yml new file mode 100644 index 000000000000..b56e3cfefdc9 --- /dev/null +++ b/.github/workflows/docker-build-push.yml @@ -0,0 +1,238 @@ +# ============================================================================= +# GQ API Docker 镜像构建与推送工作流 +# ============================================================================= +# 功能说明: +# 当 gqapi_release 分支有新代码提交时,自动构建 Docker 镜像并推送到 Docker Hub +# 版本号从项目根目录的 VERSION 文件读取 +# +# 触发条件: +# 1. 推送代码到 gqapi_release 分支 +# 2. 手动触发(workflow_dispatch) +# +# 输出镜像: +# - {DOCKER_HUB_USERNAME}/gq-api:{version} (如 v0.13.2) +# - {DOCKER_HUB_USERNAME}/gq-api:latest +# +# 前置条件: +# 需要在 GitHub 仓库 Settings → Secrets and variables → Actions 中配置: +# - DOCKER_HUB_USERNAME: Docker Hub 用户名 +# - DOCKER_HUB_ACCESS_TOKEN: Docker Hub Access Token +# - SMTP_SERVER: SMTP 服务器地址(如 smtp.qq.com) +# - SMTP_PORT: SMTP 端口(如 465) +# - SMTP_USERNAME: SMTP 用户名(邮箱地址) +# - SMTP_PASSWORD: SMTP 密码/授权码 +# - NOTIFY_EMAIL: 接收通知的邮箱地址 +# ============================================================================= + +name: Build and Push Docker Image + +# ----------------------------------------------------------------------------- +# 触发条件配置 +# ----------------------------------------------------------------------------- +on: + # 当推送到 gqapi_release 分支时触发 + push: + branches: + - gqapi_release + # 允许在 GitHub Actions 页面手动触发 + workflow_dispatch: + +# ----------------------------------------------------------------------------- +# 任务定义 +# ----------------------------------------------------------------------------- +jobs: + # --------------------------------------------------------------------------- + # Job 1: 构建并推送 Docker 镜像 + # --------------------------------------------------------------------------- + build-and-push: + # 使用 Ubuntu 最新版本作为运行环境 + runs-on: ubuntu-latest + + # 指定使用 gq-api-dockerhub 环境的 secrets + environment: gq-api-dockerhub + + # 配置权限 + # - contents: read - 读取仓库代码 + # - packages: write - 推送镜像到容器仓库 + permissions: + contents: read + packages: write + + # 输出变量供后续任务使用 + outputs: + version: ${{ steps.version.outputs.version }} + + # ------------------------------------------------------------------------- + # 构建步骤 + # ------------------------------------------------------------------------- + steps: + # 步骤 1:检出代码 + # 从 GitHub 仓库拉取最新代码到工作目录 + - name: Checkout code + uses: actions/checkout@v4 + + # 步骤 2:读取版本号 + # 从项目根目录的 VERSION 文件读取版本号(如 v0.13.2) + # 输出变量:version - 用于后续步骤的镜像标签 + - name: Read version from VERSION file + id: version + run: | + VERSION=$(cat VERSION) + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Building version: $VERSION" + + # 步骤 3:调试 - 检查 Secrets 配置 + # 安全地检查 secrets 是否已配置(不打印实际值) + - name: Debug - Check Secrets + run: | + echo "=== Checking Docker Hub Secrets ===" + echo "DOCKER_HUB_USERNAME length: ${#DOCKER_HUB_USERNAME}" + if [ -n "$DOCKER_HUB_USERNAME" ]; then echo "DOCKER_HUB_USERNAME: SET"; else echo "DOCKER_HUB_USERNAME: NOT SET"; fi + echo "DOCKER_HUB_ACCESS_TOKEN length: ${#DOCKER_HUB_ACCESS_TOKEN}" + if [ -n "$DOCKER_HUB_ACCESS_TOKEN" ]; then echo "DOCKER_HUB_ACCESS_TOKEN: SET"; else echo "DOCKER_HUB_ACCESS_TOKEN: NOT SET"; fi + env: + DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }} + DOCKER_HUB_ACCESS_TOKEN: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + + # 步骤 4:设置 Docker Buildx + # Buildx 是 Docker 的扩展构建工具,支持多平台构建和缓存 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # 步骤 5:登录 Docker Hub + # 使用配置的 secrets 进行身份验证 + # secrets.DOCKER_HUB_USERNAME - Docker Hub 用户名 + # secrets.DOCKER_HUB_ACCESS_TOKEN - Docker Hub 访问令牌 + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_HUB_USERNAME }} + password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} + + # 步骤 6:构建并推送 Docker 镜像 + # - context: . 表示使用当前目录(Dockerfile 所在目录) + # - push: true 表示构建完成后自动推送到 Docker Hub + # - tags: 镜像标签,包含版本号标签和 latest 标签 + # - cache: 使用 GitHub Actions 缓存加速后续构建 + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: | + ${{ secrets.DOCKER_HUB_USERNAME }}/gq-api:${{ steps.version.outputs.version }} + ${{ secrets.DOCKER_HUB_USERNAME }}/gq-api:latest + # 启用 GitHub Actions 缓存,加速后续构建 + cache-from: type=gha + cache-to: type=gha,mode=max + + # 步骤 7:输出构建摘要 + # 在 GitHub Actions 运行页面显示构建结果信息 + - name: Summary + run: | + echo "### Docker Image Published" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "- **Version**: \`${{ steps.version.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY + echo "- **Tags**:" >> $GITHUB_STEP_SUMMARY + echo " - \`${{ secrets.DOCKER_HUB_USERNAME }}/gq-api:${{ steps.version.outputs.version }}\`" >> $GITHUB_STEP_SUMMARY + echo " - \`${{ secrets.DOCKER_HUB_USERNAME }}/gq-api:latest\`" >> $GITHUB_STEP_SUMMARY + + # --------------------------------------------------------------------------- + # Job 2: 构建后处理 - 发送邮件通知 + # --------------------------------------------------------------------------- + # always() 确保无论构建成功还是失败都会执行邮件通知 + post-build: + runs-on: ubuntu-latest + needs: build-and-push + if: always() + + # 指定使用 gq-api-dockerhub 环境的 secrets + environment: gq-api-dockerhub + + steps: + # 获取构建任务的状态 + - name: Get build status + id: status + run: | + if [ "${{ needs.build-and-push.result }}" == "success" ]; then + echo "status=成功 ✅" >> $GITHUB_OUTPUT + echo "color=#28a745" >> $GITHUB_OUTPUT + else + echo "status=失败 ❌" >> $GITHUB_OUTPUT + echo "color=#dc3545" >> $GITHUB_OUTPUT + fi + + # 发送邮件通知 + # 使用 dawidd6/action-send-mail 发送邮件 + - name: Send email notification + uses: dawidd6/action-send-mail@v3 + with: + # SMTP 服务器配置 + server_address: ${{ secrets.SMTP_SERVER }} + server_port: ${{ secrets.SMTP_PORT }} + # SMTP 认证信息 + username: ${{ secrets.SMTP_USERNAME }} + password: ${{ secrets.SMTP_PASSWORD }} + # 邮件内容 + subject: "GQ API Docker 构建通知 - ${{ steps.status.outputs.status }}" + to: ${{ secrets.NOTIFY_EMAIL }} + from: GQ API CI/CD + # 邮件正文(HTML 格式) + html_body: | + + + + + + + +
+
+

🚀 GQ API Docker 构建通知

+
+
+

构建状态:{{ steps.status.outputs.status }}

+ + + + + + + + + + + + + + + + + + + + + +
版本号${{ needs.build-and-push.outputs.version || 'N/A' }}
分支${{ github.ref_name }}
触发者${{ github.actor }}
提交信息${{ github.event.head_commit.message }}
构建时间${{ github.event.head_commit.timestamp }}
+

+ + 查看构建详情 + +

+
+ +
+ + diff --git a/.gitignore b/.gitignore index 2e5188f9d752..6cc2fb8f1b5e 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,8 @@ build *.db-journal logs web/dist +web/node_modules +VERSION .env one-api new-api diff --git a/Dockerfile b/Dockerfile index 93279163dba7..81a31f5fdabd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,6 +27,9 @@ RUN go build -ldflags "-s -w -X 'github.com/QuantumNous/new-api/common.Version=$ FROM debian:bookworm-slim@sha256:f06537653ac770703bc45b4b113475bd402f451e85223f0f2837acbf89ab020a +RUN sed -i 's|http://deb.debian.org|http://mirrors.aliyun.com|g' /etc/apt/sources.list.d/debian.sources 2>/dev/null || \ + sed -i 's|http://deb.debian.org|http://mirrors.aliyun.com|g' /etc/apt/sources.list 2>/dev/null || true + RUN apt-get update \ && apt-get install -y --no-install-recommends ca-certificates tzdata libasan8 wget \ && rm -rf /var/lib/apt/lists/* \ diff --git a/VERSION b/VERSION index e69de29bb2d1..73c11a9675fa 100644 --- a/VERSION +++ b/VERSION @@ -0,0 +1 @@ +v0.13.2 \ No newline at end of file diff --git a/common/constants.go b/common/constants.go index 274c514f9146..c5324c593cf7 100644 --- a/common/constants.go +++ b/common/constants.go @@ -12,7 +12,7 @@ import ( var StartTime = time.Now().Unix() // unit: second var Version = "v0.0.0" // this hard coding will be replaced automatically when building, no need to manually change -var SystemName = "New API" +var SystemName = "GQ API" var Footer = "" var Logo = "" var TopUpLink = "" diff --git a/electron/main.js b/electron/main.js index 210a4565852d..b6dea0d8d3cc 100644 --- a/electron/main.js +++ b/electron/main.js @@ -397,7 +397,7 @@ function createWindow() { nodeIntegration: false, contextIsolation: true }, - title: 'New API', + title: 'GQ API', icon: path.join(__dirname, 'icon.png') }); diff --git a/scripts/all-build-and-docker.ps1 b/scripts/all-build-and-docker.ps1 new file mode 100644 index 000000000000..dc3ac2d6afaf --- /dev/null +++ b/scripts/all-build-and-docker.ps1 @@ -0,0 +1,169 @@ +# GQ API - Build & Docker Script +# This script will: +# 1. Switch to gqapi_release branch and pull latest code +# 2. Build frontend (web folder) +# 3. Update version number +# 4. Build the Docker image +# 5. Push to Docker Hub (beyondandforever/gq-api) + +param( + [string]$dockerHubUsername = "gqapi", + [string]$imageName = "gq-api", + [string]$version = "v0.13.2", + [switch]$skipPush = $false, + [switch]$skipFrontendBuild = $false, + [switch]$skipGitPull = $false +) + +# Get the project root directory (parent of scripts folder) +$scriptPath = $PSScriptRoot +$projectRoot = Split-Path $scriptPath -Parent +$webRoot = Join-Path $projectRoot "web" + +# Function to generate version +function Get-NewVersion { + param( + [string]$projectRoot + ) + + $dateStr = Get-Date -Format "yyyyMMdd" + $shortHash = git -C $projectRoot rev-parse --short HEAD 2>$null + if (-not $shortHash) { + $shortHash = "local" + } + return "$dateStr-$shortHash" +} + +# Function to check if command exists +function Test-Command { + param([string]$command) + $null -ne (Get-Command $command -ErrorAction SilentlyContinue) +} + +# Function to run command and check exit code +function Invoke-BuildStep { + param( + [string]$stepName, + [scriptblock]$scriptBlock + ) + + Write-Host "`n>>> $stepName ..." -ForegroundColor Cyan + try { + & $scriptBlock + if ($LASTEXITCODE -ne 0 -and $LASTEXITCODE -ne $null) { + throw "Step failed with exit code: $LASTEXITCODE" + } + Write-Host "✓ $stepName completed" -ForegroundColor Green + } catch { + Write-Error "✗ $stepName failed: $_" + throw + } +} + +# Main script +try { + Write-Host "==========================================" -ForegroundColor Yellow + Write-Host "GQ API - Build & Docker Script" -ForegroundColor Yellow + Write-Host "==========================================" -ForegroundColor Yellow + Write-Host "Project root: $projectRoot" -ForegroundColor Gray + Write-Host "Web root: $webRoot" -ForegroundColor Gray + + # Change to project root directory + Set-Location $projectRoot + + # Step 1: Git operations (switch to release branch and pull) + if (-not $skipGitPull) { + Invoke-BuildStep "Git: Switch to gqapi_release branch" { + git checkout gqapi_release + } + + Invoke-BuildStep "Git: Pull latest code" { + git pull origin gqapi_release + } + } else { + Write-Host "`n>>> Skipping git operations (--skipGitPull)" -ForegroundColor Yellow + } + + # Step 2: Build frontend + if (-not $skipFrontendBuild) { + if (-not (Test-Path $webRoot)) { + throw "Web folder not found at: $webRoot" + } + + Set-Location $webRoot + + # Check if node_modules exists, if not run npm install + if (-not (Test-Path "node_modules")) { + Invoke-BuildStep "Frontend: Install dependencies" { + npm install + } + } + + Invoke-BuildStep "Frontend: Build production bundle" { + npm run build + } + + # Return to project root + Set-Location $projectRoot + } else { + Write-Host "`n>>> Skipping frontend build (--skipFrontendBuild)" -ForegroundColor Yellow + } + + # Step 3: Determine version + if ([string]::IsNullOrEmpty($version)) { + $version = Get-NewVersion -projectRoot $projectRoot + Write-Host "`n>>> Auto-generated version: $version" -ForegroundColor Cyan + } else { + Write-Host "`n>>> Using specified version: $version" -ForegroundColor Cyan + } + + # Step 4: Update VERSION file + Invoke-BuildStep "Update VERSION file" { + $versionFile = Join-Path $projectRoot "VERSION" + $version | Set-Content $versionFile -NoNewline + Write-Host " VERSION file updated: $version" + } + + # Step 5: Build Docker image + $imageTag = "${dockerHubUsername}/${imageName}:${version}" + $latestTag = "${dockerHubUsername}/${imageName}:latest" + + Invoke-BuildStep "Build Docker image" { + docker build -t $imageTag -t $latestTag . + Write-Host " Image tags:" + Write-Host " - $imageTag" + Write-Host " - $latestTag" + } + + # Step 6: Push to Docker Hub (optional) + if (-not $skipPush) { + Invoke-BuildStep "Push Docker image to Hub" { + docker push $imageTag + docker push $latestTag + Write-Host " Pushed: $imageTag" + Write-Host " Pushed: $latestTag" + } + + Write-Host "`n==========================================" -ForegroundColor Green + Write-Host "✓ All operations completed successfully!" -ForegroundColor Green + Write-Host "==========================================" -ForegroundColor Green + Write-Host "Version: $version" -ForegroundColor White + Write-Host "Docker image: $imageTag" -ForegroundColor White + Write-Host " Pull with: docker pull $imageTag" -ForegroundColor Gray + Write-Host "==========================================" -ForegroundColor Green + } else { + Write-Host "`n==========================================" -ForegroundColor Green + Write-Host "✓ Build completed (push skipped)" -ForegroundColor Green + Write-Host "==========================================" -ForegroundColor Green + Write-Host "Version: $version" -ForegroundColor White + Write-Host "Docker image: $imageTag" -ForegroundColor White + Write-Host " To push later: docker push $imageTag" -ForegroundColor Gray + Write-Host "==========================================" -ForegroundColor Green + } + +} catch { + Write-Host "`n==========================================" -ForegroundColor Red + Write-Error "Build failed: $_" + Write-Host "==========================================" -ForegroundColor Red + exit 1 +} \ No newline at end of file diff --git a/scripts/build-and-docker.ps1 b/scripts/build-and-docker.ps1 new file mode 100644 index 000000000000..f1f2b7ee0b5d --- /dev/null +++ b/scripts/build-and-docker.ps1 @@ -0,0 +1,98 @@ +# GQ API - Build & Docker Script +# This script will: +# 1. Update version number +# 2. Build the Docker image +# 3. Push to Docker Hub (beyondandforever/gq-api) + +param( + [string]$dockerHubUsername = "gqapi", + [string]$imageName = "gq-api", + [string]$version = "v0.13.2", + [switch]$skipPush = $false +) + +# Get the project root directory (parent of scripts folder) +$scriptPath = $PSScriptRoot +$projectRoot = Split-Path $scriptPath -Parent + +# Function to generate version +function Get-NewVersion { + param( + [string]$projectRoot + ) + + $versionFile = Join-Path $projectRoot "VERSION" + $dateStr = Get-Date -Format "yyyyMMdd" + $shortHash = git -C $projectRoot rev-parse --short HEAD 2>$null + if (-not $shortHash) { + $shortHash = "local" + } + return "$dateStr-$shortHash" +} + +# Main script +try { + Write-Host "==========================================" + Write-Host "GQ API - Build & Docker Script" + Write-Host "==========================================" + Write-Host "Project root: $projectRoot" + + # Change to project root directory + Set-Location $projectRoot + + # Determine version + if ([string]::IsNullOrEmpty($version)) { + $version = Get-NewVersion -projectRoot $projectRoot + } + + Write-Host "Version: $version" + + # Update VERSION file + $versionFile = Join-Path $projectRoot "VERSION" + $version | Set-Content $versionFile -NoNewline + Write-Host "Updated VERSION file" + + # Build Docker image + Write-Host "`nBuilding Docker image..." + $imageTag = "${dockerHubUsername}/${imageName}:${version}" + $latestTag = "${dockerHubUsername}/${imageName}:latest" + + docker build -t $imageTag -t $latestTag . + + if ($LASTEXITCODE -ne 0) { + Write-Error "Docker build failed!" + exit 1 + } + + Write-Host "`nDocker image built successfully!" + Write-Host " - $imageTag" + Write-Host " - $latestTag" + + if (-not $skipPush) { + # Push to Docker Hub + Write-Host "`nPushing to Docker Hub..." + docker push $imageTag + docker push $latestTag + + if ($LASTEXITCODE -ne 0) { + Write-Error "Docker push failed!" + exit 1 + } + + Write-Host "`n==========================================" + Write-Host "All operations completed successfully!" + Write-Host "Version: $version" + Write-Host "Docker image: $imageTag" + Write-Host "==========================================" + } else { + Write-Host "`n==========================================" + Write-Host "Build completed (skip push)" + Write-Host "Version: $version" + Write-Host "Docker image: $imageTag" + Write-Host "==========================================" + } + +} catch { + Write-Error "An error occurred: $_" + exit 1 +} diff --git a/web/index.html b/web/index.html index d6bd2433ea08..4ab828f0e097 100644 --- a/web/index.html +++ b/web/index.html @@ -16,7 +16,7 @@ content="A unified AI model hub for aggregation & distribution. It supports cross-converting various LLMs into OpenAI-compatible, Claude-compatible, or Gemini-compatible formats. A centralized gateway for personal and enterprise model management." /> - New API + GQ API diff --git a/web/public/favicon.ico b/web/public/favicon.ico index ab5f17bcdb35..dc79dfc9ce6b 100644 Binary files a/web/public/favicon.ico and b/web/public/favicon.ico differ diff --git a/web/public/logo.png b/web/public/logo.png index 851556f62db5..7dd169e25d2e 100644 Binary files a/web/public/logo.png and b/web/public/logo.png differ diff --git a/web/src/components/table/model-pricing/layout/header/SearchActions.jsx b/web/src/components/table/model-pricing/layout/header/SearchActions.jsx index e285d3fba348..6523a6298e4d 100644 --- a/web/src/components/table/model-pricing/layout/header/SearchActions.jsx +++ b/web/src/components/table/model-pricing/layout/header/SearchActions.jsx @@ -93,7 +93,7 @@ const SearchActions = memo( <> - {/* 充值价格显示开关 */} +{/* {supportsCurrencyDisplay && (
{t('充值价格显示')} @@ -104,7 +104,7 @@ const SearchActions = memo(
)} - {/* 货币单位选择 */} + {supportsCurrencyDisplay && showWithRecharge && (