AWS CodeBuild for macOS provides help for Fastlane

0
240
AWS CodeBuild for macOS provides help for Fastlane


Voiced by Polly

I’m happy to announce the provision of Fastlane in your AWS CodeBuild for macOS environments. AWS CodeBuild is a totally managed steady integration service that compiles supply code, runs checks, and produces ready-to-deploy software program packages.

Fastlane is an open supply device suite designed to automate numerous elements of cellular utility growth. It offers cellular utility builders with a centralized set of instruments to handle duties comparable to code signing, screenshot technology, beta distribution, and app retailer submissions. It integrates with in style steady integration and steady deployment (CI/CD) platforms and helps each iOS and Android growth workflows. Although Fastlane gives important automation capabilities, builders might encounter challenges throughout its setup and upkeep. Configuring Fastlane may be advanced, significantly for groups unfamiliar with the syntax and package deal administration system of Ruby. Keeping Fastlane and its dependencies updated requires ongoing effort, as a result of updates to cellular platforms or third-party companies might necessitate changes to present workflows.

When we launched CodeBuild for macOS in August 2024, we knew that one among your challenges was to put in and preserve Fastlane in your construct atmosphere. Although it was potential to manually set up Fastlane in a customized construct atmosphere, at AWS, we take away the undifferentiated heaving lifting out of your infrastructure so you possibly can spend extra time on the elements that matter for your small business. Starting right this moment, Fastlane is put in by default, and you need to use the acquainted command fastlane constructin your buildspec.yaml file.

Fastlane and code signing
To distribute an utility on the App Store, builders should signal their binary with a personal key generated on the Apple Developer portal. This personal key, together with the certificates that validates it, have to be accessible through the construct course of. This is usually a problem for growth groups as a result of they should share the event personal key (which permits deployment on chosen take a look at units) amongst crew members. Additionally, the distribution personal key (which permits publishing on the App Store) have to be out there through the signing course of earlier than importing the binary to the App Store.

Fastlane is a flexible construct system in that it additionally helps builders with the administration of growth and distribution keys and certificates. Developers can use fastlane match to share signing supplies in a crew and make them securely and simply accessible on particular person builders’ machines and on the CI atmosphere. match permits the storage of personal keys, the certificates, and the cellular provisioning profiles on a secured share storage. It makes positive that the native construct atmosphere, whether or not it’s a developer laptop computer or a server machine within the cloud, stays in sync with the shared storage. At construct time, it securely downloads the required certificates to signal your app and configures the construct machine to permit the codesign utility to select them up.

match permits the sharing of signing secrets and techniques by means of GitHub, GitLab, Google Cloud Storage, Azure DevOps, and Amazon Simple Storage Service (Amazon S3).

If you already use one among these and also you’re migrating your initiatives to CodeBuild, you don’t have a lot to do. You solely want to verify your CodeBuild construct atmosphere has entry to the shared storage (see step 3 within the demo).

Let’s see the way it works
If you’re new to Fastlane or CodeBuild, let’s see the way it works.

For this demo, I begin with an present iOS mission. The mission is already configured to be constructed on CodeBuild. You can check with my earlier weblog put up, Add macOS to your steady integration pipelines with AWS CodeBuild, to study extra particulars.

I’ll present you the best way to get began in three steps:

  • Import your present signing supplies to a shared personal GitHub repository
  • Configure fastlane to construct and signal your mission
  • Use fastlanewith CodeBuild

Step 1: Import your signing supplies

Most of the fastlane documentation I learn explains the best way to create a brand new key pair and a brand new certificates to get began. Although that is definitely true for brand spanking new initiatives, in actual life, you in all probability have already got your mission and your signing keys. So, step one is to import these present signing supplies.

