In my previous article, I wrote about deploying a Flutter Web application on Github. Every time you submit your code, Github Actions will be triggered to complete the build and deployment of the Flutter Web. Is it also possible to build iOS packages automatically? The answer is yes, and this article explains how to build it.

Steps outlined

To achieve the goal of building a Flutter iOS package, you must perform the following steps:

  • Install the Apple certificate and configuration file
  • Specify the correct Flutter version
  • Pull the flutter packages
  • Building the application
  • Sign it with the correct Apple certificate
  • generate.xarchive
  • from.xarchiveGenerated in the.ipa
  • Share it with your users

For a smooth build, we must provide:

  • You can pack applescertificate(.p12), and the password for exporting the certificate
  • Certificate correspondingDescription file(.mobileprovision)

If you don’t know how to get a certificate and description file, please refer to this article: iOS Packaging Certificate Making.

All set, let’s get started!

What are GitHub Actions

GitHub Actions is GitHub’s continuous integration service, launched in October 2018.

As you know, continuous integration consists of many operations, such as grabbing code, running tests, logging into remote servers, publishing to third-party services, and so on. GitHub calls these actions actions.

Many operations are similar across projects and can be fully shared. GitHub noticed this and came up with the neat idea of allowing developers to write each action as a separate script file and store it in the repository so that other developers can reference it.

If you need an action, you don’t have to write a complex script, you can just refer to someone else’s action, and the whole continuous integration process becomes a combination of actions.

The basic concept

(1) Workflow: Continuous integration of a running process, that is, a workflow.

(2) Job: A Workflow consists of one or more jobs. It is a continuous integrated operation that can complete multiple tasks.

(3) Steps: Each job consists of multiple steps to be completed step by step.

(4) Action: Each step can execute one or more actions in turn.

For a quick look at GiHub Actions, see the GitHub Actions Tutorial

We’ll create a GitHub Action that lets you generate your IPA with one click.

Configuration making Actions

Let’s create our first workflow! In your project, you will need to create a workflows folder in the.github folder, and then create a new file called ios-release.yml.

The ios-release.yml file will contain our first job (job)build_ios:

name: Flutter_iOS

on:
  push:
    branches: [master]

jobs:
  build_ios:
    runs-on: macos-latest

    steps:
    - name: Checkout the code
      uses: actions/checkout@v2
Copy the code

This job is triggered when you push new changes on the Master branch. Our first step is to check out the code for our branch.

Installing an Apple Certificate

Because the project is open source, packaging requires certificates, passwords, and description files that we don’t want to make public. At this time, we can make use of the secrets function provided by GitHub, which can safely store private content.

