DEV Community

Abhishek Thapliyal
Abhishek Thapliyal

Posted on

Deploy iOS Application to AppCenter via Github Actions (Manual Code SignIn)

πŸŒ… Good Morning Guys β˜•οΈ

⏰ 25th March 2022 08:15 hrs IST

I know you have read lots of tutorials same like this. But for me, this is my latest achievement from the last 4 days to learn CI/CD which I have been procrastinating on for a long time. Here is the simplest way to automate uploading iOS build to AppCenter with Fastlane and Github Actions.

Let's make a list we needed.

  1. Apple Account Mandatory for code signing. If you are in a team/organization, you ask for a testing bundle and certificates.

  2. Xcode 13.3/13.2.1, well that is independent but I’m using both so just to mention for clarifying any confusion.

  3. Github, AppCenter, Apple accounts.

  4. Cocoapods, Fastlane lib. No worries I have added steps where ever required.

P.S.: We are pushing build with a development profile to AppCenter and NOT for AppStore because of limited access πŸ˜….

Let's start with some lazy steps.

Account Setup

Sign Up

Github: https://github.com/signup

AppCenter: https://appcenter.ms/create-account

Apple Account: I feel that is already provided by your organization. But still here: https://support.apple.com/en-in/HT204316

Xcode: Download Xcode from here https://developer.apple.com/xcode/
Open Xcode, go to top menu Xcode > Preferences. A dialogue will open, on the bottom left tap on the '+' button, Select Apple Id. Add your credentials and after that when you see your account tap on download profiles.

AppCenter Setup

Here is the helping doc for the dashboard. Login to AppCenter and you will see a dashboard like below.

AppCenter

Top right you will see Add new app button, A side menu will appear to ask below details

  1. App Name: AppCenterDemo-iOS
  2. Release Type: Beta
  3. OS: iOS
  4. Platform: Objective-C / Swift.

Tap on Add new app button on the bottom right and it will redirect you to the app’s dashboard page. There you will get app secret and cocoapods installation link as well. Save the app secret for the next section.

Xcode Project Setup

Open Xcode, create a new project any name let's say AppCenterDemo. You can learn from here as well just in case. Click on Project and you will general settings, tap on signing and capabilities, uncheck automatic sign in and

  1. Choose your organization's team in the dropdown.

  2. Setup your bundle id like com.organization.appname.

  3. Update your .gitignore file before pushing your code to GitHub Like below. We are removing pods, DeriveData, Fastlane some files which are not required in the repo.

xcuserdata/
*.xcscmblueprint
*.xccheckout

build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3

*.hmap
*.ipa
*.dSYM.zip
*.dSYM

timeline.xctimeline
playground.xcworkspace
.build/
Pods/
Carthage/Build/
Dependencies/
.accio/

fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots/**/*.png
fastlane/test_output

iOSInjectionProject/
Enter fullscreen mode Exit fullscreen mode
  1. Download the provisioning profile and keep a soft copy of the same as well for later usage in Fastlane.

Project Settings

  1. Open Keychain, and check the Apple Development certificate provided by your organization or your developer account, tap on to see the dropdown.

  2. You will see a private key. right-click on it and select the export option

Keychain

  1. Save the .p12 file for later use. Here I have created ios_dev_certificate.p12. Use the password when prompted for a password and save it for later use in this tutorial.

development p12

The hard part is done πŸ˜…

  1. Setup cocoapods from here if not done in past. Open podfile and add like below. Here we are integrating the AppCenter.
target 'AppCenterDemo' do
  pod 'AppCenter'
end
Enter fullscreen mode Exit fullscreen mode

Go to the terminal inside the root directory and run pod install in the terminal. You will observe a workspace is created like a project file. Open workspace project.

  1. In the AppDelegate file or in the main file for SwiftUI projects, add the code below. Declare a constant variable for appSecret. AppSecret is the same I mentioned at the end of the previous section.
AppCenter.start(withAppSecret: appSecret, services:[
    Analytics.self,
    Crashes.self
])
Enter fullscreen mode Exit fullscreen mode
  1. Run/Build your project in order to check everything is working.

Fastlane Setup Part 1

For all further steps, I will recommend VS Code Editor. As we will get the project structure and terminal in a single window and we can access .extension files as well.

Install fastlane via running below command.

sudo gem install fastlane 
Enter fullscreen mode Exit fullscreen mode

Open terminal, navigate to project root directory and run

fastlane init
Enter fullscreen mode Exit fullscreen mode

Helping Doc for iOS Setup.

You will see a Fastlane folder with Gemfile, AppFile, Fastfile and plugin files.
Now add AppCenter Plugin for Fastlane via command fastlane add_plugin appcenter.

Now initial Fastlane setup add these in Gemfile and run bundle install.
Here is the Gemfile setup at the end of the doc.

