Example #1
0
def filter_log(last_commit):
    commit_valid = call(
        'git -C {} cat-file -e '.format(config.config_dic['project_path']) +
        last_commit)[0]
    if commit_valid != 0:
        return '无'

    git_logs_cmd = '''git -C {} log --pretty=\"%s\" {}..HEAD --reverse'''.format(
        config.config_dic['project_path'], last_commit)
    logs = call(git_logs_cmd)

    log_has_prefix = []

    prefix = config.config_dic['filter_log']['prefix']
    if not prefix:
        prefix = '['

    for line in logs[1].split("\n"):
        if line.startswith(prefix):
            log_has_prefix.append(line)

    if not log_has_prefix:
        return '无'

    log_text = ''
    i = 0
    while i < len(log_has_prefix):
        log_text += '{}.{}'.format(i + 1, log_has_prefix[i])
        if i < len(log_has_prefix) - 1:
            log_text += '\n'
        i += 1

    return log_text
Example #2
0
def get_subject(build):
    build_info = config.config_dic['build'][build]
    version = call(
        '''/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" {}'''.
        format(config.config_dic['project_path'] +
               build_info['info_plist']))[1]
    build_version = call(
        '''/usr/libexec/PlistBuddy -c "Print CFBundleVersion" {}'''.format(
            config.config_dic['project_path'] + build_info['info_plist']))[1]
    subject = build_info['app_name'] + ' ' + str.strip(
        version) + ' ' + 'Build' + ' ' + str.strip(build_version)
    return subject
Example #3
0
def upload(archive=None, build_info=None):
    bugly_info = config.config_dic['bugly']

    dSYM_path = "{}/dSYMs/{}.app.dSYM".format(archive, build_info['scheme'])
    version = call(
        '''/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" {}'''.
        format(config.config_dic['project_path'] +
               build_info['info_plist']))[1]

    cmd = "java -jar {} -i {} -u -id {} -key {} -package {} -version {}".format(
        bugly_info['jar_file'], dSYM_path, build_info['bugly_id'],
        build_info['bugly_key'], build_info['bundle_id'], str.strip(version))
    return call(cmd, None)
Example #4
0
def build_if_need():
    git_info = config.config_dic['git']
    print('Pulling latest code...')
    if git_info['pull_before_build']:
        if git_info['branch']:
            call('git -C {} checkout {}'.format(
                config.config_dic['project_path'], git_info['branch']))
            call('git -C {} pull origin {}'.format(
                config.config_dic['project_path'], git_info['branch']))
        else:
            call('git -C {} pull'.format(config.config_dic['project_path']))

    print('Pull code complete!')

    current_commit = call(
        '''git -C {} --no-pager log --format="%H" -n 1'''.format(
            config.config_dic['project_path']))[1]

    last_try_file = config.config_dic['log_path'] + 'last_try_build.txt'
    last_build_file = config.config_dic['log_path'] + 'last_build.txt'

    if not os.path.exists(last_try_file):
        with open(last_try_file, 'w') as f:
            f.write('0')

    if not os.path.exists(last_build_file):
        with open(last_build_file, 'w') as f:
            f.write('0')

    with open(last_try_file, 'r') as f:
        last_try_commit = f.read()
    with open(last_build_file, 'r') as f:
        last_build_commit = f.read()

    if last_try_commit == current_commit:
        print('Build have tried, exit!')
        return (False, None)

    commit_msg = call('''git -C {} --no-pager log --format="%s" -n 1'''.format(
        config.config_dic['project_path']))[1]

    build_target = None
    for key in config.config_dic['build']:
        if config.config_dic['build'][key]['build_identifier'] in commit_msg:
            build_target = key
            break

    if not build_target:
        print('No build identifier, exit!')
        return (False, None)

    if last_build_commit == current_commit:
        print('This build has been builded, exit!')
        return (False, None)

    print('Build identifier detect, build start...')
    print('Build info {}'.format(config.config_dic['build'][build_target]))
    return (True, build_target)
Example #5
0
def get_current_branch(project_path):
    git_branches = call(
        'git -C {} branch'.format(project_path))[1].splitlines()
    for line in git_branches:
        if line.startswith('*'):
            return line.split()[1]
    return None