Apple App Store makes use of totally different keys and certificates for growth and distribution (there are additionally advert hoc and enterprise certificates, however these are outdoors the scope of this put up). You will need to have three recordsdata for every utilization (that’s a complete of six recordsdata):

  • A .mobileprovision file which you could create and obtain from the Apple developer console. The provisioning profile hyperlinks your id, the app id, and the entitlements the app may need.
  • A .cer file, which is the certificates emitted by Apple to validate your personal key. You can obtain this from the Apple Developer portal. Select the certificates, then choose Download.
  • A .p12 file, which comprises your personal key. You can obtain the important thing whenever you create it within the Apple Developer portal. If you didn’t obtain it however have it in your machine, you possibly can export it from the Apple Keychain app. Note that the KeyChain.app is hidden in macOS 15.x. You can open it with open /System/Library/CoreServices/Applications/Keychain Access.app. Select the important thing you need to export and proper click on to pick Export.
Export p12 files from Keychain

When you might have these recordsdata, create a fastlane/Matchfile file with the next content material:

git_url("https://github.com/sebsto/secret.git")
storage_mode("git")
kind("growth")
# or use appstore to make use of the distribution signing key and certificates
# kind("appstore")

Be positive to interchange the URL of your GitHub repository and be sure that this repository is personal. It will function a storage on your signing key and certificates.

Then, I import my present recordsdata with the fastlane match import --type appstore command. I repeat the command for every atmosphere: appstore and growth.

The very first time, fastlane prompts me for my Apple Id username and password. It connects to App Store Connect to confirm the validity of the certificates or to create new ones when obligatory. The session cookie is saved in ~/.fastlane/spaceship//cookie.

fastlane match additionally asks for a password. It makes use of this password to generate a key to crypt the signing supplies on the storage. Don’t overlook this password as a result of will probably be used at construct time to import the signing supplies on the construct machine.

Here is the command and its output in full:

 fastlane match import --type appstore

[✔] 🚀
[16:43:54]: Successfully loaded '~/amplify-ios-getting-started/code/fastlane/Matchfile' 📄

+-----------------------------------------------------+
| Detected Values from './fastlane/Matchfile'         |
+--------------+--------------------------------------+
| git_url.     | https://github.com/sebsto/secret.git |
| storage_mode | git                                  |
| kind         | growth                          |
+--------------+--------------------------------------+

