연습 - 스테이징으로 승격

완료됨

이제 릴리스 파이프라인에는 ‘빌드’, ‘개발’, ‘테스트’, 이렇게 단계가 3개 있습니다. Tailspin 팀과 구현할 단계가 하나 더 남았는데, 바로 스테이징입니다.

이 부분에서는 다음을 수행합니다.

  • Azure Pipelines에서 스테이징 환경을 만들고 자신을 승인자로 할당합니다.
  • 승인자가 ‘테스트’ 단계의 결과를 확인한 후에만 실행되는 ‘스테이징’ 단계를 정의합니다.

스테이징 환경 만들기

여기서 Azure Pipelines에서 스테이징을 위한 환경을 만듭니다. 학습 목적으로 자신을 승인자로 할당합니다. 실제로는 변경 내용이 다음 단계로 이동하기 전에 변경 내용을 승인해야 하는 사용자를 할당합니다. Tailspin 팀의 경우 Amita가 변경 내용을 승인해야 변경 내용이 테스트에서 스테이징으로 승격할 수 있습니다.

이 모듈의 앞부분에서는 ‘개발’과 ‘테스트’ 단계의 environment 설정을 지정했습니다. ‘개발’ 단계에 대한 예제는 다음과 같습니다.

- stage: 'Deploy'
  displayName: 'Deploy the web application'
  dependsOn: Build
  jobs:
  - deployment: Deploy
    pool:
      vmImage: 'ubuntu-20.04'
    environment: dev
    variables:
    - group: Release

Azure Pipelines를 통해 릴리스에 대한 특정 조건을 포함하는 환경을 정의할 수 있습니다. 이 조건에는 해당 환경에 배포할 수 있는 권한이 부여된 파이프라인이 포함될 수 있습니다. 한 단계에서 다음 단계로 릴리스를 승격하는 데 필요한 사람의 승인을 지정할 수도 있습니다. 여기에서 해당 승인을 지정합니다.

스테이징 환경을 만들려면 다음을 수행합니다.

  1. Azure Pipelines에서 환경을 선택합니다.

    A screenshot of Azure Pipelines showing the location of the Environments menu option.

  2. 새 환경을 선택합니다.

  3. 이름staging을 입력합니다.

  4. 나머지 필드는 기본값으로 둡니다.

  5. 만들기를 선택합니다.

  6. 스테이징 환경 페이지에서 드롭다운을 연 다음 승인 및 확인을 선택합니다.

    A screenshot of Azure Pipelines, showing the location of the approvals and checks menu item.

  7. 승인을 선택합니다.

  8. 승인자에서 사용자 및 그룹 추가를 선택하고 계정을 선택합니다.

  9. 승인자에 대한 지침에 ‘스테이징이 준비되면 이 변경 내용 승인’이라고 입력합니다.

  10. 만들기를 선택합니다.

스테이징으로 변경 내용 승격

