Integração contínua do iOS com o servidor Xcode explicada

Publicados: 2022-03-11

Introdução

Antes do Xcode 9, usar as ferramentas de integração contínua da Apple era um processo tedioso e complexo que exigia a compra e instalação de um aplicativo macOS Server adicional. Isso levou muitos desenvolvedores a abandonar a ideia de integração contínua para seus projetos iOS ou recorrer a soluções de terceiros, com níveis de sucesso muito variados.

No entanto, após o lançamento do Xcode 9.0 em setembro de 2017, o processo foi bastante simplificado, incluindo a opção de assinatura automática de código, e agora está completamente integrado ao Xcode. Portanto, não requer aplicativos ou ferramentas adicionais.

Embora soluções de terceiros como Fastlane, Bluepill, etc. sejam de grande ajuda e possam fazer muito trabalho pesado para você, este artigo explorará os recursos de usar apenas as ferramentas Xcode e Apple para suas necessidades de integração contínua. Também usaremos a assinatura de código manual, pois isso geralmente parece ser um problema para muitas pessoas, e a assinatura automática também tende a não ser a solução ideal quando se trata de várias configurações de compilação.

Observação: este artigo é baseado no Xcode 9.4.1 e se concentra no desenvolvimento de aplicativos para iOS, mas muito dele é aplicável ao Xcode 10 (atualmente disponível como versão beta 5) e ao desenvolvimento de aplicativos para macOS.

Configurando o servidor Xcode

Além de simplificar o processo de integração real, o Xcode 9 também simplificou o processo de configuração do Xcode Server.

Inicie o aplicativo Xcode em sua máquina macOS que foi designada como seu servidor CI e abra Preferências.

Navegue até a última guia, chamada Server & Bots .

Ferramentas de Integração Contínua: Captura de tela da guia Servidores e Bots

Ative os recursos do Xcode Server clicando no botão no canto superior direito. Em seguida, você será solicitado a selecionar um usuário para executar e executar scripts de compilação nesta máquina. Provavelmente é uma boa ideia ter um usuário dedicado apenas para essa finalidade, em vez de usar um pré-existente.

Observe que esse usuário deve estar conectado ao sistema para que qualquer bot do Xcode seja executado. Depois de fazer login, você verá um círculo verde ao lado do nome de usuário.

Servidor Xcode e Bots após login bem-sucedido

É isso! Vamos dar uma olhada nos bots do Xcode.

Como configurar bots do Xcode

Agora você está pronto para começar a configurar os bots do Xcode para serem executados neste servidor. Isso pode ser feito em qualquer máquina de desenvolvimento conectada à mesma rede do servidor.

Abra o Xcode em sua máquina de desenvolvimento e clique em Xcode > Preferences no menu superior. Em seguida, vá para a guia Contas e clique no ícone + no canto inferior esquerdo. Selecione Servidor Xcode na caixa de diálogo que aparece.

Captura de tela da seleção do tipo de conta

Para criar um bot, basta abrir seu projeto no Xcode e escolher a opção Product > Create Bot… no menu superior. A configuração do bot tem várias etapas e vamos explorá-las nas próximas seções.

Automatizando a distribuição de aplicativos

Uma das aplicações mais frequentes da automação de compilação de aplicativos iOS é configurar um bot para carregar um aplicativo em uma plataforma de distribuição iOS, como TestFlight, Fabric etc.

Como expliquei anteriormente, este artigo explorará apenas o upload para o App Store Connect e o download diretamente do seu servidor Xcode, pois essas são as ferramentas nativas da Apple para distribuição de aplicativos iOS.

Distribuição do App Store Connect usando o Xcode

Antes de configurar um bot, certifique-se de ter um registro de aplicativo App Store Connect que corresponda ao ID do pacote do seu projeto de desenvolvimento de aplicativo. Também vale a pena notar que cada compilação precisa ter um identificador exclusivo que consiste na versão da compilação e no número da compilação. Exploraremos como garantir que essas condições sejam atendidas quando discutirmos as configurações do bot Xcode posteriormente.

Etapa 1: Definir a configuração de compilação correta é a etapa crucial para obter o que você deseja. Certifique-se de selecionar o esquema e a configuração que produzem o aplicativo que você deseja carregar no App Store Connect. Isso inclui garantir que a configuração de compilação use o ID de pacote apropriado registrado no portal do desenvolvedor da Apple da sua equipe (usado para assinatura de código), bem como no portal do App Store Connect (usado para carregar automaticamente o aplicativo) .

Etapa 2: Ainda na guia “Configuração”, precisamos especificar as opções de exportação. Vamos explorar a lista de propriedades de opções de exportação, portanto, certifique-se de que “Usar Plist de opções de exportação personalizadas” esteja selecionado.

