Пример #1
0
def build_xcode_project(args):
    """调用方法: python ~/apk-builder/xcode_builder.py -a ipa --ipa SDK_V5 -p FLGamePlatformDemo -s FLGamePlatformDemoRelease --clean
工作步骤:
	1. XCode项目打包
	2. 重命名ipa为 %(ipa_name)s_v%(code_ver)s_r%(repo_ver)s_b%(build_num)s.ipa
	例如: SDK_V5_v5.1.56_r168988_b62.jar
	3. create ota plist
	"""
    # 1. build xcode project and export ipa
    Command.xcodebuild_ipa(project=args.project + '.xcodeproj',
                           scheme=args.scheme,
                           export=args.export,
                           plist=args.plist,
                           is_clean=args.clean,
                           dry_run=args.dry_run)
    print 'ipa file name:', args.ipa_name

    # 2. rename
    ipa_name = '%(ipa_name)s_v%(code_ver)s_r%(repo_ver)s_b%(build_num)s.ipa' % {
        'ipa_name':
        args.ipa_name,
        'code_ver':
        read_version_from_project(),
        'repo_ver':
        Command.git_ver('..', do_update=False)
        if args.git else Command.svn_ver('..', do_update=False),
        'build_num':
        os.environ.get('BUILD_NUMBER')
    }
    rename_cmd = 'mv %(export_path)s/%(scheme_name)s.ipa %(export_path)s/%(ipa_name)s' % {
        'scheme_name': args.scheme,
        'export_path': args.export,
        'ipa_name': ipa_name
    }
    (cost, out, err) = Command.excute(rename_cmd, args.dry_run)
    if len(err) == 0:
        logging.info('mission done for building [%s]' % ipa_name)
    else:
        logging.error('mission failed for building [%s]' % ipa_name)
    # 3. create ota plist
    # cp ipa to nginx root path
    rename_cmd = 'cp %(export_path)s/%(ipa_name)s %(root_path)s' % {
        'export_path': args.export,
        'ipa_name': ipa_name,
        'root_path': args.root_path
    }
    (cost, out, err) = Command.excute(rename_cmd, args.dry_run)

    plistBuddy = PlistBuddy(args.root_path, ipa_name)
    # create plist
    plistBuddy.create_ota_plist(os.path.join(args.ipa_url, ipa_name),
                                os.path.join(args.ipa_url, 'icon.png'))
    # create update links to plist
    plistBuddy.update_index_html(args.ipa_name, args.ipa_url)
