Logo

GitHub Actions의 아티팩트(Artifact)로 파일 올리거나 내려받기

소프트웨어 개발에서 아티팩트(Artifact)라는 용어는 보통 프로젝트에서 소스 코드를 빌드(build)한 결과물로 생성된 파일을 가리키는데요. 이번 포스팅에서는 GitHub Actions의 아티팩트 기능을 활용하여 깃허브의 CI 서버에 파일을 올리거나 내려받는 방법에 대해서 알아보겠습니다.

실습 프로젝트와 코드 저장소 생성

간단한 실습을 위해서 Create React App을 통해 자바스크립트 프로젝트를 하나 생성하겠습니다.

$ npx create-react-app github-actions-artifacts

Creating a new React app in /Users/daleseo/temp/github-actions-artifacts.

Installing packages. This might take a couple of minutes.
Installing react, react-dom, and react-scripts with cra-template...

(... 생략 ...)

We suggest that you begin by typing:

  cd github-actions-artifacts
  npm start

Happy hacking!

그 다음 본인 깃허브 계정에 새로운 코드 저장소(repository)를 하나를 만들고 위에서 생성한 프로젝트의 코드를 올립니다.

$ cd github-actions-artifacts
$ git remote add origin https://github.com/DaleSchool/github-actions-artifacts.git
$ git branch -M main
$ git push -u origin main
Enumerating objects: 32, done.
Counting objects: 100% (32/32), done.
Delta compression using up to 8 threads
Compressing objects: 100% (28/28), done.
Writing objects: 100% (32/32), 173.48 KiB | 11.57 MiB/s, done.
Total 32 (delta 3), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (3/3), done.
To https://github.com/DaleSchool/github-actions-artifacts.git
 * [new branch]      main -> main
branch 'main' set up to track 'origin/main'.

저장소의 이름은 원하는대로 지으시면 되며 저는 프로젝트 명과 동일한 github-actions-artifacts이라는 이름으로 실습 코드 저장소를 만들었습니다.

CI 서버 내 폴더 업로드

GitHub Actions에서 빌드(build)나 테스트(test)를 돌리면 보통 CI 서버 내에 결과물이 생성이 되는데요.

예를 들어, React 앱의 경우 빌드의 결과물로 build 폴더에 웹 서버에 배포할 파일들이 생성되고요. Jest로 테스트를 실행하면 coverage 폴더에 리포트 파일들이 생성되지요.

만약에 이렇게 CI 서버의 특정 폴더에 저장된 파일들을 로컬로 내려받아서 확인해보고 싶다면 GitHub Actions의 Artifact 기능을 사용하야 합니다.

간단한 실습을 위해서 .github/workflows 디렉토리에 artifacts1.yml을 생성하고 다음과 같이 buildtest, 이렇게 두 개의 작업(job)으로 이루어진 워크플로우를 작성해보겠습니다.

.github/workflows/artifacts1.yml
name: Our Artifacts 1
on: push
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm ci
      - run: npm run build      - uses: actions/upload-artifact@v3        with:          name: build          path: build  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm ci
      - run: npm test -- --coverage      - uses: actions/upload-artifact@v3        with:          name: coverage          path: coverage

두 개의 작업에서 공통적으로 actions/upload-artifact@v3 액션을 사용하고 있는데요. with 키를 통해서 Artifact로 이름을 나타내는 name 옵션과 Artifact로 경로를 나타내는 path 옵션을 명시해주고 있습니다.

따라서 첫 번째 build 작업의 경우 build 폴더를 build라는 이름의 Artifact로 업로드하고, 두 번째 test 작업의 경우 coverage 폴더를 coverage라는 이름의 Artifact로 업로드하는 것이지요.

GitHub 저장소로 부터 코드를 내려받기 위해서 사용된 actions/checkout@v3 액션에 대해서는 별도 포스팅에서 자세히 다루고 있으니 참고 바랍니다.

artifacts1.yml 파일을 깃허브 저장소로 올린 후 Actions 탭에 들어가면 워크플로우가 실행될텐데요. 그 중에 build 작업에 들어가보면 다음과 같은 실행 로그가 확인될 겁니다.

Log(build)
☑️ Set up Job
☑️ Run actions/checkout@v3
☑️ Run npm ci
☑️ Run npm run build
☑️ Run actions/upload-artifact@v3
☑️ Post Run actions/checkout@v3
☑️ Complete Job

