Original: tomczhen’s blog

By using Ant script to build iOS projects on Jenkins platform, functions such as automatic build package, upload dandelion, and send wechat notification upon completion of construction can be achieved. Release developers test distribution and click through a series of actions.


Install CocoaPods

  1. Update Ruby

     gem update --system
    Copy the code
  2. Modify the Ruby installation source

     gem sources --remove https://rubygems.org/
     gem sources -a https://ruby.taobao.org/
    Copy the code

    Note: Use the gem sources -l command to view the source list

  3. Install cocoapods

     sudo gem install cocoapods
    Copy the code

Xctool installation

  1. Install the brew

     ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    Copy the code
  2. Install Xcode’s Command Line Tools

     xcode-select install
    Copy the code
  3. Install xcTool using BREW

     brew install xctool
    Copy the code

Install the Apache Ant

  • brew install ant
    Copy the code

Configuring the Operating Environment

Set the ANT_HOME path on Jenkins’ system Settings page and add the following key values to the global properties.

  • keyLANGvaluezh_CN.UTF-8
  • keyPATHvalueSystem PATH Displays the value

Writing Ant scripts

  • Official manual, you can view available tasks or commands as well as specific parameters, instances.

Add Jenkins task

  • Create the task type “Build a freeform software project” and select source code management. Under “Add Build Steps”, select Invoke Ant, open advanced options, configure Targets, and enter the path of the build. XML File configured in Build File.

  • Note: You can configure only source control in a task, perform a task test to get the code working, and then use the Ant command from the command line interface on the server to call the build.xml file in your project for a compile test.


The script instance

Script description:

  • Ant scripts are still essentially iOS packaging by calling the xctool or Xcodebuild commands