source "https://rubygems.org"

gem 'dotenv-rails', groups: [:development, :test]
gem "fastlane"
gem "xcode-install"
gem "cocoapods"

plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile')
eval_gemfile(plugins_path) if File.exist?(plugins_path)
Enter fullscreen mode Exit fullscreen mode

These are libraries will be used by Fastlane as an initial setup. Dotenv-rails is used to load the environment while running Fastlane.

To specify the ruby version, add .ruby-version file and inside that add a single line string 2.6.8. This will be used by Fastlane.

Now add .env file like below

# General
WORKSPACE=AppCenterDemo.xcworkspace
PROJECT_PATH=AppCenterDemo.xcodeproj
BUILD_CONFIGURATION=Debug
SCHEME=AppCenterDemo
EXPORT_METHOD=development
VERSION_BUMP_TYPE=patch
APP_AUTHOR=Abhishek Thapliyal

# Appcenter
APP_CENTER_OWNER_NAME="thapliyal-fueled.com"
APP_CENTER_APP_NAME="AppCenterDemo-iOS"
APP_CENTER_DISTRIBUTION_GROUPS="Collaborators"
APP_CENTER_NOTIFY_TESTERS=true
APP_CENTER_API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
APP_CENTER_API_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

#CodeSignIn
PROVSIONING_PROFILE_REPO_PATH="./fastlane/provision/Dev_Profile.mobileprovision"
KEYCHAIN_NAME="CodeSignInData"
Enter fullscreen mode Exit fullscreen mode

These are environment variables used in shell script and Fastfile later in the tutorial.

Check the Parameters section for more details of the export method, scheme, workspace, Project Path and build configuration.

To get the APP_CENTER_APP_NAME and APP_CENTER_OWNER_NAME here is the link:

https://appcenter.ms/users/{owner_name}/apps/{app_name}

APP_CENTER_API_KEY: This is the same used previously in AppDelegate. Update here as well.
APP_CENTER_API_TOKEN: https://appcenter.ms/settings/apitokens
Use this link to get API Token.

Github Repo

You need to create a new repository in order to proceed further.
Beginner, please follow these docs for the Github repository setup.

  1. Create Repository

  2. Cloning

  3. SSH Setup

Now add a new folder name provision inside fastlane folder and move the earlier Dev_Profile.mobileprovision file inside. Now push the code to the repo.

Github Secrets

Now we have to setup Github Secrets in order to secure the .p12 file and credentials. Follow this doc for encrypted secrets and create as follow

Github Deploying Xcode Applications Doc

  1. Go to the directory where ios_dev_certificate.p12 is saved earlier. Open terminal in the same directory and run
base64 -i ios_dev_certificate.p12 | pbcopy
Enter fullscreen mode Exit fullscreen mode

This will copy the base64 string in the pasteboard. You can check it via cmd+v. Save it in Github Secrets with the key name IOS_DEVELOPMENT.

  1. The password we have saved while creating the above certificate will be saved in Github Secrets with the key name P12_PASSWORD.

  2. Add one more value KEYCHAIN_PASSWORD for the keychain that will be used in Fastlane. I recommend make it strong.

Github Actions

Now in the root directory of the project.

  1. Add nested folder .github/workflows.

  2. Add yml file name gh_actions.yml inside the workflows folder. There is no specific name you can choose any name.

  3. Update your above yml file like below.

name: iOS App Center Deployment
on: [push]
jobs:
  build:
    runs-on: macos-11
    steps:
      - uses: actions/checkout@v2
      - uses: ruby/setup-ruby@v1
        with:
          bundler-cache: true

      - name: Run Fastlane for iOS
        env:
          IOS_DEVELOPMENT: ${{ secrets.IOS_DEVELOPMENT }}
          P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
          KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
        run: bundle exec fastlane beta_app_upload
Enter fullscreen mode Exit fullscreen mode

name: Workflow name.

on: on which event it will be triggered. Here I have added push i.e. on every push a build will be triggered.

jobs: Series of actions that will be executed.

build: Action Name.

runs-on: OS Name in which actions will be executed.

uses: actions/checkout@v2: Use to checkout branch

uses: ruby/setup-ruby@v1: Ruby setup with bundler-cache: true so that Gemfile libraries can be used.

name: Specifying name.

run: to run shell script command

env: Here we will mention environment variables that will be used in Fastlane and Github actions from Github Secrets.

Here is the reference doc for actions. More details for the workflow file are here.

Well, It’s afternoon 13:30 hrs IST. Have lunch and come back πŸ˜…

Fastlane Setup Part 2

Here is the most important section that will actually deploy our app.

Below are the documented fastlane actions. Please go through once before using.

Now open fastfile inside fastlane folder. Update the code like below.
from this blog I have taken reference to certificates setup. Our agenda is divided in three setps.

  1. Add action to generate KeyChain for code signIn.

  2. Add action to generate iOS Build.

  3. Add action to upload build to AppCenter.

