Files
opencode/skill/gitea-workflow/wechat-miniprogram.md
2026-01-12 17:39:49 +08:00

11 KiB
Raw Blame History

微信小程序 Workflow 模板

适用于微信小程序的 CI/CD workflow支持自动构建和上传体验版。

适用场景

  • 微信小程序项目
  • 使用 miniprogram-ci 自动上传
  • TypeScript 小程序项目

环境要求

依赖 Runner 要求
Node.js 18+ Runner 主机已安装
miniprogram-ci 动态安装

前置配置

1. 获取小程序上传密钥

  1. 登录 微信公众平台
  2. 进入 开发管理开发设置
  3. 下载 代码上传密钥

2. Base64 编码密钥

cat private.key | base64 -w 0 > private.key.base64
# 将内容复制到 MINIPROGRAM_PRIVATE_KEY secret

3. 配置 IP 白名单

在微信公众平台添加 Runner 服务器的公网 IP 到白名单。


Workflow 骨架模板

name: Mini-Program - Build & Upload

on:
  push:
    paths:
      - 'mini-program/**'                   # 修改为实际目录
      - '.gitea/workflows/miniprogram.yml'
    tags:
      - 'miniprogram-*'                     # 修改为实际 tag 前缀

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

env:
  SERVICE_PREFIX: miniprogram               # 修改为实际服务名
  SERVICE_DIR: mini-program                 # 修改为实际目录名
  NPM_REGISTRY: https://registry.npmmirror.com
  APPID: wxYOUR_APPID_HERE                  # 修改为实际 AppID

jobs:
  build-and-upload:
    name: Build & Upload
    runs-on: darwin-arm64
    permissions:
      contents: read
    
    outputs:
      version: ${{ steps.vars.outputs.version }}
    
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Verify Node.js environment
        run: |
          node --version
          npm --version

      - name: Configure npm registry
        run: npm config set registry ${{ env.NPM_REGISTRY }}

      - name: Get npm-hashfiles
        id: hash-npm
        working-directory: ${{ env.SERVICE_DIR }}
        run: |
          HASH=$(sha256sum package.json package-lock.json 2>/dev/null | sha256sum | awk '{print $1}' | head -c 16)
          echo "hash=${HASH}" >> $GITHUB_OUTPUT

      - name: Cache npm modules
        uses: https://github.com/actions/cache@v3
        with:
          path: |
            ~/.npm
            ${{ env.SERVICE_DIR }}/node_modules
          key: npm-${{ env.SERVICE_PREFIX }}-${{ steps.hash-npm.outputs.hash }}
          restore-keys: npm-${{ env.SERVICE_PREFIX }}-

      - name: Set variables
        id: vars
        working-directory: ${{ env.SERVICE_DIR }}
        run: |
          version=$(node -p "require('./package.json').version")
          commit_title=$(git log -1 --pretty=format:"%s")
          git_tag=$(git describe --tags --abbrev=0 --always)
          
          {
            echo "version=${version}"
            echo "commit_title=${commit_title}"
            echo "git_tag=${git_tag}"
          } >> $GITHUB_ENV
          
          echo "version=${version}" >> $GITHUB_OUTPUT

      - name: Install dependencies
        working-directory: ${{ env.SERVICE_DIR }}
        run: npm ci

      - name: Build npm packages
        working-directory: ${{ env.SERVICE_DIR }}
        run: |
          npm install -g miniprogram-ci
          
          # ============================================
          # 用户自定义 npm 包构建(按项目需求修改)
          # ============================================
          # 小程序不支持直接使用 node_modules需要手动复制
          
          mkdir -p miniprogram_npm
          
          # 示例:复制 UI 组件库
          # if [ -d "node_modules/tdesign-miniprogram/miniprogram_dist" ]; then
          #   cp -r node_modules/tdesign-miniprogram/miniprogram_dist miniprogram_npm/tdesign-miniprogram
          # fi
          
          # 示例:复制工具库
          # for pkg in dayjs lodash; do
          #   [ -d "node_modules/$pkg" ] && cp -r "node_modules/$pkg" miniprogram_npm/
          # done
          
          echo "npm packages prepared"
          ls -la miniprogram_npm/ 2>/dev/null || echo "No npm packages"

      - name: TypeScript check
        working-directory: ${{ env.SERVICE_DIR }}
        run: |
          # ============================================
          # 用户自定义类型检查(按项目需求修改)
          # ============================================
          
          # 示例TypeScript 类型检查
          # npx tsc --noEmit --skipLibCheck || echo "TypeScript check completed with warnings"
          
          echo "Type check step (customize as needed)"

      - name: Setup private key
        working-directory: ${{ env.SERVICE_DIR }}
        env:
          MINIPROGRAM_PRIVATE_KEY: ${{ secrets.MINIPROGRAM_PRIVATE_KEY }}
        run: |
          if [ -n "$MINIPROGRAM_PRIVATE_KEY" ]; then
            echo "$MINIPROGRAM_PRIVATE_KEY" | base64 -d > private.key
            echo "Private key configured"
          else
            echo "WARNING: MINIPROGRAM_PRIVATE_KEY not set"
          fi

      - name: Upload to WeChat
        working-directory: ${{ env.SERVICE_DIR }}
        run: |
          [ ! -f "private.key" ] && { echo "Skip upload: no private key"; exit 0; }
          
          miniprogram-ci upload \
            --pp ./ \
            --pkp ./private.key \
            --appid ${{ env.APPID }} \
            --uv "${{ env.version }}" \
            --ud "${{ env.commit_title }}" \
            --robot 1 \
            -r 1 \
            --enable-es6 true \
            --enable-es7 true \
            --enable-minify true \
            --enable-minifyJS true \
            --enable-minifyWXML true \
            --enable-minifyWXSS true \
            --enable-autoPrefixWXSS true
          
          echo "Upload success: v${{ env.version }}"

      - name: Cleanup private key
        if: always()
        working-directory: ${{ env.SERVICE_DIR }}
        run: rm -f private.key

      - name: Create source package
        working-directory: ${{ env.SERVICE_DIR }}
        run: |
          mkdir -p ../dist
          tar --exclude='node_modules' \
              --exclude='.git' \
              --exclude='private.key' \
              -czf ../dist/${{ env.SERVICE_PREFIX }}-${{ env.version }}-source.tar.gz .

      - name: Upload artifact
        uses: actions/upload-artifact@v3
        with:
          name: ${{ env.SERVICE_PREFIX }}-source
          path: dist/${{ env.SERVICE_PREFIX }}-${{ env.version }}-source.tar.gz

      - name: Notify
        if: always()
        continue-on-error: true
        env:
          WEBHOOK_URL: ${{ vars.WEBHOOK_URL }}
        run: |
          status="${{ job.status }}"
          [ "$status" = "success" ] && status_text="Upload Success" || status_text="Upload Failed"
          
          curl -s -H "Content-Type: application/json" -X POST -d \
            "{\"msg_type\":\"text\",\"content\":{\"text\":\"Miniprogram ${status_text}\\nVersion: ${{ env.version }}\"}}" \
            "$WEBHOOK_URL" || true

  release:
    name: Create Release
    runs-on: darwin-arm64
    needs: build-and-upload
    if: startsWith(github.ref, 'refs/tags/')
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Download artifact
        uses: actions/download-artifact@v3
        with:
          name: ${{ env.SERVICE_PREFIX }}-source
          path: dist

      - name: Create Release
        env:
          GITEA_TOKEN: ${{ secrets.RELEASE_TOKEN }}
          VERSION: ${{ needs.build-and-upload.outputs.version }}
        run: |
          git_tag=$(git describe --tags --abbrev=0)
          api_url="${{ github.server_url }}/api/v1"
          repo="${{ github.repository }}"
          
          # 创建 Release
          release_id=$(curl -s -X POST \
            -H "Authorization: token $GITEA_TOKEN" \
            -H "Content-Type: application/json" \
            -d "{\"tag_name\":\"${git_tag}\",\"name\":\"Release ${git_tag} (v${VERSION})\"}" \
            "${api_url}/repos/${repo}/releases" | jq -r '.id')
          
          # 上传源码包
          curl -s -X POST \
            -H "Authorization: token $GITEA_TOKEN" \
            -F "attachment=@dist/${{ env.SERVICE_PREFIX }}-${VERSION}-source.tar.gz" \
            "${api_url}/repos/${repo}/releases/${release_id}/assets"

