Compare commits

..

5 Commits

Author SHA1 Message Date
xiaoxia 1a5bb1ab43 feat(ci): optimize web image build with multi-stage Dockerfile + buildx cache
Tests / test (pull_request) Failing after 0s
Tests / lint (pull_request) Failing after 0s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 1m59s
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Successful in 2m12s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
2026-07-13 15:11:28 +08:00
xiaoxia bf47e69fa4 feat(ci): add node_modules cache for frontend-lint job 2026-07-13 15:10:44 +08:00
xiaoxia b947bf7569 feat(ci): add node_modules cache for frontend-lint job 2026-07-13 15:09:47 +08:00
xiaoxia f110bc6f16 feat: web.Dockerfile add buildkit cache for npm install 2026-07-13 15:08:49 +08:00
xiaoxia 0c9375ff32 ci: remove temporary debug workflow - test-ssh-secret.yml
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 36s
CI/CD Pipeline / Frontend Lint (push) Failing after 0s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (push) Has been skipped
CI/CD Pipeline / Staging E2E Tests (push) Has been skipped
CI/CD Pipeline / Deploy Production (push) Has been skipped
CI/CD Pipeline / Production Browser E2E (push) Has been skipped
Fix Flake8 E741 for PR232 / fix-flake8 (push) Failing after 3h4m59s
2026-07-12 10:25:12 +08:00
5 changed files with 23 additions and 176 deletions
+11
View File
@@ -192,6 +192,7 @@ jobs:
frontend-lint:
name: Frontend Lint
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- name: Checkout code
@@ -217,7 +218,17 @@ jobs:
tar -xzf /tmp/repo.tar.gz --strip-components=1 -C .
rm -f /tmp/repo.tar.gz
- name: Cache node_modules
id: cache-node-modules
uses: actions/cache@v4
with:
path: apps/web/node_modules
key: ${{ runner.os }}-node-web-${{ hashFiles('apps/web/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-web-
- name: Install dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
shell: sh
run: |
set -eu
-94
View File
@@ -1,94 +0,0 @@
name: Fix Runner Labels (Background)
on:
push:
branches:
- ci/runner-label-fix
jobs:
fix:
runs-on: saas
steps:
- name: 后台执行runner标签修复(不阻塞当前job)
run: |
cat > /tmp/fix_runner_labels.sh << 'EOF'
#!/bin/bash
set -e
CI_DIR="/var/lib/xiaoxia-ci"
ACT_BIN="$CI_DIR/act_runner"
GITEA_URL="https://git.xiaoxiajianji.com"
LABELS="saas,runtime-builder,host,ubuntu-latest"
# 重新获取registration token
REG_TOKEN=$(curl -sk -X POST \
-H "Authorization: token 1f8058d097e3942a9ed31c44382baf7f08311272" \
"$GITEA_URL/api/v1/repos/xiaoxia/xiaoxia-saas/actions/runners/registration-token" \
| python3 -c "import sys,json; print(json.load(sys.stdin)['token'])")
echo "Got reg token: ${REG_TOKEN:0:10}..."
# 修复 runner-1(主runner
echo "Fixing main runner..."
systemctl stop act_runner.service
sleep 2
cd "$CI_DIR"
rm -f .runner
$ACT_BIN register --instance "$GITEA_URL" --token "$REG_TOKEN" \
--name "xiaoxia-ci-runner" --labels "$LABELS" --no-interactive
systemctl start act_runner.service
echo "Main runner done"
# 修复 runner-2
echo "Fixing runner-2..."
systemctl stop act_runner-2.service
sleep 2
cd "$CI_DIR/runner-2"
rm -f .runner
$ACT_BIN register --instance "$GITEA_URL" --token "$REG_TOKEN" \
--name "xiaoxia-ci-runner-2" --labels "$LABELS" --no-interactive
systemctl start act_runner-2.service
echo "Runner-2 done"
# 修复 runner-3
echo "Fixing runner-3..."
systemctl stop act_runner-3.service
sleep 2
cd "$CI_DIR/runner-3"
rm -f .runner
$ACT_BIN register --instance "$GITEA_URL" --token "$REG_TOKEN" \
--name "xiaoxia-ci-runner-3" --labels "$LABELS" --no-interactive
systemctl start act_runner-3.service
echo "Runner-3 done"
sleep 15
# 验证
echo "=== Final verification ==="
curl -sk -H "Authorization: token 1f8058d097e3942a9ed31c44382baf7f08311272" \
"$GITEA_URL/api/v1/repos/xiaoxia/xiaoxia-saas/actions/runners?limit=50" \
| python3 -c "
import sys, json
data = json.load(sys.stdin)
online = [r for r in data.get('runners', []) if r['status'] == 'online']
print(f'Online runners: {len(online)}')
for r in online:
labels = [l['name'] for l in r['labels']]
print(f' ✅ {r[\"name\"]}: {labels}')
"
echo "ALL DONE" > /tmp/runner_fix_done.txt
EOF
chmod +x /tmp/fix_runner_labels.sh
nohup /tmp/fix_runner_labels.sh > /tmp/runner_fix.log 2>&1 &
echo "后台修复脚本已启动,PID: $!"
echo "30秒后检查结果..."
sleep 30
if [ -f /tmp/runner_fix_done.txt ]; then
echo "✅ 修复完成"
cat /tmp/runner_fix.log | grep -E "(Online|✅|done|ALL DONE)"
else
echo "⏳ 还在运行,继续等..."
sleep 30
cat /tmp/runner_fix.log | tail -30
fi
-69
View File
@@ -1,69 +0,0 @@
name: Test SSH Secret
on:
push:
branches: [develop]
paths:
- '.gitea/workflows/test-ssh-secret.yml'
jobs:
test-ssh:
runs-on: ubuntu-22.04
steps:
- name: Install SSH client
run: |
which ssh || (apt-get update && apt-get install -y openssh-client)
ssh -V
- name: Debug environment
run: |
echo "=== Environment ==="
echo "Runner hostname: $(hostname)"
echo "Runner IP: $(hostname -i || echo 'unknown')"
echo "Current user: $(whoami)"
echo "=== Secrets check ==="
if [ -n "$STAGING_SSH_HOST" ]; then
echo "STAGING_SSH_HOST: [SET] value_length=${#STAGING_SSH_HOST}"
else
echo "STAGING_SSH_HOST: [EMPTY]"
fi
if [ -n "$STAGING_SSH_USER" ]; then
echo "STAGING_SSH_USER: [SET] value_length=${#STAGING_SSH_USER}"
else
echo "STAGING_SSH_USER: [EMPTY]"
fi
if [ -n "$STAGING_SSH_KEY" ]; then
echo "STAGING_SSH_KEY: [SET] value_length=${#STAGING_SSH_KEY}"
else
echo "STAGING_SSH_KEY: [EMPTY]"
fi
env:
STAGING_SSH_HOST: ${{ secrets.STAGING_SSH_HOST }}
STAGING_SSH_USER: ${{ secrets.STAGING_SSH_USER }}
STAGING_SSH_KEY: ${{ secrets.STAGING_SSH_KEY }}
- name: Setup SSH key
run: |
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "$STAGING_SSH_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh-keygen -y -f ~/.ssh/id_ed25519 > ~/.ssh/id_ed25519.pub 2>/dev/null || echo "No public key generated"
echo "=== SSH Key fingerprint ==="
ssh-keygen -lf ~/.ssh/id_ed25519 || echo "Key fingerprint failed"
env:
STAGING_SSH_KEY: ${{ secrets.STAGING_SSH_KEY }}
- name: Test SSH connection
run: |
echo "Attempting SSH connection to $STAGING_SSH_HOST..."
ssh -i ~/.ssh/id_ed25519 \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-o ConnectTimeout=10 \
-o BatchMode=yes \
-v \
$STAGING_SSH_USER@$STAGING_SSH_HOST "echo 'SSH_CONNECTION_SUCCESS' && hostname && whoami"
echo "=== SSH Test Complete ==="
env:
STAGING_SSH_HOST: ${{ secrets.STAGING_SSH_HOST }}
STAGING_SSH_USER: ${{ secrets.STAGING_SSH_USER }}
+3 -1
View File
@@ -5,7 +5,9 @@ ARG VITE_API_URL=https://saas-api.xiaoxiajianji.com
ENV VITE_API_URL=$VITE_API_URL
COPY apps/web/package.json apps/web/package-lock.json ./apps/web/
WORKDIR /app/apps/web
RUN npm config set registry https://registry.npmmirror.com \
RUN \
--mount=type=cache,target=/root/.npm \
npm config set registry https://registry.npmmirror.com \
&& npm ci
COPY apps/web/ ./
RUN npm run build
+9 -12
View File
@@ -72,28 +72,25 @@ else
fi
echo "=== Building Web image (with buildx cache) ==="
# 先构建前端产物
docker run --rm \
-v "$PWD:/workspace" \
-w /workspace/apps/web \
docker.m.daocloud.io/library/node:20 \
sh -lc "npm ci && npm run build"
test -f apps/web/dist/index.html
# 使用多阶段 Dockerfile 构建,配合 buildx cache 缓存 npm 安装和构建产物
WEB_NGINX_CONF="${WEB_NGINX_CONF:-infra/docker/nginx-production.conf}"
WEB_API_URL="${VITE_API_URL:-https://saas-api.xiaoxiajianji.com}"
if [ "$USE_CACHE" -eq 1 ]; then
docker buildx build \
--cache-from "type=registry,ref=${CACHE_REGISTRY}/web-cache:${CACHE_TAG},ignore-error=true" \
--cache-to "type=registry,ref=${CACHE_REGISTRY}/web-cache:${CACHE_TAG},mode=max" \
-f infra/docker/web-artifact.Dockerfile \
--build-arg NGINX_CONF=infra/docker/nginx-production.conf \
-f infra/docker/web.Dockerfile \
--build-arg NGINX_CONF="${WEB_NGINX_CONF}" \
--build-arg VITE_API_URL="${WEB_API_URL}" \
-t "$WEB_IMAGE" \
--load \
.
else
docker build --pull=false \
-f infra/docker/web-artifact.Dockerfile \
--build-arg NGINX_CONF=infra/docker/nginx-production.conf \
-f infra/docker/web.Dockerfile \
--build-arg NGINX_CONF="${WEB_NGINX_CONF}" \
--build-arg VITE_API_URL="${WEB_API_URL}" \
-t "$WEB_IMAGE" \
.
fi