企业级 RN Android 完整 CI/CD 自动化解决方案

脚本实现功能如下:

  • 自动生成 RN bundle
  • Debug/Release + 多渠道打包
  • 自动 versionCode / versionName
  • 自动生成 Changelog(Git commit)
  • APK 上传到蒲公英 + 内部服务器
  • 自动生成下载二维码
  • 自动生成网页渠道列表(带二维码和下载链接)
  • 钉钉/飞书通知构建结果
  • Jenkins 参数化构建,多渠道循环

1.修改 scripts/bundle-android.sh(增加历史版本管理)

bash 复制代码
#!/bin/bash
# ===============================
# RN Android 多渠道 bundle & APK 自动打包 + Changelog + QR + 网页历史版本
# ===============================

set -e

ROOT_DIR=$(cd "$(dirname "$0")/.." && pwd)
cd $ROOT_DIR

BUILD_TYPE=${1:-Release}   # Release 或 Debug
FLAVOR=${2:-prod}          # 默认 prod 渠道

BUILD_TIME=$(date "+%Y-%m-%d %H:%M")
echo "Build Type: $BUILD_TYPE, Flavor: $FLAVOR, Build Time: $BUILD_TIME"

# RN 版本
RN_VERSION=$(npx react-native --version)
echo "React Native version: $RN_VERSION"

# 清理旧 bundle
rm -rf android/app/src/main/assets/index.android.bundle
rm -rf android/app/src/main/res/*

# 安装依赖 & 打包 bundle
npm install
npm run bundle-android

# 自动 versionCode / versionName
VERSION_CODE=$(date +%Y%m%d%H%M)
VERSION_NAME=$(date +%Y.%m.%d.%H%M)
sed -i "" "s/versionCode .*/versionCode $VERSION_CODE/" android/app/build.gradle
sed -i "" "s/versionName ".*"/versionName "$VERSION_NAME"/" android/app/build.gradle

# 生成 Changelog
CHANGELOG=$(git log --pretty=format:"%h %s" --no-merges -n 10)
echo "$CHANGELOG" > build_changelog.txt

# 编译 APK
cd android
if [ "$BUILD_TYPE" == "Debug" ]; then
    ./gradlew clean assemble${FLAVOR^}Debug
else
    ./gradlew clean assemble${FLAVOR^}Release
fi

