목표
GithubActions
CI/CD 파이프라인을 구축해 서버에 APK 업로드를 자동화 하자.
- 개발 프로세스의 효율성과 생산성을 극대화하기 위함.
문제의식
기존 방법의 문제점
가상화 서버에 안드로이드 어플을 업로드하기 위해서 포털을 이용하여 직접 APK 파일을 업로드 하였다.
하지만 새로운 업데이트가 있을 때 마다 변경된 사항을 Android Studio Build로 APK를 추출하고, 포털에 들어가서 업로드를 진행해야하는 번거로움이 있었다.
Github로 관리하는 코드
어플 프로젝트 코드 및 파일은 Github로 관리하고 있었다.
따라서 이 점을 활용해 GithubActions
를 이용하여 APK를 자동으로 추출하고, 추출 뿐만 아니라 서버 업로드까지 자동화하면 어떨까? 라는 생각이 들었다.
GithubActions
로 workflow
를 작성하면, 수동으로 프로젝트 apk 빌드, 업로드를 하지 않아도 되기 때문에 생산성이 더 향상될 것이라 판단되었다. → 개발에 더욱 집중할 수 있게 된다!
활용 가능한 서버 API를 탐색
관리자 포털에서 apk 업로드가 가능하다는 점에서, 사용 가능한 API가 있을 것이라 생각이 들었다.
관리자 API Docs를 찾아 본 결과 App Upload와 관련된 API를 발견할 수 있었다.
- file을 upload한 후 response로 오는 uploadFileName을 apps에 목록에 들어가도록 하는 로직이다.
이 API를 호출하여 workflow를 구축하면 자동화를 완성할 수 있을 것이라 생각이 들었다.
Github Actions의 WorkFlow 구축
workflow를 구축하기 전 Github Actions
에 대해 알아보자.
Github Actions란?
Github Actions
는 CI/CD(지속적인 통합, 배포) 도구로, SW 개발과 배포 과정을 자동화하는 데 사용된다.
Github 플랫폼 내에서 직접 호스팅되며, 사용자가 별도로 서버를 설정할 필요가 없다. YAML 파일을 통해 작업을 정의하고 구성할 수 있어서 설정이 간편하다.
Workflow YAML 파일의 구조
- Repository 내 Actions에서 볼 수 있는 Android CI 파일이다.
- 이 파일을 통해서 YAML 파일의 구조 및 의미를 살펴보자.
name: Android CI
on:
push:
branches: [ "develop" ]
pull_request:
branches: [ "develop" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: set up JDK 11
uses: actions/setup-java@v4
with:
java-version: '11'
distribution: 'temurin'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
on
on:
push:
branches: [ "develop" ]
pull_request:
branches: [ "develop" ]
- develop 브랜치의 push 또는 PR이 발생할 경우 작업을 실행하겠다는 의미이다.
jobs
jobs:
build:
runs-on: ubuntu-latest
- 실행할 작업을 정의하는 곳이다.
runs- on
은 빌드 작업이 실행 될 환경을 지정한다.ubuntu-latest
는 Ubuntu 최신 버전 환경을 사용함을 의미한다.
steps
steps:
- uses: actions/checkout@v4
- name: set up JDK 11
uses: actions/setup-java@v4
with:
java-version: '11'
distribution: 'temurin'
cache: gradle
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
- steps 아래에 실행할 작업들을 나열한다.
- 실행할 작업을 순서대로 정의하면 된다.
CI/CD Workflow 생성하기
문제의식을 바탕으로 자동화를 위한 시나리오는 다음과 같다.
1. main 브랜치의 push, PR 이벤트가 발생할 시에 Actions 실행
2. 우분투 최신환경, Java 버전 17에서 실행
3. debug-apk 추출
4. artifact에 upload 하여 debug-apk 다운로드
5. download되는 apk file 로그 찍기
6. 2가지 API 활용하여 가상화 서버에 APK 업로드하기
시나리오 1~2 : 환경 설정
name: Android build APK to Server
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest // 우분투 최신
steps:
- uses: actions/checkout@v4
- name: set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
cache: gradle // JAVA 17 실행
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew build
- on을 활용하여 main 브랜치의 push와 PR이 있을 때 작업을 실행하도록 한다.
- jobs build 환경은 우분투 최신 환경으로 설정한다.
- steps 내부에 자바 17 환경에서 실행되도록 설정한다.
시나리오 3-5 : Debug APK 빌드
- name: Build debug APK
run: |
./gradlew clean
./gradlew assembleDebug --stacktrace
- name: Display APK file location
run: |
echo "APK is located at $(pwd)/app/build/outputs/apk/debug/app-debug.apk"
- name: Upload Debug APK
uses: actions/upload-artifact@v4
with:
name: app-debug.apk
path: app/build/outputs/apk/debug/app-debug.apk
시나리오 6: HTTP API 통신
Http 통신 API를 YAML에서 어떻게 실행가능 한지 찾아보았다.
Github Actions로 HTTP API 통신
HTTP API 통신을 위해서 curl
명령어를 사용하여 요청을 보내고 응답을 처리할 수 있다.
예시 ) POST
apk 파일 업로드 API 사용
- 이 때 header에는 TOKEN, request에는 MultiPart form-data file이 들어간다.
- curl -X 로 HTTP 요청의 메서드를 지정하는 옵션을 사용한다.
- curl -X POST $API_URL/upload 로 URL을 지정한다.
- curl -H 로 헤더에 추가할 Auth Token을 지정한다.
- curl -F 로 request인 MultiPart-form-data file을 넣어준다.
- curl -o 로 서버로부터 받은 응답을 지정 파일에 저장한다.
- curl -w로 요청 후 출력할 정보를 지정한다. (http 상태코드를 지정하였다.)
- name: Upload APK to Server
env:
API_URL: ${{secrets.API_URL}}
API_LOGIN_TOKEN: ${{secrets.API_LOGIN_TOKEN}}
run: |
response=$(curl -X POST "$API_URL/upload" \
-H "Authorization: OAuth $API_LOGIN_TOKEN" \
-F "file=@app/build/outputs/apk/debug/app-debug.apk" \
-o response.txt \
-w "\n%{http_code}")
status_code=$(echo "$response" | tail -n1)
body=$(cat response.txt)
echo "Status Code: $status_code"
echo "Response Body: $body"
if [ "$status_code" -ge 200 ] && [ "$status_code" -lt 300 ]; then
echo "POST API request was successful"
else
echo "API request failed"
exit 1
fi
- 이렇게 HTTP POST upload API 를 실행하도록 YAML 파일을 작성하였다.
- 이 때 echo를 활용하여 API 통신의 응답값, Status Code를 화면에 출력하였다.
Secerets 로 민감 정보 가리기
GithubActions에서 사용하는 url, token과 같은 가려야 하는 값들은 secrets로 환경변수처럼 안보이게 할 수 있다.
따라서 $API_URL, $API_LOGIN_TOKEN은 secrets을 활용해 가린 정보이므로 $로 사용하면 된다.
이 외에도 주요 curl 옵션은 다음과 같다.
주요 curl
옵션 설명
옵션 | 설명 |
---|---|
-X , --request |
사용할 HTTP 메서드를 지정합니다. (예: GET, POST, PUT, DELETE) |
-H , --header |
요청에 추가할 HTTP 헤더를 설정합니다. |
-d , --data |
POST 요청 시 전송할 데이터를 설정합니다. 일반적으로 URL 인코딩된 형식으로 데이터를 보냅니다. |
-F , --form |
멀티파트 폼 데이터 전송을 위해 사용됩니다. 파일 업로드 시 주로 사용됩니다. (예: -F "file=@/path/to/file" ) |
-o , --output |
서버로부터 받은 응답을 지정한 파일에 저장합니다. (예: -o filename.txt ) |
-w , --write-out |
요청 후 출력할 정보를 지정합니다. (예: HTTP 상태 코드) |
-i , --include |
응답의 HTTP 헤더를 포함하여 출력합니다. |
-v , --verbose |
요청과 응답의 상세한 정보를 출력합니다. 디버깅에 유용합니다. |
-L , --location |
리디렉션이 발생할 경우 자동으로 따라갑니다. |
-k , --insecure |
SSL 인증서 검증을 생략하고 연결합니다. (보안상 권장되지 않음) |
-u , --user |
기본 인증을 위한 사용자 이름과 비밀번호를 지정합니다. (예: username:password ) |
-T , --upload-file |
로컬 파일을 서버로 업로드할 때 사용됩니다. |
-C , --continue-at |
이전 다운로드를 재개하는 데 사용됩니다. |
예제
- GET 요청:
bashcurl -X GET "http://example.com/api/resource"
- POST 요청:
bashcurl -X POST -H "Content-Type: application/json" -d '{"key1":"value1", "key2":"value2"}' "http://example.com/api/resource"
- 파일 업로드:
bashcurl -X POST -F "file=@/path/to/file" "http://example.com/upload"
- 응답을 파일로 저장:
bashcurl -o output.txt "http://example.com/api/resource"
- 리디렉션 따라가기:
bashcurl -L "http://example.com/redirect"
- 상세 정보 출력:
bashcurl -v "http://example.com/api/resource"
이렇게 Github Actions의 YAML 파일을 작성하여 Update를 진행하였다.
그 결과 Main에 Push, PR 이벤트가 발생하였을 때 해당 YAML 파일이 작업을 실행하고 APK빌드, API를 통한 앱 업로드를 진행하여 성공적으로 가상화 서버에 어플이 올라간 것을 볼 수 있었다.
이전에 Android Studio에서 Build → 관리자 포털 로그인 → 관리자 포털 apk 파일 업로드 과정보다 Android Studio에서 Main으로 Push 만으로 3가지의 과정이 자동화되어 생산성이 향상된 것을 몸소 느낄 수 있었다.
GithubActions에 API를 활용하여 자동화할 수 있다면 해당 방법을 적극 추천한다.
'Android > 프로젝트 개발' 카테고리의 다른 글
[Android] implemantation을 Version Catalog로 바꿔보자 (0) | 2024.12.12 |
---|---|
[Android] Menu 데이터는 어디에 저장하는 게 성능이 좋을까? (RoomDB vs Object) (0) | 2024.12.05 |
[Android] PDF 뷰어 띄우기 / Activity 내에 PDF 뷰어 넣기 feat. 파일관리 (0) | 2024.09.20 |
[Android/JAVA] Zxing 활용 바코드/QR 스캐너 구현하기 (0) | 2024.08.07 |
[Android] Retrofit에서 XML 데이터 통신 및 파싱 방법 / RecyclerView XML 데이터 받아오기 (0) | 2024.02.26 |