Passo 3: Agora é a hora de fazermos nossa lista de propriedades de opções de exportação. Uma lista completa de chaves a serem usadas neste arquivo está disponível se você digitar xcodebuild --help , mas vamos explorar as usadas nesta configuração de bot aqui:

  • compileBitcode – Bitcode é o formato de saída provisório da Apple para o código-fonte do aplicativo. Em outras palavras, é o formato no qual seu código-fonte é convertido antes de ser compilado em código de máquina para uma arquitetura específica. Tem como objetivo ter um único container de código que pode ser otimizado ainda mais se for feita uma otimização no conjunto de instruções, e também poder compilá-lo para futuras arquiteturas deste mesmo formato. No entanto, isso não tem nenhum efeito em seu aplicativo. Cabe a você decidir se deseja ativá-lo ou não.
  • method – Este argumento especifica que tipo de produto você está exportando. A Apple distingue os produtos por seu público designado — o desenvolvimento só permite que você o instale em dispositivos especificados no perfil de provisionamento, a empresa permite que todos o instalem, mas eles precisam confiar explicitamente nesse perfil de desenvolvimento antes de executar o aplicativo, e a loja de aplicativos é para distribuindo-o para a App Store ou App Store Connect, então vamos usar esse valor.
  • provisioningProfiles – Isso é autoexplicativo. Mas há algumas coisas a serem observadas aqui: Os perfis de provisionamento na lista de propriedades de opções de exportação são um dicionário em que uma chave corresponde ao ID do pacote de um produto e o valor corresponde ao nome do perfil de provisionamento usado para assiná-lo.
  • signingCertificate – Outro argumento autoexplicativo. O valor desse campo pode ser um nome de certificado completo ou um hash SHA-1.
  • teamID – Outro argumento autoexplicativo. Este é o identificador de 10 caracteres que a Apple emitiu para sua organização quando você se inscreveu no programa Apple Developer.
  • uploadBitcode – se deve ou não carregar bitcode (se você optou por compilar nele) para que possa ser usado no AppStore Connect para gerar novas compilações otimizadas ou compilações para arquiteturas futuras.
  • uploadSymbols – Carrega seus símbolos de depuração para que você possa obter um relatório de falha significativo em vez de apenas um despejo de memória e uma pilha de montagem.

Então, agora, sua lista de propriedades de opções de exportação pode ser algo 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>compileBitcode</key> <false/> <key>method</key> <string>app-store</string> <key>provisioningProfiles</key> <dict> <key>com.bundle.id</key> <string>ProvisioningProfileName</string> </dict> <key>signingCertificate</key> <string>Signing Certificate Exact Name or SHA-1 hash value</string> <key>teamID</key> <string>??????????</string> <key>uploadBitcode</key> <false/> <key>uploadSymbols</key> <true/> </dict> </plist>

Etapa 4: escolha o .plist que você criou como a lista de propriedades de opções de exportação.

Etapa 5: Em seguida, é a guia "Agendar" - configure-a de acordo com suas preferências.

Etapa 6: na guia Assinatura, certifique-se de desmarcar a opção “Permitir que o servidor Xcode gerencie meus certificados e perfis” e faça o upload de um certificado de assinatura correspondente e perfil de provisionamento por conta própria, na página Certificados e perfis .

Etapa 7: a guia Dispositivos deve ser deixada como está, pois estamos carregando o aplicativo em vez de testá-lo.

Etapa 8: A guia Argumentos permite definir explicitamente argumentos xcodebuild ou variáveis ​​de ambiente que podem ser usadas em seus scripts de compilação ou pré-integração e pós-integração.

Etapa 9: Por fim, chegamos à guia Triggers , que também é a última guia na configuração do bot de integração contínua do Xcode. Esta é a ferramenta mais poderosa do arsenal do Xcode Server. Para começar, gosto de adicionar os dois comandos a seguir como um script de pré-integração:

 #!/bin/sh set printenv

O primeiro imprime todas as variáveis ​​que o Xcode Server usa e seus valores na execução da integração atual. O segundo imprime todas as variáveis ​​de ambiente e seus valores. Como esperado, isso pode ser útil na depuração de seus scripts, então eu o chamo apropriadamente de “informações de depuração”.

