GitLab CI/CD를 통해 SCP를 이용하여 Composer 및 npm 스크립트 실행

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-Managed, GitLab Dedicated

이 안내서는 GitLab CI/CD를 사용하여 PHP 프로젝트의 종속 항목을 빌드하고 npm 스크립트를 통해 에셋을 컴파일하는 방법을 다룹니다.

사용자 지정 PHP 및 Node.js 버전이 있는 이미지를 만들 수도 있지만, 간결함을 위해 PHP와 Node.js가 모두 설치된 Docker 이미지를 사용합니다.

image: tetraweb/php

다음 단계는 zip/unzip 패키지를 설치하고 composer를 사용할 수 있게 하는 것입니다. 이를 before_script 섹션에 넣습니다.

before_script:
  - apt-get update
  - apt-get install zip unzip
  - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
  - php composer-setup.php
  - php -r "unlink('composer-setup.php');"

이렇게 함으로써 모든 요구 사항을 준비할 수 있습니다. 이제 composer install을 실행하여 모든 PHP 의존성을 가져오고, npm install을 실행하여 Node.js 패키지를 로드합니다. 그런 다음 npm 스크립트를 실행합니다. 이를 before_script 섹션에 추가해야 합니다.

before_script:
  # ...
  - php composer.phar install
  - npm install
  - npm run deploy

본 사례에서 npm deploy 스크립트는 다음을 수행하는 Gulp 스크립트입니다:

  1. CSS 및 JS 컴파일
  2. 스프라이트 생성
  3. 다양한 에셋(이미지, 글꼴) 복사
  4. 일부 문자열 대체

모든 이러한 작업은 모든 파일을 build 폴더에 넣어 놓으며, 이 폴더는 실제 서버에 배포할 준비가 되어 있습니다.

실시간 서버로 파일 전송하는 방법

rsync, SCP, SFTP 등 여러 옵션이 있습니다. 지금은 SCP를 사용합니다.

이 작업을 수행하려면 GitLab CI/CD 변수를 추가해야 합니다(gitlab.example/your-project-name/variables에 접속 가능). 이 변수의 이름은 STAGING_PRIVATE_KEY이어야 하며 서버의 개인 SSH 키로 설정해야 합니다.

보안 팁

업데이트가 필요한 폴더에 액세스할 수 있는 사용자를 만드세요.

해당 변수를 만든 후, 해당 키가 실행될 때 Docker 컨테이너에 추가되었는지 확인하세요.

before_script:
  # - ....
  - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
  - mkdir -p ~/.ssh
  - eval $(ssh-agent -s)
  - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'

순서대로 말하자면:

  1. ssh-agent가 있는지 확인하고 없으면 설치합니다.
  2. ~/.ssh 폴더를 만듭니다.
  3. bash를 실행하는지 확인합니다.
  4. 호스트 확인을 비활성화합니다(서버에 처음 연결할 때 사용자 수락을 요청하지 않으며, 각 작업이 첫 번째 연결을 의미하므로 이것이 필요합니다).

이게 before_script 섹션에 필요한 모든 것입니다.

배포 방법

앞서 설명한 것처럼 Docker 이미지에서 build 폴더를 서버로 배포해야 합니다. 이를 위해 새 작업을 만듭니다:

stage_deploy:
  artifacts:
    paths:
      - build/
  rules:
    - if: $CI_COMMIT_BRANCH == "dev"
  script:
    - ssh-add <(echo "$STAGING_PRIVATE_KEY")
    - ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp"
    - scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp
    - ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live"
    - ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old"

세부 내용은 다음과 같습니다:

  1. rules:if: $CI_COMMIT_BRANCH == "dev"dev 브랜치로 무언가를 푸시할 때만 해당 빌드가 실행된다는 의미입니다. 이 블록을 완전히 제거하고 모든 푸시에서 모두 실행하도록 할 수 있지만, 아마도 원치 않을 것입니다.
  2. ssh-add ...는 웹 UI에 추가한 개인 키를 Docker 컨테이너에 추가합니다.
  3. ssh를 통해 연결하고 새로운 _tmp 폴더를 만듭니다.
  4. scp를 통해 build 폴더(여기에는 npm 스크립트에 의해 생성된 것)를 이전에 만든 _tmp 폴더로 업로드합니다.
  5. 다시 ssh를 통해 live 폴더를 _old 폴더로 이동한 다음 _tmplive로 이동합니다.
  6. ssh를 통해 _old 폴더를 제거합니다.

아티팩트는 무엇입니까? GitLab CI/CD에게 build 디렉터리를 유지하도록 지시합니다(나중에 필요할 때 이를 다운로드할 수 있습니다).

우리가 이렇게 하는 이유

스테이지 서버에만 사용한다면 다음 두 단계로 수행할 수 있습니다:

- ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/live/*"
- scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/live

문제는 앱이 서버에 없을 수 있는 잠깐의 시간이 있습니다.

따라서 운영 환경에서는 특정 시점에 기능적인 앱이 구축되어 있는 것을 보장하기 위해 추가 단계를 사용합니다.

다음은 어디로?

WordPress 프로젝트였기 때문에 실제 코드 스니펫이 포함되어 있습니다. 추후에는 다음과 같은 아이디어를 추구할 수 있습니다:

  • 기본 브랜치에 약간 다른 스크립트를 사용하면 프로덕션 서버로 배포하고 다른 브랜치에서 스테이지 서버로 배포할 수 있습니다.
  • 실시간으로 푸시하는 대신 WordPress 공식 리포지터리로 푸시할 수 있습니다.
  • 필요할 때마다 i18n 텍스트 도메인을 생성할 수 있습니다.

최종 .gitlab-ci.yml은 다음과 같습니다:

stage_deploy:
  image: tetraweb/php
  artifacts:
    paths:
      - build/
  rules:
    - if: $CI_COMMIT_BRANCH == "dev"
  before_script:
    - apt-get update
    - apt-get install zip unzip
    - php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
    - php composer-setup.php
    - php -r "unlink('composer-setup.php');"
    - php composer.phar install
    - npm install
    - npm run deploy
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
    - mkdir -p ~/.ssh
    - eval $(ssh-agent -s)
    - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
  script:
    - ssh-add <(echo "$STAGING_PRIVATE_KEY")
    - ssh -p22 server_user@server_host "mkdir htdocs/wp-content/themes/_tmp"
    - scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/_tmp
    - ssh -p22 server_user@server_host "mv htdocs/wp-content/themes/live htdocs/wp-content/themes/_old && mv htdocs/wp-content/themes/_tmp htdocs/wp-content/themes/live"
    - ssh -p22 server_user@server_host "rm -rf htdocs/wp-content/themes/_old"