Fermer

mai 7, 2023

Pipelines Bitbucket CI/CD pour Optimizely CMS 12 / Blogs / Perficient

Pipelines Bitbucket CI/CD pour Optimizely CMS 12 / Blogs / Perficient


Une grande raison derrière cet article est que ce sujet, même s’il est très pertinent, n’a jusqu’à présent que très peu ou pas de contexte disponible en ligne. Il y a des messages à ce sujet étant possible et très pipelines de build génériques pour les déploiements .net core vers azure, mais aucun ne décrivant comment créer des pipelines Bitbucket CI/CD pour Optimizely CMS 12 spécifiquement. Et parce qu’il a fallu pas mal de recherches et d’essais et d’erreurs, au cours de plusieurs semaines, pour que cela fonctionne, je pense que cet effort vaut la peine d’être partagé, afin que les autres ne finissent pas par perdre autant de temps.

Si vous lisez ceci, soit vous avez déjà travaillé avec Azure Devops et des pipelines et avez besoin d’une solution similaire avec des pipelines bitbucket, soit vous êtes tout nouveau sur Devops et vous commencez uniquement avec Bitbucket. Juste pour mettre un peu de contexte, il existe des différences clés entre les pipelines Azure Devops et Bitbucket, pour quiconque essaie de référencer les pipelines Azure Devops pour en créer des Bitbucket :

  1. Ils varient tous deux clairement dans la syntaxe – ils définissent les déclencheurs, les variables et les étapes différemment ; ils lisent les valeurs des variables différemment, la façon d’exécuter les scripts varie dans les deux cas et bien plus encore.
  2. Ils ont tous deux des différences dans le nombre de fichiers YAML que vous devez créer pour l’ensemble du pipeline CI/CD – Dans Azure Devops, vous pouvez créer 2 fichiers YAML distincts, un pour la construction et un autre pour la publication. Dans Bitbucket, il n’y a qu’un seul fichier YAML appelé bitbucket-pipelines.yml.
  3. Un autre fait intéressant pour les pipelines Bitbucket est qu’il est très sensible au formatage et à l’indentation. Vous verriez en fait des lignes sinueuses rouges dans votre code de pipeline s’il n’est pas correctement mis en retrait. Bitbucket a donc cet outil en ligne pour aider à résoudre ce type d’erreurs tôt avant d’exécuter les pipelines.

Doit savoir des choses pour Optimizely Deployment

Avant de nous lancer dans la façon dont nous avons procédé dans Bitbucket, examinons quelques éléments incontournables dont nous devons être conscients lors de la création de pipelines pour les déploiements Optimizely, qu’ils soient construits dans Azure Devops ou Bitbucket :

  1. Cela nécessite Powershell – Fournit de manière optimale un module powershell personnalisé appelé EpiCloud pour activer le déploiement à l’aide de l’API de déploiement. Cela a la plupart des scripts pré-créés et il vous suffit de les appeler avec les bonnes valeurs de paramètres spécifiques au projet. Vous pouvez trouver des détails à ce sujet ici.
  2. Format du paquet de code – Le package de code final que vous créez pour déployer doit avoir un certain format et s’il ne correspond pas à ce format spécifié, vous vous retrouverez avec des erreurs lors du déploiement ou un déploiement défectueux qui pourrait lancer le site mais avec des erreurs. Voici les détails sur ce que tout cela devrait inclure.

Accéder à bitbucket-pipelines.yml

Sauter directement à la façon dont nous avons construit notre Bitbucket Pipeline. Je vais vous expliquer étape par étape avec du code pour vous faciliter la tâche :

Image Docker

Les déploiements sont conteneurisés de nos jours et les images Docker sont un élément clé du déploiement basé sur des conteneurs, offrant un moyen fiable et cohérent de conditionner, distribuer et exécuter des applications dans des conteneurs. C’est la première chose que vous devez définir dans votre bitbucket-pipelines.yml.

Dans Bitbucket, vous commencerez généralement avec un modèle auquel une image docker peut déjà être ajoutée, mais qui ne correspond pas nécessairement au framework ou à la version dont vous avez besoin. Se référer à ici pour trouver l’image docker qui vous convient. Dans mon cas, j’ai utilisé Image du SDK .net6 pour mon De manière optimale CMS 12 projet :

image: mcr.microsoft.com/dotnet/sdk:6.0

Déclencheur de pipeline

Vous pouvez créer plusieurs pipelines dans le même fichier YAML et définir le nom de la branche ou les demandes d’extraction comme déclencheurs pour eux. J’avais besoin que le pipeline de construction s’exécute lorsque le code est engagé dans la branche « develop », donc je l’ai utilisé comme déclencheur :

pipelines:
  branches: 
    develop:

Pas

Chaque action que vous souhaitez effectuer dans le cadre du pipeline devient une étape. Idéalement, vous donneriez un nom et un script à chaque étape. De plus, vous pouvez également ajouter une image docker, qui serait spécifique à cette étape. Par exemple, dans mon cas, lorsque j’ai eu besoin de créer la partie frontale de mon code qui utilisait Node et NPM, j’ai ajouté une image docker pour Node à cette étape. Vous pouvez également ajouter des caches à votre étape, ce qui mettrait en cache les dépendances des étapes précédentes, pour permettre des builds plus rapides.

