[Github Action] 로컬환경에서 Github Action 테스트하기
개인 공부 목적으로 작성된 포스팅입니다. 왜곡된 내용이 포함되어 있습니다.
프로젝트에 Github Action Workflow를 추가 수정할때마다, 별도의 프라이빗 테스트 레포를 통해 Github Action을 테스트하는 등 테스트에 불편함이 있었다. 그러던 와중에 Github Action를 로컬에서 테스트하도록 지원하고 있는 기술을 알게 되었다.
Act
GitHub - nektos/act: Run your GitHub Actions locally 🚀
Run your GitHub Actions locally 🚀. Contribute to nektos/act development by creating an account on GitHub.
github.com
Introduction - act - User Guide | Manual | Docs | Documentation
"Think globally, act locally" Run your GitHub Actions locally! Why would you want to do this? Two reasons: Fast Feedback - Rather than having to commit/push every time you want to test out the changes you are making to your .github/workflows/ files (or for
nektosact.com
Act는 GIthub Action을 로컬에서 실행할 수 있도록 지원한다. act를 사용할 경우 다음과 같은 이점을 얻을 수 있다.
- .github/workflows/ 파일에 대한 변경사항을 테스트하기 위해 매번 커밋하거나 푸시할 필요 없이 Act를 사용하여 로컬에서 작업을 실행할 수 있다. 환경 변수와 파일 시스템은 모두 GitHub가 제공하는 것과 일치하도록 구성되어 있다.
- .github/workflows/ 파일을 통해 makefile을 대체할 수 있다.
설치
Act는 컨테이너에서 Worflow를 실행하기 위해 Docker Engine을 사용한다. 따라서 Docker를 사전에 설치해야한다. 컨테이너 격리가 필요하지 않는 경우 현재 사용중인 시스템 위에서 동작할 수 도 있다고 한다. 글쓴이의 경우 실행할 Workflow를 컨테이터 내부에 실행하기 위해 Docker를 설치하였다.
Act는 brew에서 관리하고 있었기 때문에 쉽게 설치할 수 있었다.
설치후 사용할 프로젝트에서 act -l을 통해 Worflow를 검색할 수 있다면 정상적으로 설치된 것이다.
act -l
WARN ⚠ You are using Apple M-series chip and you have not specified container architecture, you might encounter issues while running act. If so, try running it with '--container-architecture linux/amd64'. ⚠
Stage Job ID Job name Workflow name Workflow file Events
0 deploy deploy CD and request Discord Message to deploy cd-with-discord.yml push
0 build build CI and request Discord Message to review ci-with-discord.yml pull_request
0 close-issue Close Jira issue Close Jira issue close-issue-update-jira.yml issues
0 create-issue Create Jira issue Create Jira issue create-issue-to-jira.yml issues
0 send_discord_message send_discord_message review and sent Discord message request-comment-with-discord.yml pull_request_review,pull_request_review_comment
1 send_discord_message send_discord_message CD and request Discord Message to deploy cd-with-discord.yml push
1 send_discord_message send_discord_message CI and request Discord Message to review ci-with-discord.yml pull_request
Workflow 내부의 Job 단위로 list를 확인할 수 있다.
기본 Workflow를 act으로 실행해보자
name: GitHub Actions Demo
run-name: ${{ github.actor }} is testing out GitHub Actions 🚀
on: [push]
jobs:
Explore-GitHub-Actions:
runs-on: ubuntu-latest
steps:
- run: echo "🎉 The job was automatically triggered by a ${{ github.event_name }} event."
- run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by GitHub!"
- run: echo "🔎 The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}."
- name: Check out repository code
uses: actions/checkout@v4
- run: echo "💡 The ${{ github.repository }} repository has been cloned to the runner."
- run: echo "🖥️ The workflow is now ready to test your code on the runner."
- name: List files in the repository
run: |
ls ${{ github.workspace }}
- run: echo "🍏 This job's status is ${{ job.status }}."
echo 출력 만을 진행하는 Workflow이다.
act push
위 명령어를 통해 push 이벤트에 트리거 하는 Workflow를 실행할 수 있다.
[GitHub Actions Demo/Explore-GitHub-Actions] ⭐ Run Set up job
[GitHub Actions Demo/Explore-GitHub-Actions] 🚀 Start image=node:16-buster-slim
[GitHub Actions Demo/Explore-GitHub-Actions] 🐳 docker pull image=node:16-buster-slim platform= username= forcePull=true
[GitHub Actions Demo/Explore-GitHub-Actions] using DockerAuthConfig authentication for docker pull
[GitHub Actions Demo/Explore-GitHub-Actions] 🐳 docker create image=node:16-buster-slim platform= entrypoint=["tail" "-f" "/dev/null"] cmd=[] network="host"
[GitHub Actions Demo/Explore-GitHub-Actions] 🐳 docker run image=node:16-buster-slim platform= entrypoint=["tail" "-f" "/dev/null"] cmd=[] network="host"
[GitHub Actions Demo/Explore-GitHub-Actions] 🐳 docker exec cmd=[node --no-warnings -e console.log(process.execPath)] user= workdir=
[GitHub Actions Demo/Explore-GitHub-Actions] ✅ Success - Set up job
[GitHub Actions Demo/Explore-GitHub-Actions] ⭐ Run Main echo "🎉 The job was automatically triggered by a push event."
[GitHub Actions Demo/Explore-GitHub-Actions] 🐳 docker exec cmd=[bash -e /var/run/act/workflow/0] user= workdir=
| 🎉 The job was automatically triggered by a push event.
[GitHub Actions Demo/Explore-GitHub-Actions] ✅ Success - Main echo "🎉 The job was automatically triggered by a push event." [52.909875ms]
[GitHub Actions Demo/Explore-GitHub-Actions] ⭐ Run Main echo "🐧 This job is now running on a Linux server hosted by GitHub!"
[GitHub Actions Demo/Explore-GitHub-Actions] 🐳 docker exec cmd=[bash -e /var/run/act/workflow/1] user= workdir=
| 🐧 This job is now running on a Linux server hosted by GitHub!
[GitHub Actions Demo/Explore-GitHub-Actions] ✅ Success - Main echo "🐧 This job is now running on a Linux server hosted by GitHub!" [52.15425ms]
[GitHub Actions Demo/Explore-GitHub-Actions] ⭐ Run Main echo "🔎 The name of your branch is refs/heads/david-parkk and your repository is david-parkk/Test-Act."
[GitHub Actions Demo/Explore-GitHub-Actions] 🐳 docker exec cmd=[bash -e /var/run/act/workflow/2] user= workdir=
| 🔎 The name of your branch is refs/heads/david-parkk and your repository is david-parkk/Test-Act.
[GitHub Actions Demo/Explore-GitHub-Actions] ✅ Success - Main echo "🔎 The name of your branch is refs/heads/david-parkk and your repository is david-parkk/Test-Act." [42.195917ms]
[GitHub Actions Demo/Explore-GitHub-Actions] ⭐ Run Main Check out repository code
[GitHub Actions Demo/Explore-GitHub-Actions] 🐳 docker cp src=/Users/Test-Act. dst=/Users/Test-Act
[GitHub Actions Demo/Explore-GitHub-Actions] ✅ Success - Main Check out repository code [33.224292ms]
[GitHub Actions Demo/Explore-GitHub-Actions] ⭐ Run Main echo "💡 The david-parkk/Test-Act repository has been cloned to the runner."
[GitHub Actions Demo/Explore-GitHub-Actions] 🐳 docker exec cmd=[bash -e /var/run/act/workflow/4] user= workdir=
| 💡 The david-parkk/KUIT3_java-webMVC repository has been cloned to the runner.
[GitHub Actions Demo/Explore-GitHub-Actions] ✅ Success - Main echo "🍏 This job's status is success." [54.807792ms]
[GitHub Actions Demo/Explore-GitHub-Actions] ⭐ Run Complete job
[GitHub Actions Demo/Explore-GitHub-Actions] Cleaning up container for job Explore-GitHub-Actions
[GitHub Actions Demo/Explore-GitHub-Actions] ✅ Success - Complete job
[GitHub Actions Demo/Explore-GitHub-Actions] 🏁 Job succeeded
Github Action에서 제공하는 Log와 같이 실행 로그를 확인할 수 있다.
환경변수
실행중인 워크플로우에는 기본 환경 변수를 제외한 사용자 환경 변수는 직접 주입해야한다.
act -W .github/workflows/ci-with-discord.yml --secret-file .github/workflows/.act_secrets
.act_secrets 파일을 생성하여 워크플로우에 직접 주입할 환경변수를 작성한다.(해당 레포에 사용중인 환경 변수를 동일하게 사용했다)
export MONGO_URL=XXXXXX
S3_BUCKET=XXXXXX
S3_ACCESS_KEY=XXXXXX
S3_SECRET_KEY=XXXXXX
KAKAO_API_KEY=XXXXXX
DEFAULT_BUCKET_URL=XXXXXX
일부 제외된 기능
Act는 Workflow에 대한 모드 기능을 제공하지 않는다.
BUILD SUCCESSFUL in 52s
| 7 actionable tasks: 7 executed
| > IDLE
| > IDLE
|
|
|
[CI and request Discord Message to review/build] ✅ Success - Main 빌드한다. [53.414130583s]
[CI and request Discord Message to review/build] ⭐ Run Main 테스트 결과를 게시한다.
[CI and request Discord Message to review/build] 🐳 docker pull image=ghcr.io/enricomi/publish-unit-test-result-action:v2.19.0 platform= username= forcePull=true
[CI and request Discord Message to review/build] 🐳 docker create image=ghcr.io/enricomi/publish-unit-test-result-action:v2.19.0 platform= entrypoint=[] cmd=[] network="container:act-CI-and-request-Discord-Message-to-review-build-c51c95a4e0b5eec1f103ec8b5be70b3c11b82ebe2bfe5f795196a03a656fe7e0"
[CI and request Discord Message to review/build] 🐳 docker run image=ghcr.io/enricomi/publish-unit-test-result-action:v2.19.0 platform= entrypoint=[] cmd=[] network="container:act-CI-and-request-Discord-Message-to-review-build-c51c95a4e0b5eec1f103ec8b5be70b3c11b82ebe2bfe5f795196a03a656fe7e0"
| Traceback (most recent call last):
| File "/action/publish_test_results.py", line 554, in <module>
| settings = get_settings(options, gha)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
| File "/action/publish_test_results.py", line 508, in get_settings
| check_var(settings.token, 'GITHUB_TOKEN', 'GitHub token')
| File "/action/publish_test_results.py", line 344, in check_var
| raise RuntimeError(f'{label} must be provided via action input or environment variable {name}')
| RuntimeError: GitHub token must be provided via action input or environment variable GITHUB_TOKEN
테스트 결과를 공지하는 Job에 대해서 GITHUB_TOKEN 누락으로 실패하였지만 /action/publish_test_results.py 에러에서 확인할 수 있듯이 Act에서는 push 트리거를 명시적으로 선언하기 때문에 해당 이벤트에 대한 변수를 모두 제공하지 않는다. Act를 테스트 변경에 대한 테스트를 하기 위한 용도로 사용했기 때문에 이렇게 지원하지 않는 부분은 감수하고 사용하였다.
기타 오류
테스트를 진행하던 중에 문제가 발생했다. hibernate의 auto-ddl 옵션을 제거하고, ddl 스크립트를 직접 테스트 환경에 주입하여 테이블을 생성하도록 Workflow을 수정하였다.
run: |
sudo apt-get update
sudo apt-get install -y default-mysql-client
mysql -h 127.0.0.1 -P 3307 -u root -ptestdb testdb < infra/sql/ddl.sql
해당 워크플로우를 실행하니 다음과 같은 에러가 발생하였다.
Encryption not supported - caching_sha2_password plugin was built with GnuTLS support
Act를 통해 구성한 Runner에서 발생하는 문제로 추측되는데 해결하지 못했다. 문서에도 Default Runner가 불안정하다고 주의하고 있고, Alternative Runner 또는 local Runner 사용을 지원하고 있다.
https://nektosact.com/usage/runners.html
Runners - act - User Guide | Manual | Docs | Documentation
GitHub Actions offers managed virtual environments for running workflows. In order for act to run your workflows locally, it must run a container for the runner defined in your workflow file. Here are the images that act uses for each runner type and size:
nektosact.com
https://github.com/nektos/act/issues/107
command not found (in image node:12.6-buster-slim, as opposed to GH Actions) · Issue #107 · nektos/act
Hi, as documented here GitHub configures passwordless sudo, so I can have sudo in my shell scripts to perform individual commands as root. Given this minimal workflow: on: push name: Test jobs: bui...
github.com
What is the differences between mysql-client and mysql-client-core?
I wonder what is the differences between mysql-client and mysql-client-core? Also there are mysql-server and mysql-server-core.
askubuntu.com