<? xml version="1.0" encoding="UTF-8"? > <project name="antProjectName" default="config.dev, modify, pack, pgy">
    <property name="project.name" value="projectName" />
    <property name="project.workspace.name" value="workspaceName" />
    <property name="project.scheme.name" value="schemeName" />
    
    <exec executable="date" outputproperty="build.time" failifexecutionfails="false" errorproperty="DateError">
        <arg value="+%Y%m%d%H%M" />
    </exec> <! Get Git version control information --> <exec executable="git" outputproperty="git.tag" failifexecutionfails="false" errorproperty="GitTagError">
        <arg value="describe" />
        <arg value="--tags" />
    </exec>
    <exec executable="git" outputproperty="git.commit" failifexecutionfails="false" errorproperty="GitCommitError">
        <arg value="log" />
        <arg value="--pretty=format:%h" />
        <arg value="-n1" />
    </exec>
    <exec executable="git" outputproperty="git.log" failifexecutionfails="false" errorproperty="GitLogError">
        <arg value="log" />
        <arg value="--pretty=format:%B" />
        <arg value="-n1" />
    </exec>
    <target name="config.dev">
        <property name="project.profile.name" value="adhoc"/ > <! --> <property name="build.type" value="Dev" />
        <property name="build.config.name" value="Development environment" />
        <property name="build.file.path" value="dev" />
        <property name="build.file.name" value="${project.name}_${git.tag}_beta${build.time}" />
        <property name="pgy.description" value="LAN-Beta${line.separator}Tag:${git.tag} Commit:${git.commit}${line.separator}${git.log}"/ > <! -- Interface server address --> <property name="api.url" value="http://api.dev.server.com"/ > <! -- Third-party Key --> <! -- --> <property name="key.rongcloud" value="rongcloud" />
            <property name="key.rongcloud_scid" value="rongcloud_scid" />
        
        <property name="build.file.url" value="http://www.pgyer.com/pgy" />
        <property name="build.file.qrcode" value="http://www.pgyer.com/app/qrcode/pgy" />
    </target>
    
    <target name="config.beta">
        <property name="project.profile.name" value="adhoc"/ > <! -- Build test environment configuration information --> <property name="build.type" value="Beta" />
        <property name="build.config.name" value="Test environment" />
        <property name="build.file.path" value="beta" />
        <property name="build.file.name" value="${project.name}_${git.tag}_beta${build.time}" />
        <property name="pgy.description" value="Beta${line.separator}Tag:${git.tag} Commit:${git.commit}${line.separator}${git.log}"/ > <! -- Interface server address --> <property name="api.url" value="http://api.beta.server.com"/ > <! -- Third-party Key --> <! -- --> <property name="key.rongcloud" value="rongcloud" />
            <property name="key.rongcloud_scid" value="rongcloud_scid" />
        
        <property name="build.file.url" value="http://www.pgyer.com/pgy" />
        <property name="build.file.qrcode" value="http://www.pgyer.com/app/qrcode/pgy" />
    </target>
    
    <target name="config.release">
        <property name="project.profile.name" value="adhoc"/ > <! -- Build production environment configuration information --> <property name="build.type" value="Release" />
        <property name="build.config.name" value="Production Environment - Dandelion" />
        <property name="build.file.path" value="release" />
        <property name="build.file.name" value="${project.name}_${git.tag}_r${build.time}" />
        <property name="pgy.description" value="Release${line.separator}Tag:${git.tag} Commit:${git.commit}${line.separator}${git.log}"/ > <! -- Interface server address --> <property name="api.url" value="http://api.release.server.com"/ > <! -- Third-party Key --> <! -- --> <property name="key.rongcloud" value="rongcloud" />
            <property name="key.rongcloud_scid" value="rongcloud_scid" />
        
        <property name="build.file.url" value="http://www.pgyer.com/pgy" />
        <property name="build.file.qrcode" value="http://www.pgyer.com/app/qrcode/pgy" />
    </target>
    
    <target name="config.appstore">
        <property name="project.profile.name" value="appstore"/ > <! -- Build formal environment configuration information --> <property name="build.type" value="AppStore" />
        <property name="build.config.name" value="Official Environment -AppStore" />
        <property name="build.file.path" value="release" />
        <property name="build.file.name" value="${project.name}_${git.tag}_r${build.time}" />
        <property name="pgy.description" value="Release${line.separator}Tag:${git.tag} Commit:${git.commit}${line.separator}${git.log}"/ > <! -- Interface server address --> <property name="api.url" value="http://api.release.server.com"/ > <! -- Third-party Key --> <! -- --> <property name="key.rongcloud" value="rongcloud" />
        <property name="key.rongcloud_scid" value="rongcloud_scid" />
        
        <property name="build.file.url" value="http://download.server.com/IOS/${project.scheme.name}/${build.file.name}.ipa"/ > <! --> <property name="build.file.qrcode" value="http://qr.liantu.com/api.php?text=${build.file.url}" />
    </target>
    
    <target name="modify"> <! -- Configure the interface server address --> <! -- API Center Url --> <replaceregexp byline="true" encoding="UTF-8">
            <regexp pattern='^NSString\s+\*\s+const\s+APIServerUrl\s+=\s+(.*)' />
            <substitution expression='NSString * const APIServerUrl = @"${api.url}"; ' />
            <fileset dir="ProjectPath/Classes/Main/Other" includes="Const.m"/> </replaceregexp> <! -- Configure the third-party Key --> <! <replaceregexp byline="true" encoding="UTF-8">
            <regexp pattern='^#define\s+RONGCLOUD_IM_APPKEY\s+(.*)' />
            <substitution expression='#define RONGCLOUD_IM_APPKEY @"${key.rongcloud}"' />
            <fileset dir="ProjectPath/Classes/Main/Other" includes="Const.h"/> </replaceregexp> <! <replaceregexp byline="true" encoding="UTF-8">
            <regexp pattern='^#define\s+CustomerServiceId\s+(.*)' />
            <substitution expression='#define CustomerServiceId @"${key.rongcloud_scid}"' />
            <fileset dir="ProjectPath/Classes/Main/Other" includes="Const.h" />
        </replaceregexp>
        
    </target>
    
    <target name="pack">
        <property name="build.archive.path" value="build/${build.file.path}/${build.file.name}"/ > <! -- pod install--> <exec executable="pod" failonerror="true">
            <arg value="install" />
            <arg value="--verbose" />
            <arg value="--no-repo-update" />
        </exec> <! -- Clean --> <exec executable="xctool" failonerror="true">
            <arg value="-workspace" />
            <arg value="${project.workspace.name}.xcworkspace" />
            <arg value="-scheme" />
            <arg value="${project.scheme.name}" />
            <arg value="clean" />
        </exec> <! -- archive --> <exec executable="xctool" failonerror="true">
            <arg value="-workspace" />
            <arg value="${project.workspace.name}.xcworkspace" />
            <arg value="-scheme" />
            <arg value="${project.scheme.name}" />
            <arg value="build" />
            <arg value="archive" />
            <arg value="-archivePath" />
            <arg value="${build.archive.path}" />
        </exec> <! --export ipa -->
        <exec executable="xcodebuild" failonerror="true">
            <arg value="-exportArchive" />
            <arg value="-archivePath" />
            <arg value="${build.archive.path}.xcarchive" />
            <arg value="-exportPath" />
            <arg value="${build.archive.path}.ipa" />
            <arg value="-exportFormat" />
            <arg value="ipa" />
            <arg value="-exportProvisioningProfile" />
            <arg value="${project.profile.name}" />
        </exec>
        
        <condition property="isAppStore">
            <equals arg1="${build.type}" arg2="AppStore" />
        </condition>
        <antcall target="copy2share" />
        <antcall target="pgy" />
    </target>
    
    <target name="copy2share" if="isAppStore"> <! --> <copy file="${basedir}/${build.archive.path}.ipa" todir="/Jenkins/IOS/${project.scheme.name}/" />
    </target>

    <target name="pgy" unless="isAppStore"> <! --> <property name="pgy.ukey" value="pgyukey" />
        <property name="pgy.api_key" value="pgyapi_key" />
        <exec executable="curl" outputproperty="pgy.json" failifexecutionfails="true">
            <arg value="-s" />
            <arg value="-F" />
            <arg value="file=@${basedir}/${build.archive.path}.ipa" />
            <arg value="-F" />
            <arg value="uKey=${pgy.ukey}" />
            <arg value="-F" />
            <arg value="_api_key=${pgy.api_key}" />
            <arg value="-F" />
            <arg value="updateDescription=${pgy.description}" />
            <arg value="http://www.pgyer.com/apiv1/app/upload"/>
        </exec>
        <echo message="${pgy.json}" />
    </target>
    
    <target name="wechat">
        <exec executable="date" outputproperty="build.report.time" failifexecutionfails="false" errorproperty="DateError">
            <arg value="+%Y year %m month %d day %H:% m" />
        </exec> <! -- Corp.media requires permanent material ID --> <! Partyid receiving department id. Wechat. Userid receiving userid --> <property name="wechat.partyid" value="2" />
		<property name="wechat.agentid" value="12" />
		<property name="wechat.userid" value=""/ > <! -- Get wechat API Token --> <property name="corp.id" value="wechat_id" />
        <property name="corp.secret" value="wechat_secret" />
        <property name="corp.media" value="wechat_media_id" />
        
        <exec executable="curl" outputproperty="corp.token.json" failifexecutionfails="false">
            <arg value="-s" />
            <arg value="https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=${corp.id}&corpsecret=${corp.secret}"/>
        </exec> <! -- <echo message="${corp.token.json}" /> -->
        
        <script language="javascript">
            var jsonString = DJT.getProperty("corp.token.json");
            var json = eval ("(" + jsonString + ")");
            DJT.setProperty("corp.token",json.access_token); </script> <! -- <echo message="${corp.token}"/ > -- > <! --> <property name="build.digest" value=The construction is complete.${line.separator}${ant.project.name}-IOS [${build.config.name}]${line.separator}Tag:${git.tag} Commit:${git.commit}" />
        <property name="build.report" value="<p> Build complete <br/>${ant.project.name}-IOS [${build.config.name}]<br/>${build.report.time}<br/> File name <br/>${build.file.name}<br/>Tag:${git.tag} Commit:${git.commit}<br/> Update description <br/>${build.type}<br/>${git.log}<br/><a href="${build.file.url}\" src=\"${build.file.url}\ ">${build.file.url}</a><br/><img src=\"${build.file.qrcode}\"/></p>" />
        
        <property name="build.report.json" value="{"touser":"","toparty":"${wechat.partyid}","totag":"","msgtype":"mpnews","agentid":${wechat.agentid},"mpnews": {"articles": [{"title":"Jenkins build notification","thumb_media_id":"${corp.media}","author":"Jenkins","content_source_url":"","content":"${build.report}","digest":"${build.digest}","show_cover_pic":"0"}]},"safe":"0"}"/ > <! -- <echo message="${build.report.json}" /> -->
        
        <exec executable="curl" outputproperty="corp.message.json" failifexecutionfails="false">
            <arg value="-s" />
            <arg value="-l" />
            <arg value="-H" />
            <arg value="Content-type: application/json" />
            <arg value="-X" />
            <arg value="POST" />
            <arg value="-d" />
            <arg value="${build.report.json}" />
            <arg value="https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=${corp.token}"/>
        </exec>
        
        <echo message="${corp.message.json}" />
        
    </target>
</project>
Copy the code