[16:43:54]: Certificate (.cer) path:
./secrets and techniques/sebsto-apple-dist.cer
[16:44:07]: Private key (.p12) path:
./secrets and techniques/sebsto-apple-dist.p12
[16:44:12]: Provisioning profile (.mobileprovision or .provisionprofile) path or depart empty to skip
this file:
./secrets and techniques/amplifyiosgettingstarteddist.mobileprovision
[16:44:25]: Cloning distant git repo...
[16:44:25]: If cloning the repo takes too lengthy, you need to use the `clone_branch_directly` possibility in match.
[16:44:27]: Checking out department grasp...
[16:44:27]: Enter the passphrase that must be used to encrypt/decrypt your certificates
[16:44:27]: This passphrase is particular per repository and shall be saved in your native keychain
[16:44:27]: Make positive to recollect the password, as you will want it whenever you run match on a distinct machine
[16:44:27]: Passphrase for Match storage: ********
[16:44:30]: Type passphrase once more: ********
safety: SecKeychainAddInternetPassword : The specified merchandise already exists within the keychain.
[16:44:31]: 🔓 Successfully decrypted certificates repo
[16:44:31]: Repo is at: '/var/folders/14/nwpsn4b504gfp02_mrbyd2jr0000gr/T/d20250131-41830-z7b4ic'
[16:44:31]: Login to App Store Connect (sebsto@mac.com)
[16:44:33]: Enter the passphrase that must be used to encrypt/decrypt your certificates
[16:44:33]: This passphrase is particular per repository and shall be saved in your native keychain
[16:44:33]: Make positive to recollect the password, as you will want it whenever you run match on a distinct machine
[16:44:33]: Passphrase for Match storage: ********
[16:44:37]: Type passphrase once more: ********
safety: SecKeychainAddInternetPassword : The specified merchandise already exists within the keychain.
[16:44:39]: 🔒 Successfully encrypted certificates repo
[16:44:39]: Pushing adjustments to distant git repo...
[16:44:40]: Finished importing recordsdata to Git Repo [https://github.com/sebsto/secret.git]

I confirm that Fastlane imported my signing materials to my Git repository.

Fastlane match - github repo after import

I also can configure my native machine to make use of these signing supplies through the subsequent construct:

» fastlane match appstore 

[✔] 🚀 
[17:39:08]: Successfully loaded '~/amplify-ios-getting-started/code/fastlane/Matchfile' 📄

+-----------------------------------------------------+
|   Detected Values from './fastlane/Matchfile'       |
+--------------+--------------------------------------+
| git_url      | https://github.com/sebsto/secret.git |
| storage_mode | git                                  |
| kind         | growth                          |
+--------------+--------------------------------------+


+-------------------------------------------------------------------------------------------+
|                                 Summary for match 2.226.0                                 |
+----------------------------------------+--------------------------------------------------+
| kind                                   | appstore                                         |
| readonly                               | false                                            |
| generate_apple_certs                   | true                                             |
| skip_provisioning_profiles             | false                                            |
| app_identifier                         | ["com.amazonaws.amplify.mobile.getting-started"] |
| username                               | xxxx@xxxxxxxxx                                   |
| team_id                                | XXXXXXXXXX                                       |
| storage_mode                           | git                                              |
| git_url                                | https://github.com/sebsto/secret.git             |
| git_branch                             | grasp                                           |
| shallow_clone                          | false                                            |
| clone_branch_directly                  | false                                            |
| skip_google_cloud_account_confirmation | false                                            |
| s3_skip_encryption                     | false                                            |
| gitlab_host                            | https://gitlab.com                               |
| keychain_name                          | login.keychain                                   |
| power                                  | false                                            |
| force_for_new_devices                  | false                                            |
| include_mac_in_profiles                | false                                            |
| include_all_certificates               | false                                            |
| force_for_new_certificates             | false                                            |
| skip_confirmation                      | false                                            |
| safe_remove_certs                      | false                                            |
| skip_docs                              | false                                            |
| platform                               | ios                                              |
| derive_catalyst_app_identifier         | false                                            |
| fail_on_name_taken                     | false                                            |
| skip_certificate_matching              | false                                            |
| skip_set_partition_list                | false                                            |
| force_legacy_encryption                | false                                            |
| verbose                                | false                                            |
+----------------------------------------+--------------------------------------------------+

[17:39:08]: Cloning distant git repo...
[17:39:08]: If cloning the repo takes too lengthy, you need to use the `clone_branch_directly` possibility in match.
[17:39:10]: Checking out department grasp...
[17:39:10]: Enter the passphrase that must be used to encrypt/decrypt your certificates
[17:39:10]: This passphrase is particular per repository and shall be saved in your native keychain
[17:39:10]: Make positive to recollect the password, as you will want it whenever you run match on a distinct machine
[17:39:10]: Passphrase for Match storage: ********
[17:39:13]: Type passphrase once more: ********
safety: SecKeychainAddInternetPassword : The specified merchandise already exists within the keychain.
[17:39:15]: 🔓  Successfully decrypted certificates repo
[17:39:15]: Verifying that the certificates and profile are nonetheless legitimate on the Dev Portal...
[17:39:17]: Installing certificates...

+-------------------------------------------------------------------------+
|                          Installed Certificate                          |
+-------------------+-----------------------------------------------------+
| User ID           | XXXXXXXXXX                                          |
| Common Name       | Apple Distribution: Sebastien Stormacq (XXXXXXXXXX) |
| Organisation Unit | XXXXXXXXXX                                          |
| Organisation      | Sebastien Stormacq                                  |
| Country           | US                                                  |
| Start Datetime    | 2024-10-29 09:55:43 UTC                             |
| End Datetime      | 2025-10-29 09:55:42 UTC                             |
+-------------------+-----------------------------------------------------+

[17:39:18]: Installing provisioning profile...

+-------------------------------------------------------------------------------------------------------------------+
|                                          Installed Provisioning Profile                                           |
+---------------------+----------------------------------------------+----------------------------------------------+
| Parameter           | Environment Variable                         | Value                                        |
+---------------------+----------------------------------------------+----------------------------------------------+
| App Identifier      |                                              | com.amazonaws.amplify.cellular.getting-starte  |
|                     |                                              | d                                            |
| Type                |                                              | appstore                                     |
| Platform            |                                              | ios                                          |
| Profile UUID        | sigh_com.amazonaws.amplify.cellular.getting-s  | 4e497882-d80f-4684-945a-8bfec1b310b9         |
|                     | tarted_appstore                              |                                              |
| Profile Name        | sigh_com.amazonaws.amplify.cellular.getting-s  | amplify-ios-getting-started-dist             |
|                     | tarted_appstore_profile-name                 |                                              |
| Profile Path        | sigh_com.amazonaws.amplify.cellular.getting-s  | /Users/stormacq/Library/CellularDevice/Provis  |
|                     | tarted_appstore_profile-path                 | ioning                                       |
|                     |                                              | Profiles/4e497882-d80f-4684-945a-8bfec1b310  |
|                     |                                              | b9.mobileprovision                           |
| Development Team ID | sigh_com.amazonaws.amplify.cellular.getting-s  | XXXXXXXXXX                                   |
|                     | tarted_appstore_team-id                      |                                              |
| Certificate Name    | sigh_com.amazonaws.amplify.cellular.getting-s  | Apple Distribution: Sebastien Stormacq       |
|                     | tarted_appstore_certificate-name             | (XXXXXXXXXX)                                 |
+---------------------+----------------------------------------------+----------------------------------------------+

[17:39:18]: All required keys, certificates and provisioning profiles are put in 🙌

Step 2: Configure Fastlane to signal your mission

I create a Fastlane construct configuration file in fastlane/Fastfile (you need to use fastlane init command to get began):

default_platform(:ios)

platform :ios do
  before_all do
    setup_ci
  finish

  desc "Build and Sign the binary"
  lane :construct do
    match(kind: "appstore", readonly: true)
    gymnasium(
      scheme: "getting began",
      export_method: "app-store"
    )
  finish
finish

Make positive that the setup_ci motion is added to the before_all part of Fastfile for the match motion to perform accurately. This motion creates a short lived Fastlane keychain with appropriate permissions. Without this step, you could encounter construct failures or inconsistent outcomes.

And I take a look at an area construct with the command fastlane construct. I enter the password I used when importing my keys and certificates, then I let the system construct and signal my mission. When every part is accurately configured, it produces an identical output.

...
[17:58:33]: Successfully exported and compressed dSYM file
[17:58:33]: Successfully exported and signed the ipa file:
[17:58:33]: ~/amplify-ios-getting-started/code/getting began.ipa

+---------------------------------------+
|           fastlane abstract            |
+------+------------------+-------------+
| Step | Action           | Time (in s) |
+------+------------------+-------------+
| 1    | default_platform | 0           |
| 2    | setup_ci         | 0           |
| 3    | match            | 36          |
| 4    | gymnasium              | 151         |
+------+------------------+-------------+

[17:58:33]: fastlane.instruments completed efficiently 🎉

Step 3: Configure CodeBuild to make use of Fastlane

Next, I create a mission on CodeBuild. I’m not going into the step-by-step information that will help you to take action. You can check with my earlier put up or to the CodeBuild documentation.

There is only one Fastlane-specific configuration. To entry the signing supplies, Fastlane requires entry to 3 secret values that I’ll cross as atmosphere variables:

  • MATCH_PASSWORD, the password I entered when importing the signing materials. Fastlane makes use of this password to decipher the encrypted recordsdata within the GitHub repository
  • FASTLANE_SESSION, the worth of the Apple Id session cookie, positioned at ~/.fastlane/spaceship//cookie. The session is legitimate from a few hours to a number of days. When the session expires, reauthenticate with the command fastlane spaceauth out of your laptop computer and replace the worth of FASTLANE_SESSION with the brand new worth of the cookie.
  • MATCH_GIT_BASIC_AUTHORIZATION, a base 64 encoding of your GitHub username, adopted by a colon, adopted by a private authentication token (PAT) to entry your personal GitHub repository. You can generate PAT on the GitHub console in Your Profile > Settings > Developers Settings > Personal Access Token. I take advantage of this command to generate the worth of this atmosphere variable: echo -n my_git_username:my_git_pat | base64.

Note that for every of those three values, I can enter the Amazon Resource Name (ARN) of the key on AWS Secrets Manager or the plain textual content worth. We strongly suggest utilizing Secrets Manager to retailer security-sensitive values.

I’m a security-conscious person, so I retailer the three secrets and techniques in Secrets Manager with these instructions:

aws --region $REGION secretsmanager create-secret --name /CodeBuild/MATCH_PASSWORD --secret-string MySuperSecretPassword
aws --region $REGION secretsmanager create-secret --name /CodeBuild/FASTLANE_SESSION --secret-string $(cat ~/.fastlane/spaceship/my_appleid_username/cookie)
aws --region $REGION secretsmanager create-secret --name /CodeBuild/MATCH_GIT_BASIC_AUTHORIZATION --secret-string $(echo -n my_git_username:my_git_pat | base64)

If your construct mission refers to secrets and techniques saved in Secrets Manager, the construct mission’s service function should permit the secretsmanager:GetSecretValue motion. If you selected New service function whenever you created your mission, CodeBuild contains this motion within the default service function on your construct mission. However, should you selected Existing service function, you need to embody this motion to your service function individually.

For this demo, I take advantage of this AWS Identity and Access Management (IAM) coverage:

{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Action": [
				"secretsmanager:GetSecretValue"
			],
			"Resource": [
				"arn:aws:secretsmanager:us-east-2:012345678912:secret:/CodeBuild/*"
			]
		}
	]
}

