mirego / fastlane-toolkit

Boilerplate for faster fastlane integration

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Fastlane toolkit

This project provides a base Fastfile to minimize the amount of configuration required to build a project on CI using manual signing with fastlane.

What's included?

The base Fastfile provides basic model classes to make it easier to work with. These classes includes:

  • Project
    • AppExtension
  • Configuration
    • Certificate
    • ProvisioningProfile

A build is produced by providing a Project object with a Configuration object. To sign a build using Mirego's enterprise certificate, a betaConfiguration object is declared for you containing all the needed information about the certificate and the provisioning profile.

Important to note that this Fastfile is just a starting point, if you need more flexibility or more advanced features I encourage you to use fastlane as it pleases you.

Usage

Start by importing the toolkit at the very top of your Fastfile and defining your project by creating a Project instance describing what's contained in your repository.

import_from_git(url: "git@github.com:mirego/fastlane-toolkit.git")

# ...

sampleProject = Model::Project.new(
  workspacePath: "Sample.xcworkspace",
  projectPath: "Sample.xcodeproj",
  infoPlistPath: "Sample/Info.plist",
  scheme: "Sample",
  target: "Sample",
  bundleIdentifier: "com.mirego.Sample"
)

Once it's done, create a lane that import the toolkit and that calls the provided build_ios_app_with_toolkit lane with your project. You can either explicitly specify the enterprise configuration by calling build_ios_app_with_toolkit(project: sampleProject, configuration: enterprise_configuration()) or simply omit the configuration parameter as it is the default value when none is supplied.

desc "Build using the enterprise certificate and publish on AppCenter"
lane :beta do
  cocoapods(use_bundle_exec: true, try_repo_update_on_error: true)
  build_ios_app_with_toolkit(project: sampleProject)
  changelog_from_git_commits(commits_count: 10)
  appcenter_upload(
    api_token: strip_quotes(ENV["APP_CENTER_API_TOKEN"]),
    owner_type: "organization",
    owner_name: "ORG_NAME",
    app_name: "APP_NAME",
    ipa: lane_context[SharedValues::IPA_OUTPUT_PATH],
    dsym: lane_context[SharedValues::DSYM_OUTPUT_PATH],
    destination_type: "group"
    destinations: ENV["APP_CENTER_DISTRIBUTION_GROUPS"],
  )
end

Custom certificate

If you need to sign your build using a custom signing certificate, create your custom configuration object and call the build_ios_app_with_toolkit lane with it.

appStoreProvisioningProfile = Model::ProvisioningProfile.new(
  path: "./fastlane/provisioning/AppStore.mobileprovision"
)

appStoreCertificate = Model::Certificate.new(
  path: "./fastlane/provisioning/AppStore.p12",
  name: "iPhone Distribution: Sample (????????)",
  password: "SuperStrongPassword"
)

appStoreConfiguration = Model::Configuration.new(
  certificate: appStoreCertificate,
  provisioningProfile: appStoreProvisioningProfile,
  buildConfiguration: "Release",
  exportMethod: "app-store"
)

lane :release do
  build_ios_app_with_toolkit(project: sampleProject, configuration: appStoreConfiguration)
  upload_to_app_store(force: true)
  slack(message: "Successfully submitted #{sampleProject.target} to AppStore", slack_url: "https://hooks.slack.com/services/T025F65SP/AAW2V1FC3/rgMjwWCk21ag79rjdhbfDS78G")
end

Bundle identifier override

If you need to change the bundle identifier of your app before building it, simply assign the bundleIdentifierOverride property of your configuration object prior to calling the build_ios_app_with_toolkit lane.

betaConfiguration.bundleIdentifierOverride = "com.mirego.Sample.beta"

You can also simply re-assign the bundle identifier of your Project instance.

sampleProject.bundleIdentifier = "com.mirego.Sample.beta"

App extensions

If your app contains app extensions, you must provide them via your Project instance.

notificationExtension = Model::AppExtension.new(
  target: "SampleNotifications",
  bundleIdentifier: "com.mirego.Sample.notifications",
  infoPlistPath: "SampleNotifications/Info.plist"
)
sampleProject.extensions = [notificationExtension]

You also need to provide the provisioning profile to use for each of the registered app extensions in your configuration. The property takes a Hash (key value pair) of the extension bundle identifier to a ProvisioningProfile instance.

notificationExtensionProvisioningProfile = Model::ProvisioningProfile.new(
  path: "./fastlane/provisioning/AppStoreNotifications.mobileprovision"
)
configuration.extensionProvisioningProfiles = {
  notificationExtension.bundleIdentifier => notificationExtensionProvisioningProfile
}

