Jenkins no OS X: xcodebuild fornece erro de sinal de código
Summary:
A configuração do Jenkins no OS X ficou significativamente mais fácil com o instalador mais recente as de 1.449 - 9 de março de 2012), no entanto, gerenciar o processo de assinatura de código ainda é muito difícil, sem resposta diret
Motivação
Execute um servidor de IC sem cabeçalho que siga as práticas recomendadas comuns para executar serviços no OS X Alguns dos quais são explicados aqui em linguagem simples).
Fundo
12 de outubro de 2009 -Como automatizar as compilações de aplicativos para iPhone com o Hudson 15 de junho de 2011 - Jenkins no Mac OS X; chave pública git w / ssh 23 de junho de 2011 - Implantação contínua de aplicativos iOS com Jenkins e TestFlight 26 de julho de 2011 -Missing certificados e chaves no keychain ao usar Jenkins / Hudson como integração contínua para desenvolvimento iOS e Mac 30 de agosto de 2011 -Xcode Provisioning File não encontrado com Jenkins 20 de setembro de 2011 -Como configurar o Jenkins CI em um Mac 14 de setembro de 2011 -Getting Jenkins em execução em um Mac 12 de novembro de 2011 -Como: Instale o Jenkins no OS X e faça com que ele construa coisas para Mac 23 de janeiro de 2012 - Próximas alterações do instalador do Jenkins OSX 7 de março de 2012 - Obrigado por usar o OSX InstallerProcesso
Instale o 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 momento era que um projeto de estilo livre com o script de construçãoxcodebuild -target MyTarget -sdk iphoneos
Deveria trabalhar. Conforme indicado pelo título deste post, ele não falha e falha com:
Code Sign error: The identity 'iPhone Developer' doesn't match any valid certificate/private key pair in the default keychain
É óbvio o que precisa acontecer - você precisa adicionar um certificado de assinatura de código válido e uma chave privada ao chaveiro padrão. Ao pesquisar como fazer isso, não encontrei uma solução que não abra o sistema a algum nível de vulnerabilidad
Problema 1: nenhum chaveiro padrão para o daemon jenkins
sudo -u jenkins security default-keychain
... gera "Não foi possível encontrar um chaveiro padrão"
Conforme indicado abaixo porIvo Dancet, o UserShell está definido como / usr / bin / false para o daemon jenkins por padrão (acho que esse é um recurso, não um bug); siga sua resposta para alterar o UserShell para bash. Você pode usarsudo su jenkins
para efetuar login como usuário jenkins e obter um prompt do bas
sudo su jenkins
cd ~/Library
mkdir Keychains
cd Keychains
security create-keychain <keychain-name>.keychain
security default-keychain -s <keychain-name>.keychain
Certo, ótimo. Temos um chaveiro padrão agora; vamos seguir em frente? Mas, primeiro, por que nos incomodamos em criar um chaveiro padrão?
Quase todas as respostas, sugestões ou conversas que eu li ao longo da pesquisa sugerem que você deve apenas inserir os códigos e chaves de assinatura de código no chaveiro do sistema. Se você executarsecurity list-keychains
como um projeto de estilo livre em Jenkins, você vê que o único chaveiro disponível é o chaveiro 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 idéia, principalmente porque você precisará criar um script de texto sem formatação com a senha para abrir o chaveiro.
Problema 2: Adicionando certificados de assinatura de código e chave privada
É aqui que eu realmente começo a ficar melindroso. Tenho a sensação de que devo criar uma nova chave pública / privada exclusiva para uso com o Jenkins. Meu processo de pensamento é se o daemon jenkins estiver comprometido, então eu posso revogar facilmente 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, significa mais problemas (danos?) Se o serviço jenkins for atacad
Apontando paraSimon Urbanek's answer você estará desbloqueando o chaveiro de um script com uma senha de texto sem formatação. Parece irresponsável manter qualquer coisa, exceto certificados e chaves "descartáveis" nas chaves do daemon jenkin
Estou muito interessado em qualquer discussão em contrário. Estou sendo excessivamente cauteloso?
Para criar um novo CSR como o daemon jenkins no Terminal, fiz o seguinte ...
sudo su jenkins
certtool r CertificateSigningRequest.certSigningRequest
Ser-lhe-á pedido o seguinte (a maioria deles fiz palpites com a resposta correta; você tem uma melhor visão? Por favor, compartilhe.) ...Insira a chave e o rótulo do certificado:Selecione o algoritmo:r
(para RSA) Digite o tamanho da chave em bits:2048
Selecione o algoritmo de assinatura:5
(para MD5)Insira a sequência de desafio:Então um monte de perguntas para o RDNEnvie o arquivo CSR gerado (CertificateSigningRequest.certSigningRequest) ao Portal de provisionamento da Apple sob um novo ID AppleAprove a solicitação e faça o download do arquivo .cersecurity unlock-keychain
security add-certificate ios_development.cer
Isso nos leva um passo mais perto ...
Problem 3: perfil de provisionamento e desbloqueio de chaveiro
Eu criei um perfil especial de provisionamento no Portal de provisionamento para uso com a CI, na esperança de que, se algo ruim acontecer, diminua o impacto. Prática recomendada ou excessivamente cautelosa?
sudo su jenkins
mkdir ~/Library/MobileDevice
mkdir ~/Library/MobileDevice/Provisioning\ Profiles
Mova o perfil de provisionamento configurado no Portal de provisionamento para essa nova pasta. Estamos agora a dois passos de podermos executar o xcodebuild a partir da linha de comando como jenkins, e isso significa que também estamos perto de conseguir que o Jenkins CI execute compilações.security unlock-keychain -p <keychain password>
xcodebuild -target MyTarget -sdk iphoneos
Agora, obtemos uma compilação bem-sucedida a partir de uma linha de comando quando logado como o daemon jenkins; portanto, se criarmos um projeto de estilo livre e adicionarmos as duas etapas finais (nº 5 e nº 6 acima), poderemos automatizar a construção do nosso projeto iOS!
Pode não ser necessário, mas me senti melhor ao definir o jenkins UserShell de volta para / usr / bin / false, depois de obter toda essa configuração. Estou sendo paranóico?
Problema 4: o chaveiro padrão ainda não está disponíve
( EDIT: Publiquei as edições da minha pergunta, reiniciei para garantir que minha solução fosse 100% e, é claro, deixei de fora uma etapa)
Mesmo após todas as etapas acima, você precisará modificar o plist do Daemon de inicialização em /Library/LaunchDaemons/org.jenkins-ci.plist, conforme declarado emesta resposta. Observe que este também é umopenrdar bug.
Deve ficar 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 esta configuração, eu também recomendaria olugin @Xcode para Jenkins, o que facilita a configuração do script xcodebuild. Nesse ponto, eu também recomendo a leitura das páginas de manual do xcodebuild - diabos você chegou até aqui no Terminal, certo?
Esta configuração não é perfeita e qualquer conselho ou insight é muito apreciad
Eu tive dificuldade para selecionar uma resposta "correta", pois o que vim para resolver meu problema foi uma coleção de informações de quase todos. Eu tentei dar a todos pelo menos um voto positivo, mas conceda a resposta a Simon porque ele principalmente respondeu à pergunta original. Além disso, Sami Tikka merece muito crédito por seus esforços em fazer Jenkins trabalhar com o AppleScript como um aplicativo simples e antigo do OS X. Se você estiver interessado apenas em criar Jenkins e entrar rapidamente na sua sessão de usuário (ou seja, não como um servidor sem cabeça), a solução dele é muito mais parecida com o Mac.
Espero que meus esforços façam uma discussão mais aprofundada e ajude a próxima pobre coitada que aparecer pensando que pode instalar o Jenkins CI para seus projetos iOS em um fim de semana por causa de todas as coisas maravilhosas que ouviram falar sobre iss
Update: 9 de agosto de 2013Com tantos votos positivos e favoritos, pensei em voltar a isso 18 meses depois com algumas breves lições aprendida
Lição 1: Não exponha Jenkins à Internet pública
Na WWDC 2012, levei essa pergunta aos engenheiros do Xcode e do OS X Server. Eu recebi uma cacofonia de "não faça isso!" de quem eu pedi. Todos eles concordaram que um processo de criação automatizado era ótimo, mas que o servidor só deveria estar acessível na rede local. Os engenheiros do OS X Server sugeriram a permissão de acesso remoto via VP
Lição 2: Existem novas opções de instalação agora
Fiz recentemente uma palestra no CocoaHeads sobre minha experiência com Jenkins e, para minha surpresa, encontrei alguns novos métodos de instalação - Homebrew e até umBitnami Mac App Store version. Definitivamente vale a pena conferir.Jonathan Wright tem uma essência que detalha como obterHomebrew Jenkins trabalhando.
Lição 3: Não, sério, não exponha sua caixa de criação à internet
É bastante claro pela postagem original que eu não sou um administrador de sistemas nem um especialista em segurança. O bom senso sobre coisas pessoais (chaveiros, credenciais, certificados etc.) me deixou bastante desconfortável ao colocar minha caixa de Jenkins na internet.Nick Arnott no Neglected Potential foi capaz de confirmar meus heebie-jeebies com bastante facilidade emEste artig.
TL; DR
A minha recomendação para outras pessoas que desejam automatizar seu processo de criação mudou no último ano e meio. Verifique se a sua máquina Jenkins está atrás do seu firewall. Instale e configure o Jenkins como um usuário dedicado do Jenkins, usando o instalador, a versão da Bitnami Mac App Store, o AppleScript de Sami Tikka, etc; isso resolve a maior parte da dor de cabeça que eu detalho acima. Se você precisar de acesso remoto, a configuração dos serviços VPN no OS X Server leva dez minutos no máximo. Uso essa configuração há mais de um ano e estou muito feliz com isso. Boa sorte