Since certificates and description files are file types and secrets store strings, we need to base64 the files as strings at this point. Concrete steps, can read the article “How to use environment variables and secrets using making Actions” (damienaicheh. Making. IO/lot/acti…

For example: base64 build_certificate. P12 | pbcopy

We will define the following keys:

  • .p12The key of the certificate isP12_BASE64
  • The key of the associated password isP12_PASSWORD
  • Description The file key isPROVISIONING_PROFILE_BASE64

The next step is to install your Apple certificate, for which we will use an action from the community called Apple-Actions /import-codesign-certs@v1 and use the secrets we defined earlier

- name: Install Apple Certificate
  uses: apple-actions/import-codesign-certs@v1
  with:
    p12-file-base64: The ${{ secrets.P12_BASE64 }}
    p12-password: The ${{ secrets.P12_PASSWORD }}
Copy the code

To sign the application, we also need to install our description file:

- name: Install the provisioning profile
    env:
      PROVISIONING_CERTIFICATE_BASE64: The ${{ secrets.PROVISIONING_PROFILE_BASE64 }}
    run: | PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
      echo -n "$PROVISIONING_CERTIFICATE_BASE64" | base64 --decode --output $PP_PATH

      mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
      cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
Copy the code

As you can see above, this script has three operations:

  • createsecretsvariable
  • fromsecretsImport description file
  • Configuration Description File

Build Flutter code

To be able to use Flutter in our workflow, we need to install it. To achieve this, we will use another action from the community:

- name: Install and set Flutter version
  uses: Subosito/[email protected]
  with:
    flutter-version: '2.10.0'
Copy the code

We need to add this action and specify which version of Flutter we want to use. It is recommended to specify the exact version of flutter rather than using stable as the value to avoid potentially significant changes when a new stable version is released.

Now we can pull packages for our application:

- name: Restore packages
  run: flutter pub get
Copy the code

Once they are retrieved, we can build the application in Release mode without signing it:

- name: Build Flutter
  run: flutter build ios --release --no-codesign
Copy the code

We will install the certificate before applying the next step!

Generate xArchive

First, open your iOS project using XCode and select the target, and make sure that Automatically Manage Signing is not selected in Signing & Capabilities so that we can sign it using the required certificate, Without editing the XCode project.

Next, when you sign an iOS application, you don’t sign the pod associated with it, so you need to specify it in your Podfile, as follows:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    target.build_configurations.each do |config|
      config.build_settings['CODE_SIGNING_REQUIRED'] = "NO"
      config.build_settings['CODE_SIGNING_ALLOWED'] = "NO"
    end
  end
end
Copy the code

Before we can build xArchive, we need to resolve the project’s Swift dependencies. This is especially useful if you have some Flutter iOS plugin written in Swift.

- name: Build resolve Swift dependencies
  run: xcodebuild -resolvePackageDependencies -workspace ios/Runner.xcworkspace -scheme Runner -configuration Release
Copy the code

Now to create an XArchive, you need to find some information that can be found in your description file or Apple certificate:

  • Development team identifier
  • UUID, which is the identifier for your Provisioning Profile
  • Code signature identification

After all this, we can use it like this:

- name: Build xArchive
   run: | xcodebuild -workspace ios/Runner.xcworkspace -scheme Runner -configuration Release DEVELOPMENT_TEAM=YOUR_TEAM_ID -sdk 'iphoneos' -destination 'generic/platform=iOS' -archivePath build-output/app.xcarchive PROVISIONING_PROFILE=YOUR_UUID clean archive CODE_SIGN_IDENTITY="Apple Distribution: Damien Aicheh"Copy the code

Generation of ipa

Using the generated XArchive, we can export it as ipA. To do this, we need to add a new file in the project called exportoptions.plist to specify the ExportOptions.


      
<! DOCTYPEplist PUBLIC "- / / / / DTD PLIST Apple 1.0 / / EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>method</key>
  <string>app-store</string> <! -- app-store, ad-hoc, enterprise, development -->
  <key>teamID</key>
  <string>YOUR_TEAM_ID</string>
	<key>signingStyle</key>
	<string>manual</string>
  <key>provisioningProfiles</key>
	<dict>
		<key>YOUR_BUNDLE_ID</key>
		<string>YOUR_UUID</string>
	</dict>
</dict>
</plist>
Copy the code

Depending on your project configuration, you may need to add more options to this file. If desired, you can create an exportOptions.plist file for each environment of the project.

Then simply run this command line and your IPA will generate:

- name: Export ipa
  run: xcodebuild -exportArchive -archivePath build-output/app.xcarchive -exportPath build-output/ios -exportOptionsPlist ios/ExportOptions.plist
Copy the code

Release the product

To access the generated IPA from the GitHub interface, let’s add one final action:

- name: Publish iOS Artefacts
  uses: actions/upload-artifact@v1
  with:
    name: release-ios
    path: build-output/ios
Copy the code

This will release the ios folder containing our IPA. You can then install it on your device.

The last

Now you can share your application with users based on the context of your project! You’ll find sample code in this Github: flutter_BEST_practice.

Refer to the

  • How to build and sign your Flutter iOS application using GitHub Actions
  • How to use environment variables and secrets using GitHub Actions
  • Install the Apple certificate on the macOS runner for Xcode development