SlideShare una empresa de Scribd logo
1 de 51
Build automatique et
distribution OTA avec
 Xcode 4.x et Jenkins
Pour quoi faire ?


Développer depuis une autre machine

Tester sur iDevice

Fournir une version récente aux testeurs
Java


Jenkins a besoin de java pour tourner

Java n’est plus fourni par Apple pour OSX 10.7

☞ Il faut installer Java
Installation de Java
curl -O http://supportdownload.apple.com/
download.info.apple.com/Apple_Support_Area/
Apple_Software_Updates/Mac_OS_X/downloads/
041-1941.20111108.6wtg7/
JavaForMacOSX10.7.dmg

hdiutil attach JavaForMacOSX10.7.dmg

sudo installer -pkg /Volumes/Java For Mac OS X
10.7/JavaForMacOSX10.7.pkg -target /
Installation de Jenkins

Téléchargement et installation du dernier paquet
sur la machine cible

curl -O http://jenkins.mirror.isppower.de/
osx/jenkins-1.451.pkg

sudo installer -pkg jenkins-1.451.pkg -
target /
Création d’un utilisateur
sudo dscl . create /Users/jenkins

sudo dscl . create /Users/jenkins PrimaryGroupID 1

sudo dscl . create /Users/jenkins UniqueID 300

sudo dscl . create /Users/jenkins UserShell /bin/bash

sudo dscl . create /Users/jenkins home /Users/
Shared/Jenkins/Home/

sudo dscl . create /Users/jenkins
NFSHomeDirectory /Users/Shared/Jenkins/Home/

sudo dscl . passwd /Users/jenkins
Modification du fichier
de configuration
/Library/LaunchDaemons/org.jenkins-ci.plist

 ☞ Changer <UserName> <daemon> par
<UserName> <jenkins>

Changement de propriétaire pour le home de Jenkins

☞ sudo chown -R jenkins /Users/Shared/Jenkins
Lancement de Jenkins
Jenkins est déjà lancé, il faut l’arrêter

 ☞ sudo launchctl unload -w /Library/
   LaunchDaemons/org.jenkins-ci.plist

Puis le relancer

 ☞ sudo launchctl load -w /Library/
   LaunchDaemons/org.jenkins-ci.plist
Vérification

Dans /var/log/system.log

 ☞ Feb 27 11:53:32 macmini org.jenkins-
   ci[37647]: INFO: Jenkins is fully up and
   running
Connexion
http://localhost:8080
Jenkins

J’ai réussi à faire un job de compilation pour un
projet purement OSX

J’ai réussi à faire un job de compilation d’un
projet iOS pour simulateur
Jenkins
La compilation d’un projet iPhoneOS...

Le processus de la JVM est lancé par launchd
et est fils direct de launchd

l’ouverture de la keychain utilisateur n’est pas
compatible avec cette approche

Même en mettant les certificats et clefs privés
dans la keychain system
Conclusion (provisoire)


Build automatique et
distribution OTA avec
Xcode 4.x et Jenkins
Conclusion (provisoire)


Build automatique et
distribution OTA avec
Xcode 4.x et Python
Utiliser l’existant


Puisque nous avons créé un utilisateur jenkins
pour le serveur de build Jenkins, autant
utiliser ce compte pour la suite de nos
aventures
Python


Pourquoi Python ?

Pour apprendre
Schéma

   Jenkins                                              Serveur Git
                         Échange de clef SSH
  Serveur
  de build                                             Serveur de
                                                       distribution

La clef SSH de jenkins sur la machine de build ne comporte pas de passphrase.
Sur le serveur de distribution jenkins n’a AUCUN rôle administratif.
Il est aussi possible de n’autoriser les connexions sur le serveur de distribution
que par échange de clef (authentification par mot de passe interdite)
Schéma
                                      1
        2
Jenkins 3                                         Serveur Git


Serveur                              4
de build                                         Serveur de
                                                 distribution
  1.récupération des sources (ou mises à jour) depuis le dépôt
  2.compilation
  3.préparation du .ipa, du manifest, du html
  4.copie sur le serveur et mise à disposition
Étudions tout cela

               Je débute en Python, il y a surement
               plus simple ou plus «Pythonnesque» de
               faire ce script.
               En particulier, je n’utilise quasiment pas
               les caractéristiques Objet du langage

Nous n’allons pas étudier le script dans l’ordre d’entrée
en action des étapes 1,2,3,4. Nous laisserons 1 et 4
pour fignoler notre script
Étape 2 : la compilation
La compilation, c’est le boulot de xcodebuild :

Il a besoin de trouver :

  le répertoire .xcodeproj

  la target

  le SDK

  la configuration (Debug, Release, AdHoc...)
Appel de xcodebuild

# /usr/bin/xcodebuild -sdk iphone5.0 -project /mon/projet.xcodeproj  -
configuration release -target MaTarget




                      Fastoche non !
Sauf que...
xcodebuild a besoin de trouver le certificat de
développement signé par Apple et la clef privée de ce
certificat

Ces deux éléments doivent être placés dans une
keychain

J’ai décidé de mettre cela dans une keychain séparée

Le provisioning profile doit être dans ~/Library/
MobileDevices/Provisioning Profiles
Sur la machine de dev

Export du certificat et de la clef privée dans
un fichier .p12

Copie de ce fichier sur la machine de build

Copie du Provisioning Profile sur la machine
de build
Sur la machine de build
Pour créer une keychain à la ligne de commande
on utilise security

security create-keychain jenkins.keychain

On donne un mot de passe à cette keychain

Import du fichier .p12 venant de la machine de dev

security import -t cert -f pkcs12 -T /usr/bin/codesign
-T /usr/bin/xcodebuild -P MotDePasse
Security


Il y a plein d’options amusantes dans security,
je vous laisse la surprise
Retour au script

Pour faire marcher xcodebuild, nous allons
avoir besoin :

 d’ouvrir la keychain

 de la passer keychain par défaut
Security (bis)
 C’est toujours avec security que nous allons jouer
 security unlock-keychain jenkins.keychain -p MotDePasse

 security default-keychain -d user -s jenkins.keychain


 J’ai mis cela dans une fonction



Soyez conscient que le mot de passe peut être
intercepté par un simple ps au moment opportun
Modèle de fonction

Toutes les fonctions sont bâties sur le même
modèle afin de pouvoir tracer facilement ce
qui se passe

