이전에 로컬에서 도커 이미지를 빌드하고 이를 도커 허브에 올린 뒤 ec2에서 이미지를 풀하고 컨테이너를 돌리는 식으로 배포해봤었는데, 새로운 기능을 추가하고 수정도 하면 이 과정을 하나하나 하기는 귀찮다. 그래서 jenkins라는 오픈소스를 활용해 빌드하고 테스트, 배포하는 과정을 자동화해본다.

 

또한, 나름대로의 코드 품질 개선과 혹시 모를 보안 위협에 대비하기 위해 sonarqube라는 코드 정적 분석 툴을 사용할 건데, 이는 sonarcloud라는 서비스를 통해 간단하게 도입해볼 것이다.

 

그림으로 시퀀스를 나타내면 다음과 같다.

  1. pull request가 생기면 sonarqube(sonarcloud)에서 코드 정적 분석을 한다.
  2. main브랜치에 푸시가 발생하면(merge) 도커로 띄운 젠킨스로 웹훅(webhook)을 보낸다
  3. 웹훅을 수신하면, jenkins쪽에서 지정된 깃헙 리포지토리의 코드를 땡겨온다 (+ application.properties 설정)
  4. 이를 gradle을 통해 빌드하고(jar)
  5. 이를 docker image로 빌드한 뒤 도커 허브에 푸쉬.
  6. 실제 서비스가 돌아갈 ec2에서 도커 허브에 푸쉬된 이미지를 땡겨와 돌리게끔 하면 된다

 

이 때 단순히 gradle로 빌드한 jar를 서비스를 돌릴 ec2로 보낼 수도 있지만(scp등으로) 멘토님 가라사대 요즘은 도커 모르면 안 된다라고 하셔서, 도커에 익숙해질 겸 도커 이미지를 만들고 이를 전달하는 식으로 가기로 했다. 그러면 도커로 띄운 젠킨스에서 도커 이미지를 만들어내야 해서, 도커 내에 도커를 설치해야 하니 이 점 유의

 


0. sonarcloud 설정

깃헙 계정으로 가입해서 설정만 딸깍딸깍 누르면 된다. sonarcloud를 설치할 레포지토리들을 선택하면 지가 알아서 설치되고, 이후 pull request를 날리면 지가 알아서 다음과 같이 분석 결과를 남겨준다

 

 

1. ec2 띄우고 docker 설치 및 swap 메모리 설정

참고로 ec2는 public subnet에 띄웠다. private subnet에 띄우면 깃헙 쪽에서 웹훅을 보낼 때 직접 받을 수 없기 때문에, 편의를 위해 그리 한 것임.

 

아 그리고 EBS볼륨을 20GB로 해줬다! 기본인 8GB로 해줬다가 용량이 없다고 하는 문제가 생겼었기 때문.

 

나는 ec2는 ubuntu로 띄웠고, 공식 매뉴얼에 나온 대로 도커를 설치했다

https://docs.docker.com/engine/install/ubuntu/

 

Install Docker Engine on Ubuntu

Jumpstart your client-side server applications with Docker Engine on Ubuntu. This guide details prerequisites and multiple methods to install.

docs.docker.com

 

그 뒤 swap 메모리를 설정해줬다. 나같은 경우 ec2를 프리티어로 해서 젠킨스를 띄울 건데, 이 때 프리티어는 메모리가 부족해서 멈추는 경우들이 있다고 한다. swap메모리를 설정해 이를 방지할 수 있다고 해서, 설정해줬다

(swap 메모리 : 메모리의 부족한 부분을 하드디스크로 대체하는 것)

 

아래 공식문서 글을 참고하면 된다

https://repost.aws/ko/knowledge-center/ec2-memory-swap-file

 

스왑 파일을 사용하여 Amazon EC2 인스턴스의 스왑 공간으로 메모리 할당

Amazon Elastic Compute Cloud(Amazon EC2) 인스턴스에서 스왑 파일로 사용할 메모리를 할당하려고 합니다. 어떻게 해야 하나요?

