Flutter使用Jenkins+脚本打包上传至蒲公英

254 阅读1分钟

bulid.sh文件

#!/bin/zsh

  


echo "Begin build.sh script"

  


path=`pwd`

branch=$1

type=$2

build=$3

  


  


echo ">>> path=${path} branch=${branch} type=${type} build=${build}"

 

handle_branch() {

    remote_branch="${branch}"

    remote_branch=$(echo "${remote_branch}" | awk -F'/' '{print $NF}')

  


    echo "远程分支:${remote_branch}"

    git checkout .

    git fetch

    git branch -a --no-pager

    echo "列出分支"

    git checkout "${remote_branch}"

    echo "切换分支完成"

    git pull

    echo "拉取完成"

    flutter doctor

    flutter pub get

}

  


pullcode() {

    REPO_NATIVE_BRIDGE_URL="git@gitcode.deepway-inc.com:base-infrastructure/basic-client/flutter/dw_flutter_native_bridge.git"

    REPO_MODULE_URL="git@gitcode.deepway-inc.com:base-infrastructure/basic-client/flutter/dw_flutter_module.git"

  


    BRANCH_NAME="main"

  


    LOCAL_NATIVE_BRIDGE_REPO_PATH="../dw_flutter_native_bridge"

    LOCAL_MODULE_REPO_PATH="../dw_flutter_module"

  


    if [ -d "$LOCAL_NATIVE_BRIDGE_REPO_PATH" ]; then

        cd $LOCAL_NATIVE_BRIDGE_REPO_PATH

        git pull origin $BRANCH_NAME

        cd $path

    else

        git clone -b $BRANCH_NAME $REPO_NATIVE_BRIDGE_URL $LOCAL_NATIVE_BRIDGE_REPO_PATH

    fi

    

    if [ -d "$LOCAL_MODULE_REPO_PATH" ]; then

        cd $LOCAL_MODULE_REPO_PATH

        git pull origin $BRANCH_NAME

        cd $path

    else

        git clone -b $BRANCH_NAME $REPO_MODULE_URL $LOCAL_MODULE_REPO_PATH

    fi

    echo "拉取完成"

}

  


pullcode

handle_branch "${branch}"

  


echo ">>>>>>>> 开始调用 upload.py 打包"

 

python3 upload.py -t ${type} -u ${type} -b ${build}

  


echo "End build.sh script"

upload.py文件:

#!/usr/bin/python3

# -*- coding: utf-8 -*-

import requests

import  os

import getopt

import sys

from enum import Enum

from requests_toolbelt.multipart import encoder

  


  


#  检查第三方包是否安装

def check_requirement(package):

    try:

        exec("import {0}".format(package))

    except ModuleNotFoundError:

        inquiry = input("This script requires {0}. Do you want to install {0}? [y/n]".format(package))

        while (inquiry != "y") and (inquiry != "n") and (inquiry != "N") and (inquiry != "Y") :

            inquiry = input("This script requires {0}. Do you want to install {0}? [y/n]".format(package))

        if inquiry == "y" or inquiry == "Y":

            import os

            print("Execute commands: pip install {0}".format(package))

            if int(sys.version.split('.')[0])==2:

                os.system("pip install {0}".format(package))

            elif int(sys.version.split('.')[0])==3:

                os.system("pip3 install {0}".format(package))

        else:

            print("{0} is missing, so the program exits!".format(package))

            exit(-1)

  


  


  





#  编译类型 #注:只需要用默认release就行

class BuildMode(Enum):

    all=0

    debug = 1

    release =2

    @staticmethod

    def load(value):

        if value == 0:

            return BuildMode.all

        elif value == 1:

            return BuildMode.debug

        elif value ==2:

            return  BuildMode.release

#  上传类型

class UploadMode(Enum):

    all = 0

    apk = 1

    ipa = 2

    @staticmethod

    def load(value):

        if value == 0:

            return UploadMode.all

        elif value == 1:

            return UploadMode.apk

        elif value ==2:

            return  UploadMode.ipa

#  编译类别 安卓还是ios

