Git | GitLab

[GitLab] gitlab-runner 내에서 push 하기

비번변경 2025. 12. 1. 10:32

개요

GitLab을 사용하고 있는데, 레포지터리 내 특정 파일에 변경 사항이 발생하면 pipeline job 내에서 다른 파일을 변경하여 레포지터리에 push 하려는 요구사항이 있다.

때문에 이번 글에서는 gitlab 레포지터리에 push를 수행하는 gitlab 파이프라인을 구성해보려고 한다. 테스트 환경은 gitlab.com으로, 별도 러너 구성 없이 gitlab 제공 러너를 사용할 것이다.

 

+ 참고로 이번 파이프라인은 구성을 잘못하면 파이프라인이 동작할 때마다 파이프라인을 트리거하는 문제가 발생할 수 있다. 이 부분을 주의하여 구성할 필요가 있다.

 

 

인증 구성

gitlab 레포지터리에 작업을 수행하기 위해서는 인증이 필요하다.

인증 방식에는 여러 선택지가 존재하지만, 이번 글에서는 SSH 인증을 사용하여 구성한다. 다른 선택지를 사용하지 않은 이유는 다음과 같다.

  • 개인 액세스 토큰 : 구성이 간편하다. 하지만 gitlab 16.0부터 강제로 만료일을 지정하게끔 변경되었다. 만료일을 관리해야 하는 불편함이 존재한다.
  • Job Token : gitlab 17.2 이상에서는 gitlab-ci-token을 사용하여 레포지터리에 쓰기 작업을 수행할 수 있도록 개발하고 있다. 하지만 아직 테스트 상태이기도 하고, 유료 라이선스 사용자에게만 제공하는 것 같다.
  • 배포 토큰 : 레포지터리 읽기 권한은 제공하지만 쓰기 권한은 제공하지 않는다.
  • SSH 인증 : 직접 SSH 키쌍을 생성하고 배포 키와 CI/CD 변수를 사용하여 구성해야 하는 번거로움이 있지만, 별다른 만료일이 존재하지 않는다.

따라서 이번 글에서는 SSH 인증 방식으로 구성해 보겠다. 구성 방법은 다음과 같다.

 

1. SSH 키 쌍 생성

2022.04.15-[GitLab] 사용자 계정에 SSH 키 등록 글을 참고하여 키 쌍을 생성한다.

ssh-keygen -f /PATH/OUTPUT_FILENAME

# 예시
ssh-keygen -f ./gitlab-runner

개인 키와 공개 키 파일이 생성된다. 참고로 공개 키 파일이 .pub 확장자를 가진다.

 

2. 프로젝트 CI/CD 변수에 개인 키 저장

프로젝트 CI/CD 설정에서 Variables 항목을 찾는다.

변수 추가 버튼을 누르고, Type을 일반 변수로 지정한 뒤 다른 설정은 적절히 구성한다. 이 글에서는 Flags에서 보호 변수는 제거하는 정도만 지정했다.

그리고 이제 키 이름과 값을 지정해야 한다. gitlab 공식 안내에 따르면 Key 이름은 SSH_PRIVATE_KEY으로 지정하도록 권하고 있다. values에는 ssh-keygen으로 생성한 비밀 키를 복사하여 붙여 넣는다. 값은 줄 바꿈으로 끝나야 한다!

이상이 없다면 변수를 저장한다.

참고로 변수의 값을 포함한 모든 구성은 언제든지 편집을 통해 변경할 수 있다.

 

3. 배포 키 구성

프로젝트의 레포지터리 설정에서 배포 키 항목으로 이동한다.

Add new key를 누르고 Key 이름은 식별 가능한 정도로, Key에는 ssh-keygen으로 생성한 공개 키를 복사하여 붙여 넣는다.

키를 생성할 때는 레포지터리 쓰기 작업을 허용해야 하고, 만료일은 필요한 경우 지정한다. 

 

 

파이프라인 구성

이제 파이프라인을 구성한다.

 

1. SSH 인증부

https://gitlab.com/gitlab-examples/ssh-private-key/ 참고하여 구성했다.