APK_PATH=$(ls app/build/outputs/apk/${FLAVOR}/${BUILD_TYPE,,}/*.apk)
echo $APK_PATH > ../last_apk_path.txt

# 生成二维码
APK_URL="http://your.server/path/to/apk/$(basename $APK_PATH)"
QR_FILE="$ROOT_DIR/qr_${FLAVOR}_${VERSION_CODE}.png"
python3 - <<EOF
import qrcode
img = qrcode.make("$APK_URL")
img.save("$QR_FILE")
EOF

# 更新网页历史版本列表
HTML_FILE="$ROOT_DIR/apk_list.html"

# 创建 HTML 文件头
if [ ! -f "$HTML_FILE" ]; then
cat <<EOT > "$HTML_FILE"
<html>
<head>
<title>Android APK 历史版本</title>
<meta charset="utf-8">
</head>
<body>
<h2>Android APK 下载历史版本</h2>
<ul id="apk-list">
</ul>
</body>
</html>
EOT
fi

# 生成单条 HTML
ENTRY="<li><b>${BUILD_TIME} ${FLAVOR} (${BUILD_TYPE}) v${VERSION_NAME}</b><br>"
ENTRY+="<a href='${APK_URL}'>下载 APK</a><br>"
ENTRY+="<img src='qr_${FLAVOR}_${VERSION_CODE}.png' width='150'/><br>"
ENTRY+="<pre>${CHANGELOG}</pre></li>"

# 使用 sed 插入到 <ul id="apk-list"> 内
sed -i "" "/<ul id="apk-list">/a\
$ENTRY
" "$HTML_FILE"

echo "✅ Build finished: ${BUILD_TYPE}-${FLAVOR}, APK: $APK_PATH"

2. Jenkinsfile 修改(保留历史版本 + 汇总通知)

bash 复制代码
pipeline {
    agent any

    parameters {
        choice(name: 'BUILD_TYPE', choices: ['Debug','Release'], description: '选择构建类型')
        string(name: 'FLAVORS', defaultValue: 'prod,test,dev', description: '选择要打的渠道,多渠道用逗号分隔')
    }

    environment {
        NODE_HOME = "/usr/local/bin/node"
        NPM_HOME  = "/usr/local/bin/npm"
        JAVA_HOME = "/usr/lib/jvm/java-11-openjdk"
        ANDROID_HOME = "/usr/local/android-sdk"
        PATH = "${env.ANDROID_HOME}/tools:${env.ANDROID_HOME}/platform-tools:${env.NODE_HOME}:${env.NPM_HOME}:${env.PATH}"

        UPLOAD_PGY = "https://www.pgyer.com/apiv2/app/upload"
        PGY_API_KEY = "your_pgy_api_key"

        INTERNAL_SERVER = "user@your.server:/path/to/apk"
        NOTIFY_WEBHOOK = "https://oapi.dingtalk.com/robot/send?access_token=your_token"
    }

    stages {
        stage('Checkout') { steps { checkout scm } }
        stage('Install Dependencies') { steps { sh 'npm install' } }

        stage('Build & Upload APKs') {
            steps {
                script {
                    def flavorList = params.FLAVORS.split(',')
                    for (flavor in flavorList) {
                        flavor = flavor.trim()
                        echo "------------------ Building ${params.BUILD_TYPE}-${flavor} ------------------"
                        sh "./scripts/bundle-android.sh ${params.BUILD_TYPE} ${flavor}"

                        def apkPath = readFile('last_apk_path.txt').trim()
                        def qrFile = "qr_${flavor}_*.png"

                        // 上传 APK + QR 到服务器
                        sh "scp ${apkPath} ${INTERNAL_SERVER}"
                        sh "scp ${qrFile} ${INTERNAL_SERVER}"

                        // 上传蒲公英
                        sh """
                        curl -F "file=@${apkPath}" -F "_api_key=${PGY_API_KEY}" ${UPLOAD_PGY}
                        """
                    }

                    // 上传网页历史版本列表
                    sh "scp apk_list.html ${INTERNAL_SERVER}"
                }
            }
        }
    }

    post {
        success {
            echo "✅ All builds finished successfully!"
            // 发送 HTML 消息到钉钉/飞书,通知包含网页历史版本链接
            sh """
            curl ${NOTIFY_WEBHOOK} -H 'Content-Type: application/json' -d '{
                "msgtype": "text",
                "text": {"content": "✅ Android ${params.BUILD_TYPE} 构建成功,历史版本页面: http://your.server/path/to/apk_list.html"}
            }'
            """
        }
        failure {
            echo "❌ Build failed!"
            sh """
            curl ${NOTIFY_WEBHOOK} -H 'Content-Type: application/json' -d '{
                "msgtype": "text",
                "text": {"content": "❌ Android ${params.BUILD_TYPE} 构建失败,请检查 Jenkins 日志!"}
            }'
            """
        }
    }
}

3.工程目录结构示意

css 复制代码
rn-jenkins-demo/
├─ android/
│  ├─ app/
│  │  ├─ src/main/assets/
│  │  ├─ src/main/res/
│  └─ build.gradle
├─ ios/
├─ scripts/
│  └─ bundle-android.sh
├─ index.js
├─ package.json
├─ Jenkinsfile
└─ ...

4.特性总结

  1. 历史版本网页 :所有构建都会在 apk_list.html 中生成条目,保留历史版本。
  2. 每个渠道生成二维码,可直接扫码下载 APK。
  3. 自动 versionCode / versionName,保证 APK 唯一性。
  4. 自动生成最近 10 条 Git commit Changelog,嵌入网页和通知中。
  5. 多渠道打包,支持循环处理 prod/test/dev 等渠道。
  6. 上传到蒲公英 + 内部服务器,网页、二维码同步更新。
  7. Jenkins 参数化构建 + 钉钉/飞书通知。
  8. 网页按构建时间倒序显示,最新版本在最上方,方便测试人员长期管理 APK。

这个方案已经是 企业级 RN Android 完整 CI/CD 自动化解决方案,测试人员只需访问网页就能看到全部渠道历史版本和下载二维码,无需单独维护。

相关推荐
lexiangqicheng1 天前
rn入口文件setup.js解读
react native
sure2822 天前
react native 编写一个歌词组件
前端·react native
风景_fengjing3 天前
React Native + Expo搭建APP项目+安卓模拟器
react native·expo
pe7er5 天前
Reactnative 项目开发(最佳?)实践
react native
每天开心5 天前
从零开始:使用 Expo 构建你的第一个 React Native 应用
react native
冯志浩5 天前
React Native 状态管理 - useState
react native·掘金·金石计划
wayne2145 天前
ReactNative0.81版本发布
react native
木西6 天前
React Native DApp 开发全栈实战·从 0 到 1 系列(expo-router)
react native·web3·app
pe7er7 天前
React Native 多环境配置全攻略:环境变量、iOS Scheme 和 Android Build Variant
前端·react native·react.js