# 微信小程序 Workflow 模板 适用于微信小程序的 CI/CD workflow,支持自动构建和上传体验版。 ## 适用场景 - 微信小程序项目 - 使用 miniprogram-ci 自动上传 - TypeScript 小程序项目 ## 环境要求 | 依赖 | Runner 要求 | |------|------------| | Node.js 18+ | Runner 主机已安装 | | miniprogram-ci | 动态安装 | ## 前置配置 ### 1. 获取小程序上传密钥 1. 登录 [微信公众平台](https://mp.weixin.qq.com/) 2. 进入 **开发管理** → **开发设置** 3. 下载 **代码上传密钥** ### 2. Base64 编码密钥 ```bash cat private.key | base64 -w 0 > private.key.base64 # 将内容复制到 MINIPROGRAM_PRIVATE_KEY secret ``` ### 3. 配置 IP 白名单 在微信公众平台添加 Runner 服务器的公网 IP 到白名单。 --- ## Workflow 骨架模板 ```yaml 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 参数说明 ```bash 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 自动前缀 ``` --- ## 缓存配置 ### 缓存路径 ```yaml path: | ~/.npm mini-program/node_modules ``` ### Key 计算 ```bash 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/`: ```bash # 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` 读取版本号: ```bash 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_PREFIX`、`SERVICE_DIR`、`APPID` 为实际值 3. 修改 `paths` 和 `tags` 触发条件 4. 根据项目需求填充 npm 包构建步骤 5. 配置 Secrets(上传密钥) 6. 在微信公众平台添加 IP 白名单 7. 推送代码触发 workflow --- ## 版本发布 ```bash # 创建并推送 tag git tag miniprogram-1.0.0 git push origin miniprogram-1.0.0 ```