상현에 하루하루
All 개발자의 하루

Github action ci/cd

( 업데이트: )

퍼블리싱 작업을 할 때 dev repo와 upstream repo 두가지로 관리하게 된다. 그리고 main 브랜치가 머지될 때 버전이 올라가게 정하렸고 버전이 올라갈때 데모 웹페이지의 소스 코드를 업데이트해야한다.

이런 과정은 매우 번거롭다. 신경써야 할 것들도 많고 매번 똑같은 단계이기 때문에 자동화가 필요한 작업이었다. 이 과정을 자동화 한다면 개발하는데 있어서 많은 시간을 절약할 수 있다.

이제 어떻게 자동화를 할까 고민을 해봤다.

단순하게 메인 브랜치 버전이 올라가면 웹서버(글쓴이는 synolgoy)에 해당 프로젝트 루트에서 git pull origin develop을 해줄 수 없을까?

일단 기능은 간단하게 생각해두고 어떤 CI/CD들이 있는지 테스트 해보자

CI/CD – Jenkins를 빼놓을 수 없지

젠킨스는 쓰지 않을 것이다. docker로 첫 셋팅부터 오류가 많았기 때문에 앞으로 관리하면서 많은 시간 젠킨스 docker 구성에 쏟고 싶지는 않았다.

젠킨스는 PR이나 Github의 이벤트를 통해서 CI를 하고 설정한 구성대로 그 후 어떤 일을 할 것인지 구성할 수 있다.

Jenkins & docker & m1 macbook 오류

M1의 문제가 아니라는 것은 알수있지만 문제가 발생한 시점에서 내 환경이 어땟는지 알기위해 적어 놓았다.

version: '3.8'

services:
  jenkins:
    image: jenkins/jenkins:2.60.3
    ports:
      - 8080

젠킨스가 잘 실행된다. 임시로 부여된 포트로 접속해 봤다.
첫 설정에 plugin 설치에서

An error occurred during installation: No such plugin: cloudbees-folder

무슨 문제인지 잘 모르겠다.
따로 플러그인을 설치해줘야 하는 것인가?

이슈를 살펴보고 명확한 해결방법을 찾을 수 없었다.

해결 방법에 가장 근접하게 찾은 것은
“An error occurred during installation: No such plugin: cloudbees-folder” · Issue #424 · jenkinsci/docker

가볍게 테스트해본 것이기 때문에 더 고생하지 않고 다른 방법은 무엇이 있을까? 대안을 찾아 봤다.
젠킨스를 대체 할만한 매력적인 ci/cd 툴은 나에게 없었다.

“그러면 Github action으로 설정해 볼까? 잘 구성해서 모든 곳에 써먹을 수 있게”라는 생각으로 전환했다.

Let’s go Github action

Github action은 마땅히 테스트 할 곳이 없어서 테스트용 repo를 만들었다.

Github action으로는 어떤 한계점이 있을까 고민해봤는데 내가 원하는 기능까지는 한계가 없어 보여서 내가 무엇을 완료하면 될까 생각했다.

👏 Goal

  • Release assets 첨부 파일 demo web server host 업로드
  • assets, image, etc 파일 덮어쓰기
  • web server – git pull origin develop!

Release assets 첨부 파일 demo web server host 업로드

Github의 Release를 published로 게시하는 것을 트리거로 해당 릴리즈에 첨부된 deploy-src.tar파일을 데모호스트에 덮어씌우는 것을 생각하고 있다.

해당 첨부 파일에는 이미지, webpack 빌드파일 등등을 담는다.

이 과정이 필요한가?
버전관리가 되고있지 않은 이미지 에셋을 릴리즈에 첨부하기 때문에 다운로드해서 업로드하는 과정이있는데 이 부분을 자동화 할 수 있다.

Release에서 첨부파일(에셋파일) 가져오기 & 다운로드

Github action job에서 릴리즈 에셋 파일을 다운로드 해야한다.

GitHub – dsaltares/fetch-gh-release-asset: Github Action to download an asset from a Github release 을 사용했다.

업로드는 어떻게? ssh-deploy

GitHub – easingthemes/ssh-deploy: GitHub Action for deploying code via rsync over ssh

star의 갯수가 많고 많은 사라들이 의견을 주고 받고있는 것 같아서 선택하였다.

수차례의 오류를 겪고나서 이 액션으로 되지 않는다고 판단했다. 정확하게 어떤 것이 문제인지는 알 수없었지만 추측해보는 것은 자체가 js로 구성 되어있는데 이게 문제인 것 같기도하고 🤔

