진짜 제곧내입니다... github action을 이용한 CI 적용해본 것에 대한 정리 및 WIP로 더 쓸모 있는 것들을 찾아봐야겠다 생각해 정리해봤습니다.
CI란?
CI/CD 자주 들어보셨겠지만, 여기서는 CI에 대해서만 다룹니다.
CI는 무엇일까요~ 위키백과에는 아래와 같이 나와있습니다.
이중 우리는 "지속적인 통합"의 뜻으로 CI를 사용합니다.
어떤 것을 지속적으로 통합할까요? 바로 우리의 소스 코드입니다. 개인 프로젝트에도 적용이 될 수 있지만, 동아리 프로젝트, 회사 규모에서는 하나의 브랜치에 여러 사람들의 코드를 합치게 됩니다.
그런데 이런 코드를 합치는 작업, 즉 코드 통합의 단계에 있어서 반복적인 빌드와 테스트를 사람이 아닌 기계가 자동으로 해준다면.... 얼마나 편할까요?
kotlin, android lint check를 사람이 아니라 기계가 자동으로 해준다면 얼마나 편할까요?
그런데, 해줍니다! (당신이 잘 짜놓으면~)
하지만 이러한 CI/CD를 사용하기 위해선 이전에는 Jenkins로 많이 세팅을 했었으나, 진입장벽이 높고 설정이 어렵다는 단점이 있었습니다. 그러나 github action이 나오면서 진입장벽도 낮아지고(쉽고 간단하다!) 저 또한 흥미가 생겨 공부해보게 됐습니다.
CI에 대해서 쉬운 예제로 자세히 이야기 하자면, 특정 브랜치에서 pr이 올라왔을 때 빌드 체크(빌드가 성공하는지 실패하는지)를 한다던가, 브랜치가 merge되었을 때 lint check를 하는 등 사람의 수고로움을 크게 덜어줄 수 있는게 바로 CI 이고, 이를 도와주는 도구가 github actions 입니다.
즉 한줄로 표현하자면, 개발 -> 빌드 -> 테스트의 과정을 자동화하는 것을 CI라고 합니다.
사실 더 세밀하고 복잡한 작업도 할 수 있지만, 이번 포스트에서는 Android에서 쓰이는 기초 CI에 대해서만 알아보고, 조금 더 세밀한 작업은 다음 포스트에서 작성해보겠습니다.
또한 이번 포스트에는 CD에 대한 내용은 없습니다!
사전 지식
CI를 github actions를 통해 사용하기 위해선 몇가지 알아두면 좋을 것이 있는데,
- yaml or yml 파일을 사용한다
- github actions을 통해 action을 만들지 않고, .github 폴더 안에서 workflows안에 파일을 생성하면 ci가 등록된다
- 간단하게 name, on, jobs가 있다.
위의 내용들은 앞으로 이야기하면서 다시 나오니, 그냥 알아두고만 넘어가겠습니다.
Hello World 출력해보기
프로그래밍의 기초 Hello World를 출력해 보겠습니다.
1. Android project 에서 Actions를 클릭합니다.
2. android를 검색해줍니다.
아래에 목록들 중에서 Android가 없을 가능성이 높습니다. 그냥 검색해서 편하게 씁니다.
3. Android CI의 configure을 선택해줍니다.
그렇게 되면 다음과 같이 자동으로 생성이 됩니다.
먼저 첫번째, 사전지식에 나왔던 것 처럼 파일의 확장자는 yml입니다.** yaml 또는 yml으로 지정되지 않으면 CI가 등록되지 않으니, 꼭 확인해주어야 합니다.**
4. 하나하나 알아보기
name은 해당 Actions의 이름으로 해당과 같이 커밋을하여 저장하면 아래와 같이 Actions에 나타나게 됩니다.
on은 어떠한 작업이 일어났을 때 해당 action을 실행시키는지에 대한 정보입니다.
위의 사진에서는 master branch에 push가 되었을 때, pull request가 생성되었을 때 해당 action을 수행합니다.
여기서 branch는 *
를 통해 모든 브랜치에서 작동하게끔 할 수 있고, !master
와 같이 master 브랜치는 제외하거나, feature*
와 같이 feature로 시작하는 브랜치에서 작동하게끔 만들 수도 있습니다. (외에도 fork, merge, push 등 다양하게 존재합니다)
위의 사진은 실제로 Lint Check를 하기 위해 만든 yml 파일로, feature, hotfix, release 브랜치에서 생성된 pr의 경우 Lint Check를 하도록 만들었습니다.
----- 2023.08.29 수정 ---
위의 feature* 는 잘 작동하지 않습니다. 왜냐면, 아래 사진을 보면, releases로 시작하는 브랜치에 머지됐을 때 work flow가 작동하려면, *가 아닌 /* 또는 **로 사용해야 합니다. (/*와 **가 뜻하는 바도 또 다르기도 합니다. 더 자세한 글은 https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#patterns-to-match-branches-and-tags)
아래 사진을 보면 *는 문자열을 match 시키지만, '/' 문자에 대해선 매치시키지 않는다고 합니다. 즉 release*와 release/는 매칭이 되지 않는다는 뜻이죠!
그래서, release/a, release/b를 매칭 시키고 싶다면 release/*를 사용하면 되고, (한개만 적는다면 하위, 즉 release/a/b는 매칭되지 않습니다)
release/a/b, release/a/b/c, release/a 를 모두 매칭시키고 싶다면 release/** 또는 release**를 사용하면 될 것 같습니다.
---------
jobs는 workflow라고도 부르며, 하나의 작업단위입니다. jobs는 여러개의 job으로 구성이 될수도 있고, 하나만 존재할 수도 있습니다. 위의 사진에서는 한개뿐입니다.
또한 job은 순차적으로 진행이 됩니다. 이중 runs-on은 어느 os base로 진행이 될지를 선택합니다. 저희는 ubuntu로 지정되어 있기 때문에 아래 코드들이 리눅스 코드들로 구성이 되어있습니다. (ex: chmod )
uses는 저장소로부터 코드를 내려받기 위한 checkout action이라고 합니다. 쉽게 이야기 해서 안드로이드의 import와 비슷한 느낌으로 이해하시면 좋습니다.
워크플로우의 YAML 파일에서는 steps: 의 하위인 uses키에 사용하고자 하는 액션의 위치를 적어주는데 actions/checkout@v3는 이렇게 해석이 가능합니다. {소유자}/{저장소명}@{참조자}
즉 Github에서 제공하는 체크아웃 액션의 소유자는 actions이고, 저장소의 이름은 checkout, 현재 최신 버전은 v3입니다.
또한 JDK 11을 setting도 해줍니다.
name은 위의 name과는 조금 다릅니다. 이름을 정한다는 것에는 동일하지만, 작업의 이름입니다.
여기서 Print Hello World라는 작업의 name을 정해주면, workflow가 동작할 때 아래와 같이 보입니다.
run은 실제로 동작할 코드를 작성해줍니다. Hello world가 print 되는 코드를 작성해보면, 아래와 같습니다.
- name: Print Hello World
run: echo "Hello World"
이렇게 작성하게 되면 실제 CI가 돌 때 아래와 같이 실행됩니다.
쉬운 hello world 출력 뿐 아니라, 파이썬을 이용해 매주 도서를 받아오거나, 더 복잡한 내용의 기능도 수행할 수 있습니다.
자동 빌드 체크
이전에는 쉬운 Hello World를 print 했으니, 이번에는 자동으로 Build가 잘 되는지 안되는지 확인해보겠습니다.
!!!! 짜잔~ 성공했습니다. !!!!!
사실 프로젝트를 처음 생성하면 Build with Gradle이라는 name의 작업이 한개 있습니다.
- name: Build with Gradle
run: ./gradlew build
우리는 이제 master 브랜치에 push 또는 pull request를 할때마다 자동으로 빌드를 돌아줍니다.
다만 이러한 매번 빌드는 너무 오래걸립니다. 또한 무료의 github actions의 성능상 프로젝트 크기가 커지면, 하나의 빌드가 돌때 매우 오래걸리기도 합니다. 너무 싫죠?
그럴땐 캐싱을 이용해봅시다~
아래와 같이 작성해줍니다.
- name: Cache Gradle Packages
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', '**/buildSrc/**/*.kt') }}
restore-keys: |
${{ runner.os }}-gradle-
2022-12-06 기준으로 v3 버전이 최신이니, v2를 사용하게 되면 오류를 만날수도 있습니다~! (꿀팁임)
확인
이제 해당 파일을 commit하여 master 브랜치에 머지하고 Actions에 들어가보면 아래와 같이 나옵니다.
빙빙 CI가 잘 돌고 있습니다!
결과는 성공! 오른쪽 끝에는 걸린 시간도 표기됩니다만 전부 캡쳐하긴 공백이 너무 길어서 캡쳐하진 않았습니다.
쉽죠! 재밌죠! (강요아님)
이번 포스트에서는 간단한 Hello World 출력과 Build Test만 진행해봤습니다.
다음 포스트에는 더 복잡하고 어렵거나, 유용하고 쓸만한 work flow를 찾아오겠습니다.
아 그리고! 가장 중요한 공식문서에 모든 내용이 나옵니다. 양이 많으니 심심하면 읽어보시고 참고하세요! (여러 브랜치에서 사용하는법, 특정 브랜치만 빼는법 등 모든 방법이 나와있습니다)
참고
https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on
https://www.daleseo.com/github-actions-checkout/
https://velog.io/@ricky_0_k/Github-Actions-%EC%9C%BC%EB%A1%9C-Android-CICD-%EA%B5%AC%EC%B6%95%ED%95%9C-%EC%8D%B0-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EA%B8%B0-4.-on-job (요기 강추~)
'Android' 카테고리의 다른 글
Lifecycle.State와 repeatOnLifecycle에 대해서 (0) | 2023.09.14 |
---|---|
Android DeepLink 공백 (0) | 2022.12.10 |
javadoc을 이용해서 협업을 더 쉽게 해보자 (2) | 2022.11.07 |
Android API 33대응! onBackPressed()는 deprecated 된다 (1) | 2022.10.23 |
Sealed class + StateFlow (0) | 2022.10.09 |