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
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
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
66
AIが書いたコードをAIが検証する!自律的なモバイルアプリ開発の実現
henteko
1
1.3k
エンジニア経営者がハマりがちな罠
henteko
1
380
データ分析基盤を構築してみた
henteko
1
490
Unity Shader Graphで魔法陣を作ってみた
henteko
1
7.4k
ML-Agentsの簡単な環境構築
henteko
0
1.3k
2012TeRes11月部会
henteko
0
160
技術系同人誌執筆のすゝめ
henteko
1
160
ipaファイルの中身を 覗いてみよう
henteko
1
2.4k
Other Decks in Technology
See All in Technology
ruby.wasmとPicoRuby.wasmに対応した仮想DOMライブラリを作ってる話 #kaigieffect_kaigi
sue445
PRO
0
150
しくみを学んで使いこなそう GitHub Copilot app
torumakabe
2
290
ファミコンでPHPを動かす / PHP on the Famicom
tomzoh
2
340
ガバナンスの「ちょうどいい落とし所」を探れ!開発スピードを妨げない運用判断の勘所 / SRE NEXT 2026
genda
1
240
AI時代のYAGNI:「爆速で無駄になった機能」からの学び / 20260720 Naoki Takahashi
shift_evolve
PRO
2
310
ZOZOTOWNの進化と信頼性を両立する負荷試験
zozotech
PRO
2
190
Genie Ontologyは銀の弾丸かを考える / Is Genie Ontology a Silver Bullet?
nttcom
0
390
“それは自分の仕事じゃない"を越えて行け
yuukiyo
1
470
AICoEでAIネイティブ組織への進化
yukiogawa
0
190
DatabricksにおけるMCPソリューション
taka_aki
1
270
SoccerMaster: A Vision Foundation Model for Soccer Understanding
kzykmyzw
0
130
しぶいSRE: サーバから見えない障害にどう向き合うか。ラストワンマイルのデバッグ実践 / Shibui SRE
kanny
13
6.4k
Featured
See All Featured
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.6k
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
63
55k
What's in a price? How to price your products and services
michaelherold
247
13k
Practical Orchestrator
shlominoach
191
11k
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.4k
AI: The stuff that nobody shows you
jnunemaker
PRO
8
830
Discover your Explorer Soul
emna__ayadi
2
1.2k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
770
Un-Boring Meetings
codingconduct
0
350
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
270
New Earth Scene 8
popppiees
3
2.4k
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Ͱެ։த