repost.aws

 

 

2. jenkins 이미지 풀 땡기고 컨테이너로 돌리기

sudo docker pull jenkins/jenkins:lts

 

docker run --name jenkins -p 8080:8080 -p 50000:50000 -d -v /var/run/docker.sock:/var/run/docker.sock -v jenkins_home:/var/jenkins_home -u root jenkins/jenkins:lts
  • --name : 컨테이너의 이름을 지정(여기서는 jenkins라는 이름으로)
  • -p : 컨테이너를 띄우는 호스트의 포트와 컨테이너의 포트를 매핑하는 것(즉 호스트의 8080과 컨테이너의 8080이 매핑) 참고로 jenkins 웹 인터페이스가 8080으로 열리고, jenkins 슬레이브 에이전트가 50000으로 열린다
  • -d : 컨테이너를 백그라운드에서 실행. 이를 통해 터미널로 다른 작업이 가능
  • -v : 호스트와 컨테이너를 볼륨 마운트. 이를 통해 컨테이너와 호스트 머신 간에 데이터를 공유할 수 있음
  • -v /var/run/docker.sock:/var/run/docker.sock -> 컨테이너 내부에서 호스트머신의 docker 데몬과 상호작용하게끔 하는 것.
  • -v jenkins_home:/var/jenkins_home -> jenkins 설정과 데이터를 영구적으로 저장하기 위함
  • -u root : 컨테이너 내에서 jenkins를 root사용자로 실행

 

그 뒤 다음 커맨드를 통해 docker.sock파일의 권한을 수정해준다(다른 사용자도 접근 가능하게끔). 참고로 컨테이너 밖에서 실행해준다.

sudo chmod 666 /var/run/docker.sock

참고로 docker.sock은 도커 데몬과 컨테이너 간의 통신을 위한 소켓 파일이다.(그래서 ls -l로 보면 파일타입이 s가 나옴) 이를 통해 컨테이너 내부에서도 호스트 머신의 docker데몬과 통신 가능하며, 이를 통해 컨테이너 내부에서도 docker커맨드를 쓸 수 있게 되는 것. 컨테이너 내에서도 docker데몬에 대한 권한을 부여하기 위해 위 커맨드를 통해 권한을 주는 거라고 생각하면 된다.

 

 

3. 컨테이너 내 도커 설치

엇? 컨테이너 내에서도 호스트의 도커 데몬과 통신할 수 있게끔 한 거면 도커를 설치할 필요가 없지 않나? (나는 도알못이기 때문..) 왜 도커를 설치하지?

 

이럴 거면 docker run을 할 때 굳이 -v를 해서 docker.sock을 컨테이너로 마운트한 이유가 없지 않나? 그냥 컨테이너에서 도커 깔았으면 거기서 자체적으로 도커 데몬 쓰면 되지..(참고로 이를 Docker in Docker, DinD라고 부르고 소켓파일 마운트해서 호스트의 도커 데몬을 쓰는 방식을 Docker ouf of docker, Dood라고 부른다)

 

간단하다. 제 아무리 호스트 꺼여도, 어찌됐건 도커 데몬과 통신하려면 도커 클라이언트가 필요하기 때문에 도커를 설치하는거다. 다만 데몬을 호스트 꺼를 사용한다는 것. (그냥 DinD로 컨테이너 내에서 자체 도커 데몬을 써도 되나, 보안상 이를 권하지 않는다고 한다. 무려 도커공식피셜임. 참고로 도커를 요로코롬 컨테이너 내에 깔아도 docker.sock은 호스트와 마운트된 걸 사용하게 된다)

 

그림으로 표현하면 아래와 같은 형태가 되겠다.

 