Example #6
0
def filter_log(last_commit):
    commit_valid = call(
        'git -C {} cat-file -e '.format(config.config_dic['project_path']) +
        last_commit)[1]
    if commit_valid != '0':
        return '无'

    git_logs_cmd = '''git -C {} log --pretty=\"%s\" {}..HEAD'''.format(
        config.config_dic['project_path'], last_commit)
    logs = call(git_logs_cmd)

    log_has_prefix = []

    prefix = config.config_dic['filter_log']['prefix']
    if not prefix:
        prefix = '['

    for line in logs[1].split("\n"):
        if line.startswith(prefix):
            log_has_prefix.append(line)

    if log_has_prefix.count == 0:
        return '无'

    log_file = '{}log.txt'.format(config.config_dic['builds_path'])

    with open(log_file, 'w') as f:
        for line in log_has_prefix:
            f.write('{}\n'.format(line))

    with open(log_file, 'r+') as f:
        flip_cmd = "sed '1!G;h;$!d' " + log_file
        res = call(flip_cmd)
        f.write(res[1])

    with open(log_file, 'r+') as f:
        add_num_cmd = """awk '{printf NR"."" "}1' """ + log_file
        res = call(add_num_cmd)
        f.write(res[1])

    with open(log_file, 'r') as f:
        return f.read()
Example #7
0
def resign(ipa=None, build_info=None):
    if os.path.exists('Payload'):
        shutil.rmtree('Payload')
    resign_info = build_info['resign']
    tmp_dir = call('mktemp -d')[1]
    call('unzip -q {} -d {}'.format(ipa, tmp_dir))
    extentions_info = None
    if 'extentions' in resign_info:
        extentions_info = resign_info['extentions']
    if extentions_info:
        for extention in extentions_info:
            resign_app('{}/Payload/{}.app/PlugIns/{}.appex'.format(tmp_dir, build_info['scheme'], extention['scheme']), resign_info['certificate'], extention['provisioning_profile'], None, extention['bundle_id'])
    
    resign_app('{}/Payload/{}.app'.format(tmp_dir, build_info['scheme']), resign_info['certificate'], resign_info['provisioning_profile'], resign_info['app_name'], resign_info['bundle_id'])
    file_name_pieces = ipa.split('/')[-1].split('.ipa')
    resign_ipa_name = file_name_pieces[0] + '-resign.ipa'
    resign_ipa = ipa.replace(ipa.split('/')[-1], resign_ipa_name)
    zipDir(tmp_dir, resign_ipa)
    shutil.rmtree(tmp_dir)
    os.remove(ipa)
    return (0, resign_ipa)
Example #8
0
def read_profile_attribute(profile=None, attribute=None):
    if not profile:
        return None
    if not attribute:
        return None

    key_value_res = call('egrep -a -A 1 ' + attribute + ' ' + profile)
    if key_value_res[0] != 0:
        return None
    all_keys = re.findall(".*</(.*)>.*", key_value_res[1])

    value = re.findall(".*<{}>(.*)</{}>.*".format(all_keys[1], all_keys[1]), key_value_res[1])
    if value:
        return value[0]
    else:
        return None
Example #9
0
def get_latest_commit_msg(project_path):
    commit_msg = call('''git -C {} --no-pager log --format="%s" -n 1'''.format(
        project_path))[1]
    return commit_msg
Example #10
0
def get_current_commit(project_path):
    current_commit = call(
        '''git -C {} --no-pager log --format="%H" -n 1'''.format(
            project_path))[1]
    return current_commit
Example #11
0
def checkout_and_pull(project_path, repo='origin', branch='master'):
    call('git -C {} fetch {} {}'.format(project_path, repo, branch))
    call('git -C {} checkout {}'.format(project_path, branch))
    pull(project_path, repo, branch)
Example #12
0
def pull(project_path, repo='origin', branch='master'):
    call('git -C {} pull {} {}'.format(project_path, repo, branch))
