ページ

2018年5月1日火曜日

CircleCI2.0+FastlaneでFabric配布

CircleCI 2.0 / Fabric / Fabric

CircleCI 1.0と2.0の違い

  • 実行環境の違い
    • 1.0では既に用意されていた環境、2.0ではDockerコンテナを使える
    • 最新のDockerを使える
    • Workflow が登場 平行して実行できる
  • 設定ファイルの違い
    • 2.0では .circleci/config.ymlに配置
    • 1.0の書き方
      yml
      machine:
        python:
          version: 3.4.2
      test:
        override:
          - echo test
      deployment:
        deploy:
          branch: master
          commands:
            - echo deploy
      
      1.0ではmachineのsetupやtest、deploymentなどをそれぞれ書く。
      実行順はあらかじめ決められており、上の場合だとmachine -> test -> deploymentの順に実行される。
    • 2.0の書き方
      yml
      version: 2
      jobs:
        build:
          docker:
            - image: python:3.4.2
          steps:
            - checkout
        test:
          docker:
            - image: python:3.4.2
          steps:
            - checkout
            - run: echo test
        deploy:
          machine: True
          steps:
            - run: echo deploy
      workflows:
        version: 2
        build_and_test:
          jobs:
            - build
            - test:
                requires:
                  - build
            - deploy:
                requires:
                  - test
                filters:
                  branches:
                    only: master
      
      2.0では自分たちでjobsで実行するタスクを定義して、workflowsでその実行順を定義する
      ※dockerを利用した場合にCircleCIのCLIでローカルマシンでの確認もできる
  • job
    • jobsで定義するjobはmachine (VM)とdockerがある
      • それぞれの環境でstepsの内容を実行する。
  • workflow
    • jobsで実行するjobを呼ぶ
    • jobsで実行順番を指定したい場合はrequiresにどのjobが終了したらこのjobを実行するかを定義できる
    • 特定のブランチだけで動作させたい場合はfiltersを追加
  • checkout
    • 設定されたpathにソースコードをcheck outする。
    • デフォルトでは、 working_directory がそのpathになる

:computer:環境構築


ローカルで確認できるようにコマンドをインストール
$ curl -o /usr/local/bin/circleci https://circle-downloads.s3.amazonaws.com/releases/build_agent_wrapper/circleci && chmod +x /usr/local/bin/circleci
$ circleci update
  • 設定した config.ymlが正しいか確認する
    sh
    $ circleci config validate -c .circleci/config.yml
    
  • circleciをlocalで動かす
    sh
    $ circleci build .circleci/config.yml
    
    > circleci build .circleci/config.yml
    
    ====>> Spin up Environment
    Build-agent version 0.0.4775-4387c40 (2018-03-26T10:29:11+0000)
    Starting container circleci/ruby:2.4-node
      image cache not found on this host, downloading circleci/ruby:2.4-node
    2.4-node: Pulling from circleci/ruby
    ...
    0c9ca1efe50f: Pull complete
    Digest: sha256:61a151e09f55cdba38800c18395a0371d1cc9a568ff33e47c9ca5e3c5df73f3a
    Status: Downloaded newer image for circleci/ruby:2.4-node
      using image circleci/ruby@sha256:61a151e09f55cdba38800c18395a0371d1cc9a568ff33e47c9ca5e3c5df73f3a
    
    Using build environment variables:
      BASH_ENV=/tmp/.bash_env-localbuild-1522200526
      CI=true
      CIRCLECI=true
      CIRCLE_BRANCH=master
      CIRCLE_BUILD_NUM=
      CIRCLE_JOB=build
      CIRCLE_NODE_INDEX=0
      CIRCLE_NODE_TOTAL=1
      CIRCLE_REPOSITORY_URL=git@github.com:Slowhand0309/circleci-demo-ruby.git
      CIRCLE_SHA1=070ea145dd7e51b3c402b156051a64d32cb0c90a
      CIRCLE_SHELL_ENV=/tmp/.bash_env-localbuild-1522200526
      CIRCLE_WORKING_DIRECTORY=~/project
    
    ====>> Checkout code
      #!/bin/sh
    mkdir -p /home/circleci/project && cp -r /tmp/_circleci_local_build_repo/. /home/circleci/project
    ====>> Which bundler?
      #!/bin/bash -eo pipefail
    bundle -v
    Bundler version 1.16.1
    Success!
    

:pencil: 実装


概要