찾아보니 나는 젠킨스 이미지를 바로 컨테이너로 띄우면서 docker.sock을 마운트하고 컨테이너 내에 도커를 설치한 반면, 젠킨스 이미지를 베이스로 도커를 설치하는 도커이미지를 만든 다음(즉 젠킨스를 한 번 더 포장한 이미지인데 도커가 설치돼있는 이미지가 된다) 컨테이너 띄울 때 docker.sock을 마운트하는 방식도 있다.

 

암튼.. 컨테이너 내에 도커를 설치해본다

 

우선 docker exec을 해서 컨테이너 내부로 들어간 다음, 위에서 한 것과 똑같은 가이드북대로 설치했다.

 

근데 중간에 apt-get update를 하니 The repository 'https://download.docker.com/linux/ubuntu bookworm Release' does not have a Release file이라는 오류가 났었다. 이는 아래 글을 참고해 /etc/apt/sources.list.d/docker.list를 지운 뒤 실행함으로써 해결했다

 

(/etc/apt/sources.list.d : 이 디렉토리에 있는 파일들은 APT 패키지 관리자에게 소프트웨어 패키지 저장소를 추가하는 데 사용됨)

(docker.list : Docker 패키지를 제공하는 저장소를 가리키며, 이 저장소는 Docker 엔진과 관련된 패키지를 제공)

 

https://dct-wonjung.tistory.com/entry/apt-update-404-not-found

 

apt update 404 Not Found 에러 해결 방법 - The repository does not have a Release file.

TmaxOS21에서 docker를 설치하려고 했더니 설치는 안되고 apt update를 할 때마저 아래와 같은 에러가 발생했다. $ sudo apt update 기존:1 http://tos-repo.tmaxos.com/tmax nabi InRelease 기존:2 http://tos-repo.tmaxos.com/tmax t

dct-wonjung.tistory.com

 

근데 또 이번엔 sudo apt-get install docker-ce docker-ce-cli containerd.io (이하 생략) 커맨드에서 Package docker-ce is not available, but is referred to by another package. This may mean that the package is missing, has been obsoleted, or is only available from another source라는 메시지와 함께 오류가 났다. 아까 docker.list를 삭제했던게 원인인 듯 한데.. 문제는 얘를 삭제안하면 다른 오류가 계속 나던 상황이라.. 해결방법을 찾아보다가, docker.list를 지운 상태에서 아래 커맨드를 실행하니 설치가 잘 됐다.

 

curl -fsSL get.docker.com -o get-docker.sh

bash get-docker.sh // 다운받은 쉘 스크립트 파일 실행

이렇게 하니 설치가 됐다. curl을 통해 get.docker.com으로부터 도커를 설치하는 스크립트를 get-docker.sh란 파일로 다운받은 뒤 이를 실행하는 커맨드다.

 

 

4. application.properties 설정

내 프로젝트는 .gitignore를 통해 application.properties를 깃 관리 대상에서 제외했다. 따라서 나중에 젠킨스에서 깃헙 리포지토리에 있는 코드를 땡겨가도 그래도 빌드해 사용한다면 문제가 생길 것이다. application.properties를 주입하는 방법은 여러 가지가 있겠지만, 나는 컨테이너의 /home/env밑에 application.properties를 두고 나중에 젠킨스에서 이걸 가져다 쓰는 식으로 구성했다.

 

docker exec -it jenkins bash // 컨테이너 내부로 들어가기

cd /home

mkdir env // /home밑에 env 디렉토리 생성

cd env

echo "{application.properties 내용}" >> application.properties

 

이런 방식으로 만들었었다.

 

여까지 했다면, 이제 젠킨스라는 툴을 사용해 ci cd 파이프라인을 구축할 준비가 된 거다. 젠킨스 설정은 젠킨스에서 제공하는 웹 인터페이스(즉 사이트)를 통해 가능하니, 웹사이트로 들어가 설정을 진행해본다.

 

5. 젠킨스 웹사이트 접속 (ec2의 퍼블릭ip:8080)