Пример #2
0
def merge_plugin_and_build_apk(args):
    """Excute Help: python apk_builder.py -c apk -s /data/game_apks/g103_3 -ch qh
-c command type, must be apk
-s read source code from this directory
-ch witch channel plugin merge to source
lftp -c 'open -e "pget -n 4 games/qzgs_201_08211523.rar" sdk:[email protected]'
wget https://github.com/dryes/rarlinux/raw/master/rarlinux-5.2.1.tar.gz

操作逻辑说明: 
1. init: 初始化工程目录,删除存在的工程目录
2. copy: 复制项目代码到工程目录
3. clean: 清理工程目录中的默认插件代码
4. merge: 把指定插件拷贝到工程目录
5. update: 更新versionName和versionCode
6. build: 打包
7. save: 拷贝到指定目录

- 工作目录
1. sdk-u3d-plugins:根据apk_builder.py路径,从而确定plugins路径;
2. 工程目录(apk_dir, 执行ant release的目录):当前执行命令的路径下的build_<plugin name>目录,即 os.getcwd()/build_<plugin name>


- 渠道打包命名规则
应用名称_渠道编码-应用目录名-插件版本号.apk

应用举例:g20_exit/g20_noexit
插件举例:p23 - 对应的git revision
	"""
    Command.set_log_level(logging.DEBUG)
    status = 'init'

    game_dir = args.src
    channel = args.channel

    apk_dir = os.path.join(os.getcwd(), 'build_%s' % channel)
    plugin_dir = sys.path[0]
    logging.info('[%s] running_dir = %s, plugin_dir = %s, building_dir = %s' %
                 (status, os.getcwd(), plugin_dir, apk_dir))

    revision = Command.git_ver(plugin_dir)

    if len(revision) == 0:
        print 'revision missing'
        logging.warn('revision missing')

    if os.path.exists(apk_dir):
        print 'apk_dir exists, you should delete before build.'
        return -1

    apk_name = channel + '-' + os.path.basename(game_dir)

    # 拷贝母包
    status = 'copy'
    (cost, out, err) = Command.excute('cp -R %s %s' % (game_dir, apk_dir),
                                      args.dry_run)
    logging.info('[%s] from_dir = %s, to_dir = %s' %
                 (status, game_dir, apk_dir))

    # 母包初始化
    logging.info('[clean] Clean and Init Project...')
    clean_and_init_project(apk_dir)

    # cp channel keystore & ant.properties
    logging.info('[merge] Add build config for channel[%s] to Project...' %
                 channel)
    keystore = os.path.join(plugin_dir,
                            'keys.%s/%s.keystore' % (args.app, channel))
    ant_p = os.path.join(plugin_dir,
                         'keys.%s/ant_%s.properties' % (args.app, channel))
    if os.path.exists(keystore) and os.path.exists(ant_p):
        (cost, out, err) = Command.excute('cp %s %s' % (keystore, apk_dir),
                                          args.dry_run)
        (cost, out,
         err) = Command.excute('cp %s %s/ant.properties' % (ant_p, apk_dir),
                               args.dry_run)

    (cost, out, err) = Command.excute(
        'cp -Rv %s/plugin_%s/* %s' % (plugin_dir, channel, apk_dir),
        args.dry_run)
    # change versionCode&versionName in AndroidManifest.xml
    cmd = '''sed -i.bak -r '{s/android:versionCode=\s*\"[0-9]{1,}\"/android:versionCode=\"%s\"/g;s/android:versionName=\s*\"[^"]+\"/android:versionName=\"%s\"/g}' %s/AndroidManifest.xml''' % (
        args.versioncode, args.versionname, apk_dir)
    (cost, out, err) = Command.excute(cmd)
    if len(err) > 0:
        logging.warn(
            '[build] Failed to set versionCode & versionName. stderr=%s' % err)

    status = 'build'
    (cost, out, err) = Command.excute(
        'android update project -p %s -n %s -t %s' %
        (apk_dir, apk_name, args.target), args.dry_run)
    cmd_build_apk = 'ant -f %s/build.xml clean release' % apk_dir
    (cost, out, err) = Command.excute(cmd_build_apk, args.dry_run)
    if len(err) == 0:
        logging.info('[%s] Build Project to APK, channel=%s' %
                     (status, channel))
    else:
        # add last 15 lines ant build output in log
        if len(out.split('\n')) > 15: out = '\n'.join(out.split('\n')[-15:])
        logging.error(
            'Failed to build APK, channel=%s, cmd=%s, ----err-----%s\n------details-----\n%s'
            % (channel, cmd_build_apk, err, out))

    apk_save_to = apk_name + '-p' + revision + '-release_vc' + args.versioncode + '.apk'

    status = 'cp'
    cmd_cp_apk = 'cp %s/bin/%s %s' % (apk_dir, apk_name + '-release.apk',
                                      apk_save_to)
    (cost, out, err) = Command.excute(cmd_cp_apk, args.dry_run)
    logging.info('[%s] cp apk to running_dir, cmd=%s' % (status, cmd_cp_apk))
    if len(err) > 0: logging.error('Failed to copy apk. stderr=%s' % err)

    status = 'mv'
    if None != os.environ.get('BUILD_NUMBER'):
        apk_mv_to = os.path.join(os.environ.get('WORKSPACE'), 'game_apks',
                                 os.environ.get('BUILD_NUMBER'))
        if not os.path.exists(apk_mv_to):
            os.mkdir(apk_mv_to)
        cmd_mv_apk = 'mv %s %s' % (apk_save_to, apk_mv_to)
        (cost, out, err) = Command.excute(cmd_mv_apk, args.dry_run)
        logging.info('[%s] mv apk to jenkins workspace, cmd=%s' %
                     (status, cmd_mv_apk))
        if len(err) > 0: logging.error('Failed to mv apk. stderr=%s' % err)

    if len(err) == 0:
        logging.info('[%s]mission done!' % channel)
    else:
        logging.error('[%s]mission failed.' % channel)
    logging.info('======================================')