Bitcode

Bitcode is enabled by default but if for some reason you need it disabled, you can do so with the include_bitcode option.

build_ios_app_with_toolkit(project: sampleProject, configuration: configuration, include_bitcode: false)

Xcode environment variables

If you need to provide Xcode extra environment variables, you can do so using the xcargs option of the build_ios_app_with_toolkit action.

build_ios_app_with_toolkit(project: sampleProject, configuration: configuration, xcargs: "ENABLE_CONFIG_PANEL=true")

Custom Actions

The project also includes some custom actions described here.

enterprise_configuration

Create a configuration containing a generic provisioning profile and the enterprise certificate. This action take care of extracting informations in environment variables and must be run on Jenkins in order to work.

install_provisioning_profile

Internally required by the build_ios_app_with_toolkit private lane, the install_provisioning_profile action take care of parsing the provisioning profile and install it in the proper location so that Xcode can use it.

Plugins

icon_banner

Use icon_badge plugin to add badge icon to your application icon.

To install:

bundle exec fastlane add_plugin icon_banner

documentation

Jenkins Configuration

Required options

  • Prepare an environment for the run

    • Keep Jenkins Environment Variables
    • Keep Jenkins Build Variables
    • Properties File Path: ${HOME}/.build_ios_env
  • Build

    • Execute shell
      bundle install
      bundle exec fastlane beta
      

Recommended options

  • Color ANSI Console Output: xterm

Jenkins DSL Example

String clientName = 'client'
String projectDisplayName = 'Sample'
String projectName = 'sample'
String folderName = 'Client Display Name'
String slackNotificationChannel = '#project-channel'

folder("$folderName") {
    description('Jobs related to ' + clientName.capitalize())
}

job("$folderName/$clientName-$projectName-watcher") {
    description("Repository watcher for master branch of the $projectDisplayName mobile app")
    scm {
        git {
            branch('origin/master')
            remote {
                name('origin')
                url("${GIT_URL}")
                credentials('github')
            }
            extensions {
                submoduleOptions {
                  recursive()
                }
            }
        }
    }
    triggers {
        scm('H/5 * * * *')
    }
    steps {
        triggerBuilder {
            configs {
                blockableBuildTriggerConfig {
                    projects("$folderName/$clientName-$projectName-ios-fastlane")
                    block {
                        buildStepFailureThreshold("never")
                        unstableThreshold("never")
                        failureThreshold("never")
                    }
                    configs {
                        predefinedBuildParameters {
                            textParamValueOnNewLine(false)
                            properties('''Branch=${GIT_BRANCH}
Lane=beta''')
                        }
                    }
                }
            }
        }
    }
}

job("$folderName/$clientName-$projectName-ios-fastlane") {
    description("Builds $projectDisplayName Sample iOS app")
    logRotator {
        numToKeep(5)
    }
    parameters {
        stringParam {
            name('Branch')
            defaultValue('origin/master')
            description('The git branch to be built')
            trim(true)
        }
        choiceParam('Lane', ['beta', 'app_store'], 'Name of the lane to run in fastlane')
    }
    environmentVariables {
        keepBuildVariables(true)
        keepSystemVariables(true)
        propertiesFile('${HOME}/.build_ios_env')
    }
    scm {
        git {
            branch('${Branch}')
            remote {
                name('origin')
                url("${GIT_URL}")
                credentials('github')
            }
            extensions {
                submoduleOptions {
                    recursive(true)
                }
                wipeOutWorkspace()
            }
        }
    }
    steps {
        shell('''bundle install
bundle exec fastlane ${Lane}''')
    }
    wrappers {
        colorizeOutput()
    }
    publishers {
        jUnitResultArchiver {
            testResults('fastlane/test_output/report.junit')
        }
        cobertura('cobertura.xml') {
            failNoReports(false)
            sourceEncoding('ASCII')

            methodTarget(80, 0, 0)
            lineTarget(80, 0, 0)
            conditionalTarget(70, 0, 0)
        }
        slackNotifier {
            notifyBackToNormal(true)
            notifyFailure(true)
            room(slackNotificationChannel)
        }
    }
}

Contributing

If you find that something else could be useful or if your use case is not covered and you feel that it could benefit others, please take the time to contribute by opening a pull request or open an issue asking for it very very kindly ;)

About

Boilerplate for faster fastlane integration


Languages

Language:Ruby 100.0%