여기서는 파이프라인 구성을 수정하여 빌드를 ‘스테이징’ 단계로 배포합니다.

  1. Visual Studio Code에서 azure-pipelines.yml을 다음과 같이 수정합니다.

    trigger:
    - '*'
    
    variables:
      buildConfiguration: 'Release'
      releaseBranchName: 'release'
    
    schedules:
    - cron: '0 3 * * *'
      displayName: 'Deploy every day at 3 A.M.'
      branches:
        include:
        - release
      always: false 
    
    stages:
    - stage: 'Build'
      displayName: 'Build the web application'
      jobs: 
      - job: 'Build'
        displayName: 'Build job'
        pool:
          vmImage: 'ubuntu-20.04'
          demands:
          - npm
    
        variables:
          wwwrootDir: 'Tailspin.SpaceGame.Web/wwwroot'
          dotnetSdkVersion: '6.x'
    
        steps:
        - task: UseDotNet@2
          displayName: 'Use .NET SDK $(dotnetSdkVersion)'
          inputs:
            version: '$(dotnetSdkVersion)'
    
        - task: Npm@1
          displayName: 'Run npm install'
          inputs:
            verbose: false
    
        - script: './node_modules/.bin/node-sass $(wwwrootDir) --output $(wwwrootDir)'
          displayName: 'Compile Sass assets'
    
        - task: gulp@1
          displayName: 'Run gulp tasks'
    
        - script: 'echo "$(Build.DefinitionName), $(Build.BuildId), $(Build.BuildNumber)" > buildinfo.txt'
          displayName: 'Write build info'
          workingDirectory: $(wwwrootDir)
    
        - task: DotNetCoreCLI@2
          displayName: 'Restore project dependencies'
          inputs:
            command: 'restore'
            projects: '**/*.csproj'
    
        - task: DotNetCoreCLI@2
          displayName: 'Build the project - $(buildConfiguration)'
          inputs:
            command: 'build'
            arguments: '--no-restore --configuration $(buildConfiguration)'
            projects: '**/*.csproj'
    
        - task: DotNetCoreCLI@2
          displayName: 'Publish the project - $(buildConfiguration)'
          inputs:
            command: 'publish'
            projects: '**/*.csproj'
            publishWebProjects: false
            arguments: '--no-build --configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/$(buildConfiguration)'
            zipAfterPublish: true
    
        - publish: '$(Build.ArtifactStagingDirectory)'
          artifact: drop
    
    - stage: 'Dev'
      displayName: 'Deploy to the dev environment'
      dependsOn: Build
      condition: |
        and
        (
          succeeded(),
          eq(variables['Build.SourceBranchName'], variables['releaseBranchName'])
        )
      jobs:
      - deployment: Deploy
        pool:
          vmImage: 'ubuntu-20.04'
        environment: dev
        variables:
        - group: Release
        strategy:
          runOnce:
            deploy:
              steps:
              - download: current
                artifact: drop
              - task: AzureWebApp@1
                displayName: 'Azure App Service Deploy: website'
                inputs:
                  azureSubscription: 'Resource Manager - Tailspin - Space Game'
                  appName: '$(WebAppNameDev)'
                  package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/*.zip'
    
    - stage: 'Test'
      displayName: 'Deploy to the test environment'
      dependsOn: Dev
      #condition: eq(variables['Build.Reason'], 'Schedule')
      jobs:
      - deployment: Deploy
        pool:
          vmImage: 'ubuntu-20.04'
        environment: test
        variables:
        - group: 'Release'
        strategy:
          runOnce:
            deploy:
              steps:
              - download: current
                artifact: drop
              - task: AzureWebApp@1
                displayName: 'Azure App Service Deploy: website'
                inputs:
                  azureSubscription: 'Resource Manager - Tailspin - Space Game'
                  appName: '$(WebAppNameTest)'
                  package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/*.zip'
    
    - stage: 'Staging'
      displayName: 'Deploy to the staging environment'
      dependsOn: Test
      jobs:
      - deployment: Deploy
        pool:
          vmImage: 'ubuntu-20.04'
        environment: staging
        variables:
        - group: 'Release'
        strategy:
          runOnce:
            deploy:
              steps:
              - download: current
                artifact: drop
              - task: AzureWebApp@1
                displayName: 'Azure App Service Deploy: website'
                inputs:
                  azureSubscription: 'Resource Manager - Tailspin - Space Game'
                  appName: '$(WebAppNameStaging)'
                  package: '$(Pipeline.Workspace)/drop/$(buildConfiguration)/*.zip'
    

    이 코드는 ‘스테이징’ 단계를 추가합니다. 해당 단계는 릴리스 승인을 포함하는 스테이징 환경에 배포됩니다.

    세 가지 배포 단계가 모두 유사한 단계를 따르는 것을 알 수 있습니다. ‘템플릿’을 사용하여 공통 빌드 작업을 한 번 정의한 다음 여러 번 다시 사용할 수 있습니다. Azure Pipelines를 사용하여 빌드 파이프라인 만들기 모듈에서 이 기술을 이미 사용했습니다. 학습 목적으로 각 단계의 단계를 반복합니다.

  2. 통합 터미널에서 azure-pipelines.yml을 인덱스에 추가합니다. 그런 다음 변경 내용을 커밋하고 GitHub로 푸시합니다.

    해당하는 Git 명령을 실행하기 전에 azure-pipelines.yml을 저장합니다.

    git add azure-pipelines.yml
    git commit -m "Deploy to Staging"
    git push origin release
    
  3. Azure Pipelines에서 빌드로 이동합니다. 실행되는 빌드를 추적합니다.

    빌드가 스테이징에 도달하면 파이프라인이 모든 검사가 통과할 때까지 대기하는 것을 볼 수 있습니다. 이 경우에는 검사가 하나 있는데, 바로 수동 릴리스 승인입니다.

    A screenshot of Azure Pipelines showing the Staging stage, which requires manual approval.

    빌드에 승인이 필요할 때 메일 알림을 보내도록 Azure DevOps를 구성할 수 있습니다. 예를 들면 다음과 같습니다.

    A screenshot of a portion of a build approval email notification.

  4. 검토>승인을 선택합니다.

    실제로 사용자의 요구 사항을 충족하는지 확인하기 위해 변경 내용을 검사합니다.

  5. 빌드가 완료되면 웹 브라우저를 엽니다. 스테이징 환경의 App Service 인스턴스와 연결된 URL로 이동합니다.

    브라우저 탭이 아직 열려 있는 경우 페이지를 새로 고칩니다. URL을 기억할 수 없는 경우 Azure Portal의 App Service 세부 정보 페이지에서 찾습니다.

    Space Game 웹 사이트가 App Service에 배포되어 실행 중입니다.

    A screenshot of web browser showing the Space Game website in the Staging environment.

  6. 선택적 단계로 Azure Pipelines에서 환경을 선택합니다. 다음으로 스테이징 환경을 선택합니다.

    Azure Pipelines는 배포 기록을 기록하여 환경에서 코드 커밋과 작업 항목에 대한 변경 내용을 다시 추적할 수 있습니다.

    A screenshot of Azure Pipelines showing the deployment history. The history shows one successful deployment.

Tailspin 팀은 진행 상황에 대해 논의하기 위해 수집하고 있습니다. Amita는 다른 사람들이 보고 있는 상태에서 ‘테스트’ 단계에서 변경 내용을 승인합니다.

Tim: 솔직히 처음에는 자동화된 릴리스 파이프라인에 대해 약간 걱정했었어요. 하지만 이제 작동하는 것을 보니 아주 마음에 드네요. 각 단계에는 자체 환경, 연결된 테스트, 승인자가 있을 수 있습니다. 파이프라인은 수동으로 수행해야 했던 다양한 작업을 자동화합니다. 그러나 여전히 필요한 지점을 제어할 수 있습니다.

Amita: 변경 내용을 스테이징에서 프로덕션으로 승격하는 것과 유사한 작업을 진행 중이라고 생각해 보세요. 그런데...언제 프로덕션 환경을 추가하나요?

Andy: 곧 추가합니다. 내 생각에는 이를 추가하기 전에 먼저 여기에 몇 가지 부분을 채워야 할 것 같습니다.