Release Announcement - fastlane plugin for setting up GitHub Actions

Release Announcement - fastlane plugin for setting up GitHub Actions

- 7 mins

View project on GitHub 👉 fastlane-plugin-github_action

Preface

Over the past few weeks I’ve been tasked with migrating and setting up new projects on GitHub Actions. GitHub Actions is one of the newer CIs out there. Unlike most CIs, GitHub Actions isn’t the core product. Its a nicely integrated addition into repositories already hosted on GitHub.

The developer experience around GitHub Actions is very well done. Its feels seamless with the rest of GitHub’s interface. The setup process, however, felt similar to other CIs when configuring for fastlane. It requires a manual configuration for setting up SSH keys, a tedius secrets and environment variable input, and handwriting of a YAML file.

I wasn’t happy with how easy it was for me to mess up and the time it took me to setup. This is a story about how I made a scriptable and repeatable process for setting up GitHub Actions for fastlane with fastlane 🚀

The setup

Setting up match to work with match requires two repositories. One repository is the project repository. This is the repository that contains our iOS, macOS, or Android project. The second repository is our match repository. Its a repository that stores encrypted copies of Apple certificates and provisioning profiles used for signing.

The GitHub Action on our project repository does not have access to other repositories outside of itself. An SSH key (called aDeploy Key on GitHub) needs to be used to authorize a connection for our GitHub Action to clone our match repository.

After that, the private key part of the Deploy Key needs to be stored in our project repository secrets. This will be used later when writing the Workflow YAML configuration that powers our GitHub Action.

CI jobs that build and deploy native apps require secrets – and sometimes a lot of them 😉 The values of these secrets shouldn’t be committed to the repository and therefore need to be entered into the service somewhere. Unlike other CIs which have a single step for using secrets in a job, GitHub Actions requires two steps. Firstly, all of your secrets need to be added to your repository through a web interface. Secondly, all of your secrets need to be set to environment variables in your Workflow YAML configuration. Most other CIs will inject the secrets as environment variables for you automatically.

Now that all of that is done we are finally ready to create the Workflow YAML!

Every Workflow configuration needs to start with how the GitHub Action will be triggered. I usually start off with something basic like the following:

on:
  pull_request:
    branches:
      - master

Secrets need to be manually set to load into environment variables in GitHub Actions. Below is a sample of what that would look like:

        env:
          HOCKEY_API_TOKEN: $
          FIREBASE_APP_ID: $
          MATCH_DEPLOY_KEY: $
          GIT_SSH_COMMAND: "ssh -o StrictHostKeyChecking=no"

The private key part of our Deploy Key needs to be added to the GitHub Action for match to be cloned from within our fastlane execution. The following commands will do that:

        run: |
          eval "$(ssh-agent -s)"
          ssh-add - <<< "${MATCH_DEPLOY_KEY}"
          bundle exec fastlane test

I’m exhausted now 😪 That was only one project with a very simple setup.

I’m a lazy developer. I don’t want to configure CI by clicking through websites. I didn’t want to copy and paste YAML files between projects I’ve already setup.

I wanted a proven and repeatable process for setting up fastlane configured with match on a GitHub Actions.

So…

Happy release day!

Happy official release day to my latest fastlane plugin, github_action 🥳

This GitHub Action setup and configuration that we’ve gone through above can all be done with one command in CLI or calling one action in your Fastfile.

CLI

bundle exec fastlane run github_action \
  api_token:"your-github-personal-access-token-with-all-repo-permissions" \
  org:"your-org" \
  repo:"your-repo" \
  match_org:"your-match-repo-org" \
  match_repo:"your-match-repo" \
  dotenv_paths:"fastlane/.env.secret,fastlane/.env.secret2"

Fastfile

lane :init_ci do
  github_action(
    api_token: "your-github-personal-access-token-with-all-repo-permissions",
    org: "your-org",
    repo: "your-repo",
    match_org: "your-match-repo-org", # optional
    match_repo: "your-match-repo", # optional
    dotenv_paths: ["fastlane/.env.secret", "fastlane/.env.secret2"] # optional
  )
end

What does github_action all do?

Great question! It automates the steps of creating an SSH key for your Deploy Key, sets your secrets, and generates a working Workflow YAML file 💪

Below are the those steps in more detail:

1. Prompts you if setup_ci is not found in your Fastfile

Running fastlane on a CI requires the environment to be setup properly. Calling the setup_ci action does that by configuring a new keychain that will be used for code signing with match

2. Create a Deploy Key on your match repository to be used from your GitHub Action

A Deploy Key is needed for GitHub Actions to access your match repository. This action creates a new SSH key and uses the public key for the Deploy Key on your match repository.

This will only get executed if the match_org and match_repo options are specified.

3. Set the Deploy Key private key in secrets (along with secrets in your dotenv file(s)

The private key created for the Deploy Key is store encrypted in your repository secrets. The private key is stored under the name MATCH_DEPLOY_KEY.

Encrypted secrets will also get set for environment variables from dotenv files specified by the dotenv_paths option.

4. Generate a Workflow YAML file to use

A Workflow YAML file is created at .github/workflows/fastlane.yml. This will enable your repository to start running GitHub Actions right away - once committed and pushed :wink:. The Workflow YAML template will add the Deploy Key private key into the GitHub Action by loading it from the MATCH_DEPLOY_KEY secret and executing ssh-add. All of your other encrypted secrets will also be loaded into environment variables for you as well.

name: Execute fastlane

on:
  pull_request:
    branches:
      - master

jobs:
  build_dev:
    name: Execute fastlane
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@master
      - name: Install Ruby Dependencies
        run: bundle install

      - name: Match Repo Clone Test (please delete this)
        env:
          GIT_SSH_COMMAND: "ssh -o StrictHostKeyChecking=no"
          MATCH_DEPLOY_KEY: $
        run: |
          eval "$(ssh-agent -s)"
          ssh-add - <<< "${MATCH_DEPLOY_KEY}"
          git clone git@github.com:joshdholtz/match-repo-for-fastlane-plugin-github_action.git
          ls match-repo-for-fastlane-plugin-github_action

      - name: fastlane
        env:
          APPLICATION_SPECIFIC_PASSWORD: $
          HOCKEY_API_TOKEN: $
          FIREBASE_APP_ID: $
          MATCH_DEPLOY_KEY: $
          GIT_SSH_COMMAND: "ssh -o StrictHostKeyChecking=no"
          MATCH_READONLY: true
        run: |
          eval "$(ssh-agent -s)"
          ssh-add - <<< "${MATCH_DEPLOY_KEY}"
          bundle exec fastlane test

The final step

After running github_actions, the last step is to commit the generated fastlane.yml file and push up to GitHub! I will also do this in a pull request so verify that everything is working. You should see GitHub Action output similar to the below image.

GitHub Action Output Example

Here is a screen recording of the entire process if you don’t believe me that this works 🙃

Let’s wrap it up

Thanks for reading! This plugin may not work for everyone‘s workflow but I hope it can still be helpful. Create any issues or pull requests on the plugin if you see anything that needs changing. I’d be happy to build out new features if there is anything that is missing.

View project on GitHub 👉 fastlane-plugin-github_action

Feel free to message me on Twitter if you have any questions at @joshdholtz 😄

Josh Holtz

Josh Holtz

Software engineer. Open source fanboy.

rss facebook twitter github gitlab youtube mail spotify lastfm instagram linkedin google google-plus pinterest medium vimeo stackoverflow reddit quora quora