Android配置GitLab CI/CD持续集成,Shell版本的gitlab-runner,FastLane执行,上传蒲公英

news2024/12/24 20:47:37

mac环境下,

首选需要安装gitlab-runner和fastlane

brew install gitlab-runner

brew install fastlane

安装完成,来到我们在gitlab下新建的Android项目,我们开始创建gitlab-runner

1、创建runner

点开runner,点击新建runner

选择macos,自定义一个标签,把运行未打标签的作业也够选上,点击创建runner

然后来到这个页面,开始在终端挨个执行命令

执行命令,一定要选择shell,可以看到这时候就创建runner成功了

testrunner就是这个runner的名字

gitlab-runner list  

执行这个命令可以看到电脑上所有的runner

gitlab-runner status  可以查看gitlab-runner的状态

如果状态不在线,可以调用gitlab-runner  install 命令  再调用gitlab-runner  start

2、fastlane

cd到项目跟目录下,使用fastlane init

根目录下就会创建fastlane文件夹

我们要写的代码都在Fastfile中

# This file contains the fastlane.tools configuration
# You can find the documentation at https://docs.fastlane.tools
#
# For a list of all available actions, check out
#
#     https://docs.fastlane.tools/actions
#
# For a list of all available plugins, check out
#
#     https://docs.fastlane.tools/plugins/available-plugins
#

# Uncomment the line if you want fastlane to automatically update itself
# update_fastlane

default_platform(:android)
APK_TIME = Time.now.strftime("%Y%m%d")
app_versionName  = "1.0.0"


BUILD_NAME = ""
# OUTPUT_NAME_PATCH = "#{BUILD_NAME}_#{PLIST_INFO_VERSION}_#{APK_TIME}"
platform :android do
  desc "给测试用单渠道cnrmall_official的包"
  puts "APK_TIME=== #{APK_TIME}"
  channel = "cnrmall_official"
  lane :debug_cnrmall_official do
  BUILD_NAME = "android_Debug_#{channel}"
      gradle(
        task: "clean assemble#{channel}",
        build_type: "Debug"
      )
     mk_cp_apk
     pgyer_upload(channel: "#{channel}")
  end

#debug全渠道包
lane :debug do
  channel = "cnrmall_official"
  BUILD_NAME = "android_Debug"
      gradle(
        task: "clean assemble",
        build_type: "Debug"
      )
     pgyer_upload(channel: "#{channel}")
  end

#release全渠道包
  lane :release do
    channel = "cnrmall_official"
  BUILD_NAME = "android_Release"
      gradle(
        task: "clean assemble",
        build_type: "Release"
      )
     pgyer_upload(channel: "#{channel}")
  end

# 执行创建文件夹 copy apk 到最外面目录
lane :mk_cp_apk do
  puts "mk out_apk cp apk"
  gradle(task: "customBuild")
    end

lane :get_version do
  puts "Update Android version in build.gradle"
  app_version = gradle(task: "getVersionName")
      # 获取版本号
#       puts "app_version:#{versionCode}"
    end

  desc "Submit a new Beta Build to Crashlytics Beta"
  lane :beta do
    gradle(task: "clean assembleRelease")
    crashlytics

    # sh "your_script.sh"
    # You can also use other beta testing services here
  end

  desc "Deploy a new version to the Google Play"
  lane :deploy do
    gradle(task: "clean assembleRelease")
    upload_to_play_store
  end


  #
   #上传蒲公英

     lane :pgyer_upload do |option|
     sh 'ls'
     pyg_get_channel = option[:channel]
     puts "上传蒲公英channel= #{pyg_get_channel}"
#      ENV['outPutPath'] = '../app/build/outputs/apk/'+"#{pyg_get_channel}"+"/debug/cnrmall_"+"#{APK_TIME}"+"_"+"#{app_versionName}"+"_"+"#{pyg_get_channel}"+".apk"

     ENV['outPutPath'] = '../out_apk/cnrmall_'+"#{APK_TIME}"+"_"+"#{app_versionName}"+"_"+"#{pyg_get_channel}"+".apk"

     puts "outPutPath路径- #{ENV['outPutPath']}"