Voici 2 étapes que j’ai eues – une pour la construction frontale et une autre pour la construction de code Optimizely .Net :

- step:
         name: Frontend build
         image: node:16.19.1
         caches:
           - node
         script:
           # run command from within the front end directory where package.json lives
           - pushd frontend-dir
           - npm install
           - npm run build:${projectname}           
           # Go Back to previous Directory
           - popd
           - mkdir wwwroot
           # Copy FED Files from project's wwwroot folder to clone dir's wwwroot folder
           - cp -avr ${projectpath}/wwwroot/. wwwroot           
         artifacts:
           - wwwroot/**

- step:
          name: .NET Core build, publish and package
          caches:
            - dotnetcore
          script: 
              # Update Package Source & Install ZIP Library
            - apt-get update
            - apt-get install zip -y
              # Create variables
            - export VERSION=1.0.$BITBUCKET_BUILD_NUMBER   # choose your own versioning strategy here              
            - export PROJECT_PATH="$BITBUCKET_CLONE_DIR/${project path}/${projectnanme}.csproj"   
            - export PUBLISH_LOC=$BITBUCKET_CLONE_DIR/OutputFiles # new folder to hold the published code
            - export PACKAGE_NAME=${projectname}.app.$VERSION.nupkg # this needs to have .app and .{version} on it, per Optimizely Code package format
              # Create deployment folders
            - mkdir -p $PUBLISH_LOC
            - mkdir package
            - mkdir $PUBLISH_LOC/wwwroot
              # Restore Project, Build, and Publish
            - dotnet restore ${solutionName}
            - dotnet build ${solutionName} --no-restore --configuration ${buildConfiguration}  
            - dotnet publish $PROJECT_PATH --configuration ${buildConfiguration} --no-build --output $PUBLISH_LOC            
             # Copy in wwwroot files into publish location
            - cp -avr wwwroot/. $PUBLISH_LOC/wwwroot
             # Temporarily run cmommand from new directory
            - pushd $PUBLISH_LOC
             # ZIP directory contents into NUPKG file
            - zip -r $BITBUCKET_CLONE_DIR/package/$PACKAGE_NAME.nupkg ./*
          artifacts:
            - package/**
Quelques précisions sur le morceau de code ci-dessus :
  1. Tout ce qui est affiché comme ${} est une variable définie sous RepositorySettings dans Bitbucket, par exemple ${solutionName}
  2. Tout ce qui est affiché comme $ est une variable locale définie dans le pipeline lui-même avec un script d’exportation, par exemple $VERSION
  3. Il utilise un tas de commandes bash telles que pushd, popd, mkdir, cp, etc., principalement pour faciliter le travail avec les fichiers et les répertoires dans Bitbucket_Clone_Dir où le code est copié, pour le pipeline. Voici un feuille de triche pour avoir un aperçu rapide de ce qu’ils font.
  4. Nous utilisons l’outil de ligne de commande apt-get pour faciliter l’installation des packages nécessaires, comme zip dans notre cas.

Artefacts

Les étapes peuvent être suivies d’artefacts qui sont essentiellement les résultats finaux de cette étape, ce qui signifie que si nous voulons transmettre les valeurs/contenus générés d’une étape à l’autre pour un traitement ultérieur, nous l’ajoutons aux artefacts. Exemple de passage d’une valeur de variable d’une étape à l’autre.

Dans notre cas ici, nous avons d’abord exécuté la version frontale, puis compilé tous les fichiers frontaux dans le dossier wwwroot. Nous avons donc ajouté cela aux artefacts de cette étape, ce qui nous a permis de les utiliser à l’étape suivante lors de la création du package final pour le déploiement.

Étape de déploiement

Il s’agit de la dernière partie de notre pipeline de construction, où nous sélectionnons le package de code généré à l’étape de construction .net et le déployons dans l’environnement DXP (intégration). Avant de pouvoir le faire, nous devons passer par quelques étapes supplémentaires :

  1. Obtenez les informations d’identification de l’API de déploiement auprès de Paasportal.
  2. Ajoutez ces valeurs en tant que variables dans les paramètres du référentiel Bitbucket sous Pipelines > Déploiements, sous des environnements individuels.

L’étape ressemblerait à ceci :

- step:
         name: Upload and deploy to integration
         image: mcr.microsoft.com/powershell:latest #this is the docker image to allow running powershell scripts on this step
         deployment: Integration #This needs to match the environment name under Deployment settings and without this, the step can't read environment variables : Clientkey, secret and projectId
         script:

Comme vous pouvez le voir, nous avons ajouté un nouvelle image de menu fixe ici pour prendre en charge l’exécution de scripts PowerShell à cette étape. Nous avons également ajouté un déploiement valeur ici pour indiquer l’environnement dans lequel ce déploiement doit se produire, ainsi que pour indiquer au pipeline les variables d’environnement à extraire pour cette étape.

Ensuite, nous transmettons ces valeurs de variables d’environnement aux scripts powershell d’EpiCloud pour authentifier et télécharger le package à l’emplacement de l’emplacement de déploiement, d’où il sera sélectionné pour le déploiement réel.

#Install EpiCloud powershell module
Set-PSRepository -Name "PSGallery" -InstallationPolicy Trusted
Install-Module EpiCloud -Scope CurrentUser -Repository PSGallery -AllowClobber -MinimumVersion 1.0.0 -Force

#From the Artifact Path, getting the nupkg file
$packagePath = Get-ChildItem -Path $ArtifactPath -Filter *.nupkg

#Setting up the object for the Epi Deployment. This is found in the PAAS portal settings.
$getEpiDeploymentPackageLocationSplat = @{
    ClientKey = "$ClientKey"
    ClientSecret = "$ClientSecret"
    ProjectId = "$ProjectID"
}

#Generating the Blob storage location URL to upload the package
$packageLocation = Get-EpiDeploymentPackageLocation @getEpiDeploymentPackageLocationSplat

#Uploading the package to the Blob location
$deploy = Add-EpiDeploymentPackage -SasUrl $packageLocation -Path $packagePath.FullName

#Uploading the package to the Blob location
$deploy = Add-EpiDeploymentPackage -SasUrl $packageLocation -Path $packagePath.FullName

#Starting the Deployment
$deploy = Start-EpiDeployment @startEpiDeploymentSplat

$deployId = $deploy | Select -ExpandProperty "id"

#Setting up the object for the EpiServer Deployment Updates
$getEpiDeploymentSplat = @{
    ProjectId = "$ProjectID"
    ClientSecret = "$ClientSecret"
    ClientKey = "$ClientKey"
    Id = "$deployId"
}

#Setting up Variables for progress output
$percentComplete = 0
$currDeploy = Get-EpiDeployment @getEpiDeploymentSplat | Select-Object -First 1
$status = $currDeploy | Select -ExpandProperty "status"
$exit = 0

Write-Host "Percent Complete: $percentComplete%"
Write-Output "##vso[task.setprogress value=$percentComplete]Percent Complete: $percentComplete%"

#While the exit flag is not true
while($exit -ne 1){

#Get the current Deploy
$currDeploy = Get-EpiDeployment @getEpiDeploymentSplat | Select-Object -First 1

#Set the current Percent and Status
$currPercent = $currDeploy | Select -ExpandProperty "percentComplete"
$status = $currDeploy | Select -ExpandProperty "status"

#If the current percent is not equal to what it was before, send an update
#(This is done this way to prevent a bunch of messages to the screen)
if($currPercent -ne $percentComplete){
    Write-Host "Percent Complete: $currPercent%"
    Write-Output "##vso[task.setprogress value=$currPercent]Percent Complete: $currPercent%"
    #Set the overall percent complete variable to the new percent complete
    $percentComplete = $currPercent
}

#If the Percent Complete is equal to 100%, Set the exit flag to true
if($percentComplete -eq 100){
    $exit = 1    
}

#If the status of the deployment is not what it should be for this scipt, Set the exit flag to true
if($status -ne 'InProgress'){
    $exit = 1
}

#Wait 1 second between checks
start-sleep -Milliseconds 1000

}

#If the status is set to Failed, throw an error
if($status -eq "Failed"){
    Write-Output "##vso[task.complete result=Failed;]"
    throw "Deployment Failed. Errors: \n" + $deploy.deploymentErrors
}

Au fur et à mesure que vous progressez dans l’étape de déploiement ci-dessus, une fois le processus de déploiement commencé, Paasportal commencera également à refléter cela. Si cela échoue pour une raison quelconque, le pipeline échouera également avec la messagerie appropriée. Si le déploiement réussit, vous pourrez le voir dans l’historique de déploiement de Paasportal et pourrez maintenant tester votre site sur l’environnement DXP.

Conclusion

Le pipeline Release peut être construit, en supposant qu’il est similaire à la construction, avec juste un déclencheur de branche différent et un environnement de déploiement différent. Dans Azure Devops, les pipelines de mise en production ont un cycle d’approbation supplémentaire impliqué pour prendre en charge les déploiements de production après la vérification du déploiement de préproduction. Ce serait la prochaine pièce sur laquelle je ferai des recherches pour les pipelines Bitbucket.

Enfin, je voulais remercier deux collègues OMVP qui m’ont aidé à naviguer sur certains de ces chemins inconnus pour atteindre l’objectif final – d’abord David Lewismon mentor ici à Perficient et deuxième Eric Marksonex-collègue et la personne qui a aidé à configurer le Pipelines Azure Devops avant ça.

Si quelqu’un a plus de commentaires pour aider à améliorer cela, ou qui a déjà compris comment passer à l’étape suivante pour les pipelines de publication et les approbations de déploiement de production dans bitbucket, veuillez partager vos réflexions, commentaires, préoccupations ci-dessous.






Source link