C’est mon côté sysadmin qui cause...
openKeychain
def openKeychain(password, keychain):

 cmd_array=(["/usr/bin/security","unlock-keychain", "-p", password, keychain])

 try:

 
    subprocess.check_call(cmd_array)

 except OSError as e:

 
    logger.debug("Error in %s, exiting" % " ".join(cmd_string))
       logger.info( "ErrorString == %s ErrorNum == %d" % (e.strerror,e.errno)

 
    writeToSTDERR("Error, please see the log file")

 
    sys.exit(1)



   cmd_array=(["/usr/bin/security", "default-keychain","-d","user", "-s", keychain])

   try:

   
    subprocess.check_call(cmd_array)

   except OSError as e:

   
    logger.debug("Error in %s, exiting" % " ".join(cmd_array))
         logger.info( "ErrorString == %s ErrorNum == %d" % (e.strerror,e.errno)




     En python l’indentation fait partie de la syntaxe
Une fonction pour
     xcodebuild


Sur le modèle de la précédente nous pouvons
faire une fonction qui appelle xcodebuild
compileApp

def compileApp(SDK, project, configuration, target):
! cmd_array=(["/usr/bin/xcodebuild","-sdk",SDK,"-project" ,project, "configuration",
configuration, "-target", target])

! try:
! !    subprocess.check_call(cmd_array)
! except OSError as e:
! !    logger.debug("Error in %s. Exiting" % " ".join(cmd_array))
       logger.info( "ErrorString == %s ErrorNum == %d" % (e.strerror,e.errno)
! !    writeToSTDERR("Error, please see the log file")
! !    sys.exit(1)
Transformation de .app
        en .ipa
L’application générée par xcodebuild n’est
pas exploitable sur un iPhone

Il faut la transformer en .ipa

C’est xcrun avec les bons paramètres qui va
faire cette transformation
(PackageApplication)
createIPA
def createIPA(GSDK, workspace, configuration, target, DeveloperName, ProvisioningProfile,targetFolder):


 cmd_array=(["/usr/bin/xcrun","-sdk", GSDK, "PackageApplication", "-v"," %s/%s.app" % (APPPath,target),
"-o","%s/%s.ipa"%(targetFolder,target), "-sign", DeveloperName, "-embed",ProvisioningProfile])


    try:

    
    subprocess.check_call(cmd_array)

    except OSError as e:

    
    logger.debug("Error in %s. Exiting" % " ".join(cmd_array))

    
    logger.info(" Error String == %s Error Num == %d" % (e.strerror, e.errno))

    
    writeToSTDERR("Error, please see the log file")

    
    sys.exit(1)




    SDK c’est le nom du SDK nécessaire à la compilation, GSDK c’est la même chose sans le
    numéro de release (iphoneos5.0 -> iphoneos)
Manifest.plist
Le fichier manifest.plist est nécessaire à la
distribution OTA

Les informations nécessaires sont déjà dans
l’application .ipa, autant aller les chercher là.

Les .ipa sont des fichiers zip

Les informations sont dans le fichier Info.plist

Le fichier Info.plist est une plist binaire
Manifest.plist
Nous n’allons pas détailler les fonctions mais
retrieveInfo extrait le fichier Info.plist de
l’application .ipa

createManifest transforme ce Info.plist binaire
en plist texte, récolte les informations
nécessaires (CFBundleName,
CFBundleVersion, CFBundleIdentifier) et
génère le fichier manifest grâce au module
plistlib
createIndexHTML &
                fillHTML
      Ces deux fonctions permettent de créer le
      fichier index.html qui va accompagner vos
      fichiers manifest.plist et MonApplication.ipa
      pour la distribution OTA


Ce code et celui de la génération du manifest sont largement inspirés voire presque
totalement copiés de celui-ci <https://github.com/baz/ios-build-scripts/blob/master/
generate_manifest.py>.
La suite

       Votre utilisateur jenkins va faire tourner le
       script sur la machine de build

       Déposez sur le serveur de distribution la clef
       publique de cet utilisateur afin de permettre
       l’envoi des éléments


Pour faciliter l’échange, la clef de l’utilisateur n’a pas de mot de passe. En revanche,
sur la machine de distribution, il n’a aucun pouvoir. Pas de sudoers entre autre
Récupération des
        sources

Python dispose d’un module de gestion git

Il vous permet de faire le clone initial et
ensuite à chaque lancement de faire une mise
à jour des sources
Et ensuite ?

Les méthodes d’échange et de gestion de git
sont présentes dans le script final

Dans ce même script, grâce au module
argparse, nous pouvons gérer les arguments
passés au script
xcodebuild-wrapper.py
./xcodebuild-wrapper.py -h
usage: xcodebuild-wrapper.py [-h] -k KEYCHAIN -K KEYCHAINPASSWORD -p PROJECT
                             -P PROVISIONINGPROFILE -s SDK -c CONFIG -n DEVNAME
                             -t TARGET -d DEPLOY [-r REMOTEHOST] [-u USERNAME]
                             [-w REMOTEPASSWORD] [-f REMOTEFOLDER]
                             [--log LOGLEVEL]

xcodebuild wrapper parameters

optional arguments:
  -h, --help            show this help message and exit
  -k KEYCHAIN, --keychain KEYCHAIN
                        Path to the keychain file
  -K KEYCHAINPASSWORD, --keychainPassword KEYCHAINPASSWORD
                        keychain's password
  -p PROJECT, --projectPath PROJECT
                        Path to project file
  -P PROVISIONPROFILE, --provisioningProfile PROVISIONPROFILE
                        Provisioning Profile path
  -s SDK, --sdk SDK     SDK
  -c CONFIG, --configuration CONFIG
                        Configuration
  -n DEVNAME, --developerName DEVNAME
                        Developer name. This information is in the
                        provisioning profile
  -t TARGET, --target TARGET
                        Path to projet's file
  -d DEPLOY, --deploymentAddress DEPLOY
                        Deployment Address, used in manifest.plist file
  -r REMOTEHOST, --remoteHost REMOTEHOST
                        Remote host, used to distribute IPA
  -u USERNAME, --username USERNAME
                        Username on the remote host
  -w REMOTEPASSWORD, --remotePassword REMOTEPASSWORD
                        Password of the username on the remote host
  -f REMOTEFOLDER, --remoteFolder REMOTEFOLDER
                        Destination folder on remote host
  --log LOGLEVEL        LogLevel, could be DEBUG | INFO | WARNING | ERROR |
                        CRITICAL. Default value is INFO
Améliorations

Pour éviter de passer le mot de passe de la
keychain, le script pourrait utiliser un fichier de
paramètres

Lancer le script automatiquement

Envoi de mail aux testeurs pour signaler une
nouvelle version

…
One more thing...
Question


Comment connaître la version installée sur le
iDevice d’un testeur ?

Avec le viewController info/about
Question

Et la version du build ?

J’ai trouvé une solution à cette URL et je l’ai
adaptée dans mon script

http://blog.jayway.com/2011/05/31/auto-
incrementing-build-numbers-in-xcode/
Info.plist
Ajoutons dans le ficher MonApplication-
Info.plist une entrée CWBuildNumber

Incrémentons cette valeur au moment des
build OTA (dans le script Python)

Lisons cette information au moment de
l’affichage du viewController info/about
Le code Objective-C

int CWBuildNumber = [[[NSBundle mainBundle]
objectForInfoDictionaryKey:@"CWBuildNumber"] intValue];

NSString *CFBundleVersion = [[NSBundle mainBundle]
objectForInfoDictionaryKey:@"CFBundleVersion"];

NSString *CFBundleName = [[NSBundle mainBundle]
objectForInfoDictionaryKey:@"CFBundleName"];

NSString *aboutString = [NSString stringWithFormat:@"%@, version %@, (Build Number
%d)", CFBundleName, CFBundleVersion, CWBuildNumber];

aboutLibelle.text = aboutString;
L’ajout de la clef dans
         MyAPP-info.plist


/usr/libexec/PlistBuddy -c "Set :CWBuildNumber $buildNumber" 
${PROJECT_DIR}/MyApp-Info.plist
La fonction dans
     xcodebuild-wrapper.py
def increaseBuildNumber(project,subdir,plistFile):
! cmd_array=["/usr/libexec/PlistBuddy", "-c", "Print CWBuildNumber", "%s/%s/%s" %
(project,subdir,plistFile)]
! s = subprocess.Popen(cmd_array, stdout=subprocess.PIPE)
! ret = s.stdout.readline()
! buildNumber = int(ret)
! buildNumber+=1

! cmd_array=["/usr/libexec/PlistBuddy", "-c", "Set :CWBuildNumber %s" %
(buildNumber),"%s/%s/%s" % (project,subdir,plistFile)]
! try:
! !    subprocess.check_call(cmd_array)
! except OSError as e:
! !    logger.debug("Error in %s. Exiting"% " ".join(cmd_array))
! !    logger.debug("ErrorString == %s ErrorNum == %d" % (e.strerror,e.errno))
! !    writeToSTDERR("Error during increase BuildNumber")
Conclusion

J’ai mis deux semaines à écrire ce script

Il est dispo avec beaucoup plus d’explications
sur http://adminblog.foucry.net

Merci à Frank, Dominique et Benoît pour leur
aide et leur relecture
Le script est en creative commons

et il sera sur github

adminblog.foucry.net

jacques@foucry.net

Más contenido relacionado

La actualidad más candente

Intégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec JenkinsIntégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec JenkinsHugo Hamon
 
Spring boot anane maryem ben aziza syrine
Spring boot anane maryem ben aziza syrineSpring boot anane maryem ben aziza syrine
Spring boot anane maryem ben aziza syrineSyrine Ben aziza
 
Spring Meetup Paris - Back to the basics of Spring (Boot)
Spring Meetup Paris - Back to the basics of Spring (Boot)Spring Meetup Paris - Back to the basics of Spring (Boot)
Spring Meetup Paris - Back to the basics of Spring (Boot)Eric SIBER
 
20081113 - Nantes Jug - Apache Maven
20081113 - Nantes Jug - Apache Maven20081113 - Nantes Jug - Apache Maven
20081113 - Nantes Jug - Apache MavenArnaud Héritier
 
20080311 - Paris Vi Master STL TA - Initiation Maven
20080311 - Paris Vi Master STL TA - Initiation Maven20080311 - Paris Vi Master STL TA - Initiation Maven
20080311 - Paris Vi Master STL TA - Initiation MavenArnaud Héritier
 
Introduction to WebRTC on iOS
Introduction to WebRTC on iOSIntroduction to WebRTC on iOS
Introduction to WebRTC on iOSCocoaHeads France
 
5 android web_service
5 android web_service5 android web_service
5 android web_serviceSaber LAJILI
 
Android Input Method Editor
Android   Input Method EditorAndroid   Input Method Editor
Android Input Method EditorFranck SIMON
 
Les dessous du framework spring
Les dessous du framework springLes dessous du framework spring
Les dessous du framework springAntoine Rey
 
2013 01-08-php-maturite
2013 01-08-php-maturite2013 01-08-php-maturite
2013 01-08-php-maturiteRémi Alvado
 
Ces outils qui vous font gagner du temps
Ces outils qui vous font gagner du tempsCes outils qui vous font gagner du temps
Ces outils qui vous font gagner du tempsAntoine Rey
 
20091020 - Normandy Jug - Builders Battle
20091020 - Normandy Jug - Builders Battle20091020 - Normandy Jug - Builders Battle
20091020 - Normandy Jug - Builders BattleArnaud Héritier
 
Bbl microservices avec vert.x cdi elastic search
Bbl microservices avec vert.x cdi elastic searchBbl microservices avec vert.x cdi elastic search
Bbl microservices avec vert.x cdi elastic searchIdriss Neumann
 
Gérer ses environnements de développement avec Vagrant - RMLL 2012
Gérer ses environnements de développement avec Vagrant - RMLL 2012Gérer ses environnements de développement avec Vagrant - RMLL 2012
Gérer ses environnements de développement avec Vagrant - RMLL 2012Jean-Marc Fontaine
 

La actualidad más candente (20)

Xcode 4.5
Xcode 4.5Xcode 4.5
Xcode 4.5
 
Intégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec JenkinsIntégration continue des projets PHP avec Jenkins
Intégration continue des projets PHP avec Jenkins
 
Spring boot anane maryem ben aziza syrine
Spring boot anane maryem ben aziza syrineSpring boot anane maryem ben aziza syrine
Spring boot anane maryem ben aziza syrine
 
Sonar-Hodson-Maven
Sonar-Hodson-MavenSonar-Hodson-Maven
Sonar-Hodson-Maven
 
Spring Meetup Paris - Back to the basics of Spring (Boot)
Spring Meetup Paris - Back to the basics of Spring (Boot)Spring Meetup Paris - Back to the basics of Spring (Boot)
Spring Meetup Paris - Back to the basics of Spring (Boot)
 
Spring 3.0
Spring 3.0Spring 3.0
Spring 3.0
 
20081113 - Nantes Jug - Apache Maven
20081113 - Nantes Jug - Apache Maven20081113 - Nantes Jug - Apache Maven
20081113 - Nantes Jug - Apache Maven
 
20080311 - Paris Vi Master STL TA - Initiation Maven
20080311 - Paris Vi Master STL TA - Initiation Maven20080311 - Paris Vi Master STL TA - Initiation Maven
20080311 - Paris Vi Master STL TA - Initiation Maven
 
Introduction to WebRTC on iOS
Introduction to WebRTC on iOSIntroduction to WebRTC on iOS
Introduction to WebRTC on iOS
 
5 android web_service
5 android web_service5 android web_service
5 android web_service
 
Android Input Method Editor
Android   Input Method EditorAndroid   Input Method Editor
Android Input Method Editor
 
Présentation1
Présentation1Présentation1
Présentation1
 
Les dessous du framework spring
Les dessous du framework springLes dessous du framework spring
Les dessous du framework spring
 
Android NDK
Android   NDKAndroid   NDK
Android NDK
 
2013 01-08-php-maturite
2013 01-08-php-maturite2013 01-08-php-maturite
2013 01-08-php-maturite
 
UKO-JAVA1001-slides
UKO-JAVA1001-slidesUKO-JAVA1001-slides
UKO-JAVA1001-slides
 
Ces outils qui vous font gagner du temps
Ces outils qui vous font gagner du tempsCes outils qui vous font gagner du temps
Ces outils qui vous font gagner du temps
 
20091020 - Normandy Jug - Builders Battle
20091020 - Normandy Jug - Builders Battle20091020 - Normandy Jug - Builders Battle
20091020 - Normandy Jug - Builders Battle
 
Bbl microservices avec vert.x cdi elastic search
Bbl microservices avec vert.x cdi elastic searchBbl microservices avec vert.x cdi elastic search
Bbl microservices avec vert.x cdi elastic search
 
Gérer ses environnements de développement avec Vagrant - RMLL 2012
Gérer ses environnements de développement avec Vagrant - RMLL 2012Gérer ses environnements de développement avec Vagrant - RMLL 2012
Gérer ses environnements de développement avec Vagrant - RMLL 2012
 

Destacado

CocoaHeads Toulouse - Xcode et les tests - Epitez
CocoaHeads Toulouse - Xcode et les tests - EpitezCocoaHeads Toulouse - Xcode et les tests - Epitez
CocoaHeads Toulouse - Xcode et les tests - EpitezCocoaHeads France
 
Spec et test agile sur mobile @airfrance #at lille & cocoaheads tls
Spec et test agile sur mobile @airfrance #at lille & cocoaheads tlsSpec et test agile sur mobile @airfrance #at lille & cocoaheads tls
Spec et test agile sur mobile @airfrance #at lille & cocoaheads tlsekito
 
CocoaHeads Toulouse - iOS TechTalk - Mélanie Bessagnet
CocoaHeads Toulouse - iOS TechTalk - Mélanie BessagnetCocoaHeads Toulouse - iOS TechTalk - Mélanie Bessagnet
CocoaHeads Toulouse - iOS TechTalk - Mélanie BessagnetCocoaHeads France
 
Xcode formation-iphone-ipad-xcode-et-cocoa
Xcode formation-iphone-ipad-xcode-et-cocoaXcode formation-iphone-ipad-xcode-et-cocoa
Xcode formation-iphone-ipad-xcode-et-cocoaCERTyou Formation
 
Comment concilier Agilité et projet au forfait ?
Comment concilier Agilité et projet au forfait ?Comment concilier Agilité et projet au forfait ?
Comment concilier Agilité et projet au forfait ?Lorraine JUG
 
Xcode Server - Jeffrey Macko
Xcode Server - Jeffrey MackoXcode Server - Jeffrey Macko
Xcode Server - Jeffrey MackoCocoaHeads France
 
DevOps - Retour d’expérience - RivieraDev du 20 Octobre 2011
DevOps - Retour d’expérience - RivieraDev du 20 Octobre 2011DevOps - Retour d’expérience - RivieraDev du 20 Octobre 2011
DevOps - Retour d’expérience - RivieraDev du 20 Octobre 2011Henri Gomez
 
Automate your build on Android with Jenkins
Automate your build on Android with JenkinsAutomate your build on Android with Jenkins
Automate your build on Android with JenkinsBeMyApp
 
Swift, opportunités et perspectives du dernier langage d'Apple
Swift, opportunités et perspectives du dernier langage d'AppleSwift, opportunités et perspectives du dernier langage d'Apple
Swift, opportunités et perspectives du dernier langage d'AppleDamien GOSSET
 
Use In IoT : l’objet connecté de la board au dashboard
Use In IoT : l’objet connecté de la board au dashboardUse In IoT : l’objet connecté de la board au dashboard
Use In IoT : l’objet connecté de la board au dashboardMicrosoft
 
Tipos de Brackets- Introducción a la Odontología
Tipos de Brackets- Introducción a la OdontologíaTipos de Brackets- Introducción a la Odontología
Tipos de Brackets- Introducción a la Odontologíacrisppg
 
SEO Footprints by www.Netrix.co.uk - Comprehensive Guide to Website Footprints
SEO Footprints by www.Netrix.co.uk - Comprehensive Guide to Website FootprintsSEO Footprints by www.Netrix.co.uk - Comprehensive Guide to Website Footprints
SEO Footprints by www.Netrix.co.uk - Comprehensive Guide to Website FootprintsMark D. Griffin
 
9 tendances du Mobile World Congress 2017 par @hubinstitute
9 tendances du Mobile World Congress 2017 par @hubinstitute 9 tendances du Mobile World Congress 2017 par @hubinstitute
9 tendances du Mobile World Congress 2017 par @hubinstitute HUB INSTITUTE
 
Infrastructure as code: running microservices on AWS using Docker, Terraform,...
Infrastructure as code: running microservices on AWS using Docker, Terraform,...Infrastructure as code: running microservices on AWS using Docker, Terraform,...
Infrastructure as code: running microservices on AWS using Docker, Terraform,...Yevgeniy Brikman
 
Open XKE - De l'intégration continue au déploiement continu sur iOS et Androi...
Open XKE - De l'intégration continue au déploiement continu sur iOS et Androi...Open XKE - De l'intégration continue au déploiement continu sur iOS et Androi...
Open XKE - De l'intégration continue au déploiement continu sur iOS et Androi...Publicis Sapient Engineering
 
Scrum et forfait
Scrum et forfaitScrum et forfait
Scrum et forfaitIppon
 
IoT (M2M) - Big Data - Analyses : Simulation et Démonstration
IoT (M2M) - Big Data - Analyses : Simulation et DémonstrationIoT (M2M) - Big Data - Analyses : Simulation et Démonstration
IoT (M2M) - Big Data - Analyses : Simulation et DémonstrationCHAKER ALLAOUI
 
TechnoConseil - Gestion déléguée 2013
TechnoConseil - Gestion déléguée 2013TechnoConseil - Gestion déléguée 2013
TechnoConseil - Gestion déléguée 2013Véronique Chanson
 

Destacado (20)

CocoaHeads Toulouse - Xcode et les tests - Epitez
CocoaHeads Toulouse - Xcode et les tests - EpitezCocoaHeads Toulouse - Xcode et les tests - Epitez
CocoaHeads Toulouse - Xcode et les tests - Epitez
 
Spec et test agile sur mobile @airfrance #at lille & cocoaheads tls
Spec et test agile sur mobile @airfrance #at lille & cocoaheads tlsSpec et test agile sur mobile @airfrance #at lille & cocoaheads tls
Spec et test agile sur mobile @airfrance #at lille & cocoaheads tls
 
CocoaHeads Toulouse - iOS TechTalk - Mélanie Bessagnet
CocoaHeads Toulouse - iOS TechTalk - Mélanie BessagnetCocoaHeads Toulouse - iOS TechTalk - Mélanie Bessagnet
CocoaHeads Toulouse - iOS TechTalk - Mélanie Bessagnet
 
Xcode formation-iphone-ipad-xcode-et-cocoa
Xcode formation-iphone-ipad-xcode-et-cocoaXcode formation-iphone-ipad-xcode-et-cocoa
Xcode formation-iphone-ipad-xcode-et-cocoa
 
Comment concilier Agilité et projet au forfait ?
Comment concilier Agilité et projet au forfait ?Comment concilier Agilité et projet au forfait ?
Comment concilier Agilité et projet au forfait ?
 
Xcode Server - Jeffrey Macko
Xcode Server - Jeffrey MackoXcode Server - Jeffrey Macko
Xcode Server - Jeffrey Macko
 
DevOps - Retour d’expérience - RivieraDev du 20 Octobre 2011
DevOps - Retour d’expérience - RivieraDev du 20 Octobre 2011DevOps - Retour d’expérience - RivieraDev du 20 Octobre 2011
DevOps - Retour d’expérience - RivieraDev du 20 Octobre 2011
 
Automate your build on Android with Jenkins
Automate your build on Android with JenkinsAutomate your build on Android with Jenkins
Automate your build on Android with Jenkins
 
Swift, opportunités et perspectives du dernier langage d'Apple
Swift, opportunités et perspectives du dernier langage d'AppleSwift, opportunités et perspectives du dernier langage d'Apple
Swift, opportunités et perspectives du dernier langage d'Apple
 
Use In IoT : l’objet connecté de la board au dashboard
Use In IoT : l’objet connecté de la board au dashboardUse In IoT : l’objet connecté de la board au dashboard
Use In IoT : l’objet connecté de la board au dashboard
 
Tipos de Brackets- Introducción a la Odontología
Tipos de Brackets- Introducción a la OdontologíaTipos de Brackets- Introducción a la Odontología
Tipos de Brackets- Introducción a la Odontología
 
IoT Best practices
 IoT Best practices IoT Best practices
IoT Best practices
 
SEO Footprints by www.Netrix.co.uk - Comprehensive Guide to Website Footprints
SEO Footprints by www.Netrix.co.uk - Comprehensive Guide to Website FootprintsSEO Footprints by www.Netrix.co.uk - Comprehensive Guide to Website Footprints
SEO Footprints by www.Netrix.co.uk - Comprehensive Guide to Website Footprints
 
9 tendances du Mobile World Congress 2017 par @hubinstitute
9 tendances du Mobile World Congress 2017 par @hubinstitute 9 tendances du Mobile World Congress 2017 par @hubinstitute
9 tendances du Mobile World Congress 2017 par @hubinstitute
 
Infrastructure as code: running microservices on AWS using Docker, Terraform,...
Infrastructure as code: running microservices on AWS using Docker, Terraform,...Infrastructure as code: running microservices on AWS using Docker, Terraform,...
Infrastructure as code: running microservices on AWS using Docker, Terraform,...
 
Open XKE - De l'intégration continue au déploiement continu sur iOS et Androi...
Open XKE - De l'intégration continue au déploiement continu sur iOS et Androi...Open XKE - De l'intégration continue au déploiement continu sur iOS et Androi...
Open XKE - De l'intégration continue au déploiement continu sur iOS et Androi...
 
XebiConFr 15 - Swift dans la vraie vie
XebiConFr 15 - Swift dans la vraie vieXebiConFr 15 - Swift dans la vraie vie
XebiConFr 15 - Swift dans la vraie vie
 
Scrum et forfait
Scrum et forfaitScrum et forfait
Scrum et forfait
 
IoT (M2M) - Big Data - Analyses : Simulation et Démonstration
IoT (M2M) - Big Data - Analyses : Simulation et DémonstrationIoT (M2M) - Big Data - Analyses : Simulation et Démonstration
IoT (M2M) - Big Data - Analyses : Simulation et Démonstration
 
TechnoConseil - Gestion déléguée 2013
TechnoConseil - Gestion déléguée 2013TechnoConseil - Gestion déléguée 2013
TechnoConseil - Gestion déléguée 2013
 

Similar a Build automatique et distribution OTA avec Xcode 4.x et Jenkins

Spring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'tsSpring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'tsJulien Wittouck
 
Gitlab CI : Integration et Déploiement Continue
Gitlab CI : Integration et Déploiement ContinueGitlab CI : Integration et Déploiement Continue
Gitlab CI : Integration et Déploiement ContinueVincent Composieux
 
Symfony 2 : chapitre 1 - Présentation Générale
Symfony 2 : chapitre 1 - Présentation GénéraleSymfony 2 : chapitre 1 - Présentation Générale
Symfony 2 : chapitre 1 - Présentation GénéraleAbdelkader Rhouati
 
Être productif avec JHipster - Devoxx France 2017
Être productif avec JHipster - Devoxx France 2017Être productif avec JHipster - Devoxx France 2017
Être productif avec JHipster - Devoxx France 2017Julien Dubois
 
Reverse Engineering d'un ransomware
Reverse Engineering d'un ransomwareReverse Engineering d'un ransomware
Reverse Engineering d'un ransomwareNinaSAMMUT
 
Symfony2: 30 astuces et bonnes pratiques
Symfony2: 30 astuces et bonnes pratiquesSymfony2: 30 astuces et bonnes pratiques
Symfony2: 30 astuces et bonnes pratiquesNoel GUILBERT
 
découverte du langage python dans tous ses aspects
découverte du langage python dans tous ses aspectsdécouverte du langage python dans tous ses aspects
découverte du langage python dans tous ses aspectsThierry Gayet
 
Gestion des dépendances dans un projet PHP - Forum PHP 2012
Gestion des dépendances dans un projet PHP - Forum PHP 2012Gestion des dépendances dans un projet PHP - Forum PHP 2012
Gestion des dépendances dans un projet PHP - Forum PHP 2012Jean-Marc Fontaine
 
Java uik-chap1-intro java
Java uik-chap1-intro javaJava uik-chap1-intro java
Java uik-chap1-intro javaAmel Morchdi
 
Installation Et Configuration De Monkey Spider
Installation Et Configuration De Monkey SpiderInstallation Et Configuration De Monkey Spider
Installation Et Configuration De Monkey SpiderMohamed Ben Bouzid
 
Conférence #nwx2014 - Maxime Mauchaussée - Partager du code maintenable et év...
Conférence #nwx2014 - Maxime Mauchaussée - Partager du code maintenable et év...Conférence #nwx2014 - Maxime Mauchaussée - Partager du code maintenable et év...
Conférence #nwx2014 - Maxime Mauchaussée - Partager du code maintenable et év...Normandie Web Xperts
 
Ops@viadeo : Puppet & Co... 6 mois après par Xavier Krantz
Ops@viadeo : Puppet & Co... 6 mois après par Xavier KrantzOps@viadeo : Puppet & Co... 6 mois après par Xavier Krantz
Ops@viadeo : Puppet & Co... 6 mois après par Xavier KrantzOlivier DASINI
 
Presentation Symfony2
Presentation Symfony2Presentation Symfony2
Presentation Symfony2Ahmed ABATAL
 
Phoenix Presence: Le service temps réel de Phoenix - Paris.ex #8
Phoenix Presence: Le service temps réel de Phoenix - Paris.ex #8 Phoenix Presence: Le service temps réel de Phoenix - Paris.ex #8
Phoenix Presence: Le service temps réel de Phoenix - Paris.ex #8 Mickaël Rémond
 
Installation et configuration d'openbravo
Installation et configuration d'openbravoInstallation et configuration d'openbravo
Installation et configuration d'openbravoSoumia Brabije
 
Rapport openembedded
Rapport openembeddedRapport openembedded
Rapport openembeddedAyoub Rouzi
 
retour sur confoo2011 et Symfony2
retour sur confoo2011 et Symfony2retour sur confoo2011 et Symfony2
retour sur confoo2011 et Symfony2Saad Tazi
 
Conférence Shinken à SophiaConf2012 (Jean Gabès)
Conférence Shinken à SophiaConf2012 (Jean Gabès)Conférence Shinken à SophiaConf2012 (Jean Gabès)
Conférence Shinken à SophiaConf2012 (Jean Gabès)Jean Gabès
 

Similar a Build automatique et distribution OTA avec Xcode 4.x et Jenkins (20)

Spring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'tsSpring Boot & Containers - Do's & Don'ts
Spring Boot & Containers - Do's & Don'ts
 
Gitlab CI : Integration et Déploiement Continue
Gitlab CI : Integration et Déploiement ContinueGitlab CI : Integration et Déploiement Continue
Gitlab CI : Integration et Déploiement Continue
 
Symfony 2 : chapitre 1 - Présentation Générale
Symfony 2 : chapitre 1 - Présentation GénéraleSymfony 2 : chapitre 1 - Présentation Générale
Symfony 2 : chapitre 1 - Présentation Générale
 
Être productif avec JHipster - Devoxx France 2017
Être productif avec JHipster - Devoxx France 2017Être productif avec JHipster - Devoxx France 2017
Être productif avec JHipster - Devoxx France 2017
 
Reverse Engineering d'un ransomware
Reverse Engineering d'un ransomwareReverse Engineering d'un ransomware
Reverse Engineering d'un ransomware
 
Symfony2: 30 astuces et bonnes pratiques
Symfony2: 30 astuces et bonnes pratiquesSymfony2: 30 astuces et bonnes pratiques
Symfony2: 30 astuces et bonnes pratiques
 
découverte du langage python dans tous ses aspects
découverte du langage python dans tous ses aspectsdécouverte du langage python dans tous ses aspects
découverte du langage python dans tous ses aspects
 
Gestion des dépendances dans un projet PHP - Forum PHP 2012
Gestion des dépendances dans un projet PHP - Forum PHP 2012Gestion des dépendances dans un projet PHP - Forum PHP 2012
Gestion des dépendances dans un projet PHP - Forum PHP 2012
 
Jenkins Workflow
Jenkins WorkflowJenkins Workflow
Jenkins Workflow
 
Java uik-chap1-intro java
Java uik-chap1-intro javaJava uik-chap1-intro java
Java uik-chap1-intro java
 
Installation Et Configuration De Monkey Spider
Installation Et Configuration De Monkey SpiderInstallation Et Configuration De Monkey Spider
Installation Et Configuration De Monkey Spider
 
Conférence #nwx2014 - Maxime Mauchaussée - Partager du code maintenable et év...
Conférence #nwx2014 - Maxime Mauchaussée - Partager du code maintenable et év...Conférence #nwx2014 - Maxime Mauchaussée - Partager du code maintenable et év...
Conférence #nwx2014 - Maxime Mauchaussée - Partager du code maintenable et év...
 
Ops@viadeo : Puppet & Co... 6 mois après par Xavier Krantz
Ops@viadeo : Puppet & Co... 6 mois après par Xavier KrantzOps@viadeo : Puppet & Co... 6 mois après par Xavier Krantz
Ops@viadeo : Puppet & Co... 6 mois après par Xavier Krantz
 
Presentation Symfony2
Presentation Symfony2Presentation Symfony2
Presentation Symfony2
 
Phoenix Presence: Le service temps réel de Phoenix - Paris.ex #8
Phoenix Presence: Le service temps réel de Phoenix - Paris.ex #8 Phoenix Presence: Le service temps réel de Phoenix - Paris.ex #8
Phoenix Presence: Le service temps réel de Phoenix - Paris.ex #8
 
Installation et configuration d'openbravo
Installation et configuration d'openbravoInstallation et configuration d'openbravo
Installation et configuration d'openbravo
 
Rapport openembedded
Rapport openembeddedRapport openembedded
Rapport openembedded
 
retour sur confoo2011 et Symfony2
retour sur confoo2011 et Symfony2retour sur confoo2011 et Symfony2
retour sur confoo2011 et Symfony2
 
JAVA Chapitre2
JAVA Chapitre2JAVA Chapitre2
JAVA Chapitre2
 
Conférence Shinken à SophiaConf2012 (Jean Gabès)
Conférence Shinken à SophiaConf2012 (Jean Gabès)Conférence Shinken à SophiaConf2012 (Jean Gabès)
Conférence Shinken à SophiaConf2012 (Jean Gabès)
 

Más de CocoaHeads France

Más de CocoaHeads France (20)

Mutation testing for a safer Future
Mutation testing for a safer FutureMutation testing for a safer Future
Mutation testing for a safer Future
 
iOS App Group for Debugging
iOS App Group for DebuggingiOS App Group for Debugging
iOS App Group for Debugging
 
Asynchronous swift
Asynchronous swiftAsynchronous swift
Asynchronous swift
 
Visual accessibility in iOS11
Visual accessibility in iOS11Visual accessibility in iOS11
Visual accessibility in iOS11
 
My script - One year of CocoaHeads
My script - One year of CocoaHeadsMy script - One year of CocoaHeads
My script - One year of CocoaHeads
 
Ui testing dealing with push notifications
Ui testing dealing with push notificationsUi testing dealing with push notifications
Ui testing dealing with push notifications
 
CONTINUOUS DELIVERY WITH FASTLANE
CONTINUOUS DELIVERY WITH FASTLANECONTINUOUS DELIVERY WITH FASTLANE
CONTINUOUS DELIVERY WITH FASTLANE
 
L'intégration continue avec Bitrise
L'intégration continue avec BitriseL'intégration continue avec Bitrise
L'intégration continue avec Bitrise
 
Super combinators
Super combinatorsSuper combinators
Super combinators
 
Design like a developer
Design like a developerDesign like a developer
Design like a developer
 
Handle the error
Handle the errorHandle the error
Handle the error
 
Quoi de neuf dans iOS 10.3
Quoi de neuf dans iOS 10.3Quoi de neuf dans iOS 10.3
Quoi de neuf dans iOS 10.3
 
SwiftyGPIO
SwiftyGPIOSwiftyGPIO
SwiftyGPIO
 
Présentation de HomeKit
Présentation de HomeKitPrésentation de HomeKit
Présentation de HomeKit
 
Programme MFI retour d'expérience
Programme MFI retour d'expérienceProgramme MFI retour d'expérience
Programme MFI retour d'expérience
 
How to communicate with Smart things?
How to communicate with Smart things?How to communicate with Smart things?
How to communicate with Smart things?
 
Build a lego app with CocoaPods
Build a lego app with CocoaPodsBuild a lego app with CocoaPods
Build a lego app with CocoaPods
 
Let's migrate to Swift 3.0
Let's migrate to Swift 3.0Let's migrate to Swift 3.0
Let's migrate to Swift 3.0
 
Project Entourage
Project EntourageProject Entourage
Project Entourage
 
What's new in iOS9
What's new in iOS9What's new in iOS9
What's new in iOS9
 

Build automatique et distribution OTA avec Xcode 4.x et Jenkins

  • 1. Build automatique et distribution OTA avec Xcode 4.x et Jenkins
  • 2. Pour quoi faire ? Développer depuis une autre machine Tester sur iDevice Fournir une version récente aux testeurs
  • 3. Java Jenkins a besoin de java pour tourner Java n’est plus fourni par Apple pour OSX 10.7 ☞ Il faut installer Java
  • 4. Installation de Java curl -O http://supportdownload.apple.com/ download.info.apple.com/Apple_Support_Area/ Apple_Software_Updates/Mac_OS_X/downloads/ 041-1941.20111108.6wtg7/ JavaForMacOSX10.7.dmg hdiutil attach JavaForMacOSX10.7.dmg sudo installer -pkg /Volumes/Java For Mac OS X 10.7/JavaForMacOSX10.7.pkg -target /
  • 5. Installation de Jenkins Téléchargement et installation du dernier paquet sur la machine cible curl -O http://jenkins.mirror.isppower.de/ osx/jenkins-1.451.pkg sudo installer -pkg jenkins-1.451.pkg - target /
  • 6. Création d’un utilisateur sudo dscl . create /Users/jenkins sudo dscl . create /Users/jenkins PrimaryGroupID 1 sudo dscl . create /Users/jenkins UniqueID 300 sudo dscl . create /Users/jenkins UserShell /bin/bash sudo dscl . create /Users/jenkins home /Users/ Shared/Jenkins/Home/ sudo dscl . create /Users/jenkins NFSHomeDirectory /Users/Shared/Jenkins/Home/ sudo dscl . passwd /Users/jenkins
  • 7. Modification du fichier de configuration /Library/LaunchDaemons/org.jenkins-ci.plist ☞ Changer <UserName> <daemon> par <UserName> <jenkins> Changement de propriétaire pour le home de Jenkins ☞ sudo chown -R jenkins /Users/Shared/Jenkins
  • 8. Lancement de Jenkins Jenkins est déjà lancé, il faut l’arrêter ☞ sudo launchctl unload -w /Library/ LaunchDaemons/org.jenkins-ci.plist Puis le relancer ☞ sudo launchctl load -w /Library/ LaunchDaemons/org.jenkins-ci.plist
  • 9. Vérification Dans /var/log/system.log ☞ Feb 27 11:53:32 macmini org.jenkins- ci[37647]: INFO: Jenkins is fully up and running
  • 11. Jenkins J’ai réussi à faire un job de compilation pour un projet purement OSX J’ai réussi à faire un job de compilation d’un projet iOS pour simulateur
  • 12. Jenkins La compilation d’un projet iPhoneOS... Le processus de la JVM est lancé par launchd et est fils direct de launchd l’ouverture de la keychain utilisateur n’est pas compatible avec cette approche Même en mettant les certificats et clefs privés dans la keychain system
  • 13. Conclusion (provisoire) Build automatique et distribution OTA avec Xcode 4.x et Jenkins
  • 14. Conclusion (provisoire) Build automatique et distribution OTA avec Xcode 4.x et Python
  • 15. Utiliser l’existant Puisque nous avons créé un utilisateur jenkins pour le serveur de build Jenkins, autant utiliser ce compte pour la suite de nos aventures
  • 17. Schéma Jenkins Serveur Git Échange de clef SSH Serveur de build Serveur de distribution La clef SSH de jenkins sur la machine de build ne comporte pas de passphrase. Sur le serveur de distribution jenkins n’a AUCUN rôle administratif. Il est aussi possible de n’autoriser les connexions sur le serveur de distribution que par échange de clef (authentification par mot de passe interdite)
  • 18. Schéma 1 2 Jenkins 3 Serveur Git Serveur 4 de build Serveur de distribution 1.récupération des sources (ou mises à jour) depuis le dépôt 2.compilation 3.préparation du .ipa, du manifest, du html 4.copie sur le serveur et mise à disposition
  • 19. Étudions tout cela Je débute en Python, il y a surement plus simple ou plus «Pythonnesque» de faire ce script. En particulier, je n’utilise quasiment pas les caractéristiques Objet du langage Nous n’allons pas étudier le script dans l’ordre d’entrée en action des étapes 1,2,3,4. Nous laisserons 1 et 4 pour fignoler notre script
  • 20. Étape 2 : la compilation La compilation, c’est le boulot de xcodebuild : Il a besoin de trouver : le répertoire .xcodeproj la target le SDK la configuration (Debug, Release, AdHoc...)
  • 21. Appel de xcodebuild # /usr/bin/xcodebuild -sdk iphone5.0 -project /mon/projet.xcodeproj - configuration release -target MaTarget Fastoche non !
  • 22. Sauf que... xcodebuild a besoin de trouver le certificat de développement signé par Apple et la clef privée de ce certificat Ces deux éléments doivent être placés dans une keychain J’ai décidé de mettre cela dans une keychain séparée Le provisioning profile doit être dans ~/Library/ MobileDevices/Provisioning Profiles
  • 23. Sur la machine de dev Export du certificat et de la clef privée dans un fichier .p12 Copie de ce fichier sur la machine de build Copie du Provisioning Profile sur la machine de build
  • 24. Sur la machine de build Pour créer une keychain à la ligne de commande on utilise security security create-keychain jenkins.keychain On donne un mot de passe à cette keychain Import du fichier .p12 venant de la machine de dev security import -t cert -f pkcs12 -T /usr/bin/codesign -T /usr/bin/xcodebuild -P MotDePasse
  • 25. Security Il y a plein d’options amusantes dans security, je vous laisse la surprise
  • 26. Retour au script Pour faire marcher xcodebuild, nous allons avoir besoin : d’ouvrir la keychain de la passer keychain par défaut
  • 27. Security (bis) C’est toujours avec security que nous allons jouer security unlock-keychain jenkins.keychain -p MotDePasse security default-keychain -d user -s jenkins.keychain J’ai mis cela dans une fonction Soyez conscient que le mot de passe peut être intercepté par un simple ps au moment opportun
  • 28. Modèle de fonction Toutes les fonctions sont bâties sur le même modèle afin de pouvoir tracer facilement ce qui se passe C’est mon côté sysadmin qui cause...
  • 29. openKeychain def openKeychain(password, keychain): cmd_array=(["/usr/bin/security","unlock-keychain", "-p", password, keychain]) try: subprocess.check_call(cmd_array) except OSError as e: logger.debug("Error in %s, exiting" % " ".join(cmd_string)) logger.info( "ErrorString == %s ErrorNum == %d" % (e.strerror,e.errno) writeToSTDERR("Error, please see the log file") sys.exit(1) cmd_array=(["/usr/bin/security", "default-keychain","-d","user", "-s", keychain]) try: subprocess.check_call(cmd_array) except OSError as e: logger.debug("Error in %s, exiting" % " ".join(cmd_array)) logger.info( "ErrorString == %s ErrorNum == %d" % (e.strerror,e.errno) En python l’indentation fait partie de la syntaxe
  • 30. Une fonction pour xcodebuild Sur le modèle de la précédente nous pouvons faire une fonction qui appelle xcodebuild
  • 31. compileApp def compileApp(SDK, project, configuration, target): ! cmd_array=(["/usr/bin/xcodebuild","-sdk",SDK,"-project" ,project, "configuration", configuration, "-target", target]) ! try: ! ! subprocess.check_call(cmd_array) ! except OSError as e: ! ! logger.debug("Error in %s. Exiting" % " ".join(cmd_array)) logger.info( "ErrorString == %s ErrorNum == %d" % (e.strerror,e.errno) ! ! writeToSTDERR("Error, please see the log file") ! ! sys.exit(1)
  • 32. Transformation de .app en .ipa L’application générée par xcodebuild n’est pas exploitable sur un iPhone Il faut la transformer en .ipa C’est xcrun avec les bons paramètres qui va faire cette transformation (PackageApplication)
  • 33. createIPA def createIPA(GSDK, workspace, configuration, target, DeveloperName, ProvisioningProfile,targetFolder): cmd_array=(["/usr/bin/xcrun","-sdk", GSDK, "PackageApplication", "-v"," %s/%s.app" % (APPPath,target), "-o","%s/%s.ipa"%(targetFolder,target), "-sign", DeveloperName, "-embed",ProvisioningProfile]) try: subprocess.check_call(cmd_array) except OSError as e: logger.debug("Error in %s. Exiting" % " ".join(cmd_array)) logger.info(" Error String == %s Error Num == %d" % (e.strerror, e.errno)) writeToSTDERR("Error, please see the log file") sys.exit(1) SDK c’est le nom du SDK nécessaire à la compilation, GSDK c’est la même chose sans le numéro de release (iphoneos5.0 -> iphoneos)
  • 34. Manifest.plist Le fichier manifest.plist est nécessaire à la distribution OTA Les informations nécessaires sont déjà dans l’application .ipa, autant aller les chercher là. Les .ipa sont des fichiers zip Les informations sont dans le fichier Info.plist Le fichier Info.plist est une plist binaire
  • 35. Manifest.plist Nous n’allons pas détailler les fonctions mais retrieveInfo extrait le fichier Info.plist de l’application .ipa createManifest transforme ce Info.plist binaire en plist texte, récolte les informations nécessaires (CFBundleName, CFBundleVersion, CFBundleIdentifier) et génère le fichier manifest grâce au module plistlib
  • 36. createIndexHTML & fillHTML Ces deux fonctions permettent de créer le fichier index.html qui va accompagner vos fichiers manifest.plist et MonApplication.ipa pour la distribution OTA Ce code et celui de la génération du manifest sont largement inspirés voire presque totalement copiés de celui-ci <https://github.com/baz/ios-build-scripts/blob/master/ generate_manifest.py>.
  • 37. La suite Votre utilisateur jenkins va faire tourner le script sur la machine de build Déposez sur le serveur de distribution la clef publique de cet utilisateur afin de permettre l’envoi des éléments Pour faciliter l’échange, la clef de l’utilisateur n’a pas de mot de passe. En revanche, sur la machine de distribution, il n’a aucun pouvoir. Pas de sudoers entre autre
  • 38. Récupération des sources Python dispose d’un module de gestion git Il vous permet de faire le clone initial et ensuite à chaque lancement de faire une mise à jour des sources
  • 39. Et ensuite ? Les méthodes d’échange et de gestion de git sont présentes dans le script final Dans ce même script, grâce au module argparse, nous pouvons gérer les arguments passés au script
  • 40. xcodebuild-wrapper.py ./xcodebuild-wrapper.py -h usage: xcodebuild-wrapper.py [-h] -k KEYCHAIN -K KEYCHAINPASSWORD -p PROJECT -P PROVISIONINGPROFILE -s SDK -c CONFIG -n DEVNAME -t TARGET -d DEPLOY [-r REMOTEHOST] [-u USERNAME] [-w REMOTEPASSWORD] [-f REMOTEFOLDER] [--log LOGLEVEL] xcodebuild wrapper parameters optional arguments: -h, --help show this help message and exit -k KEYCHAIN, --keychain KEYCHAIN Path to the keychain file -K KEYCHAINPASSWORD, --keychainPassword KEYCHAINPASSWORD keychain's password -p PROJECT, --projectPath PROJECT Path to project file -P PROVISIONPROFILE, --provisioningProfile PROVISIONPROFILE Provisioning Profile path -s SDK, --sdk SDK SDK -c CONFIG, --configuration CONFIG Configuration -n DEVNAME, --developerName DEVNAME Developer name. This information is in the provisioning profile -t TARGET, --target TARGET Path to projet's file -d DEPLOY, --deploymentAddress DEPLOY Deployment Address, used in manifest.plist file -r REMOTEHOST, --remoteHost REMOTEHOST Remote host, used to distribute IPA -u USERNAME, --username USERNAME Username on the remote host -w REMOTEPASSWORD, --remotePassword REMOTEPASSWORD Password of the username on the remote host -f REMOTEFOLDER, --remoteFolder REMOTEFOLDER Destination folder on remote host --log LOGLEVEL LogLevel, could be DEBUG | INFO | WARNING | ERROR | CRITICAL. Default value is INFO
  • 41. Améliorations Pour éviter de passer le mot de passe de la keychain, le script pourrait utiliser un fichier de paramètres Lancer le script automatiquement Envoi de mail aux testeurs pour signaler une nouvelle version …
  • 42.
  • 44. Question Comment connaître la version installée sur le iDevice d’un testeur ? Avec le viewController info/about
  • 45. Question Et la version du build ? J’ai trouvé une solution à cette URL et je l’ai adaptée dans mon script http://blog.jayway.com/2011/05/31/auto- incrementing-build-numbers-in-xcode/
  • 46. Info.plist Ajoutons dans le ficher MonApplication- Info.plist une entrée CWBuildNumber Incrémentons cette valeur au moment des build OTA (dans le script Python) Lisons cette information au moment de l’affichage du viewController info/about
  • 47. Le code Objective-C int CWBuildNumber = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CWBuildNumber"] intValue]; NSString *CFBundleVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]; NSString *CFBundleName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"]; NSString *aboutString = [NSString stringWithFormat:@"%@, version %@, (Build Number %d)", CFBundleName, CFBundleVersion, CWBuildNumber]; aboutLibelle.text = aboutString;
  • 48. L’ajout de la clef dans MyAPP-info.plist /usr/libexec/PlistBuddy -c "Set :CWBuildNumber $buildNumber" ${PROJECT_DIR}/MyApp-Info.plist
  • 49. La fonction dans xcodebuild-wrapper.py def increaseBuildNumber(project,subdir,plistFile): ! cmd_array=["/usr/libexec/PlistBuddy", "-c", "Print CWBuildNumber", "%s/%s/%s" % (project,subdir,plistFile)] ! s = subprocess.Popen(cmd_array, stdout=subprocess.PIPE) ! ret = s.stdout.readline() ! buildNumber = int(ret) ! buildNumber+=1 ! cmd_array=["/usr/libexec/PlistBuddy", "-c", "Set :CWBuildNumber %s" % (buildNumber),"%s/%s/%s" % (project,subdir,plistFile)] ! try: ! ! subprocess.check_call(cmd_array) ! except OSError as e: ! ! logger.debug("Error in %s. Exiting"% " ".join(cmd_array)) ! ! logger.debug("ErrorString == %s ErrorNum == %d" % (e.strerror,e.errno)) ! ! writeToSTDERR("Error during increase BuildNumber")
  • 50. Conclusion J’ai mis deux semaines à écrire ce script Il est dispo avec beaucoup plus d’explications sur http://adminblog.foucry.net Merci à Frank, Dominique et Benoît pour leur aide et leur relecture
  • 51. Le script est en creative commons et il sera sur github adminblog.foucry.net jacques@foucry.net

Notas del editor

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n