Sommario:
La configurazione di Jenkins su OS X è stata notevolmente semplificata con il programma di installazione più recente ( dall'1.449 al 9 marzo 2012 ), tuttavia la gestione del processo di firma del codice è ancora molto difficile senza una risposta semplice.
Motivazione:
Esegui un server CI headless che segue le migliori pratiche comuni per l'esecuzione di servizi su OS X ( alcuni dei quali sono spiegati qui in un linguaggio semplice ).
Sfondo:
- 12 ottobre 2009 - Come automatizzare le build di app per iPhone con Hudson
- 15 giugno 2011 - Jenkins su Mac OS X; git con chiave pubblica ssh
- 23 giugno 2011 - Distribuzione continua di app iOS con Jenkins e TestFlight
- 26 luglio 2011 - Certificati e chiavi mancanti nel portachiavi durante l'utilizzo di Jenkins / Hudson come integrazione continua per lo sviluppo iOS e Mac
- 30 agosto 2011 - File di provisioning Xcode non trovato con Jenkins
- 20 settembre 2011 - Come configurare Jenkins CI su un Mac
- 14 settembre 2011 - Far funzionare Jenkins su un Mac
- 12 novembre 2011 - Howto: Installa Jenkins su OS X e fagli costruire roba per Mac
- 23 gennaio 2012 - Modifiche imminenti del programma di installazione di Jenkins OSX
- 7 marzo 2012 - Grazie per aver utilizzato OSX Installer
Processi:
Installare Jenkins CI tramite OS X pacchetto di installazione . Per il passaggio "Tipo di installazione", fai clic sul pulsante Personalizza e scegli "Avvia all'avvio come" jenkins "".
Discussione:
L'ingenua aspettativa a questo punto era che un progetto in stile libero con lo script di compilazione xcodebuild -target MyTarget -sdk iphoneos
avrebbe funzionato. Come indicato dal titolo di questo post, non funziona e fallisce con:
Code Sign error: The identity 'iPhone Developer' doesn't match any valid certificate/private key pair in the default keychain
È abbastanza ovvio ciò che deve accadere: è necessario aggiungere un certificato di firma del codice valido e una chiave privata nel portachiavi predefinito. Nella ricerca di come ottenere questo risultato, non ho trovato una soluzione che non apra il sistema a un certo livello di vulnerabilità.
Problema 1: nessun portachiavi predefinito per il demone jenkins
sudo -u jenkins security default-keychain
... restituisce "Impossibile trovare un portachiavi predefinito"
Come sottolineato di seguito da Ivo Dancet , UserShell è impostato su / usr / bin / false per il daemon jenkins per impostazione predefinita (penso che questa sia una funzionalità, non un bug); segui la sua risposta per cambiare UserShell in bash. È quindi possibile utilizzare sudo su jenkins
per accedere come utente jenkins e ottenere un prompt bash.
sudo su jenkins
cd ~/Library
mkdir Keychains
cd Keychains
security create-keychain <keychain-name>.keychain
security default-keychain -s <keychain-name>.keychain
Va bene, fantastico. Ora abbiamo un portachiavi predefinito; andiamo avanti giusto? Ma prima perché ci siamo presi la briga di creare un portachiavi predefinito?
Quasi tutte le risposte, i suggerimenti o le conversazioni che ho letto durante la ricerca suggeriscono che si dovrebbe semplicemente inserire i certificati e le chiavi di firma del codice nel portachiavi del sistema. Se corri security list-keychains
come progetto in stile libero a Jenkins, vedrai che l'unico portachiavi disponibile è il portachiavi di sistema; Penso che sia qui che la maggior parte delle persone ha avuto l'idea di inserire il proprio certificato e la chiave. Ma questa sembra solo una pessima idea, soprattutto dato che dovrai creare uno script di testo semplice con la password per aprire il portachiavi .
Problema 2: aggiunta di certificati di firma del codice e chiave privata
È qui che comincio davvero a diventare schizzinoso. Ho la sensazione viscerale che dovrei creare una nuova chiave pubblica / privata unica per l'uso con Jenkins. Il mio pensiero è che se il daemon jenkins è compromesso, posso facilmente revocare il certificato nel portale di provisioning di Apple e generare un'altra chiave pubblica / privata. Se utilizzo la stessa chiave e certificato per il mio account utente e Jenkins, significa più problemi (danni?) Se il servizio jenkins viene attaccato.
Indicando la risposta di Simon Urbanek sbloccherai il portachiavi da uno script con una password in testo semplice. Sembra irresponsabile mantenere qualsiasi cosa tranne i certificati e le chiavi "usa e getta" nel portachiavi del demone jenkins.
Sono molto interessato a qualsiasi discussione contraria. Sono eccessivamente cauto?
Per creare un nuovo CSR come demone jenkins in Terminal ho fatto quanto segue ...
sudo su jenkins
certtool r CertificateSigningRequest.certSigningRequest
Ti verrà chiesto di fornire quanto segue (la maggior parte di questi ho fatto ipotesi plausibili alla risposta corretta; hai una visione migliore? Per favore condividi.) ...- Immettere la chiave e l'etichetta del certificato:
- Seleziona algoritmo:
r
(per RSA) - Immettere la dimensione della chiave in bit:
2048
- Seleziona algoritmo di firma:
5
(per MD5) - Inserisci la stringa della sfida:
- Poi un mucchio di domande per RDN
- Invia il file CSR generato (CertificateSigningRequest.certSigningRequest) al portale di provisioning di Apple con un nuovo ID Apple
- Approva la richiesta e scarica il file .cer
security unlock-keychain
security add-certificate ios_development.cer
Questo ci fa fare un passo avanti ...
Problema 3: profilo di provisioning e sblocco del portachiavi
Ho creato uno speciale profilo di provisioning nel portale di provisioning solo per l'uso con CI nella speranza che se succede qualcosa di brutto ho ridotto un po 'l'impatto. Best practice o eccessivamente cauto?
sudo su jenkins
mkdir ~/Library/MobileDevice
mkdir ~/Library/MobileDevice/Provisioning\ Profiles
- Sposta il profilo di provisioning che hai configurato nel portale di provisioning in questa nuova cartella. Siamo ora a due brevi passi dall'essere in grado di eseguire xcodebuild dalla riga di comando come jenkins, e quindi questo significa che siamo anche vicini alla possibilità di eseguire build in esecuzione della CI di Jenkins.
security unlock-keychain -p <keychain password>
xcodebuild -target MyTarget -sdk iphoneos
Ora otteniamo una build di successo da una riga di comando quando accediamo come demone jenkins, quindi se creiamo un progetto in stile libero e aggiungiamo quei due passaggi finali (# 5 e # 6 sopra) saremo in grado di automatizzare la creazione di il nostro progetto iOS!
Potrebbe non essere necessario, ma mi sono sentito meglio impostare jenkins UserShell su / usr / bin / false dopo aver ottenuto con successo tutta questa configurazione. Sono paranoico?
Problema 4: portachiavi predefinito ancora non disponibile!
( EDIT: ho pubblicato le modifiche alla mia domanda, riavviato per assicurarmi che la mia soluzione fosse al 100% e, naturalmente, avevo tralasciato un passaggio )
Anche dopo tutti i passaggi precedenti, sarà necessario modificare il plist di avvio del demone su /Library/LaunchDaemons/org.jenkins-ci.plist come indicato in questa risposta . Tieni presente che anche questo è un bug di openrdar .
Dovrebbe sembrare come questo:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>EnvironmentVariables</key>
<dict>
<key>JENKINS_HOME</key>
<string>/Users/Shared/Jenkins/Home</string>
</dict>
<key>GroupName</key>
<string>daemon</string>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>org.jenkins-ci</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/Library/Application Support/Jenkins/jenkins-runner.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>UserName</key>
<string>jenkins</string>
<!-- **NEW STUFF** -->
<key>SessionCreate</key>
<true />
</dict>
</plist>
Con questa configurazione, consiglierei anche il plugin Xcode per Jenkins , che rende un po 'più semplice la configurazione dello script xcodebuild. A questo punto, consiglierei anche di leggere le pagine man per xcodebuild - diavolo sei arrivato così lontano in Terminal, giusto?
Questa configurazione non è perfetta e qualsiasi consiglio o intuizione è molto apprezzata.
Ho avuto difficoltà a selezionare una risposta "corretta" poiché ciò che ho utilizzato per risolvere il mio problema era una raccolta di input di quasi tutti. Ho cercato di dare a tutti almeno un voto positivo, ma assegnare la risposta a Simon perché ha risposto per lo più alla domanda originale. Inoltre, Sami Tikka merita molto credito per i suoi sforzi nel far funzionare Jenkins tramite AppleScript come una semplice app OS X. Se sei interessato solo a far funzionare Jenkins e ad andare velocemente all'interno della tua sessione utente (cioè non come un server headless) la sua soluzione è molto più simile a quella di un Mac.
Spero che i miei sforzi suscitino ulteriori discussioni e aiutino la prossima povera anima che arriva pensando di poter installare Jenkins CI per i loro progetti iOS in un fine settimana a causa di tutte le cose meravigliose di cui hanno sentito parlare.
Aggiornamento: 9 agosto 2013
Con così tanti voti positivi e preferiti, ho pensato di tornare a questo 18 mesi dopo con alcune brevi lezioni apprese.
Lezione 1: non esporre Jenkins a Internet pubblico
Al WWDC del 2012 ho rivolto questa domanda agli ingegneri di Xcode e OS X Server. Ho ricevuto una cacofonia di "non farlo!" da chiunque io abbia chiesto. Tutti concordavano sul fatto che un processo di compilazione automatizzato fosse ottimo, ma che il server dovrebbe essere accessibile solo sulla rete locale. Gli ingegneri di OS X Server hanno suggerito di consentire l'accesso remoto tramite VPN.
Lezione 2: ora sono disponibili nuove opzioni di installazione
Di recente ho tenuto un discorso a CocoaHead sulla mia esperienza con Jenkins e, con mia grande sorpresa, ho trovato alcuni nuovi metodi di installazione: Homebrew e persino una versione di Bitnami per Mac App Store . Vale sicuramente la pena provarli. Jonathan Wright ha un'idea che dettaglia come funziona Homebrew Jenkins .
Lezione 3: No, seriamente, non esporre la tua build box a Internet
È abbastanza chiaro dal post originale che non sono né un amministratore di sistema né un esperto di sicurezza. Il buon senso per le cose private (portachiavi, credenziali, certificati, ecc.) Mi ha fatto sentire piuttosto a disagio nel mettere la mia scatola Jenkins su Internet. Nick Arnott di Neglected Potential è stato in grado di confermare i miei heebie-jeebies abbastanza facilmente in questo articolo .
TL; DR
La mia raccomandazione ad altri che cercano di automatizzare il loro processo di creazione è cambiata nell'ultimo anno e mezzo. Assicurati che la tua macchina Jenkins sia dietro il firewall. Installa e imposta Jenkins come utente Jenkins dedicato utilizzando il programma di installazione, la versione di Bitnami per Mac App Store, AppleScript di Sami Tikka, ecc .; questo risolve la maggior parte del mal di testa che ho descritto sopra. Se hai bisogno di un accesso remoto, la configurazione dei servizi VPN in OS X Server richiede al massimo dieci minuti. Uso questa configurazione da oltre un anno e ne sono molto soddisfatto. In bocca al lupo!