#      ENV['outPutPath'] = '../app/build/outputs/apk/option/debug/cnrmall_#{APK_TIME}_1.0.0_cnrmall_official.apk'
#      sh "open ../app/build/outputs/apk/debug/"
     sh "./pgyer_upload.sh  -k 4df7384110457be3f5bce0c391ef1cd3  #{ENV['outPutPath']} "
  end


end

上传蒲公英脚本

#!/bin/bash
#
# 通过shell脚本来实现将本地app文件通过API上传到蒲公英
# https://www.pgyer.com/doc/view/api#fastUploadApp
#

# Display log. 1=enable, 0=disable
LOG_ENABLE=1

printHelp() {
    echo "Usage: $0 -k <api_key> [OPTION]... file"
    echo "Upload iOS or Android app package file to PGYER."
    echo "Example: $0 -k xxxxxxxxxxxxxxx /data/app.apk"
    echo ""
    echo "Description:"
    echo "  -k api_key                       (required) api key from PGYER"
    echo "  -t buildInstallType              build install type, 1=public, 2=password, 3=invite"
    echo "  -p buildPassword                 build password, required if buildInstallType=2"
    echo "  -d buildUpdateDescription        build update description"
    echo "  -e buildInstallDate              build install date, 1=buildInstallStartDate~buildInstallEndDate, 2=forever"
    echo "  -s buildInstallStartDate         build install start date, format: yyyy-MM-dd"
    echo "  -e buildInstallEndDate           build install end date, format: yyyy-MM-dd"
    echo "  -c buildChannelShortcut          build channel shortcut"
    echo "  -h help                          show this help"
    echo ""
    echo "Report bugs to: <https://github.com/PGYER/pgyer_api_example/issues>" 
    echo "Project home page: <https://github.com/PGYER/pgyer_api_example>" 
    exit 1
}

while getopts 'k:t:p:d:s:e:c:h' OPT; do
    case $OPT in
        k) api_key="$OPTARG";;
        t) buildInstallType="$OPTARG";;
        p) buildPassword="$OPTARG";;
        d) buildUpdateDescription="$OPTARG";;
        e) buildInstallDate="$OPTARG";;
        s) buildInstallStartDate="$OPTARG";;
        e) buildInstallEndDate="$OPTARG";;
        c) buildChannelShortcut="$OPTARG";;
        ?) printHelp;;
    esac
done

shift $(($OPTIND - 1))
readonly file=$1

# check api_key exists
if [ -z "$api_key" ]; then
    echo "api_key is empty"
    printHelp
fi

# check file exists
if [ ! -f "$file" ]; then
    echo "file not exists"
    printHelp
fi

