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