Example #13
0
def build(build_target, send_msg=True):
    last_try_file = config.config_dic['log_path'] + 'last_try_build.txt'
    last_build_file = config.config_dic['log_path'] + 'last_build.txt'

    if not os.path.exists(last_try_file):
        with open(last_try_file, 'w') as f:
            f.write('0')

    if not os.path.exists(last_build_file):
        with open(last_build_file, 'w') as f:
            f.write('0')

    with open(last_build_file, 'r') as f:
        last_build_commit = f.read()

    current_commit = call('''git -C {} log --format="%H" -n 1'''.format(
        config.config_dic['project_path']))[1]

    with open(last_try_file, 'w') as f:
        f.write(current_commit)

    build_info = config.config_dic['build'][build_target]
    print('Building...')
    build_res = build_ipa.build_ipa(build_target)
    if build_res[0] != 0:
        print('Build failure!')
        failture_mail_info = config.config_dic['email_after_failure']
        if failture_mail_info['enable']:
            mail.send_failture_msg('Build failure!', build_target)
    else:
        print('Build success!')
        cp_info = config.config_dic['copy_to']
        if cp_info['enable']:
            path = cp_info['path']
            if not os.path.exists(path):
                os.mkdir(path)
            shutil.copy(build_res[2], path)
            print('Copy to {}'.format(path))

        fir_info = config.config_dic['upload_to_fir']
        if fir_info['enable']:
            print('Upload to fir.im...')
            fir.upload(fir_info['path'], build_res[2], fir_info['token'])
            print('Upload complete!')

        bugly_info = config.config_dic['bugly']
        if bugly_info['enable']:
            print('Upload symbol file to bugly...')
            bugly.upload(build_res[1], build_info)
            print('Upload complete!')

        if send_msg:
            mail_info = config.config_dic['email_after_build']
            if mail_info['enable']:
                print('Send email...')
                if mail_info['send_filter_log']:
                    log = filter_log.msg_with_intall_info(
                        last_build_commit, build_target)
                    mail.send_success_msg(log, build_target)
                else:
                    mail.send_success_msg("Build success!", build_target)
                print('Send complete!')

            ding_info = config.config_dic['send_ding_msg_after_build']
            if ding_info['enable']:
                print('Send dingtalk message...')
                tokens = ding_info['tokens']
                if ding_info['send_filter_log']:
                    log = filter_log.msg_with_intall_info(
                        last_build_commit, build_target)
                    dingtalk_bot.sendMessage(log, tokens)
                else:
                    dingtalk_bot.sendMessage('打包成功!', tokens)
                print('Send complete!')

    with open(last_build_file, 'w') as f:
        f.write(current_commit)
    print('Build complete!')
Example #14
0
def build_ipa(target=None):
    build_info = config.config_dic['build'][target]

    scheme_name = build_info['scheme']
    archive_path = config.config_dic['builds_path'] + scheme_name + '.xcarchive'

    archive_cmd = "xcodebuild archive -workspace {} -scheme {} -archivePath {} ONLY_ACTIVE_ARCH=NO TARGETED_DEVICE_FAMILY=1 -allowProvisioningUpdates".format(config.config_dic['project_path'] + config.config_dic['worspace_name'], scheme_name, archive_path)
    log_file = config.config_dic['log_path'] + config.config_dic['builg_log']
    file = open(log_file, 'w+')
    res = call(archive_cmd, file)

    if res[0] != 0:
        return (1, None, None)

    sign_certificate = 'iPhone Distribution'
    if build_info['export_mothod'] == 'development':
        sign_certificate = 'iPhone Developer'

    export_plist_template = """
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>compileBitcode</key>
    <false/>
    <key>method</key>
    <string>{}</string>
    <key>provisioningProfiles</key>
    <dict>
        <key>{}</key>
        <string>{}</string>
    </dict>
    <key>signingCertificate</key>
    <string>{}</string>
    <key>signingStyle</key>
    <string>manual</string>
    <key>stripSwiftSymbols</key>
    <true/>
    <key>teamID</key>
    <string>{}</string>
    <key>thinning</key>
    <string>&lt;none&gt;</string>
</dict>
</plist>
    """
    export_plist = export_plist_template.format(build_info['export_mothod'], build_info['bundle_id'], build_info['provisioning_profile'], sign_certificate, build_info['team_id'])
    export_plist_path = config.config_dic["builds_path"] + "export.plist"

    with open(export_plist_path, 'w') as f:
        f.write(export_plist)

    export_cmd = "xcodebuild -exportArchive -archivePath {} -exportOptionsPlist {} -exportPath {} -allowProvisioningUpdates".format(archive_path, export_plist_path, config.config_dic['builds_path'])
    res = call(export_cmd, file)

    if res[0] != 0:
        return [1, None, None ]

    version = call('''/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" {}'''.format(config.config_dic['project_path'] + build_info['info_plist']))[1]
    build_version = call('''/usr/libexec/PlistBuddy -c "Print CFBundleVersion" {}'''.format(config.config_dic['project_path'] + build_info['info_plist']))[1]

    ipa_name = '{}-{}-Build-{}.ipa'.format(scheme_name, str.strip(version), str.strip(build_version))

    ipa_path = config.config_dic["builds_path"] + ipa_name

    shutil.move(config.config_dic['builds_path'] + scheme_name + '.ipa', ipa_path)
    
    if not os.path.exists(ipa_path):
        return [1, None, None ]

    file.close
    return [0, archive_path,  ipa_path]
