Git Action으로 간단하게 CI/CD 구축하기

choko's avatar
Jun 29, 2024
Git Action으로 간단하게 CI/CD 구축하기
 

Git Action

  • Github에서 제공하는 CI/CD 서비스로, GitHub 리포지토리 내에서 직접 워크플로우를 정의하고 실행할 수 있다.
  • Test code, 배표, 스크립트 등을 지원
  • Git Action에서의 개념
    • Workflow
      • 여러 Job으로 구성되고, Event에 의해 트리거될 수 있는 자동화된 프로세스
      • 프로젝트 Repo의 .github/workflows 폴더 내에 yaml 파일들로 저장된다.
    • Event
      • Workflow를 실행하는 특정 활동이나 규칙
      • Push, Pull Request, Cron 등의 이벤트 발생 시 작업
    • Job
      • 여러 Step들로 구성되어 가상 환경의 인스턴스에서 실행됨
      • 의존 관계, 병렬 실행 등이 가능
    • Step
      • Task들의 집합, 거맨드를 날리거나 action을 실행시킬 수 있다.
    • Action
      • Workflow의 가장 작은 블럭
      • Job을 만들기 위해 Step들을 연결할 수 있음
    • Runner
      • Workflow가 실행될 인스턴스
      • 깃허브에서 제공하는 Runner를 사용할수도, 직접 Runner를 구축하여 사용할수도 있다.
      •  

Git Action 프로세스

Worlfow 정의

name: CI # Workflow 이름 지정 on: push: # master 브런치에 push를 할 때 branches: [ master ] pull_request: # master 브런치에 pull_request를 할 때 branches: [ master ] jobs: build: # job 이름 -> build runs-on: ubuntu-latest # 어떤 os에서 실행시킬 것인가? steps: - uses: actions/checkout@v2 # git action 진행을 위한 checkout - name: Run a one-line script run: echo Hello, world! - name: Run a multi-line script run: | echo Add other actions to build, echo test, and deploy your project.
 

example - Build(Java CI with Gradle)

name: Java CI with Gradle on: pull_request: # develop 브런치에 pull request를 할 때 branches: [ 'develop' ] permissions: contents: read jobs: build: name: Build and test runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up JDK 17 # JDK 설정 uses: actions/setup-java@v3 with: java-version: '17' distribution: 'temurin' # secrets 환경 변수는 Github Repo의 Secrets(비밀 변수)로 사용된다. # 암호, API 토큰 등과 같은 중요한 데이터를 안전하게 관리하고, 이는 로그에 절대 # 노출되지 않는다. # Settings -> Secrets 섹션에서 세팅해줄 수 있다. - name: Create application.yml run: | echo "${{ secrets.APPLICATION_YML }}" > src/main/resources/application.yml # microsoft/variable-substitution 액션을 사용하여 지정된 YML 파일들 # (application.yml, application-gcs.yml, application-youtube.yml)에서 # 환경 변수를 대체합니다. - name: Set yml file uses: microsoft/variable-substitution@v1 with: files: ./src/main/resources/application.yml, ./src/main/resources/application-gcs.yml, ./src/main/resources/application-youtube.yml env: spring.datasource.driver-class-name: ${{ secrets.BUILD_DATASOURCE_DRIVER_CLASS_NAME }} spring.datasource.url: ${{ secrets.BUILD_DATASOURCE_URL }} spring.datasource.username: root spring.datasource.password: 1234 spring.jpa.hibernate.ddl-auto: ${{ secrets.BUILD_JPA_DDL_AUTO }} spring.data.redis.database: ${{ secrets.BUILD_REDIS_DATABASE }} server.port: ${{ secrets.SERVER_PORT }} server.ssl.key-store-password: ${{ secrets.KEYSTORE_PASSWORD }} jwt.secret: ${{ secrets.JWT_SECRET }} spring.cloud.gcp.storage.credentials.location: ${{ secrets.GCS_KEY_LOCATION }} spring.cloud.gcp.storage.project-id: ${{ secrets.GCS_PROJECT_ID }} spring.cloud.gcp.storage.bucket-name: ${{ secrets.GCS_BUCKET_NAME }} spring.cloud.gcp.storage.bucket-dir: ${{ secrets.GCS_TEST_BUCKET_DIR }} spring.cloud.gcp.storage.key-name: ${{ secrets.GCS_KEY_NAME }} youtube.api-key1: ${{ secrets.YOUTUBE_API_KEY_1 }} # Json 파일을 생성 - name: Create-json id: create-json uses: jsdaniell/create-json@v1.2.2 with: name: ${{ secrets.GCS_KEY_NAME }} json: ${{ secrets.GCS_KEY_JSON }} dir: ${{ secrets.GCS_KEY_DIR_LOCATION }} # Keysotre 파일 저장 - name: Keystore Save run: echo "${{ secrets.KEYSTORE }}" | base64 --decode > ./src/main/resources/keystore.p12 # Gradle 빌드 권한 부여, 실행 - name: Run chmod to make gradlew executable run: chmod +x ./gradlew - name: Build with Gradle run: ./gradlew build
 

example - Deploy(Build 후 develop repo pull test)

... build: ...(중략) deploy: name: Deploy needs: build # build 이후 실행 runs-on: ubuntu-latest steps: - name: executing remote ssh commands using ssh key uses: appleboy/ssh-action@v1.0.0 with: host: ${{ secrets.SERVER_IP }} username: ${{ secrets.SSH_USERNAME }} key: ${{ secrets.SSH_KEY }} passphrase: ${{ secrets.SSH_PASSPHRASE }} port: ${{ secrets.SSH_PORT }} # Docker로 잘 빌드, 실행되는지 확인 후, 이상 없으면 통과 script: | docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} docker system prune -a docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.APPLICATION_NAME }}:test docker tag ${{ secrets.DOCKER_USERNAME }}/${{ secrets.APPLICATION_NAME }}:test ${{ secrets.APPLICATION_NAME }}-test if [ "$(docker ps -aq -f name=${{ secrets.APPLICATION_NAME }}-test)" ] then echo "[ ${{ secrets.APPLICATION_NAME }}-test is running ]" docker stop ${{ secrets.APPLICATION_NAME }}-test docker rm ${{ secrets.APPLICATION_NAME }}-test else echo "[ ${{ secrets.APPLICATION_NAME }}-test is not running ]" fi docker run -d --name ${{ secrets.APPLICATION_NAME }}-test -p ${{ secrets.TEST_SERVER_PORT }}:${{ secrets.TEST_SERVER_PORT }} ${{ secrets.APPLICATION_NAME }}-test
 
Share article

Tom의 TIL 정리방