새 인스턴스로 확장 이전과 후기

이번 연휴(2018. 12. 22 ~ 2018. 12. 25) 동안 지금까지 운영해오던 UzukiLive 서버를 확장이전 하여 새롭게 환경을 구축하게 되었습니다.

기존 인스턴스와 문제점

기존 환경은 이렇게 설정되어 있습니다.

  • Vultr VC2 1core 2GB (UzukiLive 인스턴스) -> 블로그, nextcloud. 도커로 되있지 않음
  • Vultr VC2 2core 4GB (Artifactory 인스턴스) -> Artifactory, Jenkins. 도커로 되어있음

그리고 메일 서버의 경우 Zoho 플랫폼을 빌려 사용하였고, 처음에 삽질을 너무 크게 한 나머지 uzuki.live 로 접속하면 SSL 에러가 발생하곤 했습니다.
그 외 문제점이라고 하면 FTP를 쉽게 사용할 수 없거나, 너무 설정이 여기저기 있어 확장하려고 해도 쉽지 않았습니다. (오죽하면 인스턴스를 두개 생성해서 관리를 했지만요… (._. )

당연히 비용도 비용이니 좋지 않은 사양에 월 30달러나 지불해야 한다는 것은 이해가 가지도 않긴 합니다.

따라서 이번 연휴때 계획을 잡고 신규 인스턴스에 전부 이전하기로 결정했습니다.

신규 인스턴스

신규 인스턴스는 Vultr의 VC2 4core 8GB, 100GB SSD 입니다. 이전 사양보다 약 2(Artifactory 인스턴스 기준) ~ 4(UzukiLive 인스턴스 기준)배 이상 사양이 증가하였습니다.

사양을 대폭 올린 이유로는 Jenkins 때문인데, 2core 4GB 사양에서 gradle 빌드를 두 개 이상 돌리는 순간 컨테이너가 메모리 부족으로 죽어버리는 대참사가 발생하여, 빌드를 두 개 이상 동시에 돌리더라도 문제가 없도록 구성하였습니다.

신규 인스턴스는 모든 요소가 Docker에 의해 관리되는 Dockerize 환경을 사용할 것이고, 아래 범주로 서비스를 관리할 예정입니다.

  • Reverse Proxy -> nginx
  • Stack: Infra -> adminer, pure-ftpd, docker-telegram-notifier
  • Stack: Blog -> MariaDB + WordPress
  • Stack: Build-Automation -> Jenkins, Artifactory
  • Stack: Mail -> docker-mailserver(IMAP/SMTP) + rainloop (Web UI)
  • Stack: Intro -> uzukilive-intropage
  • Stack: Octobox -> Octobox + Redis + PostgreSQL

그러면, 각 범주마다 설명을 약간 추가하면서 기능을 소개하려 합니다.

Reverse Proxy + SSL

기존 UzukiLive 에서도 사용했던 Nginx를 사용하고, 여기에 LetsEncrypt를 이용하여 모든 외부용 서비스에 SSL를 제공할 계획입니다.

보통 nginx-proxy + letsencrypt-companion 조합으로 사용하지만 이 조합의 경우 docker 소켓에 붙어 일정 시간마다 스캔을 해서 추가하는 방식으로 되어있어, 그거보다는 좀 더 귀찮지만 하나의 설정 파일(conf)로 존재하는 것이 좋다고 생각되었습니다.

따라서 새 서비스를 연동할 때 마다 아래의 명령어를 통해 인증서를 발급받았습니다.

docker run -it --rm -v /data/cert:/etc/letsencrypt -v /data/cert-data:/data/letsencrypt certbot/certbot certonly --webroot --webroot-path=/data/letsencrypt -d uzuki.live

저 방법을 사용하기 위해서는 일정의 예제 conf 파일을 만들어 nginx를 가동시킬 필요가 있는데, 샘플 nginx 파일을 만들고 DONAME_NAME 만 교체해서 생성하도록 했습니다.

server {
    listen      80;
    listen [::]:80;
    server_name uzuki.live;

    location / {
        rewrite ^ https://$host$request_uri? permanent;
    }

    location ^~ /.well-known {
        allow all;
        root  /data/letsencrypt/;
    }
}

Stack: Infra

여기에는 3개의 서비스가 들어가는데, adminer 는 MySQL/MariaDB의 정보를 보거나 수정할 수 있는 프로그램으로 phpmyadmin 대체용입니다

그 다음으로 pure-ftpd는 FTP 서버로 /home/pyxis 경로에 접근하여 데이터를 주고 받을 수 있게 설정했습니다.

마지막으로 docker-telegram-notifier 는 미리 만들어둔 Telegram bot로 컨테이너의 시작/중지 등의 상태를 보내줍니다.

가령 Jenkins가 시작되었다면 아래의 메세지를 보내줍니다.

Started container jenkins
Image: windsekirun/jenkins-android-docker:1.0.2
Container ID: ae8f526e8b42d216146fb68ee49f6506631259780f3c75195718786da6245cb6
오늘도 약 400개의 메세지를 받아내는 우즈키(..)

Stack: Blog

여기에는 2개의 서비스가 들어가는데, 워드프레스와 그 DB로 MariaDB를 선택했습니다. 기존 인스턴스에는 MySQL로 되어있고, 이 데이터를 그대로 가져갈 필요가 있었습니다.
따라서 PostgreSQL 보다는 MariaDB를 선택했습니다.

주소는 기존의 blog.uzuki.live 에서 pyxispub.uzuki.live 로 변경했는데, 기존 주소로 들어가면 새로운 주소로 리다이렉션 되도록 기존 인스턴스의 nginx 단을 수정했습니다.

기존 인스턴스는 2주 뒤인 1월 11일쯤에 제거될 예정입니다.

Stack: Build-Automation

여기에는 2개의 서비스가 들어가는데, 각각 Gradle Repository용 Artifactory와 Jenkins가 들어갑니다. 이 두개 서비스에 대해서는 일전 블로그 글로 설명한 적이 있으므로 별도로 설명할 것은 없다고 생각됩니다.

다만 아주 잉여롭지만 봇을 만든 겸에 빌드 시작 / 결과를 알려주는 별도의 Jenkins 호환용 그루비 스크립트를 작성해서 적용했습니다

Stack: Mail

기존 메일([email protected]) 는 Zoho Mail에서 수신/발신하도록 되어있어 내 것이 아니기도 한 존재였습니다.
따라서 이번 인스턴스에는 IMAP/SMTP 서버를 직접 구축하여 메일을 수신/발신할 수 있도록 설정하였습니다.

…다만, vultr가 SMTP 포트인 25번을 막아버리는 바람에 일단은 Gmail에 의존하여 발신하도록 설정하였으나 좀 더 Postfix를 공부하여 수정할 계획입니다.

메인 화면
글쓰기 화면

웹 메일 UI는 rainloop를 사용하였고, 특출나게 UI가 세련된 건 아니지만 나름대로 들어갈 기능은 전부 포함되어 있습니다.

Stack: Intro

물론 반응형입니다.

CSS Toolkit인 타키온(https://tachyons.io/) 을 이용하여 5~10분만에 대충 만든 인트로 페이지로, 이 서버에서 제공하는 서비스의 링크와 Github, Telegram, Contact 링크를 포함합니다.

물론, 이 인트로 페이지(라고 해도 HTML 1개 + CSS 1개) 도 docker 이미지를 만들어서 제공했으며, 도커 이미지는 https://github.com/WindSekirun/uzukilive-intropage 입니다.

Stack: Octobox

Octobox 라고 하는 Github의 알림을 관리하는 서비스가 있는데, 이 서비스가 self hosted로 하면 프라이빗 프로젝트까지 포함되어 설치하게 되었습니다.

이 서비스의 자세한 설명은 공식 홈페이지 (https://octobox.io/) 를 들어가는 것이 편리합니다.

마무리

일전에도 Jenkins나 Artifactory를 도커로 활용하고 있었지만 이번 기회를 통해 도커를 통한 관리가 얼마나 확장성과 자유성을 가져주는지 깨달았습니다.

개인 목적으로는 나름대로 규모가 있고, 따로 설치하라고 한다면 아마 멘탈 여러번 나가서 쉽게 던졌을텐데, 명령어 한 두줄 만으로 모든 것을 설정할 수 있다는 것이 큰 장점인 것 같습니다.

컨테이너가 14개가 되다보니 docker-compose로 각 스택별로 모아 필요한 스택만 켜고 끄고 할 수 있게 설정해두니, 패치할 때도 다운타임이 5~10분 내로 할 수 있다는 것도 좋았습니다.

열심히 가동되는 컨테이너(들)

그러면, 새로운 인스턴스와 새로운 환경에서 남은 6일, 앞으로 다가올 2019년에도 PyxisPub와 이 주인장(._. … )을 잘 부탁드립니다.

Run Docker + Jenkins for Android Build

이번 글에서는 Vultr VC2 2core 4GB instance 에 Jenkins 를 올려 안드로이드 앱을 빌드하고 테스트하려 한다.

사용할 인스턴스는 기존에 사용중이던 Artifcatory 인스턴스이지만 사양을 올려 사용할 것이기 때문에, Docker 기본 설정 같은 것들은 이전 글인 ‘Upload Android Library into Gradle with Artifactory‘ 를 참조하면 된다.

DockerFile 커스텀하기

대부분 인터넷에 나온 CI/CD 적용기를 보면 이 단계부터 설명하는 글이 많은데, 처음 도커를 접하는 유저라면 상당히 골치아픈 작업이기도 하다. Dockerfile 자체가 자체 포맷으로 되어있기도 해서 그걸 익혀야 되는 문제점이 있다.

그리고 이번 글의 중점 취지는 아닌 것 같아 제작했던 Dockerfile 를 공유해서 바로 적용할 수 있게 했고, 그것이 WindSekirun/Jenkins-Android-Docker 이다.

DockerHub에도 공유되어 있으니, 바로 pulling 를 받으면 최신 안드로이드 환경 (API 28 + build tools 28.0.3) 을 사용할 수 있게 된다.

따라서 이번 글에서는 미리 제작된 도커 이미지로 이 과정을 대체한다.

먼저 실행되야 될 작업

본격적으로 이미지를 풀링 받기 전에, 이 이미지를 실행하기 위한 커맨드를 살펴볼 필요가 있다. (버전 1.0.1 같은 경우 2018-12-18 기준 최신으로, 가장 최신은 릴리즈 페이지를 참고하면 된다.)

sudo docker run -d -p 8080:8080 -p 50000:50000 -v /data/jenkins-android-docker:/var/jenkins_home windsekirun/jenkins-android-docker:1.0.1

여기에서 -d (백그라운드 작업) 과 -p(포트 바인딩) 은 넘겨도 되나 /data/jenkins-andorid-docker:/var/jenkins_home 부분에 신경을 써야 한다. 이 부분은 ‘실제 저장소내 공간:도커 컨테이너 공간’ 의 형식을 가지고 있는 디렉토리 바인딩 부분으로, 실제 저장소내 공간 부분에 작성한 폴더는 실제 존재하는 폴더여야 한다.

따라서 sudo 권한으로 아래 커맨드를 실행하면 된다.

mkdir /data/jenkins-android-docker
sudo chown -R 1000:1000 /data/jenkins-android-docker

이 ‘실제 저장소내 공간’에 모든 데이터가 들어가므로, 도커 컨테이너를 지워도 이 폴더가 남아있다면 데이터 또한 그대로 보존되게 된다.

위 mkdir 와 chown 을 시작했다면, 맨 위의 shell script 를 실행하면 된다.

귀찮은 사람들은 WindSekirun/Jenkins-Android-Docker 를 VPS 안에서 clone 받아서 sudo sh runImage.sh 를 실행하면 된다. mkdir 부터 docker run 까지 다 된다.

처음 관리자 설정하기

명령어로 도커를 시작했다면, 서버 주소:8080 으로 들어가면 Jenkins home 이 보일 것이다.

Jenkins 를 설정하는 사람이 관리자인지 확인하는 과정인데, 이를 확인하기 위해서는 도커 컨테이너에 접근할 필요가 있다.

SSH 에서 docker container ls 를 입력하면 현재 실행중인 컨테이너 정보가 나오는데, 그 곳에서 Jenkins-Android-Docker 를 찾는다.

위 정보에 따르면 jenkins-android-docker 가 설치된 컨테이너의 id는 d88376885153 이고, 이 컨테이너 id를 이용해 도커 컨테이너의 bash로 접근할 수 있다. 명령어는 docker exec -i -t [컨테이너 id] /bin/bash이다.

bash에 접근했으면 cat /var/jenkins_home/secrets/initialAdminPassword 로 도커 초기 관리자 비밀번호를 알아낸다.

아래 비밀번호를 복사해서 칸에 넣고 Continue 를 누르면 된다.

그 다음 Plugin 창이 나올텐데, 그 곳에서 Install Suggested Plugin를 누른다. 차후에 다시 설치가 가능하니, 지금은 기본만 설치한다.

설치가 다 되고, 관리자 계정을 만들면 Jenkins 를 사용할 준비가 모두 끝난다. 이제 blueocean 플러그인을 설치하여 첫 안드로이드 빌드를 해보도록 한다.

Blueocean 설치하기

Blueocean 은 Jenkins 에서 나온 새 UI/UX 툴로, 기존 Jenkins 가 다소 전문가의 영역에 가깝다고 하면 Blueocean 는 이를 좀 더 간결하고 알아보기 쉽게 만든 것이다.

Jenkins 메인에 접속되면 Manage Jenkins > Manage Plugin > Available 의 검색창에서 Blueocean 을 검색한다.

여기에서 Install without restart 를 누르면 플러그인 설치 페이지로 이동하는데, 여기에서 맨 마지막의 체크박스를 체크해서 바로 재시작될 수 있도록 한다.

여기까지 끝내면 첫 안드로이드 프로젝트를 빌드를 할 모든 준비가 완료된다.

프로젝트 빌드하기

다시 젠킨스 메인으로 돌아와서 옆의 Open Blueocean 을 누른다. 그러면 이제까지 보지 못했던 새로운 Jenkins 가 보이게 된다.

여기에서 ‘Create a new Pipeline’ 를 누른다.

프로젝트 저장소를 선택하고, 가져올 프로젝트를 맨 밑에서 설정한다. 만일 해당 프로젝트에 Jenkinsfile 가 없다면 설정하는 메뉴로 갈 것이고, 이미 있다면 바로 빌드를 시도할 것이다. 이번에는 Jenkins 로 연동해보지 않은 프로젝트를 설정했다.

그러면 이 페이지로 나오게 될텐데, 이 곳이 Jenkins 가 한 빌드당 거칠 파이프라인을 설정하는 곳이다. 가운데의 +를 누르게 되면 새 작업을 추가할 수 있다.


일단 여기에서는 간단히 빌드만 성공하는지 테스트할 것이므로, Add step 에서 Shell script 를 선택하고 ./gradlew assembleDebug --stacktrace를 입력해준다.

그 다음 위 Save를 누르면 파이프라인 저장 다이얼로그가 표시되고, Save&run 을 누르면 바로 빌드가 시작된다.

빌드 지켜보기

이제 프로젝트가 빌드될 때 까지 기다리는 것 만 남았다.

만일 오류가 나온다면 왜 오류가 나오는지 이제 구글링을 열심히 해볼 차례다. 아래는 지금까지 겪은 CI 오류를 정리해본 것이다.

흔한 오류

local.properties (No such file or directory)

assembleDebug 전에 ‘echo “sdk.dir=/opt/android-sdk-linux” >> local.properties’ 를 추가한다. 또는 젠킨스 관리 > Configure System > 맨 하단의 Android SDK Path 에 /opt/android-sdk-linux 를 적어준다.

File google-services.json is missing.

이 글을 참고하되 Environment Variable 를 Jenkins 내부에서 설정해주면 된다.

그리고 추가할 Shell script 는 echo $GOOGLE_SERVICES_JSON | base64 --decode --ignore-garbage > /app/google-services.json“` 이다.

Gradle build daemon disappeared unexpectedly

제일 골치아픈 문제로, 서버의 램 용량이 부족해서 Gradle 데몬이 죽는 현상이다. 이를 해결하기 위해서는 빌드 커맨드를 ./gradlew --no-daemon assembleDebug --stacktrace 로 설정하거나, 아니면 아예 메모리 제한을 거는 방법도 있다.

메모리 제한을 거는 방법은 현재 실행중인 컨테이너를 docker container kill [컨테이너 id]  – docker container stop [컨테이너 id] 로 삭제하고 (데이터는 상기했듯이 남아있다.) 컨테이너 실행할 때 -m 2500m 를 삽입한다. 2500m은 2.5g로 k, m, g 가 사용이 가능하다. 자신의 서버 환경에 맞게 적절히 조정하면 된다.

예제: sudo docker run -d -m 2500m -p 8080:8080 -p 50000:50000 -v /data/jenkins-android-docker:/var/jenkins_home windsekirun/jenkins-android-docker:1.0.1

빌드 성공

CI상 오류를 전부 해결하면 빌드 성공이 나오며, 이제야 첫 프로젝트의 빌드가 끝난 셈이다. 이제 다른 프로젝트를 연동하거나, 좀 더 심화해서 유닛 테스트나 마켓 업로드 기능 들을 구현하면 된다.

마지막으로 위 프로젝트의 빌드에 성공한 JenkinsFile는 다음과 같다. 다른 프로젝트의 루트 폴더에 똑같은 파일 이름으로 만들고 Jenkins 에서 추가하면 바로 인식이 된다.

pipeline {
  agent any
  stages {
    stage('Make Environment') {
      parallel {
        stage('Touch local.properties') {
          steps {
            sh 'echo "sdk.dir=/opt/android-sdk-linux" >> local.properties'
          }
        }
        stage('Touch google-services.json') {
          steps {
            sh 'echo $GOOGLE_SERVICES_JSON | base64 --decode --ignore-garbage > demo/google-services.json'
          }
        }
        stage('Display directory') {
          steps {
            sh 'ls -la'
          }
        }
      }
    }
    stage('assembleDebug') {
      steps {
        sh './gradlew --no-daemon assembleDebug --stacktrace'
      }
    }
  }
  environment {
    GOOGLE_SERVICES_JSON = ''
  }
}

Upload Android Library into Gradle with Artifactory

Bintray 를 서비스하는 JFrog 에서 아키펙트 패키지(Gradle 나 maven, docker 등 저장소)를 관리하는 소프트를 제작하는데, 그것이 바로 Artifactory 이다. 그 중 Pro 버전은 유료지만, oss라 하여 오픈 소스 버전 (즉 커뮤니티 버전) 이 있는데, 이 것을 사용해서 자체적인 Gradle 저장소를 만들 수 있다.

이 글에서는 VPS 환경에서 자체적인 Gradle 저장소를 만들고, 배포하는 방법을 작성하려 한다.

주의할 점으로, 이 글에서는 Docker 설치나 환경 설정에 대해 언급하지는 않는다.

서버 환경

Vultr Cloud Compute의 $10 서버, 즉 40GB SSD / 2GB RAM / 2TB Bandwidth / 1 CPU(Skylake CPU) 를 사용헀고, OS 는 Ubuntu 18.04.1 LTS 이다.

추가적으로, Artifactory 를 안정적으로 Serve 하기 위해 Docker, PostgreSQL 를 사용했다.

Docker-compose 준비

Artifactory 도커 이미지에는 standalone 으로 돌아갈 수 있게 하는 프로그램이 들어가 있기 때문에, 아래의 명령어 1줄이면 쉽게 구동할 수 있다.

docker run --name artifactory -d -p 8081:8081 docker.bintray.io/jfrog/artifactory-oss:latest  

다만 이 방법은 여러 설정을 하려면 명령어가 길어지고, 여러 개의 컨테이너를 동시에 사용해야 될 경우 각각 하나마다 동작 상태를 확인해야 하는 문제가 있어 Docker-compose 를 사용하여 임의의 설정 파일을 만들고 설정 파일을 docker 에 올리는 방법을 사용한다.

여기서 Docker-compose 란 여러 개의 컨테이너를 한 데에 묶어 컨테이너를 순차적으로 생성하는 역할을 한다. Artifcatory 를 구동하기 위해서는 Artifactory 컨테이너와 DB 역할이 되는 PostgreSQL 컨테이너가 필요하기 때문에, 일일히 run 으로 돌리기 보다는 Docker-compose 를 이용해 한번에 관리하려 한다.

다행히도, JFrog가 Github 에 Docker-compose 예제 파일을 올려두어 모든 것을 다 작업할 필요는 없지만, 위 서버 환경에서 적용했을 때 문제가 있어 아래에 정리하려 한다.

Artifactory 구동에 필요한 환경 설정

구동에 필요한 환경 설정 작업은 다음과 같다.

  • 데이터 폴더 생성
  • 기본 설정 파일 복사
  • 권한 설정

데이터 폴더 생성

# mkdir -p /data/postgresql
# mkdir -p /data/artifactory/etc
# mkdir -p /data/nginx/conf.d
# mkdir -p /data/nginx/logs
# mkdir -p /data/nginx/ssl

sudo 권한으로 접근해 위 명령어를 실행하면 된다.

기본 설정 파일 복사

기본 설정 파일에 대해서는 Jfrog/artifactory-docker-examples에 전부 포함되어 있다. 기본 설정 파일 자체를 수정할 필요는 없으니 각각 맞는 경로에 복사하면 된다. 기본 설정 파일의 경로는 이쪽이다.

  1. /data/artifactory 폴더에 access 폴더 안 내용을 삽입한다. 즉, /data/artifactory/access/etc/keys 에 private.key, root.crt 가 있어야 한다.
  2. /data/nginx/conf.d/oss 폴더에 artifactory.conf 를 삽입한다.

권한 설정

Artifactory 6.2.0 부터 artifactory 라는 유저를 생성하여 그 유저만 /data/artifactory 폴더를 접근할 수 있게 변경되었다.

# chown -R 1030:1030 /data/artifactory
# chown -R 104:107 /data/nginx

sudo 권한으로 접근해 위 명령어를 실행하면 된다. 여기서 1030, 104 및 107은 미리 정의된 값으로 사용자에 맞게 수정하면 될 것 같다.

Docker-compose 파일 작성

일반적 문법은 여기서 설명하지 않으나, 기본적인 것을 설명하자면 Docker-compose 의 설정 파일은 yml 확장자를 가지고 있으며, 각 depth 에 컨테이너 이름과 그 정보를 넣는다. 자세한 문법은 Docker-compose version 2 reference 문서를 참고하면 된다.

version: '2'
services:
  postgresql:
    image: library/postgres:latest
    container_name: postgresql
    ports:
     - 5432:5432
    environment:
     - POSTGRES_DB=artifactory
     # The following must match the DB_USER and DB_PASSWORD values passed to Artifactory
     - POSTGRES_USER=artifactory
     - POSTGRES_PASSWORD=password
    volumes:
     - /data/postgresql:/var/lib/postgresql/data
    restart: always
    ulimits:
      nproc: 65535
      nofile:
        soft: 32000
        hard: 40000
  artifactory:
    image: docker.bintray.io/jfrog/artifactory-oss:latest
    container_name: artifactory
    ports:
     - 80:8081
    depends_on:
     - postgresql
    links:
     - postgresql
    volumes:
     - /data/artifactory:/var/opt/jfrog/artifactory
    environment:
     - DB_TYPE=postgresql
     # The following must match the POSTGRES_USER and POSTGRES_PASSWORD values passed to PostgreSQL
     - DB_USER=artifactory
     - DB_PASSWORD=password
     # Add extra Java options by uncommenting the following line
     #- EXTRA_JAVA_OPTIONS=-Xmx4g
    restart: always
    ulimits:
      nproc: 65535
      nofile:
        soft: 32000
        hard: 40000

위 코드를 artifcatory-oss-postgres.yml 라는 이름으로 만들어 서버에 올리면 된다.

Docker-compose 실행

환경 설정도 완료되고, yml 파일도 만들었다면 이제 실행만 하면 된다.

sudo docker-compose -f artifactory-oss-postgresql.yml up -d

위 명령어를 실행하면 postgresql 이미지 와 artifactory 이미지를 pulling 하여 자동으로 받아오고, 실행을 시작한다. up 뒤 -d 옵션을 주는 것으로 사용자가 종료하지 않는 이상 이 컨테이너는 백그라운드에서 계속 구동될 것이다.

이제, 브라우저 등으로 http://localhost 에 접속하면 아래와 같은 창이 나올 것이다.

사진에선 나오지 않아 설명하기 어려우나 처음에 들어가면 초기 설정 팝업이 뜨면서 비밀번호 설정 – 프록시 설정 – 사용 저장소 설정 순서로 나오게 되는데, 프록시 설정은 넘겨도 무방하며, 사용 저장소는 ‘Gradle’ 와 ‘Maven’ 을 선택한다.

여기까지 하면 Gradle 저장소에 대한 구축은 모두 된 것이며, 이제 스튜디오로 넘어와 라이브러리를 업로드하면 된다.

라이브러리 업로드

라이브러리를 업로드하는 것은 다소 어렵지 않게 구성이 가능하다. 업로드 플러그인을 추가하고, 정보를 기재해 명령어를 실행하는 것 뿐이다.

업로드 플러그인 추가

루트 프로젝트의 build.gradle 에 아래 classpath 를 추가한다.

//Check for the latest version here: http://plugins.gradle.org/plugin/com.jfrog.artifactory
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4+"

라이브러리 프로젝트의 build.gradle 에 플러그인을 적용한다.

apply plugin: "com.jfrog.artifactory"
apply plugin: 'maven-publish'

프로젝트 정보 기재

플러그인을 정의한 곳 밑에 변수를 추가한다.

def groupId = "com.github.windsekirun"
def version = "1.0.0"
def artifectId = "AwesomeLibraryForDebug"

def Properties properties = new Properties()
properties.load(project.rootProject.file("local.properties").newDataInputStream())

groupId, version, artifectId 는 각각 그룹, 버전, 아키펙트 이름을 나타낸다. gradle 의존성 문구의 규칙 또한 그룹:아키펙트 이름:버전 이므로 위 정보를 가지고 올리면 com.github.windsekirun:AwesomeLibraryForDebug:1.0.0 이 된다.

그 다음 줄의 Properties 의 경우에 저장소에 올리기 위해 아이디 / 비밀번호를 적어야 하는데, 개인 정보가 코드에 올라가야 되지 않게 해야 하므로 local.properties 에서 불러오도록 코드를 추가하였다. 이와 관련된 자세한 사항은 Insert resValue in gradle file 글에서 볼 수 있다.

플러그인 설정

위에서 프로젝트마다 별도로 설정해야 하는 정보는 모두 기재했으므로, 아래부터는 공통 정보이다.

publishing {
    publications {
        aar(MavenPublication) {
            groupId packageName
            version = libraryVersion
            artifactId projectName

            // Tell maven to prepare the generated "*.aar" file for publishing
            artifact("$buildDir/outputs/aar/${project.getName()}-release.aar")
        }
    }
}

artifactory {
    contextUrl = 'ARTIFACTORY URL'
    publish {
        repository {
            // The Artifactory repository key to publish to
            repoKey = 'libs-release-local'

            // personal information will locate at local.properties
            username = properties.getProperty("artifactory.username", "")
            password = properties.getProperty("artifactory.password", "")
        }
        defaults {
            // Tell the Artifactory Plugin which artifacts should be published to Artifactory.
            publications('aar')
            publishArtifacts = true

            // Publish generated POM files to Artifactory (true by default)
            publishPom = true
        }
    }
}

위 코드를 dependencies 문단 밑 (즉 맨 하단)에 넣어주면 된다.

명령어 실행

./gradlew assembleRelease artifactoryPublish

모든 작업이 완료되면, 위 커맨드를 터미널에 실행함으로서 Gradle 저장소에 올라가게 된다.

올라간 정보는 Artifactory 페이지 내 Artifacts 부분에서 찾아볼 수 있다.

위 사진과 같이 aar 와 pom 파일이 같이 올라가고, aar 파일을 클릭했을 때 Dependency Declaration 부분에 정상적으로 나오면 성공이다.

다른 프로젝트에서 불러오기

다른 프로젝트에서 불러오기 위해서는, 모듈의 build.gradle 에 아래 코드를 삽입하면 된다.

repositories {
    maven { url "ARTIFACTORY_URL/list/libs-release-local/" }
}

dependencies {
    implementation "com.github.windsekirun:AwesomeLibraryForDebug:1.0.0"
}

참고로 여기서 예제로 들은 AwesomeLibraryForDebug 는 존재하지 않으므로 시도하지 않아도 된다.