default_platform(:ios)

platform :ios do

  private_lane :setup_certificates do
    create_keychain(
      name: ENV["CodeSignInData"],
      password: ENV["KEYCHAIN_PASSWORD"],
      default_keychain: true,
      unlock: true,
      timeout: 3600,
      lock_when_sleeps: false
    )
    install_provisioning_profile(path: ENV["PROVSIONING_PROFILE_REPO_PATH"])    
    setup_ios_profiles
    import_certificate(
      certificate_path: "fastlane/certificates/ios_dev_certificate.p12",
      certificate_password: ENV["P12_PASSWORD"],
      keychain_name: ENV["CodeSignInData"],
      keychain_password: ENV["KEYCHAIN_PASSWORD"]
    )
  end

  desc "AppCenter iOS App. Upload"
  lane :beta_app_upload do
    xcversion(version: "13.2.1")
    setup_certificates
    clear_derived_data
    xcclean(scheme: ENV["SCHEME"])
    cocoapods(repo_update: true)
    build_ios_app(
      workspace: ENV["WORKSPACE"],
      configuration: ENV["BUILD_CONFIGURATION"],
      scheme: ENV["SCHEME"],
      silent: true,
      clean: false,
      disable_xcpretty: false,
      export_options: {
        method: ENV['EXPORT_METHOD']
      }
    )
    appcenter_upload(
      api_token: ENV["APP_CENTER_API_TOKEN"],
      owner_name: ENV["APP_CENTER_OWNER_NAME"],
      owner_type: "user",
      app_name: ENV["APP_CENTER_APP_NAME"],
      notify_testers: ENV["APP_CENTER_NOTIFY_TESTERS"]
    )
  end
end
Enter fullscreen mode Exit fullscreen mode
  1. create_keychain: use to create keychain in github runner environment. Doc

  2. install_provisioning_profile: use to install provision profiles for code sign in. Doc

  3. import_certificate: use to import .p12 certificate from github secrets mentioned in env file inside github actions yml file previously. Doc

  4. setup_ios_profiles: It’s the custom Fastlane action created by me. Doc Example

  5. Open terminal and run

bundle exec fastlane new_action
Enter fullscreen mode Exit fullscreen mode

It will ask you name for action. I have added setup_ios_profiles. A setup_ios_profiles.rb will be generated inside fastlane folder. Add below code.

module Fastlane
  module Actions
    class SetupIosProfilesAction < Action
      def self.run(params)
        UI.message "Setup Keychain"
        sh "./fastlane/actions/setup_code_signin.sh"
      end

      def self.is_supported?(platform)
        platform == :ios
      end
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

Now create new file setup_code_signin.sh, open terminal in same directory and run

chmod u+x ./setup_code_signin.sh
Enter fullscreen mode Exit fullscreen mode

This command will make file executable for user. After that update code below

DEV_CERTIFICATE_PATH=./fastlane/certificates/ios_dev_certificate.p12

mkdir -p ./fastlane/certificates

echo "$IOS_DEVELOPMENT" | base64 -d -o $DEV_CERTIFICATE_PATH
Enter fullscreen mode Exit fullscreen mode

This script will convert saved base64 string from github secrets, mentioned in yml file, to .p12 file.

  1. xcversion: use to specify Xcode version.

  2. clear_derived_data: use to clear derive data use to clear derive data

  3. xcclean: use to clean project with specified scheme.

  4. cocoapods: use to install cocoapods with repo update if specified.

Now code signIn and fastlane project in github action is almost setup. We have to configure rest two setps. As shown above fastfile code build_ios_app will generate build for iOS (Reference Doc). It will take values mentioned in .env file. Have a closer to export method, you can change to as per doc

export_method // Method used to export the archive. Valid values are: app-store, validation, ad-hoc, package, enterprise, development, developer-id and mac-application.
Enter fullscreen mode Exit fullscreen mode

And the last part upload to AppCenter i.e. appcenter_upload: This method will take App. Name, API Token and Owner Name from .env file. We have discussed earlier as well. As per doc

owner_type: "user" // # Default is user - set to organization for appcenter organizations 

app_name: "<appcenter app name (as seen in app URL)>", 

notify_testers: true // # Set to false if you don't want to notify testers of your new release (default: `false`)
Enter fullscreen mode Exit fullscreen mode

Now push your code and see the magic. If all goes well then in a sample logs for successful app upload to AppCenter will looks like below.

Github Actions

You can cmd+click the link to navigate app center release page as well.

I hope you will get an idea CI/CD works. You can explore more yourself for TestFlight builds as well as managing several environments.

HAPPY CODING πŸ˜ƒπŸ˜ƒ

Good Night 😴 πŸ›Œ

Discussion (0)