CircleCI2.0+Fastlaneでは証明書はmatchを使うのがデフォルトになっているらしい。
matchだとプライベートなリポジトリに証明書など一式アップしないといけないので、
今回はmatchは使わずにデプロイできるようにする。
※ keychainの作成に関する調べ物で参考にしたリンク
https://qiita.com/nomadmonad/items/baf089e7d7bcf27ab8ee

セットアップ

  • CircleCIでプロジェクトの設定をする
    「ADD PROJECTS」>「対象のプロジェクト」>「Set Up Project」を選択 
    image.png (126.1 kB)
    Operating SystemはmacOSでLaunguageはSwiftを選択し、Start buildingで設定します。
  • ローカルでFastlane初期化
    Gemfile
    source "https://rubygems.org"
    
    gem 'fastlane'
    gem 'cocoapods'
    
    sh
    $ bundle exec fastlane init
    

設定ファイル

最終的に以下でファイル作成しました。
circleci/config.yml
references:
  defaults: &defaults
    macos:
      xcode: "9.2.0"
    working_directory: ~/project
    shell: /bin/bash --login -eo pipefail
    environment:
      TZ: "/usr/share/zoneinfo/Asia/Tokyo"
      LANG: en_US.UTF-8
      LC_ALL: en_US.UTF-8

version: 2
jobs:
  build:
    <<: *defaults
    branches:
      only:
        - develop
    environment:
      FASTLANE_LANE: crashlytics_stg
    steps:
      - checkout:
          path: ~/project
      - run:
          name: Set Ruby Version
          command:  echo "ruby-2.4" > ~/.ruby-version
      - run:
          name: Decode certificates
          command: base64 -D -o XXXXXX.p12 <<< $CERTIFICATES
      - run:
          name: Make Provisioning Profiles directory
          command: mkdir -pv ~/Library/MobileDevice/Provisioning\ Profiles/
      - run:
          name: Decode Provisioning Profiles
          command: base64 -D -o ~/Library/MobileDevice/Provisioning\ Profiles/xxxxxx.mobileprovision <<< $PROVISIONING_PROFILES


      - restore_cache:
          key: v1-gems-{{ checksum "Gemfile.lock" }}
          path: vendor/bundle
      - run:
          name: Bundle install
          command: bundle check || bundle install
          environment:
            BUNDLE_JOBS: 4
            BUNDLE_RETRY: 3
      - save_cache:
          key: v1-gems-{{ checksum "Gemfile.lock" }}
          paths: vendor/bundle
      - restore_cache:
          keys:
          - v1-pods-{{ checksum "Podfile.lock" }}
          path: Pods
      - run:
          name: Running pod install
          command: bundle exec fastlane ios setup
          environment:
            BUNDLE_JOBS: 4
            BUNDLE_RETRY: 3
      - save_cache:
          key: v1-pods-{{ checksum "Podfile.lock" }}
          paths: Pods
      - run:
          name: Fastlane
          command: bundle exec fastlane ios $FASTLANE_LANE
事前にcircleci側に$CERTIFICATES$PROVISIONING_PROFILESの環境変数を設定しておきます。
※値としては証明書とProvisioning Profileを一旦base64にエンコードした物を設定してます、。
sh
$ base64 -i xxxxx.p12 | pbcopy
$ base64 -i xxxxx. mobileprovision | pbcopy
Fastfile
default_platform(:ios)

