Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
RubyでiOSアプリをビルドしよう
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
henteko
August 25, 2016
Technology
1.6k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
RubyでiOSアプリをビルドしよう
iOSDC 2016 前夜祭
henteko
August 25, 2016
More Decks by henteko
See All by henteko
Gitが世界を制した理由は「革新」ではなく「運用」だった
henteko
0
76
AIが書いたコードをAIが検証する!自律的なモバイルアプリ開発の実現
henteko
1
1.4k
エンジニア経営者がハマりがちな罠
henteko
1
390
データ分析基盤を構築してみた
henteko
1
500
Unity Shader Graphで魔法陣を作ってみた
henteko
1
7.5k
ML-Agentsの簡単な環境構築
henteko
0
1.3k
2012TeRes11月部会
henteko
0
170
技術系同人誌執筆のすゝめ
henteko
1
160
ipaファイルの中身を 覗いてみよう
henteko
1
2.4k
Other Decks in Technology
See All in Technology
20260903 Tokyo Jazug Night #62 | Azure エンジニアよ、 その環境は本当にセキュアか?
olivia_0707
1
620
JAWS-UG初心者支部#88わいわい初心塾(夏休みの宿題やったかGit編)
otsuki
0
140
2026-09-04 SRE Tech Talk #15 怠惰なTerraform / Lazy Terraform
masasuzu
0
200
Tab5をRubyで動くパソコンにする
kishima
1
190
AI活用の現在地、 ちゃんと見えてますか?/XPfest-2026
visional_engineering_and_design
0
160
AI-DLCって実際どう? 〜聞きたいこと全部聞いてみる〜
news_it_enj
0
230
Sigmaユーザーのための有用リソース一挙公開 & Sigmaで使えるMCP #sigma_ucj /useful-resources-for-sigma-computing-users-and-mcps-with-sigma
shinyaa31
0
120
AI時代におけるプロダクト横断勉強会の設計
zozotech
PRO
0
160
現場に行くだけでは足りない——プロダクトエンジニアが業務の流れを捉える観点と、その鍛え方
takumiengineering
0
300
enechainの内製セルフサービスプラットフォーム
hiyosi
0
110
スクラムで身についていた動き方を、XPで捉え直してみた
codmoninc
PRO
1
240
Beyond the Hype: Practical AI for Your Oracle Database with MCP
thatjeffsmith
1
270
Featured
See All Featured
Technical Leadership for Architectural Decision Making
baasie
3
550
Optimising Largest Contentful Paint
csswizardry
37
3.9k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
220
Speed Design
sergeychernyshev
33
2.1k
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
230
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
510
Getting science done with accelerated Python computing platforms
jacobtomlinson
2
470
How Fast Is Fast Enough? [PerfNow 2025]
tammyeverts
3
870
Bootstrapping a Software Product
garrettdimon
PRO
306
120k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
490
Between Models and Reality
mayunak
4
450
Transcript
3VCZͰJ04ΞϓϦΛ Ϗϧυ͠Α͏ J04%$લࡇ Μͯ͜
%FQMPZ(BUF 5XJUUFS!IFOUFLP ࣗݾհ Μͯ͜
3VCZͰJ04ΞϓϦΛ Ϗϧυ͢Δख๏
EHEFQMPZ
None
EHBEEEFWJDFT
BEEEFWJDFTҎલ
Ϣʔβʔ͕ΞϓϦͷςετʹࢀՃ ͜ͷ࣌Ͱ·ͩΞϓϦͷΠϯετʔϧ͕ग़དྷͳ͍ 6%*%͕։ൃऀʹΘΔ खಈͰ%FW$FOUFSʹొ্ͯ͛͠͠ ΞϓϦΠϯετʔϧͰ͖ΔΑ͏ʹ
BEEEFWJDFT͏ͱ
Ϣʔβʔ͕ΞϓϦͷςετʹࢀՃ ͜ͷ࣌Ͱ·ͩΞϓϦͷΠϯετʔϧ͕ग़དྷͳ͍ BEEEFWJDFTΛୟ͚ͩ͘ ΞϓϦΠϯετʔϧͰ͖ΔΑ͏ʹ
BEEEFWJDFTTFSWFS
Ϣʔβʔ͕ΞϓϦͷςετʹࢀՃ ͜ͷ࣌Ͱ·ͩΞϓϦͷΠϯετʔϧ͕ग़དྷͳ͍ ࣗಈͰΞϓϦ͕Ϗϧυ͞ΕΔ ͙͢ʹΞϓϦΠϯετʔϧͰ͖ΔΑ͏ʹ ਆ
None
3VCZ
ओʹ͍ͯ͠Δ͜ͱ 9DPEFϓϩδΣΫτͷղੳ ϩʔΧϧͷ1SPWJTJPOJOH1SPpMFͷղੳ J04ΞϓϦͷϏϧυ
9DPEFϓϩδΣΫτղੳ #VOEMF*EFOUJpFSͷऔಘ ྫDPNIFOUFLPMPPQFS ઃఆ͍ͯ͠Δ1SPWJTJPOJOH1SPpMFͷಛఆ
9DPEFϓϩδΣΫτղੳ Ϗϧυ͢Δ4DIFNFΛಛఆ͢Δ ͦͷ4DIFNFͷYDTDIFNFϑΝΠϧΛऔಘ͢Δ YDTDIFNFϑΝΠϧ͔Β5BSHFU/BNFΛऔಘ͢Δ 9DPEFϓϩδΣΫτΛऔಘ͢Δ
4DIFNFऔಘ Ϗϧυରͷ4DIFNFΛऔಘ͢Δ
None
4DIFNFऔಘ HZN GBTUMBOF Λ͍ͬͯΔ 1 def target_scheme 2 config =
FastlaneCore::Configuration.create( 3 Gym::Options.available_options, 4 { 5 workspace: XCODE_WORKSPACE_PATH 6 } 7 ) 8 project = FastlaneCore::Project.new(config) 9 project.select_scheme 10 project.options[:scheme] 11 end
YDTDIFNFϑΝΠϧऔಘ औಘͨ͠4DIFNF͔ΒYDTDIFNFϑΝΠϧΛऔಘ ͢Δ ී௨ʹσΟϨΫτϦΛ୳ࡧ BQQYDPEFQSPKYDVTFSEBUBVTFSYDVTFSEBUBE YDTDIFNFTUBSHFU@TDIFNFYDTDIFNF
1 def find_xcschemes(target_scheme) 2 Dir[ 3 File.join( 4 XCODE_PROJECT_PATH, 5
'xcuserdata', 6 '*.xcuserdatad', 7 'xcschemes', 8 '*.xcscheme' 9 ) 10 ].reject do |scheme| 11 target_scheme != 12 File.basename(scheme, '.xcscheme') 13 end 14 end
5BSHFU/BNFͷऔಘ औಘͨ͠YDTDIFNFϑΝΠϧ͔ΒUBSHFUOBNFΛ औಘ͢Δ YDPEFQSPKΛ͍ͬͯΔ
1 xs = Xcodeproj::XCScheme.new(scheme_file) 2 target_name = xs. 3 profile_action.
4 buildable_product_runnable. 5 buildable_reference. 6 target_name
9DPEFϓϩδΣΫτऔಘ ϓϩδΣΫτΛऔಘ͢Δ 1 project = Xcodeproj::Project.open( 2 XCODE_PROJECT_PATH) 3 project
= project. 4 native_targets. 5 reject{|target| target.name != target_name}. 6 first
#VJME$POpHVSBUJPO ֤#VJMEDPOpHVSBUJPO͝ͱͷઃఆΛऔಘͰ͖Δ 1 def target_build_configuration(target_project) 2 target_project. 3 build_configuration_list. 4
build_configurations. 5 reject{|conf| conf.name != 'Release'}. 6 first 7 end
֤ઃఆΛऔಘ #VOEMF*EFOUJpFSͳͲΛऔಘͰ͖Δ 1 target_project. 2 product_name 3 target_build_configuration. 4 build_settings['PRODUCT_BUNDLE_IDENTIFIER']
5 target_build_configuration. 6 build_settings['PROVISIONING_PROFILE']
1SPWJTJPOJOH1SPpMFղੳ ϩʔΧϧʹ͋Δ1SPWJTJPOJOH1SPpMFΛղੳ͢Δ 1SPWJTJPOJOH1SPpMFͷূ໌ॻ͕.BDʹΠϯετʔ ϧ͞Ε͍ͯΔ͔ݟΔ
QSPpMFͷऔಘ NPCJMFQSPWJTJPOϑΝΠϧΛऔಘ͢Δ d-JCSBSZ.PCJMF%FWJDF1SPWJTJPOJOH1SPpMFT ʹଘࡏ͍ͯ͠Δ
1 def load_profile_paths 2 profiles_path = 3 File.expand_path("~") + 4
"/Library/MobileDevice/Provisioning 5 Profiles/*.mobileprovision" 6 Dir[profiles_path] 7 end
QSPpMFΛղੳ PQFOTTMͱQMJTUͰղੳ͢Δ 1 def profile_to_plist(profile_path) 2 File.open(profile_path) do |profile| 3
asn1 = OpenSSL::ASN1.decode(profile.read) 4 plist_str = asn1.value[1].value[0].value[2]. 5 value[1].value[0].value 6 plist = Plist.parse_xml plist_str. 7 force_encoding('UTF-8') 8 plist['Path'] = profile_path 9 return plist 10 end 11 end
66*% ༗ޮظݶ "QQMJDBUJPO*EFOUJpFS 5FBNOBNF 1 profile['UUID'] 2 profile['ExpirationDate'] 3 if
profile['Entitlements'] 4 profile['Entitlements']['application- 5 identifier'] 6 end 7 profile['TeamName']
"EIPD͔Ͳ͏͔ 1SPWJTJPOJOH1SPpMF͕"EIPD༻͔Ͳ͏͔֬ೝͰ͖ Δ 1SPWJTJPOT"MM%FWJDFT͕͋Δͱ*O)PVTF༻ 1 def adhoc?(profile) 2 !profile['Entitlements']['get-task-allow'] &&
3 profile['ProvisionsAllDevices'].nil? 4 end
ূ໌ॻͷ֬ೝ .BDʹ1SPWJTJPOJOH1SPpMFͷূ໌ॻ͕Πϯετʔ ϧ͞Ε͍ͯΔ͔Ͳ͏͔ͷ֬ೝ Πϯετʔϧ͞Ε͍ͯͳ͍ͱJ04ΞϓϦͷϏϧυʹ ࣦഊ͢Δ
ূ໌ॻҰཡऔಘ TFDVSJUZίϚϯυΛ͏ 1 def installed_certificates 2 available = `security find-identity
-v -p 3 codesigning` 4 certificates = [] 5 available.split("\n").each do |current| 6 next if current.include? "REVOKED" 7 certificates << current 8 end 9 10 certificates 11 end
J1IPOF%JTUSJCVUJPO༻Λऔಘ J1IPOF%JTUSJCVUJPO)0(&ͳͷ͚ͩΛऔಘ 1 def installed_distribution_certificate_ids 2 certificates = installed_certificates() 3
ids = [] 4 certificates.each do |current| 5 next unless current.match(/iPhone 6 Distribution:/) 7 (ids << current.match(/.*\) (.*) \".*/)[1]) 8 end 9 10 ids 11 end
Πϯετʔϧ֬ೝ PQFOTTMͰ1SPpMFͷJEΛ֬ೝ ΠϯετʔϧࡁΈͷJEʹͦΕؚ͕·Ε͍ͯͨΒΠϯ ετʔϧࡁΈ
1 def installed_certificate?(profile_path) 2 profile = profile_to_plist profile_path 3 certs
= profile['DeveloperCertificates'].map 4 do |cert| 5 certificate_str = cert.read 6 certificate = OpenSSL::X509::Certificate. 7 new certificate_str 8 id = OpenSSL::Digest::SHA1.new(certificate. 9 to_der).to_s.upcase 10 installed_distribution_certificate_ids. 11 include?(id) 12 end 13 certs.include?(true) 14 end
J04ΞϓϦϏϧυ HZN GBTUMBOF Λ͏ ಛʹԿߟ͑ͳͯ͘ɺࠓ·ͰಘͨใͰϏϧυ͕ Ͱ͖Δ
1 EXPORT_METHOD = 'ad-hoc' 2 WORKSPACE = '/path/to/ios-app/app.xcodeproj' 3 CONFIGURATION
= 'Release' 4 SCHEME = 'target_scheme' 5 CODESIGNING_IDENTITY = 'iPhone Distribution: 6 HOGE (xxxxxxxxx)' 7 8 def build 9 values = { 10 export_method: EXPORT_METHOD, 11 workspace: WORKSPACE, 12 configuration: CONFIGURATION, 13 scheme: SCHEME, 14 codesigning_identity: 15 CODESIGNING_IDENTITY 16 } 17 v = FastlaneCore::Configuration.create(Gym:: 18 Options.available_options, values) 19 20 File.expand_path(Gym::Manager.new.work(v)) 21 end
·ͱΊ 3VCZͰ9DPEFϓϩδΣΫτͷղੳ͕Ͱ͖·͢ 1SPWJTJPOJOH1SPpMFͷղੳ ϏϧυGBTUMBOFܦ༝ͰYDPEFCVJMEΛୟ͘ͷ͕ ͓͢͢Ί IUUQTHJUIVCDPNIFOUFLP JPTED@@TBNQMF
EHΑΖ͘͠Ͷʂ ιʔείʔυ(JUIVCͰެ։த