跳转至

CI/CD流水线

KanjiIQ使用Forgejo Actions进行持续集成和部署。Forgejo Actions兼容GitHub Actions YAML语法,运行在自托管的运行器上。

工作流结构

.forgejo/workflows/
├── deploy-frontend.yml    # Build & deploy Flutter Web
├── deploy-backend.yml     # Build & deploy Dart Frog API
└── deploy-docs.yml        # Build & deploy documentation site

每个工作流遵循相同的模式:

graph TD
    A[Push to main] --> B{Path filter<br/>matches?}
    B -->|Yes| C[Checkout code]
    B -->|No| X[Skip]
    C --> D[Login to Forgejo<br/>Container Registry]
    D --> E[Docker build<br/>--no-cache]
    E --> F[Push :latest +<br/>:COMMIT_SHA]
    F --> G[kubectl set image]
    G --> H[Wait for rollout<br/>timeout: 5m]
    H --> I[Cleanup: logout]

前端工作流

name: Deploy Frontend to k3s

on:
  push:
    branches: [main]
    paths:
      - 'frontend/**'
      - 'Dockerfile.frontend'
      - 'nginx.frontend.conf'

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Login to registry
        run: echo "$FORGEJO_TOKEN" | docker login $REGISTRY_URL -u $REGISTRY_USER --password-stdin

      - name: Build image
        run: |
          docker build --no-cache --pull \
            --build-arg CACHEBUST=$(date +%s) \
            -f Dockerfile.frontend \
            -t <registry>/jlpt-kanji-frontend:latest \
            -t <registry>/jlpt-kanji-frontend:$(git rev-parse --short HEAD) .

      - name: Push & deploy
        run: |
          docker push <registry>/jlpt-kanji-frontend:latest
          docker push <registry>/jlpt-kanji-frontend:$(git rev-parse --short HEAD)
          kubectl set image deployment/jlpt-kanji \
            frontend=<registry>/jlpt-kanji-frontend:$(git rev-parse --short HEAD) \
            -n jlpt-kanji
          kubectl rollout status deployment/jlpt-kanji -n jlpt-kanji --timeout=5m

密钥

工作流使用一个密钥:

密钥 用途
FORGEJO_TOKEN 容器仓库推送和Kubernetes访问的认证凭据

该令牌在Forgejo的仓库设置 > 密钥中配置。

镜像仓库

所有镜像存储在Forgejo Container Registry中:

<registry>/jlpt-kanji-frontend:latest
<registry>/jlpt-kanji-frontend:<commit-sha>
<registry>/jlpt-kanji-backend:latest
<registry>/jlpt-kanji-backend:<commit-sha>
<registry>/jlpt-kanji-docs:latest
<registry>/jlpt-kanji-docs:<commit-sha>

滚动更新验证

执行kubectl set image后,工作流等待滚动更新完成:

kubectl rollout status deployment/jlpt-kanji -n jlpt-kanji --timeout=5m

此命令会阻塞直到:

  • 所有新Pod通过就绪探针,或者
  • 超时到期(工作流失败,通知开发者)

如果滚动更新失败,Kubernetes会自动停止发布,之前的版本继续提供服务。

手动回滚

要恢复到之前的版本:

# Rollback to previous revision
kubectl rollout undo deployment/jlpt-kanji -n jlpt-kanji

# Or roll back to a specific image
kubectl set image deployment/jlpt-kanji \
  frontend=<registry>/jlpt-kanji-frontend:<previous-sha> \
  -n jlpt-kanji