docker exec -it {컨테이너명} bash 같은 걸로 컨테이너 안에 들어가서 저 경로로 cat찍으면 패스워드 볼 수 있으니 그리 하면 된다. (사실 엄밀히 말하면 들어간다기보다는 컨테이너에서 작업할 수 있게 해주는 커맨드라고 보는게 맞다)

 

추천해주는 플러그인 설치한 뒤, 회원가입 페이지(?)같은 게 나온다. 자신의 플젝에 맞게 설정하면 된다.

 

6. 젠킨스 설정  - jdk, gradle, github & dockerhub token

jar 빌드를 위해 jdk와 gradle을 설정해줄 필요가 있고, 깃허브 리포지토리에 있는 코드들을 땡겨와야 하기 때문에 github token이 필요하며, 도커 이미지를 도커허브에 올리기 위해 dockerhub token도 필요하다. 우선 jdk와 gradle설정부터 시작해본다

 

프로젝트에서 jdk11버전을 썼다면 모를까, 나는 17버전을 쓰기 때문에 따로 설정을 해줘야 한다.

jenkins관리 - tools로 가서 jdk를 설정해준다.

이 설정은 아래 글을 참고했었다.

https://royleej9.tistory.com/entry/Jenkins-jdk-%EC%84%A4%EC%A0%95

 

[Jenkins] pipeline jdk 설정

[Jenkins] pipeline jdk 설정 작업 순서 JDK 설정 pipeline에서 특정 버전의 JDK 사용하기 1. JDK 설정 Jenkins 관리 > Global Tool Configuration > JDK 항목 > Add JDK https://stackoverflow.com/questions/55243120/jenkins-add-jdk-11-to-jdk-l

royleej9.tistory.com

 

download url : 내가 원하는 버전의 jdk를 다운받는 경로

https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.8.1%2B1/OpenJDK17U-jdk_x64_linux_hotspot_17.0.8.1_1.tar.gz

 

subdirectory : url을 통해 다운된 파일을 압축 해제 했을 때 나오는 폴더 이름

jdk-17.0.8.1+1

 

gradle 설정도 jenkins관리 - tools에서 해주며, 플젝에서 쓰는 spring boot에서 사용중인 버전과 똑같은 놈으로 하면 된다.

본인 스프링부트 프로젝트의 gradle > wrapper > gradle-wrapper.properties에서 확인 가능하다

 

그리고 jenkins관리 - Credentials로 가서 깃허브 토큰을 등록한다. 깃허브 토큰을 발급받는 과정은 생략한다.

이 때 kind를 secret text가 아닌 username with password로 해준다. git이 뭐 지원 안한다고 함

username : 깃허브 계정 (이메일)

password : 깃헙 토큰

id : 본인이 식별할 수 있는 거 암거나 작성

 

마찬가지로 dockerhub token도 발급받은 뒤 똑같이 username with password로 등록해주면 된다. username은 도커허브 계정(아이디) 넣으면 되고, password에 토큰값 넣어주면 되고, id도 본인이 식별가능한 거 써주면 된다

 

7. 젠킨스 설정 - ssh 관련 설정

