Resumo:
Configurar o Jenkins no OS X ficou significativamente mais fácil com o instalador mais recente ( de 1.449 - 9 de março de 2012 ), no entanto, gerenciar o processo de assinatura de código ainda é muito difícil sem uma resposta direta.
Motivação:
Execute um servidor CI sem periférico que segue as práticas recomendadas comuns para a execução de serviços no OS X ( algumas das quais são explicadas aqui em linguagem simples ).
Fundo:
- 12 de outubro de 2009 - Como automatizar as compilações de seu aplicativo para iPhone com Hudson
- 15 de junho de 2011 - Jenkins no Mac OS X; git com chave pública ssh
- 23 de junho de 2011 - implantação contínua de aplicativos iOS com Jenkins e TestFlight
- 26 de julho de 2011 - Certificados e chaves ausentes nas chaves ao usar Jenkins / Hudson como integração contínua para desenvolvimento iOS e Mac
- 30 de agosto de 2011 - Arquivo de provisionamento Xcode não encontrado com Jenkins
- 20 de setembro de 2011 - Como configurar o Jenkins CI em um Mac
- 14 de setembro de 2011 - Fazendo o Jenkins rodar em um Mac
- 12 de novembro de 2011 - Howto: Instale o Jenkins no OS X e faça com que ele crie coisas para Mac
- 23 de janeiro de 2012 - Próximas mudanças no instalador do Jenkins OSX
- 7 de março de 2012 - Obrigado por usar o OSX Installer
Processo:
Instale Jenkins CI via OS X pacote de instalação . Para a etapa "Tipo de instalação", clique no botão Personalizar e escolha "Iniciar na inicialização como 'jenkins'"
Discussão:
A expectativa ingênua neste ponto era que um projeto de estilo livre com o script de construção xcodebuild -target MyTarget -sdk iphoneos
deveria funcionar. Conforme indicado pelo título desta postagem, ele não funciona e falha com:
Code Sign error: The identity 'iPhone Developer' doesn't match any valid certificate/private key pair in the default keychain
É bastante óbvio o que precisa acontecer - você precisa adicionar um certificado de assinatura de código válido e uma chave privada nas chaves padrão. Ao pesquisar como fazer isso, não encontrei uma solução que não abra o sistema a algum nível de vulnerabilidade.
Problema 1: nenhum keychain padrão para daemon jenkins
sudo -u jenkins security default-keychain
... produz "Não foi possível encontrar um chaveiro padrão"
Conforme apontado abaixo por Ivo Dancet , o UserShell é definido como / usr / bin / false para o daemon jenkins por padrão (acho que isso é um recurso, não um bug); siga sua resposta para alterar o UserShell para bash. Você pode usar sudo su jenkins
para fazer o login como o usuário jenkins e obter um prompt do bash.
sudo su jenkins
cd ~/Library
mkdir Keychains
cd Keychains
security create-keychain <keychain-name>.keychain
security default-keychain -s <keychain-name>.keychain
Certo, ótimo. Agora temos um chaveiro padrão; vamos seguir em frente certo? Mas, primeiro, por que nos incomodamos em fazer um chaveiro padrão?
Quase todas as respostas, sugestões ou conversas que li ao longo da pesquisa sugerem que se deve apenas jogar seus certificados de assinatura de código e chaves nas chaves do sistema. Se você executar security list-keychains
como um projeto de estilo livre no Jenkins, verá que as únicas chaves disponíveis são as do sistema; Acho que foi aí que a maioria das pessoas teve a ideia de colocar seu certificado e chave lá. Mas, isso parece uma péssima ideia - especialmente considerando que você precisará criar um script de texto simples com a senha para abrir as chaves .
Problema 2: Adicionar certificados de assinatura de código e chave privada
É aqui que eu realmente começo a ficar enjoado. Tenho a sensação de que devo criar uma nova chave pública / privada exclusiva para uso com Jenkins. Meu processo de pensamento é, se o daemon jenkins estiver comprometido, posso facilmente revogar o certificado no Portal de provisionamento da Apple e gerar outra chave pública / privada. Se eu usar a mesma chave e certificado para minha conta de usuário e Jenkins, isso significa mais problemas (danos?) Se o serviço jenkins for atacado.
Apontando para a resposta de Simon Urbanek, você estará desbloqueando o chaveiro de um script com uma senha em texto simples. Parece irresponsável manter qualquer coisa, exceto certificados e chaves "descartáveis" nas chaves do daemon jenkins.
Estou muito interessado em qualquer discussão em contrário. Estou sendo excessivamente cauteloso?
Para fazer um novo CSR como o daemon jenkins no Terminal, fiz o seguinte ...
sudo su jenkins
certtool r CertificateSigningRequest.certSigningRequest
Você será solicitado a responder o seguinte (a maioria dessas eu fiz suposições fundamentadas na resposta correta; você tem uma visão melhor? Por favor, compartilhe.) ...- Insira a chave e a etiqueta do certificado:
- Selecione o algoritmo:
r
(para RSA) - Insira o tamanho da chave em bits:
2048
- Selecione o algoritmo de assinatura:
5
(para MD5) - Insira a string de desafio:
- Em seguida, um monte de perguntas para RDN
- Envie o arquivo CSR gerado (CertificateSigningRequest.certSigningRequest) para o Portal de aprovisionamento da Apple com um novo ID Apple
- Aprove a solicitação e baixe o arquivo .cer
security unlock-keychain
security add-certificate ios_development.cer
Isso nos leva um passo mais perto ...
Problema 3: perfil de provisionamento e desbloqueio de chaves
Fiz um perfil de provisionamento especial no Portal de provisionamento apenas para uso com CI, na esperança de que, se algo ruim acontecer, eu diminua um pouco o impacto. Melhor prática ou excessivamente cauteloso?
sudo su jenkins
mkdir ~/Library/MobileDevice
mkdir ~/Library/MobileDevice/Provisioning\ Profiles
- Mova o perfil de provisionamento que você configurou no Portal de provisionamento para esta nova pasta. Estamos agora a dois passos de poder executar xcodebuild a partir da linha de comando como jenkins, e isso significa que também estamos perto de conseguir fazer o Jenkins CI rodar compilações.
security unlock-keychain -p <keychain password>
xcodebuild -target MyTarget -sdk iphoneos
Agora obtemos uma construção bem-sucedida de uma linha de comando quando conectado como o daemon jenkins, então se criarmos um projeto de estilo livre e adicionarmos essas duas etapas finais (# 5 e # 6 acima), seremos capazes de automatizar a construção de nosso projeto iOS!
Pode não ser necessário, mas me senti melhor configurando o jenkins UserShell de volta para / usr / bin / false depois de obter toda essa configuração. Estou sendo paranóico?
Problema 4: chaveiro padrão ainda não disponível!
( EDITAR: postei as edições da minha pergunta, reiniciei para ter certeza de que minha solução era 100% e, claro, deixei uma etapa de fora )
Mesmo depois de todas as etapas acima, você precisará modificar o plist Launch Daemon em /Library/LaunchDaemons/org.jenkins-ci.plist conforme declarado nesta resposta . Observe que este também é um bug do openrdar .
Deve ser assim:
<?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>
Com essa configuração, eu também recomendaria o plugin Xcode para Jenkins , que torna a configuração do script xcodebuild um pouco mais fácil. Nesse ponto, eu também recomendo ler as páginas de manual do xcodebuild - diabos, você chegou até aqui no Terminal, certo?
Esta configuração não é perfeita e qualquer conselho ou visão é muito apreciado.
Tive dificuldade em selecionar uma resposta "correta", pois o que passei a usar para resolver meu problema foi uma coleção de opiniões de quase todos. Tentei dar a todos pelo menos um voto favorável, mas conceda a resposta a Simon porque ele respondeu principalmente à pergunta original. Além disso, Sami Tikka merece muito crédito por seus esforços para fazer o Jenkins funcionar por meio do AppleScript como um aplicativo OS X simples e antigo. Se você está interessado apenas em fazer o Jenkins funcionar rapidamente na sua sessão de usuário (ou seja, não como um servidor sem comando), sua solução é muito mais semelhante a um Mac.
Espero que meus esforços gerem mais discussões e ajudem a próxima pobre alma que vier pensando que pode configurar o Jenkins CI para seus projetos iOS em um fim de semana por causa de todas as coisas maravilhosas que ouviram sobre isso.
Atualização: 9 de agosto de 2013
Com tantos votos positivos e favoritos, pensei em voltar a isso 18 meses depois com algumas breves lições aprendidas.
Lição 1: não exponha o Jenkins à Internet pública
No WWDC de 2012, levei essa pergunta aos engenheiros do Xcode e do OS X Server. Recebi uma cacofonia de "não faça isso!" de qualquer pessoa a quem eu perguntei. Todos concordaram que um processo de construção automatizado era ótimo, mas que o servidor só deveria estar acessível na rede local. Os engenheiros do OS X Server sugeriram permitir o acesso remoto via VPN.
Lição 2: Existem novas opções de instalação agora
Recentemente, dei uma palestra no CocoaHeads sobre minha experiência com o Jenkins e, para minha surpresa, encontrei alguns novos métodos de instalação - Homebrew e até mesmo uma versão Bitnami Mac App Store . Definitivamente vale a pena conferir. Jonathan Wright tem uma essência que detalha como o Homebrew Jenkins funciona .
Lição 3: Não, sério, não exponha sua caixa de construção à Internet
Ficou bem claro na postagem original que não sou um administrador de sistema nem um especialista em segurança. O bom senso sobre coisas privadas (chaveiros, credenciais, certificados, etc.) me deixou bastante desconfortável em colocar minha caixa Jenkins na Internet. Nick Arnott, da Neglected Potential, foi capaz de confirmar meus heebie-jeebies com bastante facilidade neste artigo .
TL; DR
Minha recomendação para outras pessoas que buscam automatizar seu processo de criação mudou no último ano e meio. Certifique-se de que sua máquina Jenkins esteja protegida por firewall. Instale e configure o Jenkins como um usuário dedicado do Jenkins usando o instalador, a versão Bitnami Mac App Store, o AppleScript de Sami Tikka, etc; isso resolve a maior parte da dor de cabeça que detalhei acima. Se você precisar de acesso remoto, configurar serviços VPN no OS X Server leva no máximo dez minutos. Eu uso essa configuração há mais de um ano e estou muito feliz com isso. Boa sorte!