Lembre-se de que mencionamos que precisamos garantir que cada compilação carregada no App Store Connect tenha uma versão de compilação exclusiva e um par de número de compilação. Podemos usar a ferramenta integrada PlistBuddy, mas também precisamos de uma maneira de ter um número de compilação exclusivo. Uma coisa que está sempre presente durante a integração do Xcode Server - e também é convenientemente exclusiva - é o número de integração, pois é incrementado automaticamente. Criaremos outro script de pré-integração, chamado “set build number” com o seguinte conteúdo para garantir que sempre tenhamos um número de compilação exclusivo:

 #!/bin/sh buildNumber=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${PROJECT_DIR}/${INFOPLIST_FILE}") buildNumber=$XCS_INTEGRATION_NUMBER /usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildNumber" "${PROJECT_DIR}/${INFOPLIST_FILE}"

Se você estiver usando CocoaPods e optou por não confirmar o diretório Pods em seu DVCS, inclua também um script de pré-integração com o seguinte conteúdo:

 #!/bin/sh cd $XCS_PRIMARY_REPO_DIR pod install

Etapa 10: Estamos quase terminando, mas não especificamos em nenhum lugar que queremos carregar a compilação para o AppStore Connect ou para qual conta. Para isso, adicionaremos o script de pós-integração e outra ferramenta incorporada, chamada Application Loader. Coloque o seguinte no script:

 #!/bin/sh /Applications/Xcode.app/Contents/Applications/Application\ Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Support/altool --upload-app -f $XCS_PRODUCT -u $TESTFLIGHT_USERNAME -p $TESTFLIGHT_PASSWORD

O $XCS_PRODUCT é uma variável do Xcode Server e contém o caminho para o aplicativo que foi criado na execução de integração atual. No entanto, o $TESTFLIGHT_USERNAME e $TESTFLIGHT_PASSWORD não são variáveis ​​do sistema nem do servidor Xcode. Eles devem ser configurados por você e ter o valor do seu ID Apple e senha. Infelizmente, a Apple descontinuou o suporte para gerar uma chave de API para upload de compilação do AppStore Connect. Como essas informações são confidenciais, é a melhor prática configurá-las diretamente no servidor Mac (supondo que sejam suas) como uma variável de ambiente em vez de na configuração do bot do Xcode Server.

Distribuição do servidor Xcode

Na verdade, o bot de distribuição do Xcode Server usa a mesma configuração da distribuição do App Store Connect, com exceção dos scripts de pós-integração. No entanto, baixar o aplicativo e instalá-lo ainda pode ser complicado. Você ainda precisa garantir que o perfil de provisionamento com o qual você assinou seu aplicativo permita que o aplicativo seja instalado no dispositivo que você está usando.

Com isso, você precisará abrir o Safari no seu dispositivo iOS e navegar até o painel da web do servidor Xcode do seu servidor. Por exemplo, se o nome do seu servidor for “servidor Mac”, você poderá encontrá-lo em “mac-server-name.local/xcode” se estiver na mesma rede que o servidor. Lá, você encontrará uma lista de todos os seus bots Xcode e as estatísticas de suas integrações mais recentes.

Selecione aquele que criou o aplicativo que você deseja baixar. Na tela a seguir, você terá dois botões— Instalar e Perfil . Se esta é a primeira vez que você baixa deste servidor, você deve clicar em Perfil para adicionar seu certificado à lista de fontes confiáveis. Depois, clique no botão Instalar na mesma página e você será saudado com a caixa de diálogo de confirmação do iOS “Tem certeza de que deseja instalar * no seu dispositivo?” Confirme clicando em Sim e seu aplicativo será instalado e executável na tela inicial.

Captura de tela das opções de instalação do aplicativo

Para iOS 10.3 e posterior , um motivo pelo qual pode falhar com “Não é possível conectar a *.local” é que o certificado autoassinado deve ser confiável manualmente em Configurações no dispositivo de teste.

Siga esses passos:

Etapa 1: instale o(s) certificado(s) autoassinado(s) da página de bots do servidor Xcode no seu iPhone.

Etapa 2: Vá para Configurações do iPhone> Geral> Sobre> Configurações de confiança do certificado .

Etapa 3: encontre o(s) certificado(s) autoassinado(s) do seu servidor na seção HABILITAR CONFIANÇA TOTAL PARA CERTIFICADOS DE RAIZ e LIGUE a chave.

Etapa 4: retorne à página de integração do bot no Xcode Server, clique em Instalar .

Teste automático de aplicativos do servidor Xcode

Outro grande uso do Xcode Server é o teste automático de aplicativos, seja teste de unidade ou de interface do usuário. Para fazer isso, você precisa ter o destino apropriado configurado para o seu projeto. Ou seja, você precisa ter um destino que execute testes de unidade ou de interface do usuário, dependendo do seu objetivo.