# check ext supported
buildType=${file##*.}
if [ "$buildType" != "" ] && [ "$buildType" != "apk" ]; then
    echo "file ext is not supported"
    printHelp
fi

# ---------------------------------------------------------------
# functions
# ---------------------------------------------------------------

log() {
    [ $LOG_ENABLE -eq 1 ]  && echo "[$(date +'%Y-%m-%d %H:%M:%S')] $*"
}

logTitle() {
    log "-------------------------------- $* --------------------------------"
}

execCommand() {
    log "$@"
    result=$(eval $@)
}

# ---------------------------------------------------------------
# 获取上传凭证
# ---------------------------------------------------------------

logTitle "获取凭证"

command="curl -s"
[ -n "$api_key" ]                && command="${command} --form-string '_api_key=${api_key}'";
[ -n "$buildType" ]              && command="${command} --form-string 'buildType=${buildType}'";
[ -n "$buildInstallType" ]       && command="${command} --form-string 'buildInstallType=${buildInstallType}'";
[ -n "$buildPassword" ]          && command="${command} --form-string 'buildPassword=${buildPassword}'";
[ -n "$buildUpdateDescription" ] && command="${command} --form-string $'buildUpdateDescription=${buildUpdateDescription}'";
[ -n "$buildInstallDate" ]       && command="${command} --form-string 'buildInstallDate=${buildInstallDate}'";
[ -n "$buildInstallStartDate" ]  && command="${command} --form-string 'buildInstallStartDate=${buildInstallStartDate}'";
[ -n "$buildInstallEndDate" ]    && command="${command} --form-string 'buildInstallEndDate=${buildInstallEndDate}'";
[ -n "$buildChannelShortcut" ]   && command="${command} --form-string 'buildChannelShortcut=${buildChannelShortcut}'";
command="${command} http://www.pgyer.com/apiv2/app/getCOSToken";
execCommand $command

[[ "${result}" =~ \"endpoint\":\"([\:\_\.\/\\A-Za-z0-9\-]+)\" ]] && endpoint=`echo ${BASH_REMATCH[1]} | sed 's!\\\/!/!g'`
[[ "${result}" =~ \"key\":\"([\.a-z0-9]+)\" ]] && key=`echo ${BASH_REMATCH[1]}`
[[ "${result}" =~ \"signature\":\"([\=\&\_\;A-Za-z0-9\-]+)\" ]] && signature=`echo ${BASH_REMATCH[1]}`
[[ "${result}" =~ \"x-cos-security-token\":\"([\_A-Za-z0-9\-]+)\" ]] && x_cos_security_token=`echo ${BASH_REMATCH[1]}`

if [ -z "$key" ] || [ -z "$signature" ] || [ -z "$x_cos_security_token" ] || [ -z "$endpoint" ]; then
    log "get upload token failed"
    exit 1
fi

# ---------------------------------------------------------------
# 上传文件
# ---------------------------------------------------------------

logTitle "上传文件"

file_name=${file##*/}

execCommand "curl --progress-bar -o /dev/null -w '%{http_code}' \
--form-string 'key=${key}' \
--form-string 'signature=${signature}' \
--form-string 'x-cos-security-token=${x_cos_security_token}' \
--form-string 'x-cos-meta-file-name=${file_name}' \
-F 'file=@${file}' ${endpoint}"
if [ $result -ne 204 ]; then # if http code != 204, upload failed
    log "Upload failed"
    exit 1
fi

# ---------------------------------------------------------------
# 检查结果
# ---------------------------------------------------------------

logTitle "检查结果"

# 获取 .apk 文件所在的目录
Directory=$(dirname "$file")

echo "获取 .apk 文件所在的目录 $Directory"

jsonFilePath="$Directory/result.json"
qrCodeFilePath="$Directory/qr_code.png"



for i in {1..60}; do
    execCommand "curl -s http://www.pgyer.com/apiv2/app/buildInfo?_api_key=${api_key}\&buildKey=${key}"
    [[ "${result}" =~ \"code\":([0-9]+) ]] && code=`echo ${BASH_REMATCH[1]}`
    if [ $code -eq 0 ]; then
       echo $result

       echo $result > "$jsonFilePath"  # 将 JSON 保存到文件

        # 提取 buildQRCodeURL 的值
#        qrCodeURL=$(jq -r '.data.buildQRCodeURL' <<< "$result")
      qrCodeURL=$(echo "$result" | grep -o '"buildQRCodeURL":"[^"]*' | cut -d '"' -f 4 | sed 's/\\//g')
               # 使用 curl 下载并保存 QR Code 文件
      echo "Downloading QR Code from: $qrCodeURL"
         #         curl -s "$qrCodeURL" -o "$qrCodeFilePath"
      curl --location-trusted -o "$qrCodeFilePath" "$qrCodeURL"

      echo "curl Result: $curlResult"
      break

    else
        sleep 1
    fi
done

.gitlab-ci.yml,只需要写上执行哪个fastlane即可 ,debug_cnrmall_official是fastlane名字

在Android studio中的Terminal中,也可以使用命令去执行某一个fastlane

如:fastlane lane:debug_cnrmall_official

stages:
  - build

job:
  stage: build
  script:
    - echo "开始打包4"
    - ls -a
    # - ./build.sh
    - fastlane debug_cnrmall_official

  artifacts:
    paths:
      - out_apk/*

项目跟目录的build.gradle文件中,还自定义了一个task

因为Android默认打包完的apk位置太深了,所以把它复制到外面一点,方便测试拿到

cnrmallshop_ci_2.0是项目名 out_apk是创建的文件夹
task customBuild(type: Exec) {
    def date = new SimpleDateFormat("yyyyMMdd").format(new Date())
    def versionName = rootProject.android.versionName
    commandLine 'sh','-c','mkdir -p ../cnrmallshop_ci_2.0/out_apk && cp app/build/outputs/apk/cnrmall_official/debug/cnrmall_'+date+'_'+versionName+'_cnrmall_official.apk ../cnrmallshop_ci_2.0/out_apk/cnrmall_'+date+'_'+versionName+'_cnrmall_official.apk'
}

最后可以在流水线上中看到构建成功的流水线,可以点击下载按钮下载产物

​​​​​​​

产物中有apk有二维码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1431893.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

map容器的基本概念及常用成员函数

map&#xff08;字典&#xff09;的基本概念 map是一个将一个值映射到另一个值的一种数据结构。&#xff08;即两个值之间有一一对应关系&#xff09;。 map的所有元素都是pair类型&#xff0c;pair中的第一个元素称为键值&#xff08;key&#xff09;第二个元素称为实值&…

Vue工程引入Element-ui

npm 安装ELement-ui npm i element-ui -S 于package.json中发现有“element-ui”版本号即可 引入 Element 在 main.js 中写入以下内容&#xff1a; import element-ui/lib/theme-chalk/index.css; import ElementUI from element-ui;Vue.use(ElementUI);之后根据自己的需求设计…

【Apache POI库读取Excel文件,并使用HashMap来存储和检查重复项】

目录 下面是一个示例代码,使用Apache POI库读取Excel文件,并使用HashMap来存储和检查重复项。 import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook;import java.io.FileInputStream; import java.io.IOException; import java.util.…

Web html

目录 1 前言2 HTML2.1 元素(Element)2.1.1 块级元素和内联(行级)元素2.1.2 空元素 2.2 html页面的文档结构2.3 常见标签使用2.3.1 注释2.3.2 标题2.3.3 段落2.3.4 列表2.3.5 超链接2.3.6 图片2.3.7 内联(行级)标签2.3.8 换行 2.4 属性2.4.1 布尔属性 2.5 实体引用2.6 空格2.7 D…

python_ACM模式《剑指offer刷题》二叉树1

题目&#xff1a; 面试tips&#xff1a; 1. 询问是否可以使用双端队列 (看后面思路就可知为什么要问这个) 思路&#xff1a; 时复和空复都为O(n) 思路一&#xff1a;利用双端队列。总体思想是利用二叉树层序遍历(二叉树的层序遍历就是用队列dq&#xff0c;且从左往右每一层…

java高级开发 章节练习题(选择、填空、判断)

第九章 常用实用类 一. 单选题 1. (单选题)String类的equals方法&#xff0c;其作用是&#xff1a; A. 比较2个字符串对象是否为同一个对象B. 比较2个字符串对象的字符长度是否相同C. 比较2个字符串对象的首地址是否相同D. 比较2个字符串对象的字符序列是否相同 答案: D:比…

HBase 数据导入导出

HBase 数据导入导出 1. 使用 Docker 部署 HBase2. HBase 命令查找3. 命令行操作 HBase3.1 HBase shell 命令3.2 查看命名空间3.3 查看命名空间下的表3.4 新建命名空间3.5 查看具体表结构3.6 创建表 4. HBase 数据导出、导入4.1 导出 HBase 中的某个表数据4.2 导入 HBase 中的某…

2V2无人机红蓝对抗仿真

两架红方和蓝方无人机分别从不同位置起飞&#xff0c;蓝方无人机跟踪及击毁红方无人机 2020a可正常运行 2V2无人机红蓝对抗仿真资源-CSDN文库

css1字体属性

一.font-family(字体系列&#xff09; 不同字体系统用&#xff0c;隔开&#xff1b; 多个字母的字体系统用“”&#xff1b; 二.font-size&#xff08;字体大小&#xff09;&#xff08;有单位px&#xff09;&#xff08;默认字体16px&#xff09; 三.font-weight&#xff08…

大数据信用报告在线查询平台哪个好?

随着大数据技术在金融风控的运用&#xff0c;大数据信用越来越被人熟知&#xff0c;由于线下没有查询大数据信用的地方&#xff0c;想要查询大数据信用报告只有在线上查询&#xff0c;那大数据信用报告在线查询平台哪个好呢?本文贷你一起去了解市面上比较好的三个平台。 大数据…

Unity 渲染管线自动转换的实现 支持HDRP转URP,URP转HDRP

HDRP和URP无法平滑切换&#xff0c;因为属性、功能差异巨大。 本脚本仅对可对应的默认脚本和属性做了转换处理。细节调整还需自己搞。 自动转换可以节省手动更换shader、texture、通用属性的劳动成本。 操作步骤 使用前确保当前项目中存在HDRP和URP的包&#xff0c;没有请到p…

Vue.js 学习14 集成H265web.js播放器实现webpack自动化构建

Vue.js 学习14 集成H265web.js播放器实现webpack自动化构建 一、项目说明1. H265web.js 简介2. 准备环境 二、项目配置1. 下载 H265web.js2. 在vue项目里引入 H265web3. 设置 vue.config.js 三、代码引用1. 参照官方demo &#xff0c; 创建 executor.js2. 在 vue 页面里引用htm…

批量检测微信小程序是否封禁接口源码

<?php // 要检测的 appid 列表 $appids array(appid1, appid2, appid3); // 使用实际的 appid // 循环调用接口检测小程序状态 foreach ($appids as $appid) { $url https://yan.changxunwangluo.cn/xcx/check_mini_program.php?appid . urlencode($appid); $…

【已解决】c++ qt选中该行为什么该列部分变色

笔者开启了QTableView中交替行改变颜色&#xff0c;发现笔者自定义绘制的水平滚动条&#xff0c;在选中后不发生颜色改变&#xff0c;这让笔者很疑惑。笔者查阅资料后发现&#xff0c;自定义绘制的控件&#xff0c;要自身设置颜色。当笔者解决了这个问题时&#xff0c;顺手就将…

GPT原始论文:Improving Language Understanding by Generative Pre-Training论文翻译

1 摘要 自然语理解包括文本蕴含、问题回答、语义相似性评估和文档分类等一系列多样化的任务。尽管大量未标注的文本语料库很丰富&#xff0c;但用于学习这些特定任务的标注数据却很稀缺&#xff0c;这使得基于区分性训练的模型难以充分发挥作用。我们展示了通过在多样化的未标…

高级Java开发工程师岗位的基本职责(合集)

高级Java开发工程师岗位的基本职责1 职责&#xff1a; 1、负责区块链产品的研发&#xff0c;独立或与团队合作&#xff0c;按时保质完成软件开发项目; 2、参与产品系统设计、概要设计工作&#xff0c;核心功能的代码编写; 3、独立解决和指导其他同事处理开发中遇到的难点问题; …

GaussDB新体验,新零售选品升级注入新思路【华为云GaussDB:与数据库同行的日子】

选品思维&#xff1a;低频VS高频 一个的商超&#xff0c;假设有50个左右的品类&#xff0c;每个品类下有2到10个不等的商品。然而如此庞大的商品&#xff0c;并非所有都是高频消费品。 结合自身日常的消费习惯&#xff0c;对于高频和低频的区分并不难。一般大型家电、高端礼盒…

14.2 Java正则表达式(❤❤)

14.2 Java正则表达式 1. 正则表达式1.1 简介1.2 字符范围匹配1.3 元字符1.4 多次重复匹配1.5 定位匹配1.6 贪婪模式与非贪婪模式1.7 表达式分组1. 正则表达式 1.1 简介 开源 在线正则表达式测试 1.2 字符范

mapbox 高亮相同特征的要素数据

一、完整代码 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>Highlight features containing similar data</title> <meta name"viewport" content"initial-scale1,maximum-scale1,user-scal…

VUE3+TS使用OpenSeadragon学习之旅,实现多图片切换效果

1.官方网站&#xff1a;OpenSeadragon 2.使用npm下载插件&#xff1a;npm install openseadragon 3.在 index.html文件引入资源 <link rel"stylesheet" href"node_modules/openseadragon/build/openseadragon/openseadragon.css" /><script src…