Esiste un modo per creare un array in PowerShell e eseguirlo in loop in Azure DevOps YAML?

Aug 27 2020

Sto cercando di creare una pipeline per le nostre distribuzioni di database su oltre 140 database su 10 istanze. Il nostro team IT ha affermato che ci sono situazioni in cui i database verranno spostati da un'istanza all'altra per il bilanciamento del carico. Quindi non posso fidarmi che il database rimarrà sulla stessa istanza per ogni versione. Possiamo anche inserire un nuovo cliente senza che il nostro team ne sappia nulla. Ciò significa che devo scrivere una pipeline che può distribuire dinamicamente solo al database sull'istanza data. Ogni istanza avrà un singolo agente.

Il flusso di lavoro che sto pianificando adesso.

  1. Costruisci il DacPac dal nostro ramo principale.
  2. Aggiungi una fase che è legata a un ambiente che richiede che una delle persone del nostro team approvi il rilascio.
  3. Esegui uno script PowerShell per ottenere tutti i database sull'istanza e tornare come elenco.
  4. Scorri l'elenco fornito e crea un'attività per ogni database.

In questo momento ho problemi con la parte in cui passo l'elenco dei database come variabile alla pipeline YAML da PowerShell. Idealmente potrei restituire un elenco e quindi utilizzare la funzionalità di loop YAML per creare un'attività di distribuzione di SQL Server con il nome di database specificato. È possibile restituire un elenco da Powershell e scorrerli utilizzando la funzionalità di loop? Un esempio dello YAML che sto usando sotto meno cose che non voglio condividere là fuori.


/*Pipeline Being Called*/
variables:
- name: BuildConfiguration
  value: release
- name: BuildPlatform
  value: any cpu
- name: system.debug
  value: true
- name: datamode 
  value: 0 
- name: APIMode
  value: 0
- name: Instance 
  value: "[ServerInstance]"
- name: var01
trigger: 
 - FixingDRDeployments

stages: 
- stage: Powershell 
  pool: [Agent Pool Name]
  jobs:
  - job: Powershell
    steps:
       - task: PowerShell@2
         inputs:
           targetType: 'inline'
           script: |
             $ServerInstance = "$(Instance)"
             
             
             $Databases = Get-DbaDatabase -SqlInstance $ServerInstance 
             $ReturnValues = @() $query = "
                Query to validate database is one we want to deploy against. 
             "
             
             
             foreach ( $db in $Databases) {
               $Results = Invoke-DbaQuery -SqlInstance $serverInstance -Database $db.name -Query $query
               if ($Results.Valid -eq 1) { $ReturnValues += $db.Name } } Write-Host $ReturnValues
             



#stages:
- template: deploytemplates/BuildTemplate.yml
- template: template.yml
  parameters:
    param: ["TestDatabase1","TestDatabase2"]
**^ Instead of having a defined set of static databases, I'd like to be able to pass an array of databases from the powershell script above.**

/*deploytemplates/BUildTemplate.yml*/

stages:
- stage: Build 
  jobs:
    - job: build 
      pool:
       name: mn-vs2017
       demands:
        - msbuild
        - visualstudio
      steps:
       - task: VSBuild@1
         displayName: 'Build solution **\*.sln'
         inputs:
           solution: '**\*.sln'
           vsVersion: "15.0"
           msbuildArgs: '/p:OutDir=$(build.artifactstagingdirectory) /p:CmdLineInMemoryStorage=True' platform: '$(BuildPlatform)'
           configuration: '$(BuildConfiguration)' clean: true maximumCpuCount: true msbuildArchitecture: x64 - task: PublishBuildArtifacts@1 displayName: 'Publish Artifact: MasterDacPac' inputs: PathtoPublish: '$(build.artifactstagingdirectory)'
          ArtifactName: DacPac

/*template.yml*/
parameters: 
  param : []


stages:
- stage: ApprovalGate1
  displayName:  ApprovalGate1
  dependsOn: Build
  jobs: 
  - deployment: 
    displayName: ApprovalGate1
    pool: [Pool Name Here]
    environment: Databases
    strategy:
      runOnce:
        deploy: 
         steps:
          - task: DownloadSecureFile@1
            name: PublishProfile
            displayName: 'Download secure file'
            inputs:
              secureFile: Production.publish.xml
          - ${{ each p in parameters.param }}: - task: SqlDacpacDeploymentOnMachineGroup@0 displayName: ${{ p }}
               inputs:
                 DacpacFile: '$(Pipeline.Workspace)\DacPac\DacPacName.dacpac' ServerName: $(Instance)
                 DatabaseName: ${{ p }} PublishProfile: '$(PublishProfile.secureFilePath)'
               continueOnError: true
               condition: succeededOrFailed()

Risposte

1 KrzysztofMadej Aug 28 2020 at 08:15

No, non è possibile. Se crei una variabile in PowerShell, creerai una variabile di tipo stringa. È anche peggio :

Le variabili Yaml sono sempre state string: string mappings.

Ci stiamo preparando a rilasciare una funzionalità nel prossimo futuro per consentirti di superare strutture più complesse. Rimanete sintonizzati!

Puoi usare gli array per i parametri ma questo è solo statico e lo sai già:

steps:
- template: template.yaml
  parameters:
    instances: 
    - test1
    - test2
    server: someServer