연습 - 템플릿을 사용하여 여러 구성 빌드

완료됨

이전 연습에서 Space Game 웹 사이트를 빌드하는 파이프라인을 구현했습니다. 먼저 각 빌드 작업을 수행하고 각 작업을 해당 파이프라인 태스크에 매핑하는 스크립트부터 시작했습니다. 파이프라인의 출력은 컴파일된 웹앱을 포함하는 .zip 파일입니다.

이 연습에서는 템플릿을 사용하여 프로젝트 파일에 정의된 모든 구성을 빌드할 수 있는 빌드 작업을 정의합니다. 템플릿을 사용하면 논리를 한 번 정의한 다음 여러 번 다시 사용할 수 있습니다. 템플릿은 여러 YAML 파일의 내용을 단일 파이프라인으로 결합합니다.

모듈에서 이 단계는 선택 사항입니다. 현재 템플릿에 대해 알아보지 않으려면 다음 단계인 Azure DevOps 환경 정리를 진행합니다. 템플릿에 대한 자세한 내용은 템플릿 형식 및 사용량을 참조하세요.

먼저 Mara, Amita와 체크인해 보겠습니다.

데모

Mara는 결과를 공유할 생각에 들떠 있고 빌드 파이프라인을 보여 주기 위해 Amita를 찾아왔습니다.

Amita: 이 일을 이렇게 빨리 해내다니 놀라워요! 사실, 빌드가 준비되었다는 메일을 받았기 때문에 Mara 님을 보러 가려고 했어요. 감사합니다! 파이프라인이 릴리스 구성만으로 빌드된 것을 확인했어요. 또한 디버그 빌드를 사용하여 앱 충돌 시 추가 정보를 캡처할 수 있도록 했는데, 추가할 수 있나요?

Mara: 물론이죠. 설정할 때 디버그 빌드를 고려하지 못했어요. 함께 앉아서 추가해 보면 어떨까요?

Amita: 빌드 단계를 정의하는 YAML 파일을 보여 주었지만 수정 방법을 잘 모르겠습니다.

Mara: 괜찮아요. 입력하는 동안 한 번 보세요. 함께 생각해 봐요.

두 빌드 구성을 어떻게 정의할 수 있나요?

Space Game 웹 프로젝트의 릴리스 구성을 빌드, 게시 다음 작업을 고려합니다. (이 코드를 azure-pipelines.yml파일에 추가하지 마세요.)

- task: DotNetCoreCLI@2
  displayName: 'Build the project - Release'
  inputs:
    command: 'build'
    arguments: '--no-restore --configuration Release'
    projects: '**/*.csproj'

- task: DotNetCoreCLI@2
  displayName: 'Publish the project - Release'
  inputs:
    command: 'publish'
    projects: '**/*.csproj'
    publishWebProjects: false
    arguments: '--no-build --configuration Release --output $(Build.ArtifactStagingDirectory)/Release'
    zipAfterPublish: true

디버그 구성을 빌드하려면 이러한 두 가지 작업을 반복할 수 있지만 ReleaseDebug로 바꿉니다.

이렇게 하면 원하는 결과를 얻을 수 있지만 빌드가 더 복잡하거나 요구 사항이 변경되면 어떻게 될까요? 각 빌드 작업의 변형은 수동으로 찾아서 변경해야 합니다. 빌드 요구 사항을 추가한 후에는 디버그 구성과 릴리스를 위한 작업을 하나씩 두 개 만들어 해당 요구 사항을 충족해야 합니다.

더 나은 해결 방법은 템플릿을 사용하는 것입니다.

템플릿이란?

템플릿을 사용하면 공통 빌드 작업을 한 번 정의한 다음, 해당 작업을 여러 번 다시 사용할 수 있습니다.

상위 파이프라인에서 템플릿을 빌드 단계로 호출합니다. 상위 파이프라인에서 템플릿으로 매개 변수를 전달할 수 있습니다.

Mara는 앱을 빌드하여 템플릿으로 게시하는 작업을 정의한 다음 필요한 각 구성에 해당 템플릿을 적용할 수 있습니다.

템플릿 정의

템플릿을 사용하면 공통 빌드 작업을 한 번 정의한 다음, 해당 작업을 여러 번 다시 사용할 수 있음을 기억하세요. 부모 템플릿에서 템플릿을 빌드 단계로 호출하고 부모 파이프라인에서 템플릿으로 매개 변수를 전달합니다.

