Upgrade to Pro — share decks privately, control downloads, hide ads and more …

iOS Dev Workflow Automation for note

laprasDrum
September 21, 2020

iOS Dev Workflow Automation for note

iOSDC Japan 2020 で登壇しました。

「それ、自動化できますよ」: note を支えるワークフロー大全
https://fortee.jp/iosdc-japan-2020/proposal/a6fcae29-405e-4923-aa45-8132a2444e60

補足版を技術書典で販売しています。
よければ見てくれるとうれしいです。

Zapier ではじめる iOS 開発ワークフロー自動化
https://techbookfest.org/product/5017415553384448

laprasDrum

September 21, 2020
Tweet

More Decks by laprasDrum

Other Decks in Technology

Transcript

  1. desc "[CI] add new device UDID. It requires options: name,

    udid" lane :add_new_device do |options| if (options[:name].nil? or options[:name].empty?) or (options[:udid].nil? or options[:udid].empty?) UI.user_error!("missing options! call with name:{device name} udid:{device udid}") end UI.important("registering #{options[:name]} (#{options[:udid]})") register_device( name: options[:name], udid: options[:udid] ) # ূ໌ॻߋ৽ match( app_identifier: ['com.myapp.viewer'], # ొ࿥͍ͨ͠ identifier ͢΂ͯೖΕΔ type: 'adhoc', # ඞཁͳΒ development ΋ force_for_new_devices: true ) # Ϗϧυ gym(...) # ഑৴ firebase_app_distribution(...) end fastlane add_new_device udid:xxx name:yyy
  2. import json # Zapier Ͱઃఆͨ͠؀ڥม਺͸ input_data ͰऔಘՄೳ headers = {

    'Accept': 'application/json', 'Content-Type': 'application/json' } auth = (input_data['circleci_token'], '') response = requests.post( "https://circleci.com/api/v2/project/gh/org/repo/pipeline", data=json.dumps({ "branch": "master", "parameters": { "run_device_registration_from_ci": True, "device_name": input_data['device_name'], "device_udid": input_data['device_udid'] }}), headers = headers, auth = auth) response.raise_for_status() output = response.json() parameters: run_device_registration_from_ci: type: boolean default: false workflows: version: 2.1 # --- API ܦ༝ͷΈ # fastlane register_device Λ࣮ߦ͢Δ add_new_device_from_ci: when: << pipeline.parameters.run_device_registration_from_ci >> steps: - checkout - run: *build - run: bundle exec fastlane add_new_device name:<< pipeline.parameters.device_name >> udid:<< pipeline.parameters.device_udid >> config.yml CI ্Ͱ fastlane ࣮ߦ
  3. release branch ࡞੒ import json import base64 headers = {

    "Content-type": "application/json", "Authorization": f"token {input_data['github_token']}" } # master branch HEAD ͷ SHA Λऔಘ master_ref_url = "https://api.github.com/repos/org/repo/git/ref/heads/master" master_ref_response = requests.get(master_ref_url, headers=headers) master_ref_response.raise_for_status() master_ref_json = master_ref_response.json() master_sha = master_ref_json['object']['sha'] # release/x.y.z branch Λ࡞੒ release_branch_url = "https://api.github.com/repos/org/repo/git/refs" payload = { "ref": f"refs/heads/{input_data['branch']}", # branch = 'x.y.z' "sha": master_sha } release_branch_response = requests.post( release_branch_url, data=json.dumps(payload), headers=headers ) release_branch_response.raise_for_status() output = release_branch_response.json()
  4. CircleCI ্Ͱ࣮ߦ workflows: version: 2.1 auto_update_commit: when: << pipeline.parameters.run_auto_update_commit >>

    jobs: - "Commit and Push version update": filters: branches: only: /^release\/.+$ jobs: "Commit and Push version update": steps: - run: *checkout_and_build - run: name: "commit & push version update to ${NEXT_VERSION}" command: | NEXT_VERSION=<< pipeline.parameters.next_version >> git reset --hard HEAD git config user.email "[email protected]" git config user.name "your auto committer" bundle exec fastlane update_version to:${NEXT_VERSION} git add . git commit -m "[ci skip] [auto commit] update to ${NEXT_VERSION}" git push origin release/${NEXT_VERSION} - when: condition: << pipeline.parameters.run_integration_tests >> steps: *upload_latest_note_to_magic_pod release branch ͷΈ࣮ߦ fastlane update_version Λ࣮ߦͯ͠ commit & push
  5. fastlane update_version desc "[CI] update version & deploy adhoc apps"

    lane :update_version do |options| increment_version_number(version_number: options[:to].to_s) generate_changelog match(...) gym(...) upload_to_firebase(...) end github-changelog-generator Ͱ 3.0.0 tag ~ HEAD ؒͷ diff Λऔͬͯ ReleaseNote Λ࡞੒
  6. release tag ࡞੒ # generator Ͱ࡞੒ͨ͠ ReleaseNote ͷຊจΛऔಘ branch =

    f"release/{input_data['version']}" release_note_url = f"https://api.github.com/repos/org/repo/contents/LatestReleaseCheckIssue.md?ref={branch}" body_response = requests.get(release_note_url, headers=headers) body_response.raise_for_status() body_json = body_response.json() decoded_body = base64.b64decode(body_json['content']).decode('utf-8') # version tag ࡞੒ release_tag_url = "https://api.github.com/repos/org/repo/releases" payload = { 'tag_name': input_data['version'], 'target_commitish': branch, 'name': input_data['version'], 'body': decoded_body, 'draft': False, 'prereleases': False } released_response = requests.post(release_tag_url, data=json.dumps(payload), headers=headers) released_response.raise_for_status() released_json = released_response.json()
  7. merge # master ʹ޲͚ͯ PR ࡞੒ pr_url = "https://api.github.com/repos/org/repo/pulls" payload

    = { 'title': f"[Auto Create & Merge] {input_data['version']}", 'head': branch, 'base': 'master', 'body': 'created by zapier' } pr_response = requests.post(pr_url, data=json.dumps(payload), headers=headers) pr_response.raise_for_status() pr_json = pr_response.json() pr_number = str(pr_json['number']) pr_link = f"https://github.com/org/repo/pull/{pr_number}" # merge merge_url = f"https://api.github.com/repos/org/repo/pulls/{pr_number}/merge" merge_response = requests.put(merge_url, headers=headers) result = merge_response.json() # Slack ʹ౤ߘ͢ΔϝοηʔδΛ࡞੒ʢauto merge ੒ޭ or ࣦഊʣ if 'merged' in result and result['merged'] == True: return { 'message': f"{input_data['version']} ϦϦʔεʂmaster merge ͨ͠Α {pr_link}" } else: return { 'message': f"{input_data['version']} ϦϦʔεʂ͚ͩͲ master merge Ͱ͖ͳ͔ͬͨΑ {pr_link}" }
  8. ϦϦʔεϝʔϧˠdSYM lane :upload_dsym do |options| version = options[:version] || get_info_plist_value(path:

    "path/to/info.plist", key: "CFBundleShortVersionString") app_identifier = options[:app_identifier] || 'com.you.app' # ֘౰ ver. ͷ dSYM Λμ΢ϯϩʔυ sh 'rm -rf ../output/dsyms' sh 'mkdir -p ../output/dsyms' download_dsyms( version: version, app_identifier: app_identifier, output_directory: 'output/dsyms' ) Dir.chdir("../") do # FirebaseCrashlytics/upload-symbols ͰΞοϓϩʔυ͢ΔεΫϦϓτΛ࣮ߦ sh 'realpath output/dsyms/*.zip ɹɹɹɹɹ | xargs -I{} ./scripts/upload_dsyms.sh {} ./note/GoogleService-Info-Prod.plist' sh 'rm -rf output/dsyms' end end