Example #15
0
def upload(fir_path=None, ipa=None, token=None):
    upload_cmd = "{} p  {} -T {}".format(fir_path, ipa, token)
    return call(upload_cmd, None)
Example #16
0
def resign_app(app=None, cert=None, profile=None, app_name=None, bundle_id=None):
    signature = app + '/_CodeSignature'
    if os.path.exists(signature):
        shutil.rmtree(signature)
    shutil.copyfile(profile, app + '/embedded.mobileprovision')
    tmp_entitlements = '/tmp/entitlements.plist'
    with open(tmp_entitlements, 'w+') as f:
        call('codesign -d --entitlements - ' + app, f)

    with open(tmp_entitlements, 'r+', encoding='ISO-8859-1') as f:
        lines = f.read().split('\n')
        to_delete = lines[0]
        f.seek(0)
        for line in lines:
            if line != to_delete:
                if line == lines[1]:
                    words = line.split('xml')
                    line = line.replace(words[0], '<?')
                f.write(line + '\n')
        f.truncate()
    
    team_id = read_profile_attribute(profile, 'com.apple.developer.team-identifier')

    if bundle_id:
        call("/usr/libexec/PlistBuddy -c \"Set :application-identifier {}\" {}".format('{}.{}'.format(team_id, bundle_id), tmp_entitlements))
        call("/usr/libexec/PlistBuddy -c \"Set :com.apple.developer.team-identifier {}\" {}".format(team_id, tmp_entitlements))
        call("/usr/libexec/PlistBuddy -c \"Set :CFBundleIdentifier {}\" {}/Info.plist".format(bundle_id, app))
    else:
        entitlements_bundle_id = read_profile_attribute(profile, 'application-identifier')
        pure_bundle_id = entitlements_bundle_id.replace('{}.'.format(team_id), '')

        call("/usr/libexec/PlistBuddy -c \"Set :application-identifier {}\" {}".format(entitlements_bundle_id, tmp_entitlements))
        call("/usr/libexec/PlistBuddy -c \"Set :com.apple.developer.team-identifier {}\" {}".format(team_id, tmp_entitlements))
        call("/usr/libexec/PlistBuddy -c \"Set :CFBundleIdentifier {}\" {}/Info.plist".format(pure_bundle_id, app))

    if app_name:
        call("/usr/libexec/PlistBuddy -c \"Set :CFBundleName {}\" {}/Info.plist".format(app_name, app))


    aps_env = read_profile_attribute(profile, 'aps-environment')
    if aps_env:
        call("/usr/libexec/PlistBuddy -c \"Set :aps-environment {}\" {}".format(aps_env, tmp_entitlements))

    call('codesign -f -s \"{}\" \'--entitlements\' \'{}\' {}'.format(cert, tmp_entitlements, app))
    os.remove(tmp_entitlements)