# Azure Pipelines에서 GitHub Actions로 마이그레이션하기

GitHub Actions와 Azure Pipelines는 여러 구성상 유사점이 있어 GitHub Actions(으)로의 마이그레이션이 비교적 간단합니다.

## 소개

Azure Pipelines와 GitHub Actions를 사용하면 코드를 자동으로 빌드, 테스트, 게시, 릴리스 및 배포하는 워크플로를 만들 수 있습니다. Azure Pipelines와 GitHub Actions는 워크플로 구성에서 몇 가지 유사점이 있습니다:

* 워크플로 구성 파일은 YAML로 작성되며 코드의 리포지토리에 저장됩니다.
* 워크플로에는 하나 이상의 작업이 포함됩니다.
* 작업에는 하나 이상의 단계 또는 개별 명령이 포함됩니다.
* 단계 또는 작업을 다시 사용하고 커뮤니티와 공유할 수 있습니다.

자세한 내용은 [GitHub Actions에 대한 이해](/ko/actions/get-started/understand-github-actions)을(를) 참조하세요.

## 주요 차이점

Azure Pipelines 마이그레이션할 때는 다음과 같은 차이점을 고려해야 합니다.

* Azure Pipelines YAML 파일에서 파이프라인 정의를 만드는 대신 GUI 편집기에서 CI 구성을 정의할 수 있는 레거시 \_클래스 편집기\_를 지원합니다.
  GitHub Actions 에서는 YAML 파일을 사용하여 워크플로를 정의하며 그래픽 편집기를 지원하지 않습니다.
* Azure Pipelines 작업 정의의 일부 구조를 생략할 수 있습니다. 예를 들어 단일 작업만 있는 경우 작업을 정의할 필요가 없으며 단계를 정의하기만 하면 됩니다.
  GitHub Actions 에는 명시적 구성이 필요하며 YAML 구조를 생략할 수 없습니다.
* Azure Pipelines 배포 워크플로를 만드는 데 사용할 수 있는 YAML 파일에 정의된 \_stages\_를 지원합니다.
  GitHub Actions 에서는 스테이지를 별도의 YAML 워크플로 파일로 구분해야 합니다.
* 기능을 사용하여 온-프레미스 Azure Pipelines 빌드 에이전트를 선택할 수 있습니다.
  GitHub Actions 레이블을 사용하여 자체 호스팅 실행기를 선택할 수 있습니다.

## 작업 및 단계 마이그레이션

Azure Pipelines의 작업과 단계는 GitHub Actions의 작업과 단계와 매우 유사합니다. 두 시스템 모두에서 작업은 다음과 같은 특징을 갖습니다.

* 순차적으로 실행되는 일련의 단계를 포함합니다.
* 작업은 별도의 가상 머신 또는 별도의 컨테이너에서 실행됩니다.
* 기본적으로 동시에 실행되지만 순차적으로 실행되도록 구성할 수 있습니다.

## 스크립트 단계의 마이그레이션 수행