오류문구는

...
⚠️ [Rsync] cmd:  rsync /home/runner/work/github-action-test-space/github-action-test-space/subdir/ ***@***:/volume1/docker/***/***/test --rsh "ssh -p *** -i /home/runner/.ssh/deploy_key -o StrictHostKeyChecking=no" --recursive --exclude= -rltgoDzvO --delete
...
Permission denied, please try again.
무엇이 문제일까? 🥲

필자의 서버환경에서는 rsync가 server(syonology)에서는 관리자에서 활성화를 해줘야하고 따로 포트도 지정해줘야한다.

rsync가 ssh sftp랑 동일한 포트를 사용하는 것으로 알고 있어서 이 부분을 놓쳤다.

하지만 결국 또 다시 Permission denied, please try again.
그런데 해당 커멘드를 로컬에서 실행하면 아주 잘 작동하는 것을 확인했다.

결국 해당 액션에 대해서 다시 의심을 품었고 다른 액션으로 시도를 해봤다.

Change: ssh-deploy > rsync-deploy

GitHub – AEnterprise/rsync-deploy 한번에 작동되었다!!

rsync로 덮어쓸 deploy-src.tar 만들기

deploy-src.tar를 생성해서 프로젝트 루트 경로에서 압축을 풀어 각 해당하는 파일들을 덮어쓰는 것이다.

. # project root
├── CHANGELOG.md
├── README.md
├── bp-online-training.code-workspace
├── config
├── docker-compose.dev.yaml
├── docker-compose.yaml
├── node_modules
├── package-lock.json
├── package.json
├── github-action-upload.zip
└── src
# github-action-upload.zip
.
└── src
    ├── dist
    │   ├── main.js
    │   ├── main.js.map
    │   ├── style.css
    │   └── style.css.map
    └── media
        └── zeplin

이런식으로 zeplin 폴더와 dist 폴더를 덮어씌는 것이 목표다.

그래서 그런데 media의 zeplin 파일은 변경 사항을 체크해서 해당 파일들만 가져오는 것이 좋을 것같아서 어떻게 해야할까? 고민했다.

TODO

  • 버전간 변경된 이미지파일만 압축
  • 파일구조 src/... 동일하게
버전관리 media 파일 압축

프로젝트 루트의 .git이외에 src/media 폴더에 모든 이미지와 파일들을 버전관리한다. 루트 파일의 메이저 버전 업데이트 또는 Release 할때마다 커밋을 남긴다.

그럼 해당 커밋간의 변경사항으로 어떤 파일들이 변경되었는지 알게되어서 업로드할 파일들을 손쉽게 가져올 수있다.

## 환경변수
deployfile=deploy-src.tar # 압축파일 이름
searchDir1=./src/media    # 이미지경로 (깃으로 관리중)
# 압축파일 초기화 & 생성
rm $deployfile
touch $deployfile

for f in $(git diff -C $searchDir1 --name-only HEAD^); do
  tar -rvf deploy-src.tar $searchDir1/$f
done

추가적으로 npm build된 파일은 src/dist로 만들어짐

...
for $f in ./src/dist/*; do
  tar -rvf deploy-src.tar $f
done

Github action 내부에서 @sync라는 폴더 아래 압축 해제하고 rsync로 무든 파일 프로젝트 루트에 overwrite 🥳

Github git pull

git pull을 왜해야 할까?
dist 파일들은 모두 버전관리가 안되는데?!

  1. php, html 등등 정적으로 가져가야하는 파일들은 버전관리가 되기 때문에 git pull이 필요하다.

GitHub action에서 이 것을 어떻게 수행할 것인가?!

appleboy/ssh-action

ssh로 접속해서 내가 설정하는 커맨드를 수행할 수 있다.

ssh에 접속하기 위해서 ssh key로만 접속 할 수 있기 때문에 여러가지 ssh 접속 액션들을 찾아봤지만 key 관련해서도 설정되어있는 star가 많은 액션이 appleboy/ssh-action 액션이었다.

내부에 자신이 만든 커스텀 docker 이미지를 사용하고있어서 나중에 이 docker 이미지를 파악해서 내껄로 만들어야 할 것같다.

코드는 매우 단순 할 것같아서

그런데왜? 이 녀석은 sftp 포트로도 작동이 잘되는 것일까? 의문이다 🤔
결국 이것도 ssh 포트롤 변경했다.

호스트에 접속해서 git pull origin develop !!! 완료 git pull 커맨드는 아주 손쉽게 해결 할 수 있었다.


Github action 참고

tar 관련 참고

rsync