After I created the mission within the CodeBuild part of the AWS Management Console, I enter the three atmosphere variables. Notice that the worth is the title of the key in Secrets Manager.

Codebuild - environment variables for Fastlane match

You also can outline the atmosphere variables and their Secrets Manager secret title in your buildpsec.yaml file.

Next, I modify the buildspec.yaml file on the root of my mission to make use of fastlane to construct and signal the binary. My buildspec.yaml file now seems to be like this one:

# buildspec.yml
model: 0.2
phases:
  set up:
    instructions:
      - code/ci_actions/00_install_rosetta.sh
  pre_build:
    instructions:
      - code/ci_actions/02_amplify.sh
  construct:
    instructions:
      - (cd code && fastlane construct)
artifacts:
  title: getting-started-$(date +%Y-%m-%d).ipa
  recordsdata:
    - 'getting began.ipa'
  base-directory: 'code'

The Rosetta and Amplify scripts are required to obtain the Amplify configuration for the backend. If you don’t use AWS Amplify in your mission, you don’t want these.

Notice that there’s nothing within the construct file that downloads the signing key or prepares the keychain within the construct atmosphere; fastlane match will try this for me.

I add the brand new buildspec.yaml file and my ./fastlane listing to Git. I commit and push these recordsdata. git commit -m "add fastlane help" && git push

When every part goes nicely, I can see the construct operating on CodeBuild and the Succeeded message.

Codebuild - succeed message

Pricing and availability
Fastlane is now pre-installed at no additional price on all macOS pictures that CodeBuild makes use of, in all Regions the place CodeBuild for macOS is on the market. At the time of this writing, these are US East (Ohio, N. Virginia), US West (Oregon), Asia Pacific (Sydney), and Europe (Frankfurt).

In my expertise, it takes a little bit of time to configure fastlane match accurately. When it’s configured, having it engaged on CodeBuild is fairly simple. Before making an attempt this on CodeBuild, make sure it really works in your native machine. When one thing goes unsuitable on CodeBuild, triple-check the values of the atmosphere variables and ensure CodeBuild has entry to your secrets and techniques on AWS Secrets Manager.

Now go construct (on macOS)!

LEAVE A REPLY

Please enter your comment!
Please enter your name here