도커 이미지를 도커 허브에 푸시한 뒤, ssh로 서비스를 배포할 ec2에 접속해 도커허브로부터 이미지를 땡기는 작업을 하게 된다. 이를 위해 ssh를 사용하는데, 예전엔 Publish Over SSH라는 걸 썼던 듯 하나 지금은 못 쓰는 듯 하다. (새로운 openssh에서 ssh-rsa키 유형이 비활성화됐다고 한다. https://github.com/jenkinsci/publish-over-ssh-plugin/issues/247#issuecomment-1153768171)

 

그러면 이제 젠킨스가 띄워진 ec2에 ssh키를 물리적으로 둘 수도 있을 텐데, 이건 사실상 현관문 바로 앞에 키를 두는 방식이니 좋지 않다. 찾아보니 ssh agent플러그인을 젠킨스에서 다운받아 쓰는 방법이 있어, 이를 쓰기로 한다.

 

jenkins관리 -> 플러그인 -> available plugins로 가서 ssh agent를 install한다

난 이미 설치해서 안 뜬다

 

그 다음 아까 깃헙&도커허브 토큰을 등록했을 때처럼 ssh key정보를 등록한다. 

cat으로 ec2의 ssh key(pem파일)을 본 다음, 내용물을 적어주면 된다.

 

8. 깃허브 웹훅 설정

리포지토리 세팅 -> Webhooks로 가서 http://젠킨스서버ip:8080/github-webhook/을 등록한다

그리고 깃허브 쪽에서 보내는 웹훅을 젠킨스서버가 잘 받기 위해, 젠킨스 서버에 대한 보안그룹에서 깃허브 쪽에서 오는 인바운드들이 열려 있어야 한다.

 

https://api.github.com/meta

요기에서 현재 깃허브에서 웹훅을 보낼 때 쓰는 ip들을 확인 가능하다. 현재

 

"hooks": [
    "192.30.252.0/22",
    "185.199.108.0/22",
    "140.82.112.0/20",
    "143.55.64.0/20",
    "2a0a:a440::/29",
    "2606:50c0::/32"
  ],

 

요 ip들에서 8080으로 오는 인바운드들을 다 열어주면 된다.

 

 

9. 파이프라인 작성

새로운 아이템 - 파이프라인을 선택해주고 이름을 지어준다

General - GitHub project에 리포지토리 url(.git으로 끝나는..)을 입력한다.

 

그리고 build triggers에서 다음과 같이 체크해준다

 

그리고 파이프라인 스크립트를 작성한다.

난 다음과 같이 작성해줬다.

pipeline {
    environment { 
        repository = "{도커허브계정}/{레포지토리 이름}" // 이메일말고 아이디
        DOCKERHUB_CREDENTIALS = credentials('등록해둔 도커허브토큰id') // jenkins에 등록해 놓은 docker hub credentials 이름
        dockerImage = '' 
    }
    
    tools {
        jdk "{jdk이름}" //아까 jdk등록할 때 name으로 준 값
    }
    
    agent any 
    
    stages {
        stage('GitHub Repository Clone') { 
            steps { // url의 main branch 내용을 credential을 통해 땡겨온다
              
                git branch: 'main', credentialsId: '{등록해둔 깃헙토큰id}', url: '{깃헙 리포지토리 주소(.git으로 끝나는)}'
              
            }
        }
        
        stage('Set Application.properties') {
            steps {
                sh '''
                    if [ ! -d ./src/main/resources ]; then
                        mkdir ./src/main/resources
                    else
                        echo "resources directory alreay exist"
                    fi
                    
                    if [! -e ./src.main/resources/application.properties ]; then
                        rm ./src/main/resources/application.properties
                    fi
                    
                    cp /home/env/application.properties /var/jenkins_home/workspace/{지어준 파이프라인 이름}/src/main/resources
                    
                    cat ./src/main/resources/application.properties
                    '''
                
            }
        }
        
        stage('Build jar') {
            steps{
                sh '''
                    echo 'start bootJar'
                    echo $JAVA_HOME
                    ./gradlew clean bootJar
                    '''
            }
        }
        
        stage('Docker build') {
            steps {
                sh '''
                    docker build -t $repository:latest .
                    '''
            }
        }
        
        stage('Dockerhub Login'){
            steps {
                sh '''
                    echo $DOCKERHUB_CREDENTIALS_PSW | docker login -u $DOCKERHUB_CREDENTIALS_USR --password-stdin
                    '''
            }
        }
        
        stage('Push Docker image') {
            steps {
                sh '''
                    docker push $repository:latest
                    '''
            }
            
            post {
                success {
                    echo 'push success'
                }
                
                failure {
                    echo 'push failure'
                }
            }
        }
        
        stage('Run New Docker Container'){
            steps {
                sshagent(credentials: ['ssh-key']) {
                    sh '''
                    ssh -o StrictHostKeyChecking=no ubuntu@{서비스 띄울 ec2 ip} 'sudo docker ps -a'
                    
                    // 기존에 돌아가던 컨테이너 삭제
                    ssh -o StrictHostKeyChecking=no ubuntu@{서비스 띄울 ec2 ip} '
                        if [ "$(sudo docker ps -q --filter name={삭제할 컨테이너명}" ]; then
                            sudo docker rm -f $(sudo docker ps -aq --filter name={삭제할 컨테이너명})
                        else
                            echo "no there containers"
                        fi
                    '
                    
                    // 기존 이미지 삭제
                    ssh -o StrictHostKeyChecking=no ubuntu@{서비스 띄울 ec2 ip} '
                        if [ "$(sudo docker images -q)" ]; then
                            sudo docker rmi $(sudo docker images -q)
                        else
                            echo "no there images"
                        fi
                    '
                    
                    ssh -o StrictHostKeyChecking=no ubuntu@{서비스 띄울 ec2 ip} 'sudo docker pull {아까 푸시한 이미지명}'
                    ssh -o StrictHostKeyChecking=no ubuntu@{서비스 띄울 ec2 ip} 'sudo docker run -d --name={컨테이너명} -p 8080:8080 {풀받은 이미지명}'
                    
                    '''
                }
            }
        }
        
        stage('Clean Docker Image') {
            steps {
                sh '''
                    docker rmi $repository:latest
                    '''
            }
        }
    }
}

참고 : docker image -q 또는 docker ps -q -> 아이디값만 보게 해준다.

 

이후 깃헙에서 푸시를 해보니..

 

다음과 같이 파이프라인이 잘 돌아가는 걸 확인할 수 있다.


어찌보면 남들 다 하는 ci cd 구성이지만.. 그래도 처음 해보면서 삽질 여러가지 하면서 배운 게 많은 것 같다. DinD나 DooD도 있고, 특히 쉘 스크립트 작성을 꽤나 해보게 됐다ㅋㅋㅋㅋ.. jar로 빌드하고, 도커 이미지 빌드하고, 도커허브에 푸쉬하고, 서비스 띄울 ec2에선 기존 컨테이너랑 이미지 삭제한 뒤에 새로 풀받아서 돌리고.. 한 스텝 한 스텝 성공할 때마다 왠지 모를 희열이 느껴졌다. 

 

다만 아직 고려해야할 부분들이 더 많다. 당장 도커 이미지만 봐도 일단 전부다 latest를 달아서 하게끔 했는데, 이것보다는 빌드별로 번호를 매겨서 붙여주는게 더 나을 거다. 또한 지금 구축한 것대로라면 기존에 돌아가던 컨테이너를 내리고 새로 이미지를 받은 뒤 컨테이너를 띄우는 동안은 서비스가 중단된다!! 즉 무중단 배포도 고려해야 할 것이다.

 

기능 개발을 해야 할 게 남아 있는 만큼, 그리고 https 구축도 해야 하는 만큼 일단 그것들에 먼저 신경을 쓰고 해야 할 듯 하다..

'INFRA & DEVOPS > CI & CD' 카테고리의 다른 글

[GitHub Action] 플러터 프로젝트 CI 구축하기  (0) 2023.07.09

CI란?

Continuous Intergration의 줄임말로, 지속적인 통합을 의미한다. CD(Continuous Delivery&Deployment)와 짝꿍 관계기도 하다. 

 

그럼 지속적 통합은 뭘까? 우선 통합의 의미를 살펴보자. 나 또는 다른 사람이 어떠한 코드 변경(새로운 기능 추가, 수정, 삭제 등)을 했을 때 그 코드가  빌드 및 테스트되어 우리의 공유 리포지토리(깃헙 등)에 병합되는 걸 통합이라 부른다. 지속적 통합이란, 이 과정이 정기적으로 계속해서 일어난다는 것을 의미하는 것이다.

 

이는 다수의 개발자가 다 함께 코드 작업을 할 경우, 서로 충돌이 일어날 수 있는 문제를 해결하기 위해 도입된 개념이라고 한다. 통합 과정을 주기적하게 되니, 자연스럽게 충돌 과정이 최소화된다는 거다. CI는 다시 말해 빌드 및 테스트를 자동으로 실시하여 공유 리포지토리에 통합하는 과정이라고 이해할 수 있으며, 이를 통해 코드 변경 내용을 우리 손을 거치지 않고 자동으로 빌드하고 테스트할 수 있다.

 

 

GitHub Action이란?

GitHub에서 제공하는 서비스로, CI & CD 플랫폼이다. 리포지토리에 .github폴더를 만들고, 그 안에 workflows폴더를 만든 뒤 그 안에 yaml파일을 만드는 것으로 구축할 수 있다. 그러면 어떤 동작이 발생했을때, yaml파일에 내가 작성했던 workflow가 실행되게 할 수 있다.

 

 

플러터 프로젝트 CI 구축

GitHub marketplace에 flutter란 이름으로 검색하면, Flutter Action라는 이름의 Action이 있다

 

https://github.com/marketplace/actions/flutter-action

 

Flutter action - GitHub Marketplace

Setup your runner with Flutter environment

github.com

 

친절하게 사용법이 나와있어서 따라하면 된다.

난 우분투, 윈도우, 맥 모두에서 테스트 & 빌드를 해볼 수 있게끔 만들었다.

 

name: Flutter CI (test & build)

on:
  pull_request:
    branches: [ main ]
  push:
    branches: [ main ]
    
jobs:
  Tests-and-build-ubuntu-and-window:
    name: Tests and Build on ${{ matrix.os }}
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-java@v2
        with:
          distribution: 'zulu'
          java-version: '11'
      - uses: subosito/flutter-action@v2
        with:
          flutter-version: '3.10.0'
          channel: 'stable'
      - run: flutter pub get
      - run: flutter test
      - run: flutter build apk
      - run: flutter build appbundle

  Tests-and-build-macos:
    name: Tests and Build on MacOS
    runs-on: macos-latest
    steps:
    - uses: actions/checkout@v3
    - uses: subosito/flutter-action@v2
      with:
        flutter-version: '3.10.0'
        channel: 'stable'
        architecture: x64
    - run: flutter pub get
    - run: flutter test
    - run: flutter build ios --release --no-codesign

 

 

uses : 다른 사람들이 이미 만든 action을 이용하는 것

run : 직접 커맨드를 실행하는 것

 

이라고 이해하면 된다.

 

[ runs-on ] 작업들이 실행될 인스턴스 환경(OS)

[ uses: actions/checkout@v3 ] 작업한 깃헙 레포지토리의 소스코드 가져오기(일단 코드를 가져와야 테스트하든 빌드하든 하니까)

[ uses: actions/flutter-action@v2 ] 플러터 SDK 설치. with로 버전명, 채널을 설정 가능

[ run : flutter pub get ] 체크아웃으로 가져온 프로젝트가 사용하는 패키지들 설치

 

 

 

음..사실 yaml파일을 내가 한 것보다 더 리팩토링이 가능했다. if문 등을 통해 더 줄일 수 있겠다는 생각이 들었지만 GitHub Action을 처음 하던지라 일단 동작하게끔 만들자는 생각으로 macos에서 실행되는 건 따로 분리를 했다. 우리의 킹갓지피티에게 물어보니 더 줄일 수 있는 것 같다.

 

CI/CD를 구축해본 적이 없어 GitHub Action 공부를 많이 해야 할 것 같아 좀 걱정이었는데 막상 해보니까 되게 간단하다는 생각이 든다. (물론 CD는 구축하지도 않았지만ㅋㅋ) 역시 뭐든 직접 해봐야 더 잘 알게 되는 것 같다.

+ Recent posts