Gerando artefatos .ipa com GitHub Actions
Em algum momento em sua jornada como pessoa desenvolvedora Swift você irá precisar gerar um .ipa para seu projeto e disponibilizar ele para o time de Read Team, para enviar para o cliente reassinar ou para outro objetivo qualquer que necessite transportar o arquivo .ipa para algum local ou para alguém baixar. Este post vai lhe ajudar a fazer isso de uma forma segura e utilizando automação para tal finalidade.
Vamos lá!
Vamos utilizar um repositório no GitHub e o recurso de automação de workflow GitHub Actions.
No final do post vou deixar links de referências bibliográficas que usei para escrever este post.
Quem programa para a plataforma da Apple sabe que é sempre uma dor de cabeça lidar com os Certificados e Profiles, neste post vou mostra uma forma que o GitHub tem para usar eles de forma mais simplificada sem precisar gerar novos(caso você não queira).
Criando secrets para seu certificado e perfil de provisionamento
O processo de assinatura envolve armazenar certificados e perfis de provisionamento, transferi-los para o runner, importá-los para o controle de secrets do runner e usá-los em seu build.
Para usar seu certificado e perfil de provisionamento em um runner, é altamente recomendável usar secrets do GitHub. Para obter mais informações sobre como criar secrets e usá-los em um workflow, clique aqui. Nas orientações abaixo vou considerar que você sabe onde armazenar a secrets no seu repositório do GitHub.
Para resumir os secrest ficam dentro de uma url neste padrão: https://github.com/meu_usuario/meu_repo/settings/secrets/actions
Gerando secret de seu certificado de assinatura da Apple.
Este é o seu arquivo de certificado p12. Para obter mais informações sobre como exportar seu certificado de assinatura do Xcode, clique aqui.
Você deve converter seu certificado para Base64 ao salvá-lo como secret. Neste exemplo, o secret no GitHub é denominado BUILD_CERTIFICATE_BASE64.
Use o seguinte comando para converter seu certificado em Base64 e copiá-lo para a área de transferência:
base64 -i distribuition_certificate.p12 | pbcopy
OBS: Executei este comando dentro da pasta de onde armazenei meus certificados.
Com o comando executado a string de base64 já está na sua área de transferência e pode ser colada em um novo secrets no GitHub
Quando você exportou o certificado de assinatura você precisou colocar uma senha precisamos colocar esta senha em um secret do GitHub também. Neste exemplo vou criar uma entrada P12_PASSWORD.
Gerando secret para seu Profile
A documentação do GitHub indica um link que explica como fazer o download manual via Xcode. Mas fiz de outra forma que considerei mais simples. Acesse sua conta de desenvolvedor: https://developer.apple.com/account/. E Na sessão de Certificates, Identifiers & Profiles acesse o menu Profiles
Acesse o menu Profiles desta página que abriu e você terá a lista de profiles disponíveis na sua conta. Escolha o Profile de AppStore e faça o Download.
OBS: Você pode usar profile de Ad-Hoc ou enterprise também, desde que ele possa exportar o .ipa
Com o profile em sua maquina vamos fazer o mesmo procedimento de executar o comando base64 só que desta vez no arquivo .mobileprovision que você fez download no passo acima. Neste caso será denominado BUILD_PROVISION_PROFILE_BASE64
base64 -i MeuAppBacanaAppStoreDistribuition.mobileprovision | pbcopy
O ultimo secret
Um novo KEYCHAIN será criado no runner, então a senha para o novo chaveiro pode ser qualquer nova string aleatória. Neste exemplo, o segredo é denominado KEYCHAIN_PASSWORD.
Com isso concluímos nosso passos para criação dos secrets.
Criando steps no workflow
Aqui é meio que uma receita de bolo até a parte — name: Build app você pode sempre considerar copiar, após isso adicione o trecho de steps para realizar os demais passos que você quer considerar:
name: App build
on: pushjobs:
build_with_signing:
runs-on: macos-lateststeps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install the Apple certificate and provisioning profile
env:
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
BUILD_PROVISION_PROFILE_BASE64: ${{ secrets.BUILD_PROVISION_PROFILE_BASE64 }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
# create variables
CERTIFICATE_PATH=$RUNNER_TEMP/build_certificate.p12
PP_PATH=$RUNNER_TEMP/build_pp.mobileprovision
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db# import certificate and provisioning profile from secrets
echo -n "$BUILD_CERTIFICATE_BASE64" | base64 --decode --output $CERTIFICATE_PATH
echo -n "$BUILD_PROVISION_PROFILE_BASE64" | base64 --decode --output $PP_PATH# create temporary keychain
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH# import certificate to keychain
security import $CERTIFICATE_PATH -P "$P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH# apply provisioning profile
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
- name: Build app
...
Por motivos de indentação e para posterior consulta deixei o arquivo final em um Gist para que você possa entender melhor.
IMPORTANTE: Você vai se deparar com um comando que tem esta propriedade:
-exportOptionsPlist ./distribution-files/production-ci.plist
Neste caso na raiz do meu projeto criei uma pasta distribution-files
E dentro desta pasta um arquivo production-ci.plist com o seguinte conteúdo
<?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>br.com.meubundleid</key> <string>MeuAppBacanaAppStoreDistribuition</string> </dict></dict></plist>
Um detalhe para a string MeuAppBacanaAppStoreDistribuition. Ela deve ser igual ao nome arquivo do profile que você enviou no secrets dos passos anteriores, neste tutorial geramos o base64 do profile: MeuAppBacanaAppStoreDistribuition.mobileprovision lembra?
Feito, configurações realizadas, não esqueça de editar seu yml do workflow para que se adeque a seu processo de geração de artefatos. Escolhendo branch, tags … Ao final vocês terá o artefato no workflow executado. Como na imagem abaixo.
OBS: neste Script eu deixei o artefato com validade de 1 dia você pode editar isso na propriedade retention-days: 1 no yml
Até a próxima
Glossário:
Runner: Executor de scripts, é uma maquina Linux, macOS ou Windows que executa os comandos do workflow. Você pode transformar sua maquina em um Runner também saiba mais aqui.
Bibliografia:
Export signing certificates and provisioning profiles: https://help.apple.com/xcode/mac/current/#/dev8a2822e0b
Download manual provisioning profiles: https://help.apple.com/xcode/mac/current/#/deva899b4fe5
Apoie o meu trabalho
Se gosta do meu conteúdo, você pode demonstrar o seu apoio com uma contribuição e me ajudar produzir ainda mais.