이 중 Run actions/upload-artifact@v3 항목을 열어보시면 15개의 파일이 총 크기가 558KB인데 187KB로 압축되어 Artifact로 업로드되었다고 나올 것입니다.

Log(build)
Run actions/upload-artifact@v3
  with:
    name: build
    path: build
    if-no-files-found: warn
With the provided path, there will be 15 files uploaded
Starting artifact upload
For more detailed logs during the artifact upload process, enable step-debugging: https://docs.github.com/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging#enabling-step-debug-logging
Artifact name is valid!
Container for artifact "build" successfully created. Starting upload of file(s)
Total size of all the files uploaded is 187368 bytes
File upload process has finished. Finalizing the artifact upload
Artifact has been finalized. All files have been successfully uploaded!

The raw size of all the files that were specified for upload is 559325 bytes
The size of all the files that were uploaded is 187368 bytes. This takes into account any gzip compression used to reduce the upload size, time and storage

Note: The size of downloaded zips can differ significantly from the reported size. For more information see: https://github.com/actions/upload-artifact#zipped-artifact-downloads

Artifact build has been successfully uploaded!

이번에는 test 작업에 들어가보면 유사한 실행 로그가 보일텐데요.

Log(test)
☑️ Set up Job
☑️ Run actions/checkout@v3
☑️ Run npm ci
☑️ Run npm test -- --coverage
☑️ Run actions/upload-artifact@v3
☑️ Post Run actions/checkout@v3
☑️ Complete Job

마찬가지로 Run actions/upload-artifact@v3 항목을 열어보시면 14개의 파일이 총 크기가 60KB인데 20KB로 압축되어 Artifact로 업로드되었다고 나올 것입니다.

Log(test)
Run actions/upload-artifact@v3
  with:
    name: coverage
    path: coverage
    if-no-files-found: warn
With the provided path, there will be 14 files uploaded
Starting artifact upload
For more detailed logs during the artifact upload process, enable step-debugging: https://docs.github.com/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging#enabling-step-debug-logging
Artifact name is valid!
Container for artifact "coverage" successfully created. Starting upload of file(s)
Total size of all the files uploaded is 19188 bytes
File upload process has finished. Finalizing the artifact upload
Artifact has been finalized. All files have been successfully uploaded!

The raw size of all the files that were specified for upload is 60023 bytes
The size of all the files that were uploaded is 19188 bytes. This takes into account any gzip compression used to reduce the upload size, time and storage

Note: The size of downloaded zips can differ significantly from the reported size. For more information see: https://github.com/actions/upload-artifact#zipped-artifact-downloads

Artifact coverage has been successfully uploaded!

두 개의 작업이 실행이 끝나면 워크플로우 화면의 하단에서 2개의 Artifact를 다운로드 받을 수 있는 링크가 보일 것입니다. 링크를 클릭하시면 해당 Artifact를 zip 압축 파일로 로컬로 내려받을 수 있습니다.

github-actions-artifacts

GitHub Actions를 사용하여 자바스크립트 프로젝트의 CI를 구성하는 방법에 대해서는 별도 포스팅에서 자세히 다루고 있습니다.

작업 간 파일 공유

GitHub Actions에서 작업(job)은 독립된 CI 서버에서 완전히 격리되어 실행되기 때문에 기본적으로 데이터 공유되지 않는데요. Artifact로 파일을 한 작업에서 올리고 다른 작업에서 내려받으면 서로 다른 작업 간에 데이터를 공유가 가능해집니다.

이번에는 저장소의 .github/workflows 디렉토리에 artifacts2.yml을 생성하고 updown 작업으로 이루어진 워크플로우를 작성해볼께요.

name: Our Artifacts 2
on: push
jobs:
  up:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Hello, GitHub Actions!" > hello.txt      - uses: actions/upload-artifact@v3        with:          name: hello          path: hello.txt  down:
    runs-on: ubuntu-latest
    needs: up    steps:
      - run: cat hello.txt
        continue-on-error: true
      - uses: actions/download-artifact@v3        with:          name: hello      - run: cat hello.txt