class BuildType(Enum):

    all = 0

    apk = 1

    ipa = 2

    @staticmethod

    def load(value):

        if value == 1:

            return BuildType.apk

        elif value == 2:

            return BuildType.ipa

        elif value ==0:

            return  BuildType.all

  


  


  


class Runner:

    buildMode = BuildMode.release

    uploadMode = None

    buildType = None

    fileLength=1

    currentPath=''

  


  


    def main(self,argv):

        try:

            ops,args = getopt.getopt(argv,'-h-b:-u:-t:',['help','build=','upload=','type='])

        except getopt.GetoptError:

            sys.exit()

        count = 0

        for op,value in ops:

            if op in ('-h','--help'):

                count +=1

                self.pHelp()

                return

            elif op in ('-u', '--upload'):

                count += 1

                if ['all','apk','ipa'].__contains__(value) ==False:

                    self.pHelp()

                else:

                    self.uploadMode=UploadMode(['all','apk','ipa'].index(value))

            elif op in('-b','--build'):

                count += 1

                # self.p('-b:{0}'.format(value))

                if ['all','debug','release'].__contains__(value)==False:

                    self.pHelp()

                else:

                    self.buildMode=BuildMode.load(['all','debug','release'].index(value))

            elif op in('-t','--type'):

                count += 1

                # self.p('-t:{0}'.format(value))

                if ['all','apk','ipa'].__contains__(value)==False:

                    self.pHelp()

                else:

                    self.buildType=BuildType.load(['all','apk','ipa'].index(value))

        if count ==0:

            self.pHelp()

            return

        else:

            if not self.buildType:

                self.p('\n 请输入 -b buildType 参数 \n')

                self.pHelp()

                return

            if not self.uploadMode:

                self.p('\n 请输入 -u uploadMode 参数 \n')

                self.pHelp()

                return

  


        self.p('{0}{1}{2}'.format(self.buildMode, self.buildType,self.uploadMode))

        # 开始编译和上传ipa

        self.currentPath = os.getcwd()

        self.build()

        self.upload()

  


  


    def p(self,str):

        # 结束标示: \n\033[0m

        print('\033[0;35;48m  '+str+'')

  


  


    def pHelp(self):

        self.p('-h --help 获取帮助信息')

        self.p('-b --build 编译模式[release(default),debug,all]注:只需要用默认release就行')

        self.p('-u --upload 上传模式[apk,ipa]')

        self.p('-t --type  编译种类[all,apk,ipa]')

  


    def buildAPK(self):

        try:

            if self.buildMode==BuildMode.release :

                os.system('flutter --no-color build apk --flavor env_release -t lib/main_env_release.dart'),

            if self.buildMode==BuildMode.debug :

                os.system('flutter --no-color build apk --flavor env_debug -t lib/main_env_debug.dart'),

        except KeyError as e:

            print(e)

    def buildIPA(self,):

        try:

            if self.buildMode==BuildMode.release:

                os.system('source ~/.bash_profile'),

                os.system('flutter --no-color build ios --flavor env_release -t lib/main_env_release.dart'),

                os.chdir(self.currentPath+'/ios')

                plus='agvtool next-version -all'

                arch = 'xcodebuild -workspace Runner.xcworkspace -scheme Runner archive -archivePath ./build/Runner.xcarchive'

                export = 'xcodebuild -exportArchive -archivePath $PWD/build/Runner.xcarchive -exportOptionsPlist "./exportOptions.plist" -exportPath ./build/'

                os.system(arch)

                os.system(plus)

                os.system(export)

            elif self.buildMode==BuildMode.debug:

                os.system('source ~/.bash_profile'),

                os.system('flutter --no-color build ios --flavor env_debug -t lib/main_env_debug.dart'),

                os.chdir(self.currentPath+'/ios')

                plus='agvtool next-version -all'

                arch = 'xcodebuild -workspace Runner.xcworkspace -scheme Runner archive -archivePath ./build/Runner.xcarchive'

                export = 'xcodebuild -exportArchive -archivePath $PWD/build/Runner.xcarchive -exportOptionsPlist "./exportOptions.plist" -exportPath ./build/'

                os.system(arch)

                os.system(plus)

                os.system(export)

  


        except KeyError as e:

            print(e)

  


    # 编译函数

    def build(self,):

        if self.buildType==BuildType.apk:

            self.buildAPK()

        elif self.buildType==BuildType.ipa:

            self.buildIPA()

        elif self.buildType==BuildType.all:

            self.buildAPK()

            self.buildIPA()

            

    def uploadFile(self,filePath,name='DeepWay服务.ipa'):

        self.p(' 开始上传' + filePath)

        url = 'https://www.pgyer.com/apiv2/app/upload'

        file = open(filePath, 'rb')

  


        e = encoder.MultipartEncoder(

            fields={

                '_api_key': '3f74f8fe3044845cebbd76964dd204a3',

                    'file': (name,file,'application/x-www-form-urlencoded'),

                    },

        )

        m = encoder.MultipartEncoderMonitor(e, self.my_callback)

        h = {'Content-Type': m.content_type,"enctype":"multipart/form-data"}

        self.fileLength = os.path.getsize(filePath)

        r = requests.post(url, data=m,headers=h).json()

  


  


        if int(dict(r).get('code')) != 0:

            raise Exception('上传失败:{0}'.format(dict(r).get('message')), )

        else:

            self.p(str(r).replace('u\'','\''))# 去掉前边的u

            self.p(filePath + '上传成功')

  


    def my_callback(self,monitor):

        total = 50

        pro =int((monitor.bytes_read *1.0)/self.fileLength * 1.0 * total)

        unit = 1000 * 1000.0

        sys.stdout.write(

            '\r' + str(pro * '\033[46;34m \033[0m') + str((total - pro) * '\033[40;30m \033[0m') + '[{0}M/{1}M]'.format( round(monitor.bytes_read/unit,2),round(self.fileLength/unit,2)))

        sys.stdout.flush()

    # 上传函数

    def upload(self,):

        currentPath=self.currentPath

        if self.uploadMode== UploadMode.apk or self.uploadMode==UploadMode.all:

            if self.buildMode==BuildMode.debug or self.buildMode==BuildMode.all:

                filePath=currentPath+'/build/app/outputs/apk/env_debug/release/app-env_debug-release.apk'

  


                try:

                    self.uploadFile(filePath, name='app-env_debug-release.apk')

  


                except Exception as e:

                    self.p(e.__str__())

                    exit()

            if self.buildMode==BuildMode.release or self.buildMode==BuildMode.all:

                filePath = currentPath+'/build/app/outputs/apk/env_release/release/app-env_release-release.apk'

                try:

                    self.uploadFile(filePath, name='app-env_release-release.apk')

                except Exception as e:

                    self.p(e.__str__())

                    exit()

  


        if self.uploadMode==UploadMode.ipa or self.uploadMode==UploadMode.all:

            file = self.currentPath+'/ios/build/DeepWay服务.ipa'

            if os.path.isdir(file) or os.path.isfile(file):

                self.uploadFile(file,name='DeepWay服务.ipa')

                source_file = os.path.join(self.currentPath, 'ios', 'build', 'DeepWay服务.ipa')

                destination_file = os.path.join(self.currentPath, 'ios', 'output', 'DeepWay服务.ipa')

                source_save_file = os.path.join(self.currentPath, 'ios', 'build/')

                os.system(f'mv {source_file} {destination_file}') # 移动ipa

                os.system(f'rm -rf {source_save_file}')# 删除 build文件夹

            else:

                self.p('没有发现ipa文件:'+file)

  


  


  


if __name__ == '__main__':

    libs = ['requests','requests_toolbelt']

    for i in libs:

        check_requirement(i)  # 检查是否安装该安装包

    Runner().main(sys.argv[1:])

jenkins中shell脚本配置

#!/bin/bash

export LANG=en_US.UTF-8

pwd

path=`pwd`

echo "path=${path}"

export PATH=/Users/deepway/flutter/bin:$PATH

sh build.sh ${branch} ${type} ${build}


本地可执行

python3 upload.py -t ipa -u ipa -b debug

python3 upload.py -t apk -u apk -b debug

sh build.sh origin/main ipa debug

配置多环境参考 juejin.cn/post/705003…