워크플로의 단계로 스크립트 또는 셸 명령을 실행할 수 있습니다. Azure Pipelines `script` 키 또는 `bash`, `powershell` 또는 `pwsh` 키를 사용하여 스크립트 단계를 지정할 수 있습니다. 스크립트는 [Bash 작업](https://docs.microsoft.com/azure/devops/pipelines/tasks/utility/bash?view=azure-devops) 또는 [PowerShell 작업](https://docs.microsoft.com/azure/devops/pipelines/tasks/utility/powershell?view=azure-devops)에 대한 입력으로 지정할 수도 있습니다.

GitHub Actions에서는 모든 스크립트가 `run` 키를 사용하여 지정됩니다. 특정 셸을 선택하려면 스크립트를 제공할 때 `shell` 키를 지정합니다. 자세한 내용은 [GitHub Actions에 대한 워크플로 구문](/ko/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idstepsrun)을(를) 참조하세요.

다음은 각 시스템에 대한 구문의 예입니다.

### 스크립트 단계에 대한 Azure Pipelines 구문

```yaml
jobs:
  - job: scripts
    pool:
      vmImage: 'windows-latest'
    steps:
      - script: echo "This step runs in the default shell"
      - bash: echo "This step runs in bash"
      - pwsh: Write-Host "This step runs in PowerShell Core"
      - task: PowerShell@2
        inputs:
          script: Write-Host "This step runs in PowerShell"
```

### GitHub Actions 스크립트 단계에 대한 구문

```yaml
jobs:
  scripts:
    runs-on: windows-latest
    steps:
      - run: echo "This step runs in the default shell"
      - run: echo "This step runs in bash"
        shell: bash
      - run: Write-Host "This step runs in PowerShell Core"
        shell: pwsh
      - run: Write-Host "This step runs in PowerShell"
        shell: powershell
```

## 스크립트 오류 처리의 차이점

Azure Pipelines에서 스크립트를 구성하여 출력이 `stderr`로 전송될 때 오류를 발생시키도록 할 수 있습니다.
GitHub Actions 에서는 이 구성을 지원하지 않습니다.

GitHub Actions 는 가능하면 셸을 "빠르게 실패"하도록 구성하며, 스크립트의 명령 중 하나가 오류 코드로 종료되면 즉시 스크립트를 중지합니다. 반면, Azure Pipelines 오류 발생 시 즉시 종료하려면 명시적 구성이 필요합니다. 자세한 내용은 [GitHub Actions에 대한 워크플로 구문](/ko/actions/reference/workflows-and-actions/workflow-syntax#exit-codes-and-error-action-preference)을(를) 참조하세요.

## Windows 기본 셸의 차이점

Azure Pipelines Windows 플랫폼의 스크립트에 대한 기본 셸은 명령 셸(*cmd.exe*)입니다. Windows GitHub Actions플랫폼의 스크립트에 대한 기본 셸은 PowerShell입니다. PowerShell에는 기본 제공 명령, 변수 확장 및 흐름 제어에 몇 가지 차이점이 있습니다.

간단한 명령을 실행하는 경우 PowerShell에서 명령 셸 스크립트를 변경하지 않고 실행할 수 있습니다. 그러나 대부분의 경우 PowerShell 구문을 사용하여 스크립트를 업데이트하거나 PowerShell 대신 명령 셸을 사용하여 스크립트를 실행하도록 지시 GitHub Actions 해야 합니다.
`shell`을 `cmd`로 지정하여 이 작업을 수행할 수 있습니다.

다음은 각 시스템에 대한 구문의 예입니다.

### 기본적으로 CMD를 사용하는 Azure Pipelines 구문

```yaml
jobs:
  - job: run_command
    pool:
      vmImage: 'windows-latest'
    steps:
      - script: echo "This step runs in CMD on Windows by default"
```

### GitHub Actions CMD를 지정하는 구문

```yaml
jobs:
  run_command:
    runs-on: windows-latest
    steps:
      - run: echo "This step runs in PowerShell on Windows by default"
      - run: echo "This step runs in CMD on Windows explicitly"
        shell: cmd
```

자세한 내용은 [GitHub Actions에 대한 워크플로 구문](/ko/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idstepsshell)을(를) 참조하세요.

## 조건 및 식 구문 마이그레이션

Azure Pipelines와 GitHub Actions는 모두 단계를 조건부로 실행할 수 있습니다. Azure Pipelines 조건식은 `condition` 키를 사용하여 지정됩니다.
GitHub Actions에서는 조건식이 `if` 키를 사용하여 지정됩니다.

Azure Pipelines 식 내의 함수를 사용하여 조건부로 단계를 실행합니다. 반면에 GitHub Actions 접두사 표기법을 사용합니다. 예를 들어, Azure Pipelines의 `eq` 함수를 `==`의 GitHub Actions 연산자로 바꿔야 합니다.

다음은 각 시스템에 대한 구문의 예입니다.

### Azure Pipelines의 조건식 구문

```yaml
jobs:
  - job: conditional
    pool:
      vmImage: 'ubuntu-latest'
    steps:
      - script: echo "This step runs with str equals 'ABC' and num equals 123"
        condition: and(eq(variables.str, 'ABC'), eq(variables.num, 123))
```

### GitHub Actions 조건식 구문

```yaml
jobs:
  conditional:
    runs-on: ubuntu-latest
    steps:
      - run: echo "This step runs with str equals 'ABC' and num equals 123"
        if: ${{ env.str == 'ABC' && env.num == 123 }}
```

자세한 내용은 [워크플로 및 작업에서 식 평가](/ko/actions/reference/workflows-and-actions/expressions)을(를) 참조하세요.

## 작업 간의 종속성

Azure Pipelines와 GitHub Actions 모두 작업의 종속성을 설정할 수 있습니다. 두 시스템 모두에서 작업은 기본적으로 병렬로 실행되지만 작업 종속성을 명시적으로 지정할 수 있습니다. Azure Pipelines 이 작업은 `dependsOn` 키로 수행됩니다.
GitHub Actions에서는 이 작업을 `needs` 키로 수행합니다.

다음은 각 시스템에 대한 구문의 예입니다. 워크플로는 이름이 `initial`인 첫 번째 작업을 시작하고 해당 작업이 완료되면 이름이 `fanout1` 및 `fanout2`인 두 개의 작업이 실행됩니다. 마지막으로 해당 작업이 완료되면 `fanin` 작업이 실행됩니다.

### 작업 간 종속성에 대한 Azure Pipelines 구문

```yaml
jobs:
  - job: initial
    pool:
      vmImage: 'ubuntu-latest'
    steps:
      - script: echo "This job will be run first."
  - job: fanout1
    pool:
      vmImage: 'ubuntu-latest'
    dependsOn: initial
    steps:
      - script: echo "This job will run after the initial job, in parallel with fanout2."
  - job: fanout2
    pool:
      vmImage: 'ubuntu-latest'
    dependsOn: initial
    steps:
      - script: echo "This job will run after the initial job, in parallel with fanout1."
  - job: fanin
    pool:
      vmImage: 'ubuntu-latest'
    dependsOn: [fanout1, fanout2]
    steps:
      - script: echo "This job will run after fanout1 and fanout2 have finished."
```

### GitHub Actions 작업 간 종속성에 대한 구문

```yaml
jobs:
  initial:
    runs-on: ubuntu-latest
    steps:
      - run: echo "This job will be run first."
  fanout1:
    runs-on: ubuntu-latest
    needs: initial
    steps:
      - run: echo "This job will run after the initial job, in parallel with fanout2."
  fanout2:
    runs-on: ubuntu-latest
    needs: initial
    steps:
      - run: echo "This job will run after the initial job, in parallel with fanout1."
  fanin:
    runs-on: ubuntu-latest
    needs: [fanout1, fanout2]
    steps:
      - run: echo "This job will run after fanout1 and fanout2 have finished."
```

자세한 내용은 [GitHub Actions에 대한 워크플로 구문](/ko/actions/reference/workflows-and-actions/workflow-syntax#jobsjob_idneeds)을(를) 참조하세요.

## 작업을 액션으로 마이그레이션

Azure Pipelines 여러 워크플로에서 다시 사용할 수 있는 애플리케이션 구성 요소인 *tasks* 사용합니다.
GitHub Actions 는 *작업을* 수행하고 워크플로를 사용자 지정하는 데 사용할 수 있는 작업을 사용합니다. 두 시스템 모두에서 실행할 작업(task) 또는 작업(action)의 이름과 필요한 입력을 키/값 쌍으로 지정할 수 있습니다.

다음은 각 시스템에 대한 구문의 예입니다.

### 작업에 대한 Azure Pipelines 구문

```yaml
jobs:
  - job: run_python
    pool:
      vmImage: 'ubuntu-latest'
    steps:
      - task: UsePythonVersion@0
        inputs:
          versionSpec: '3.7'
          architecture: 'x64'
      - script: python script.py
```

### GitHub Actions 작업에 대한 구문

```yaml
jobs:
  run_python:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-python@v5
        with:
          python-version: '3.7'
          architecture: 'x64'
      - run: python script.py
```

워크플로에서 [GitHub Marketplace](https://github.com/marketplace?type=actions)사용할 수 있는 작업을 찾거나 고유한 작업을 만들 수 있습니다. 자세한 내용은 [자동화 재사용](/ko/actions/how-tos/reuse-automations)을(를) 참조하세요.