- Azure
- Azure DevOps
- Xamarin
Lorsque vous développez une application mobile, vous travaillez souvent en équipe; chaque membre de l’équipe code une fonctionnalité et la propose par le système de Pull Request aux autres développeurs. Lorsqu’un ou deux développeurs de votre équipe la valideront, votre code sera fusionné avec le reste du code.
Pour être sûr que votre projet compile toujours, il est recommandé de le builder régulièrement dans un environnement de référence, ce qui, dans notre cas est Azure DevOps. Pour ce faire, une façon consiste à builder votre projet chaque jour ouvrable à minuit.
Dans ce tutoriel, je vais vous montrer comment configurer une nightly builds en utilisant une application Xamarin.Forms.
Dans mon précédent tutoriel nous avons vu comment exécuter et publier des tests unitaires dans Azure DevOps. Ce tutoriel fait partie d’une série complète de tutoriels Azure DevOps utilisant une application Xamarin.Forms en tant qu’exemple. Ce tutoriel peut être lu indépendamment et les concepts peuvent être appliqués à n’importe quelle technologie mobile que vous utilisez.
Passons à Azure DevOps et créons un nouveau pipeline.
Dans l’onglet Pipelines, créez un New pipeline et suivez les 4 étapes pour obtenir le code source à partir du repository approprié. Azure DevOps créera automatiquement un nouveau fichier azure-pipelines.yml
à la racine du dossier de votre projet. C’est à cet endroit que la définition du job sera définie et ensuite interprétée par Azure DevOps.
Si vous avez fait le tutoriel précédent, vous disposez déjà d’un modèle appelé init_restore.yml
pour restaurer les packages Nuget de votre projet dans un dossier templates
à la racine de votre projet de solution qui contient ces lignes:
parameters:
solutionPath: ''
steps:
- task: NuGetToolInstaller@1
- task: NuGetCommand@2
inputs:
restoreSolution: '${{ parameters.solutionPath }}'
Nous utiliserons quelque chose appelé stages
qui nous permet d’exécuter différents travaux sur des agents distincts. Ci-dessous, nous avons défini une liste de stages
, un pour iOS et un pour Android. Dans chacun, nous restaurons nos packages Nuges en utilisant le modèle que nous avons créé précédemment.
trigger:
- master
pool:
vmImage: 'macOS-10.14'
stages:
- stage: Build_Xamarin_Android
dependsOn: []
jobs:
- job:
displayName: 'Build Xamarin.Android'
workspace:
clean: all
steps:
- template: templates/init_restore.yml
parameters:
solutionPath: '$(solutionPath)'
## Steps to build your Xamarin Android application
- stage: Build_Xamarin_iOS
dependsOn: []
jobs:
- job:
displayName: 'Build Xamarin.iOS'
workspace:
clean: all
steps:
- template: templates/init_restore.yml
parameters:
solutionPath: '$(solutionPath)'
## Steps to build your Xamarin Android application
Par défaut, chaque stage
dépend de la précédente, ils démarrent donc un par un. Pour éviter que vos stage
ne dépendent les uns des autres, il vous suffit de définir la propriété dependsOn
à un tableau vide comme ci-dessus. Si vous avez upgradé votre abonnement Azure DevOps, vous pourrez exécuter plusieurs travaux en parallèle. Il créera donc votre application iOS et Android en même temps. Pour vérifier cela, allez dans Project settings > Parallel jobs et vous verrez le nombre de travaux en parallèles dont vous disposez.
Il est temps d’ajouter les tasks de builds et de signature en fonction de ce que je vous ai montré dans les tutoriels précédents.
Créons un nouveau fichier appelé variables.yml
dans notre dossier templates
. Il contiendra toutes les variables du pipeline. En les séparant dans un fichier spécifique, il sera plus facile à maintenir.
Voici les variables dont nous avons besoin à ce stade pour pouvoir builder notre projet:
variables:
- name: xamarinSdkVersion
value: '6_6_0'
- name: solutionPath
value: '**/*.sln'
- name: buildConfiguration
value: 'Release'
La dernière version actuelle du SDK Xamarin est la version 6.6.0, c’est pourquoi nous avons défini la valeur du xamarinSdkVersion
à 6_6_0
. Cela nous permet également d’avoir une nouvelle fonctionnalité pour Xamarin.Android: les Android App Bundle !
Pour des raisons de sécurité, nous devrons créer un groupe de variables pour stocker l’alias et les mots de passe associés au keystore et au provisioning profile pour signer notre application. Si vous n’êtes pas familier avec cela, vous pouvez consulter mon précédent tutoriel à ce sujet.
Pour ce tutoriel, les groupes de variables seront appelés xamarin-full-pipeline
, ils contiennent tous les mots de passe du keystore et du provisioning profile. Il ressemblera à ceci:
N’oubliez pas d’uploader votre provisioning profile et votre keystore dans les fichiers sécurisés pour pouvoir signer vos applications.
Avant vos steps
, chargeons le groupe de variables et le variables.yml
comme ceci:
variables:
- group: xamarin-full-pipeline
- template: templates/variables.yml
Pour Android, créons un nouveau modèle appelé build_xamarin_android.yml
dans le dossier templates
. Ce template définira une version personnalisée pour le SDK Xamarin, buildera l’application Android et la signera:
parameters:
xamarinSdkVersion: ''
packageFormat: 'apk'
projectFile: ''
buildConfiguration: ''
apksignerKeystoreFile: ''
apksignerKeystorePassword: ''
apksignerKeyPassword: ''
steps:
- script: sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh ${{ parameters.xamarinSdkVersion }}
displayName: 'Select the Xamarin SDK version'
enabled: true
- task: DownloadSecureFile@1
name: keyStore
displayName: "Download keystore from secure files"
inputs:
secureFile: '${{ parameters.apksignerKeystoreFile }}'
- task: Bash@3
displayName: "Download keystore from secure files"
inputs:
targetType: "inline"
script: |
msbuild -restore ${{ parameters.projectFile }} -t:SignAndroidPackage -p:AndroidPackageFormat=${{ parameters.packageFormat }} -p:Configuration=${{ parameters.buildConfiguration }} -p:AndroidKeyStore=True -p:AndroidSigningKeyStore=$(keyStore.secureFilePath) -p:AndroidSigningStorePass=${{ parameters.apksignerKeystorePassword }} -p:AndroidSigningKeyAlias=${{ parameters.apksignerKeystoreAlias }} -p:AndroidSigningKeyPass=${{ parameters.apksignerKeyPassword }}
Comme vous pouvez le voir, ce template nous permet de créer et de signer un apk ou aab (Android App Bundle), selon la valeur de la propriété packageFormat
que vous choisissez: apk
ou aab
.
Si vous souhaitez comprendre en détail comment une application Xamarin.Android peut être créée à l’aide d’Azure DevOps, il est recommandé de lire les tutoriels précédents à ce sujet:
Maintenant, dans notre azure-pipelines.yml
, nous pouvons utiliser ce modèle juste après la restauration des packages Nugets pour l’application Xamarin.Android:
- template: templates/build_xamarin_android.yml
parameters:
xamarinSdkVersion: '$(xamarinSdkVersion)'
packageFormat: 'aab' # Choose apk or aab depending on your needs
projectFile: '$(Build.SourcesDirectory)/XamarinDevOps.Android/*.csproj'
buildConfiguration: '$(buildConfiguration)'
apksignerKeystoreFile: 'production.jks'
apksignerKeystorePassword: $(keystore.password)
apksignerKeystoreAlias: $(key.alias)
apksignerKeyPassword: $(key.password)
Pour iOS, créons un nouveau template appelé build_xamarin_ios_ipa.yml
dans le dossier templates
. Ce template ressemblera au précédent; définissez une version personnalisée pour le SDK Xamarin, buildez l’application iOS et la signer:
parameters:
xamarinSdkVersion: ''
p12FileName: ''
p12Password: ''
provisioningProfile: ''
solutionPath: ''
buildConfiguration: ''
signingIdentity: ''
signingProvisioningProfileID: ''
steps:
- script: sudo $AGENT_HOMEDIRECTORY/scripts/select-xamarin-sdk.sh ${{ parameters.xamarinSdkVersion }}
displayName: 'Select the Xamarin SDK version'
enabled: true
- task: InstallAppleCertificate@2
inputs:
certSecureFile: '${{ parameters.p12FileName }}'
certPwd: '${{ parameters.p12Password }}'
keychain: 'temp'
deleteCert: true
- task: InstallAppleProvisioningProfile@1
inputs:
provisioningProfileLocation: 'secureFiles'
provProfileSecureFile: '${{ parameters.provisioningProfile }}'
removeProfile: true
- task: XamariniOS@2
inputs:
solutionFile: '${{ parameters.solutionPath }}'
configuration: '${{ parameters.buildConfiguration }}'
packageApp: true
buildForSimulator: false
runNugetRestore: false
signingIdentity: '${{ parameters.signingIdentity }}'
signingProvisioningProfileID: '${{ parameters.signingProvisioningProfileID }}'
Si vous voulez comprendre en détail ce que fait chaque task dans ce template, il est recommandé de lire mon précédent tutoriel à ce sujet.
Revenez à notre azure-pipelines.yml
et appelez ce modèle juste après la restauration des packages Nugets pour l’application Xamarin.iOS:
- template: templates/build_xamarin_ios_ipa.yml
parameters:
xamarinSdkVersion: '$(xamarinSdkVersion)'
p12FileName: '$(p12FileName)'
p12Password: '$(p12Password)'
provisioningProfile: '$(provisioningProfile)'
solutionPath: '$(solutionPath)'
buildConfiguration: '$(buildConfiguration)'
signingIdentity: '$(APPLE_CERTIFICATE_SIGNING_IDENTITY)'
signingProvisioningProfileID: '$(APPLE_PROV_PROFILE_UUID)'
Prochaine étape, nous devons ajouter la possibilité à notre pipeline d’être démarré automatiquement chaque nuit pendant la semaine. Cela buildera notre application et lorsque vous retournerez au bureau le lendemain, il vous suffira de vérifier si tout c’est bien passé. Cela garantira que votre code se compile également en dehors de votre machine personnelle.
Pour ce faire, avant de définir les stages
à l’intérieur de votre azure-pipeline.yml
, ajoutez ces lignes:
schedules:
- cron: "0 0 * * 1-5"
displayName: Daily midnight build
branches:
include:
- master
La task cron
fait fonctionner le pipeline du lundi au vendredi à minuit.
0
correspond aux minutes de 0 à 590
correspond aux heures de 0 à 23*
correspond aux jours de 1 à 31*
correspond au mois de 1 à 121-5
correspond aux jours, 0 est le dimancheMaintenant, basé sur le précédent tutoriel nous ajouterons un étape pour exécuter nos tests unitaires avant les étapes de builds de notre application iOS et Android:
- stage: Run_Unit_Tests
jobs:
- job:
displayName: 'Run Unit Tests'
steps:
- template: templates/run_unit_tests.yml
parameters:
solutionPath: '$(solutionPath)'
projects: '$(Build.SourcesDirectory)/XamarinDevOps.Tests/*.csproj'
buildConfiguration: '$(buildConfiguration)'
Ensuite, pour exécuter les tests avant de builder votre application, définissez la valeur dependsOn
du stage
iOS et Android comme ceci:
dependsOn: Run_Unit_Tests
Si vous le faites correctement et exécutez votre pipeline, vous verrez quelque chose comme ceci:
Vous avez maintenant une configuration de nightly build, qui garantit la réussite du build de votre projet et des templates réutilisables dans vos projets.
Dans le prochain tutoriel de cette série, nous nous concentrerons sur la gestion de votre application par environnement !
Sources:
Vous trouverez tout le code source sur ce répertoire Github sur la branche nightly_builds
.
Happy coding!
Vous avez aimé ce tutoriel ? Laissez une étoile sur le répertoire Github associé !