platform :ios do

  before_all do
    ENV["SLACK_URL"] = 'xxxxxxxxx'
    ENV["CRASHLYTICS_API_TOKEN"] = xxxxxxxx'
    ENV["CRASHLYTICS_BUILD_SECRET"] = 'xxxxxxxxxx'
    ENV["FL_OUTPUT_DIR"] = 'temp'

    clear_derived_data(derived_data_path: "./DerivedData")
    sh "rm -rf ../build"
  end

  desc "Runs setup"
  lane :setup do
    unless File.exist?("../Pods/Manifest.lock") && FileUtils.cmp("../Podfile.lock", "../Pods/Manifest.lock") then
      cocoapods(verbose: true)
    end
  end

  desc "Runs build to stging"
  lane :build_stg do

    if is_ci?
      setup_circle_ci
      import_certificate(
        keychain_name: ENV["MATCH_KEYCHAIN_NAME"],
        keychain_password: ENV["MATCH_KEYCHAIN_PASSWORD"],
        certificate_path: 'xxxxxxx.p12',
        certificate_password: ''
      )
    end

    update_app_identifier(
      xcodeproj: "Xxxxx.xcodeproj",
      plist_path: "Xxxxx/Info.plist",
      app_identifier: 'com.xxxx.xxxx'
    )

    gym(
      scheme: 'Xxxx',
      configuration: 'Debug',
      derived_data_path: "./DerivedData",
      export_method: "ad-hoc",
      clean: true,
      verbose: true,
      output_directory: "build",
      output_name: 'Xxxxx,
      xcargs: "OTHER_SWIFT_FLAGS='$(inherited) -DSTGING' PROVISIONING_PROFILE_SPECIFIER='com.xxxx.xxxx AdHoc' CODE_SIGN_IDENTITY='iPhone Distribution'",
      export_xcargs: "-allowProvisioningUpdates",
      export_options: {
        provisioningProfiles: {
          'com.xxxx.xxxx' => 'com.xxxx.xxxx AdHoc'
        }
      }
    )
  end

  lane :crashlytics_stg do
    build_stg
    crashlytics(
      crashlytics_path: './Pods/Crashlytics/iOS/Crashlytics.framework',
      api_token: ENV['CRASHLYTICS_API_TOKEN'],
      build_secret: ENV['CRASHLYTICS_BUILD_SECRET'],
      ipa_path: './build/Xxxxx.ipa',
      notifications: true,
      notes: "Fastlaneからの自動デプロイです",
      groups: "xxxxx"
    )
    if is_ci?
      slack(
        message: "Successfully deployed new App Update."
      )
    end
  end

  error do |lane, exception|
    if is_ci?
      slack(
        message: exception.message,
        success: false
      )
    else
      puts exception.message
    end
  end
end
ポイントとしては、build_stgの先頭で
ruby
    setup_circle_ci
    import_certificate(
      keychain_name: ENV["MATCH_KEYCHAIN_NAME"],
      keychain_password: ENV["MATCH_KEYCHAIN_PASSWORD"],
      certificate_path: 'xxxxxxx.p12',
      certificate_password: ''
    )
上記で一時的なKeychainをCircleCI上に作成し、デコードした
証明書とプロビジョニングプロファイルを設定しています。

:bomb: バッドノウハウ


  • Error computing cache key
    Error computing cache key: template: cacheKey:1:19: executing "cacheKey"
    
    チェックサム化するファイルのパスが間違っていた為...
    https://qiita.com/sawadashota/items/d1382b1e1b9a5595ab66
  • The key you are authenticating with has been marked as read only
    ERROR: The key you are authenticating with has been marked as read only.
    
    今回の実装とは関係ないですが、Githubにpushしようとしたら↑のエラーに遭遇
    CircleCIのProjectの設定でCheckout SSH Keysから設定する
    Authrization Githubというのがあったので追加して見たらうまく行きました:+1:

  • OSをMacでCI実行した時のrubyバージョンエラー
    Jwt-2.1.0 requires ruby version >= 2.1, which is incompatible with the current version, ruby 2.0.0p648
    
          - run:
              name: Set Ruby Version
              command:  echo "ruby-2.4" > ~/.ruby-version
    
    上を追加してOKデシタ
  • CocoaPodsで設定したライブライが provisioning profilesでエラーになる
    [19:03:54]: ▸ === BUILD TARGET FAPanels OF PROJECT Pods WITH CONFIGURATION Release ===
    [19:03:54]: ▸ Check dependencies
    [19:03:54]: ▸ Code Signing Error: XXXXXX does not support provisioning profiles. XXXXXX does not support provisioning profiles, but provisioning profile NO_SIGNING/ has been manually specified. Set the provisioning profile value to "Automatic" in the build settings editor.
    [19:03:54]: 
    [19:03:54]: ⬆️  Check out the few lines of raw `xcodebuild` output above for potential hints on how to solve this error
    [19:03:54]: 📋  For the complete and more detailed error log, check the full log at:
    [19:03:54]: 📋  /Users/distiller/Library/Logs/gym/XXXX.log
    [19:03:54]: 
    [19:03:54]: Looks like fastlane ran into a build/archive error with your project
    [19:03:54]: It's hard to tell what's causing the error, so we wrote some guides on how
    [19:03:54]: to troubleshoot build and signing issues: https://docs.fastlane.tools/codesigning/getting-started/
    [19:03:54]: Before submitting an issue on GitHub, please follow the guide above and make
    [19:03:54]: sure your project is set up correctly.
    [19:03:54]: fastlane uses `xcodebuild` commands to generate your binary, you can see the
    [19:03:54]: the full commands printed out in yellow in the above log.
    [19:03:54]: Make sure to inspect the output above, as usually you'll find more error information there
    
    PROVISIONING_PROFILE_SPECIFIERを設定してやる事でうまく行きました
    参考URL

:link: 関連リンク


0 件のコメント:

コメントを投稿