test-job:
  stage: test
  before_script:
    ##
    ## Docker 사용 시 ssh-agent 설치 필요
    ## 아래 명령은 debian 기반으로 작성됨. RPM 기반 이미지 사용 시 yum 사용 필요
    ##
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client git -y )'

    ##
    ## 빌드 환경 내에서 ssh-agent 실행
    ##
    - eval $(ssh-agent -s)

    ##
    ## SSH_PRIVATE_KEY 변수에 저장된 SSH 키를 에이전트 저장소에 추가
    ## We're using tr to fix line endings which makes ed25519 keys work without extra base64 encoding.
    ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
    ##
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -

    ##
    ## SSH 디렉터리 생성 및 권한 부여
    ##
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh

    ##
    ## ssh-keyscan로 서버 키 스캔
    ##
    - ssh-keyscan ${CI_SERVER_SHELL_SSH_HOST} >> ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts
    
    ##
    ## SSH_SERVER_HOSTKEYS 변수 생성 시 주석 해제 필요
    ##
    #- echo "$SSH_SERVER_HOSTKEYS" > ~/.ssh/known_hosts
    #- chmod 644 ~/.ssh/known_hosts

    ##
    ## 호스트 키 검사 비활성화. 단, man-in-the-middle attacks에 노출될 수 있음
    ## Docker executor에서만 사용할 것. Shell executor 사용 시 사용자의 SSH 구성을 덮어쓰게 됨
    ##
    #- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'

    ##
    ## git 명령어 사용 시 사용자 이름과 메일 지정 필요 (선택 사항)
    ##
    - git config --global user.email "${GITLAB_USER_EMAIL}"
    - git config --global user.name "${GITLAB_USER_NAME}"
  script:
    - ssh git@${CI_SERVER_SHELL_SSH_HOST}

SSH 구성에 문제가 없다면 ssh 명령 수행 시 다음과 같은 출력을 확인할 수 있다.

 

2. 로컬 레포지터리 구성

먼저 Gitlab 파이프라인이 동작하면 Preparing Environment 단계에서 Git 레포지터리를 내려받는다.

로컬 레포지터리의 설정을 확인하면 다음과 같은데, gitlab job token은 gitab 원격 저장소에 push 할 권한이 없다.

따라서 아래 스크립트를 추가하여 push 명령어 사용 시 사용할 URL을 별도로 지정해주어야 한다.

.. before_script 생략 ..
  script:
    ## 
    ## SSH 연결 확인
    ##
    - ssh git@${CI_SERVER_SHELL_SSH_HOST}

    ##
    ## push url 생성
    ##
    - git remote set-url --push origin git@${CI_SERVER_SHELL_SSH_HOST}:${CI_PROJECT_PATH}

설정하면 다음과 같이 설정이 변경된다.

 

3. 파일 작업

gitlab 레포지터리에 반영할 파일을 작업한다. 이 글에서는 간단히 text 파일을 생성하고 commit 했다.

.. 생략 ..
    ## 
    ## push 할 파일 작업
    ## 
    - echo 'hello, world!\n' >> pipeline_result.txt
    - git add pipeline_result.txt
    - git status
    - git commit -m "pipeline_text"
    - git log -1

 

4. 원격 저장소에 commit push

아래 스크립트로 변경 사항을 원격 저장소로 push 한다.

.. 생략 ..
    ##
    ## git push 수행
    ##
    - git push -o ci.skip origin HEAD:${CI_COMMIT_REF_NAME}

ci.skip 옵션은 파이프라인을 트리거하지 않고 commit을 push 할 때 사용한다. CI_COMMIT_REF_NAME는 현재 브랜치로 push 할 때 사용하는데, 필요시 다른 브랜치로 push해도 괜찮다.

 

+ push 부분 전체 스크립트는 접은글로 적어둔다.

더보기
  script:
    ## 
    ## SSH 연결 확인
    ##
    - ssh git@${CI_SERVER_SHELL_SSH_HOST}

    ##
    ## push url 생성
    ##
    - git remote set-url --push origin git@${CI_SERVER_SHELL_SSH_HOST}:${CI_PROJECT_PATH}

    ##
    ## 레포지터리 설정 확인
    ##
    - git remote -v
    - git config --list

    ## 
    ## push 할 파일 작업
    ## 
    - echo 'hello, world!\n' >> pipeline_result.txt
    - git add pipeline_result.txt
    - git status
    - git commit -m "pipeline_text"
    - git log -1
    
    ##
    ## git push 수행
    ##
    - git push -o ci.skip origin HEAD:$CI_COMMIT_REF_NAME

 

 

 

결과 확인

push 한 파일을 원격지에서 보이는지 확인한다.

매우 잘 동작하는 것을 확인할 수 있다.

 

 

참고 문서

https://forum.gitlab.com/t/git-push-from-inside-a-gitlab-runner/30554/4

https://stackoverflow.com/questions/51716044/how-do-i-push-to-a-repo-from-within-a-gitlab-ci-pipeline

https://docs.gitlab.com/ci/jobs/ssh_keys/

https://gitlab.com/gitlab-examples/ssh-private-key/

https://www.reddit.com/r/gitlab/comments/1arymxp/is_it_possible_to_push_the_code_from_gitlab/

https://docs.gitlab.com/ci/pipelines/

728x90