up 작업에서는 Hello, GitHub Actions!라는 내용이 들어있는 hello.txt 파일을 만들고 hello라는 이름의 Artifact로 올리고 있습니다. 그리고 down 작업에서는 hello라는 이름의 Artifact를 내려받기 전과 후에 한 번씩, 총 2번 hello.txt 파일 콘솔에 출력하고 있는데요. 첫 번째 출력할 때는 continue-on-error 옵션을 true로 설정하여 hello.txt 파일이 없어서 오류가 발생하더라도 작업 실행이 멈추지 않도록 하였습니다.

GitHub Actions의 단계(step)의 실패를 무시할 때 사용하는 continue-on-error 옵션에 대해서는 별도 포스팅에서 자세히 다루고 있으니 참고 바랍니다.

여기서 중요한 부분이 needs 속성을 사용해서 down 작업이 up 작업에 의존하도록 설정해주고 있다는 건데요. 이렇게 해주지 않으면 두 개의 작업이 동시에 시작되기 때문에 down 작업에서 Artifact를 다운받으려는 시점에 아직 up 작업에서 Artifact의 업로드가 끝나지 않았을 수도 있으니 주의 바랍니다.

GitHub Actions의 작업(job) 간의 의존 관계를 설정할 때 사용하는 needs 속성에 대해서는 별도 포스팅에서 자세히 다루고 있으니 참고 바랍니다.

자 이제 그럼, artifacts2.yml 파일을 깃허브의 코드 저장소로 올린 후 Actions 탭에서 up 작업에 들어가볼까요? 아래와 같이 23 바이트의 파일 하나가 성공적으로 업로드된 것을 볼 수 있습니다. 용량이 너무 작아서 그런지 이번에는 압축을 하지는 않네요.

Log(up)
☑️ Set up Job
☑️ Run echo "Hello, GitHub Actions!" > hello.txt
☑️ Run actions/upload-artifact@v3
Run actions/upload-artifact@v3
  with:
    name: hello
    path: hello.txt
    if-no-files-found: warn
With the provided path, there will be 1 file uploaded
Starting artifact upload
For more detailed logs during the artifact upload process, enable step-debugging: https://docs.github.com/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging#enabling-step-debug-logging
Artifact name is valid!
Container for artifact "hello" successfully created. Starting upload of file(s)
Total size of all the files uploaded is 23 bytes
File upload process has finished. Finalizing the artifact upload
Artifact has been finalized. All files have been successfully uploaded!

The raw size of all the files that were specified for upload is 23 bytes
The size of all the files that were uploaded is 23 bytes. This takes into account any gzip compression used to reduce the upload size, time and storage

Note: The size of downloaded zips can differ significantly from the reported size. For more information see: https://github.com/actions/upload-artifact#zipped-artifact-downloads

Artifact hello has been successfully uploaded!
☑️ Complete Job

이 번에는 down 작업의 실행 로그를 확인해볼까요?

처음 hello.text를 콘솔에 출력하려고 할 때는 CI 서버에 파일이 없어서 오류가 나는데요. 하지만 hello라는 이름의 Artifact를 내려받은 후에는 hello.text의 내용이 콘솔에 정확히 출력되는 것을 볼 수 있습니다.

Log(down)
☑️ Set up Job
☑️ Run cat hello.txt
Run cat hello.txtcat: hello.txt: No such file or directoryError: Process completed with exit code 1.
☑️ Run actions/download-artifact@v3
Run actions/download-artifact@v3
  with:
    name: hello
Starting download for helloDirectory structure has been setup for the artifactTotal number of files that will be downloaded: 1Artifact hello was downloaded to /home/runner/work/github-actions-artifacts/github-actions-artifactsArtifact download has finished successfully☑️ Run cat hello.txt
Run cat hello.txtHello, GitHub Actions!☑️ Complete Job

실습 코드

본 포스팅에서 작성한 YAML 파일과 워크플로우 실행 결과는 아래 코드 저장소에서 확인하실 수 있습니다.

https://github.com/DaleSchool/github-actions-artifacts

마치면서

지금까지 GitHub Actions에서 파일이나 폴더를 업로드하거나 다운로드 할 때 유용하게 사용할 수 있는 Artifact 기능에 대해서 살펴보았습니다. 업로드/다운로드 Artifact에 액션에 대한 좀 더 자세한 내용은 아래 2개의 GitHub Marketplace 링크를 참고 바랍니다.

GitHub Actions 관련 포스팅은 GitHub Actions 태그를 통해서 쉽게 만나보세요!