miniprogram-ci 参数说明

miniprogram-ci upload \
  --pp ./                       # 项目路径
  --pkp ./private.key           # 私钥路径
  --appid wx123456789           # 小程序 AppID
  --uv "1.0.0"                  # 版本号
  --ud "提交描述"                # 版本描述
  --robot 1                     # 机器人编号 (1-30)
  -r 1                          # 提交轮次
  --enable-es6 true             # ES6 转 ES5
  --enable-es7 true             # ES7 支持
  --enable-minify true          # 压缩代码
  --enable-minifyJS true        # 压缩 JS
  --enable-minifyWXML true      # 压缩 WXML
  --enable-minifyWXSS true      # 压缩 WXSS
  --enable-autoPrefixWXSS true  # CSS 自动前缀

缓存配置

缓存路径

path: |
  ~/.npm
  mini-program/node_modules

Key 计算

HASH=$(sha256sum package.json package-lock.json | sha256sum | awk '{print $1}' | head -c 16)

Secrets 配置

Secret 用途
MINIPROGRAM_PRIVATE_KEY Base64 编码的上传密钥
RELEASE_TOKEN Gitea API 令牌(创建 Release

npm 包处理

小程序不支持直接使用 node_modules,需要手动复制到 miniprogram_npm/

# UI 组件库(使用 miniprogram_dist 目录)
cp -r node_modules/tdesign-miniprogram/miniprogram_dist miniprogram_npm/tdesign-miniprogram
cp -r node_modules/vant-weapp/lib miniprogram_npm/vant-weapp

# 工具库(直接复制)
cp -r node_modules/dayjs miniprogram_npm/
cp -r node_modules/lodash miniprogram_npm/

版本管理

package.json 读取版本号:

version=$(node -p "require('./package.json').version")

体验版说明

  • 上传成功后自动成为体验版
  • 需要在微信后台手动提交审核发布正式版
  • --robot 参数可区分不同 CI 环境1-30

项目结构

mini-program/
├── pages/                    # 页面
├── components/               # 组件
├── miniprogram_npm/          # npm 包(构建生成)
├── app.ts                    # 应用入口
├── app.json                  # 应用配置
├── project.config.json       # 项目配置
├── package.json              # 依赖配置
└── tsconfig.json             # TypeScript 配置

使用步骤

  1. 复制上方 workflow 模板到 .gitea/workflows/miniprogram.yml
  2. 修改 SERVICE_PREFIXSERVICE_DIRAPPID 为实际值
  3. 修改 pathstags 触发条件
  4. 根据项目需求填充 npm 包构建步骤
  5. 配置 Secrets上传密钥
  6. 在微信公众平台添加 IP 白名单
  7. 推送代码触发 workflow

版本发布

# 创建并推送 tag
git tag miniprogram-1.0.0
git push origin miniprogram-1.0.0