O processo de configuração é o mesmo que o anterior, mas selecionaremos opções diferentes. A primeira grande diferença está na guia Configuração . Obviamente, vamos marcar as caixas “Analisar” e “Testar”, pois esse é nosso objetivo principal. Eu também aconselho não arquivar nem exportar o produto com este bot. É possível realizar testes e distribuição com a mesma configuração de bot. No entanto, esses dois cenários diferem em sua saída, bem como em sua programação. A distribuição geralmente é executada no final do ciclo.

Esteja você trabalhando em Scrum ou Kanban ou em alguma outra estrutura, deve haver um ciclo predefinido orientado a tempo ou a eventos no final do qual você deve ter um produto exportado e utilizável. Por outro lado, você deve executar seu bot de teste em cada commit, já que é sua primeira linha de defesa contra regressões. Como o bot de teste obviamente é executado com mais frequência, mesclar esses dois bots em um único pode usar rapidamente o espaço em disco em seu servidor. E também levaria mais tempo para concluir cada integração.

Com isso fora do caminho, estamos migrando para a guia “Schedule”, e já abordamos isso no parágrafo anterior. Assim, o próximo tópico de interesse é a assinatura de código. Observe que, embora seu destino de teste possa declarar que não precisa de perfil de provisionamento na página de configurações do projeto, você deve configurá-lo para usar a mesma equipe e certificado de assinatura do aplicativo host. Isso é necessário se você quiser testar seu aplicativo em um dispositivo iOS em vez de apenas em um simulador. Se este for o seu caso, você também precisa garantir que o dispositivo iOS usado para teste não seja bloqueado devido à inatividade, pois isso pode fazer com que sua execução de integração seja interrompida indefinidamente sem notificá-lo.

Agora estamos na aba “Dispositivos” que não precisa de explicação específica. Basta selecionar um, vários ou todos os dispositivos (iOS e simulador) com os quais você deseja testar seu código. Você também pode verificar se deseja executar testes em vários dispositivos em paralelo ou sequencialmente. Para configurar isso, você deve considerar as necessidades do seu projeto (se você está direcionando um conjunto específico de dispositivos ou todos os dispositivos iOS suportados) e também os recursos de hardware do servidor.

Na guia Argumentos . não há necessidade de especificar nada explicitamente, pois usaremos apenas variáveis ​​de ambiente internas.

Por fim, na guia Triggers , apresentaremos um script de pré-integração e um script de pós-integração. O primeiro está lá apenas para nos ajudar a depurar caso tenhamos alguns problemas. Na verdade, é o que já usamos:

 #!/bin/sh set printenv

O segundo é aquele que nos notificará caso um ou mais de nossos testes falhe na integração atual. Certifique-se de que ele esteja configurado para ser executado apenas em falhas de teste. E digite o seguinte:

 #!/bin/sh echo "$XCS_TEST_FAILURE_COUNT test(s) failed for $XCS_BOT_NAME bot on build $XCS_INTEGRATION_NUMBER" echo "You can see bot integration at:" echo "https://$HOSTNAME/xcode/bots/$XCS_BOT_TINY_ID/integrations/$XCS_INTEGRATION_TINY_ID"

Há algumas coisas que devem ser explicadas aqui. Em primeiro lugar, as variáveis ​​$HOSTNAME armazenam o valor no seguinte formato: computer-name.local. Obviamente, o link só funcionaria se você pudesse acessar aquele servidor pela rede local. Além disso, você provavelmente receberá um aviso de segurança do seu navegador ao visitar este link, pois é uma conexão https para um destino que não é confiável. Finalmente, este é apenas um ponto de partida para o seu script “Falha no teste”. Você pode enviar um e-mail para toda a equipe de desenvolvimento ou abrir um problema do JIRA por meio de uma solicitação de API ou qualquer outra coisa que considere mais apropriada e produtiva.

Empacotando

Espero que este artigo tenha incentivado você a explorar os recursos do Xcode Server além de simplesmente criar um aplicativo. Embora este post possa não ter ajudado exatamente da maneira que você queria ou esperava, o objetivo era apresentar uma maneira de mente aberta de usar ambientes internos e variáveis ​​do Xcode Server para alcançar um nível mais alto de automação.

Existem muitos serviços de terceiros que permitem mais funcionalidades e podem fazer muito mais trabalho para você, incluindo Fabric, Bluepill e Fastlane. Mas, inevitavelmente, confiar em um terceiro introduz uma nova dependência ao seu projeto e requer configuração e configuração às vezes simples, às vezes complexas. As técnicas descritas aqui exigem apenas ferramentas já instaladas em todos os Macs, portanto, não requer tempo de configuração além de configurar os próprios bots que executarão suas compilações automatizadas!