블로그 자동 빌드 시스템


요약

이 글에서 이미 Git hook을 이용한 배포를 설명하고 있는데, 몇가지 고치고 싶은 부분이 있어서 그 부분을 보충하려고 한다.

  • 단순 카피라면 git hook 내에서 처리해도 되겠지만, 시간이 걸리는 빌드 과정이 들어간다면 클라이언트가 불필요하게 기다리게 된다.
  • 빌드 과정에 Lock이 필요하다. 한 빌드를 처리하는 도중에 다른 빌드를 처리하게 되면 희박한 확률로 빌드과정 사이에 충돌이 발생할 수 있다.

빌드 시스템

처음에는 빌드가 번개같이 빨랐었는데, 몇몇 그림을 PlantUML로 생성한다던지 하는 삽질을 하고 나니 빌드가 이젠 수십초 정도 걸리는 번거로운 작업이 되기도 했고, Java 의존성(PlantUML은 java application이다)도 생긴데다가 왜인지는 모르겠지만 Mac에서는 빌드가 안되기 시작했다. 작은 수정 정도는 어디서든 원격으로 수행할 수 있었으면 좋겠어서 서버에서 빌드를 처리할 방법에 대해 알아보기 시작했다.

원래는 전문 CI툴에서 처리해야 할 것이긴 한데, 고작 블로그 하나 관리하겠다고 Jenkins를 설치하기는 좀 애매하고, 빌드 결과물을 통째로 로컬 서버에 복사해 와야 하는데 외부 서비스 의존성을? 하는 것도 좀 이상해서, 그냥 아주 기본적인 녀석을 만들어 굴리기로 맘먹었고, git hook을 쓰기로 마음먹은 다음에 위 글을 찾아서 따라했다.

개선점

요약에서 제시한 문제들을 개선하기 위해서, tsp를 이용하기로 했다. 이걸 쓰는 것만으로 이미 불필요한 대기 문제는 해결되지만, 혹시라도 있을 수 있는 빌드 사이의 충돌 문제를 해결하기 위해선 Concurrency를 기본값인 1로 두는 것이 필요하다. 뭐, 충돌 발생하면 그때그때 해결하겠다 하는 전사의 심장을 가진 자라면 그냥 맘대로 하시라.

결론?

FROM node:18

RUN apt update && apt install -y default-jre-headless

WORKDIR /app

ADD package.json package-lock.json ./

RUN npm install

ADD . ./
#!/bin/bash

echo "buliding image"
docker build -t survived-today_build .

DIST=$(mktemp -d)
chmod +rx $DIST
echo "building website"
docker run -v ${DIST}:/app/dist survived-today_build npm run build
echo "Deploying"
rsync -azvv --delete --delete-after -e ssh ${DIST}/ web:/usr/share/nginx/www/survived.today/
echo "Cleaning up ${DIST}"
sudo rm -rf ${DIST}

요렇게 빌드 및 배포 스크립트를 만들었고,

#!/bin/bash

REPO=$(mktemp -d)
GIT_REPO=...
BRANCH=main

git --git-dir=$GIT_REPO --work-tree=$REPO checkout -f $BRANCH
(cd $REPO; ./build.sh)
rm -rf $REPO

요렇게 CI 작업을 하나의 스크립트로 묶은 다음에

#!/bin/bash

BRANCH="main"

while read oldrev newrev ref
do
        if [[ $ref = refs/heads/$BRANCH ]]; then
                echo "Deploying"
                tsp $(dirname "$0")/deploy.sh
        else
                echo "Ref $ref ignored"
        fi
done

(꼭 git_repo/hooks/에 post-receive란 이름으로 저장하고 +x속성 설정해줘야함. Git 국룰임)

이렇게 hook에서 CI 작업을 tsp로 큐에 넣어주면 언젠가는 처리가 될 것입니다… 라는게 오늘의 결론