이제 프로젝트 파일에 정의된 구성을 빌드할 수 있는 템플릿을 만듭니다.

  1. Visual Studio Code 통합 콘솔의 프로젝트 루트에서 ‘템플릿’ 디렉터리를 만듭니다.

    mkdir templates
    

    실제로 템플릿 파일은 모든 위치에 저장할 수 있습니다. 템플릿을 ‘템플릿’ 디렉터리에 저장할 필요는 없습니다.

  2. Visual Studio Code에서 파일 > 새 파일을 선택합니다. 그런 다음 프로젝트의 templates 디렉터리에 빈 파일을 build.yml로 저장하려면 파일 > 저장을 선택합니다. 예를 들어 ~/mslearn-tailspin-spacegame-web/templates가 될 수 있습니다.

    중요

    이전과 마찬가지로 Windows에서 파일 형식 목록에서 YAML를 선택합니다.

  3. Visual Studio Code에서 이 코드를 build.yml에 추가합니다.

    parameters:
      buildConfiguration: 'Release'
    
    steps:
    - task: DotNetCoreCLI@2
      displayName: 'Build the project - ${{ parameters.buildConfiguration }}'
      inputs:
        command: 'build'
        arguments: '--no-restore --configuration ${{ parameters.buildConfiguration }}'
        projects: '**/*.csproj'
    
    - task: DotNetCoreCLI@2
      displayName: 'Publish the project - ${{ parameters.buildConfiguration }}'
      inputs:
        command: 'publish'
        projects: '**/*.csproj'
        publishWebProjects: false
        arguments: '--no-build --configuration ${{ parameters.buildConfiguration }} --output $(Build.ArtifactStagingDirectory)/${{ parameters.buildConfiguration }}'
        zipAfterPublish: true
    

    이러한 작업은 앱을 빌드하고 게시하기 위해 이전에 정의한 작업과 유사해 보입니다. 그러나 템플릿에서는 일반 변수를 사용하는 것과 다르게 입력 매개 변수를 사용합니다. 다음과 같은 두 가지 차이점이 있습니다.

    • 템플릿 파일에서는 variables 대신 parameters 섹션을 사용하여 입력을 정의합니다.
    • 템플릿 파일에서는 $() 대신 ${{ }} 구문을 사용하여 매개 변수의 값을 읽습니다. 매개 변수의 값을 읽을 때 매개 변수 이름에 parameters 섹션을 포함합니다. 예: ${{ parameters.buildConfiguration }}

파이프라인에서 템플릿 호출

이제 파이프라인에서 방금 빌드한 템플릿을 호출합니다. 디버그 구성에 대해 이와 같이 한 번 수행한 다음 릴리스 구성에 대해 해당 프로세스를 반복합니다.

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

    trigger:
    - '*'
    
    pool:
      vmImage: ubuntu-latest
    
    variables:
      buildConfiguration: 'Release'
      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'
    
    - template: templates/build.yml
      parameters:
        buildConfiguration: 'Debug'
    
    - template: templates/build.yml
      parameters:
        buildConfiguration: 'Release'
    
    - task: PublishBuildArtifacts@1
      displayName: 'Publish Artifact: drop'
      condition: succeeded()
    
    trigger:
    - '*'
    
    pool:
      name: 'Default' #replace if needed with name of your agent pool
    
    variables:
      buildConfiguration: 'Release'
      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'
    
    - template: templates/build.yml
      parameters:
        buildConfiguration: 'Debug'
    
    - template: templates/build.yml
      parameters:
        buildConfiguration: 'Release'
    
    - task: PublishBuildArtifacts@1
      displayName: 'Publish Artifact: drop'
      condition: succeeded()
    

    이 파일은 빌드와 게시 작업을 동일한 작업을 수행하는 템플릿 호출로 바꾼다는 점을 제외하고 원본 파일과 같습니다.

    각 구성에 대해 템플릿이 한 번 호출되는 것을 볼 수 있습니다. 구성 이름을 템플릿에 전달하기 위해 각 template 작업은 parameters 인수를 사용합니다.

파이프라인 실행

변경 내용을 GitHub로 푸시하고 파이프라인 실행을 확인합니다.

  1. 통합 터미널에서 azure-pipelines.ymltemplates/build.yml을 인덱스에 추가하고, 변경 내용을 커밋하고, 변경 내용을 GitHub에 푸시합니다.

    git add azure-pipelines.yml templates/build.yml
    git commit -m "Support build configurations"
    git push origin build-pipeline
    
  2. Azure Pipelines에서 이전처럼 각 단계를 통해 빌드를 추적합니다.

    파이프라인이 실행되면 프로세스가 템플릿 내에서 작업을 확장하는 것을 볼 수 있습니다. 프로젝트를 빌드 및 게시하는 작업은 각 빌드 구성에 대해 한 번씩 두 번 실행됩니다.

    확장된 템플릿 작업을 보여 주는 Azure Pipelines의 스크린샷. 디버그 및 릴리스 구성 모두에 대한 빌드 및 게시 작업을 포함합니다.

  3. 빌드가 완료되면 요약 페이지로 돌아가 이전에 수행한 것처럼 게시된 아티팩트를 선택합니다. 저장 폴더를 확장합니다.

    파이프라인이 디버그 구성과 릴리스 구성 둘 다를 위한 .zip 파일을 생성합니다.

    디버그 및 릴리스 구성 모두에 대한 패키지된 애플리케이션을 보여 주는 Azure Pipelines의 스크린샷.

기본으로 분기 병합

이제는 Mara에게 당장 필요한 모든 작업을 달성하는 작동 중인 빌드 파이프라인이 있습니다.

실제로 build-pipeline 분기를 main분기에 병합하는 ‘끌어오기 요청’을 제출했습니다.

지금은 이 단계를 건너뜁니다. 다음 모듈에서는 끌어오기 요청을 제출, 검토, 병합하는 방법을 비롯하여 GitHub에서 팀과 협업하는 몇 가지 방법을 알아봅니다.