Android build setting

Andriod 앱을 빌드하기 위해서는 당연히 android sdk가 있어야 한다.

예전엔 android sdk를 다운받을 수 있었는데, 지금은 sdk tools를 별도로 제공하고 있다. 사용하려면 명령줄에서 실행해야 한다.

필자는 jenkins를 docker로 띄워 놓은 상태였고 git repository로부터 webhook이 걸리면 gradlew명령어를 사용해서 apk를 자동으로 빌드하려는 상황이었다.

jenkins 컨테이너 내에 jenkins 사용자의 홈디렉토리는 기본으로 /var/jenkins_home에 세팅된 것을 기준으로 정리하였다.

이후에 tools/bin에 있는 sdkmanager를 실행하여 sdk들을 설치하게 되면 관련 sdk들이 tools 디렉토리의 상위 디렉토리에 위치하게 되며 해당 디렉토리를 anroid sdk 디렉토리로 사용하게 된다. 따라서 android sdk 디렉토리를 먼저 생성해 주어야 한다.

mkdir /var/jenkins_home/android-sdk

그리고 android sdk tools의 압축을 풀면 tools 디렉토리에 내용이 담겨있다. android sdk 디렉토리로 복사하였다.

cp -R tools /var/jenkins_home/android-sdk/tools

안드로이드 sdk에는 기본적으로는 platform, build tool 정도만 설치하면 앱을 빌드할 수 있다. 하지만 추가로 외부 라이브러리들을 사용한다면 해당 라이브러리들은 리포지터리에서 찾는 과정을 거치게 된다.

필자가 작업하는 프로젝트는 안드로이드 23버전을 사용하여 제작하고 있다. 그리고 외부 라이브러리들을 사용하고 있었다. 이에 필요한 sdk들을 아래의 명령을 사용하여 설치하였다.

sdkmanager \
  "platform-tools" \
  "platforms;android-23" \
  "build-tools;23.0.3" \
  "extras;android;m2repository" \
  "extras;google;m2repository"

앞의 3가지는 앱 빌드에 필요한 안드로이드 sdk들이고, 뒤의 두 개의 extras는 안드로이드와 구글 리포지터리이다. 외부 라이브러리를 사용하면서 리포지터리를 이렇게 추가해주지 않으면 gradle을 실행했을 때 라이브러리들을 찾을 수 없다고 하며 오류가 발생한다.

안드로이드 스튜디오를 사용하지 않고 빌드를 해야 하는 상황이 되다보니 처음엔 막막했지만, gradle이 오류를 친절히 알려주어서 방향을 빨리 잡을 수 있었다.

이제 sdk를 설치했으니 sdk가 어디에 있는지 알려주어야 한다.

안드로이드 프로젝트의 최상위 디렉토리에 local.properties에 다음과 같이 적어주었다.

sdk.dir=/var/jenkins_home/android-sdk
ANDROID_HOME=/var/jenkins_home/android-sdk

이제 gradlew을 실행하면 빌드에 성공한다.

Gitlab with docker and setup ssl using letsencrypt on macOS

Docker image를 생성하고 실행한다.

컨테이너의 443, 80, 22 포트는 각각 Mac의 8443, 8080, 8022로 매핑해준다. 동일한 포트로 사용하기 원하면 443:443과 같이 써주면 된다.

sudo docker run --detach \
 --hostname gitlab.example.com \
 --publish 8443:443 --publish 8080:80 --publish 8022:22 \
 --name gitlab \
 --restart always \
 --volume /Users/[username]/apps/gitlab/config:/etc/gitlab \
 --volume /Users/[username]/apps/gitlab/logs:/var/log/gitlab \
 --volume /Users/[username]/apps/gitlab/data:/var/opt/gitlab \
 gitlab/gitlab-ce:latest

Letsencrypt 인증서 생성을 위해 certbot을 설치한다.

brew install certbot

certbot을 사용하여 인증서를 만들려고 시도하였다.

sudo certbot certonly --manual -d mydomain.org

하지만 augeas 와 관련된 오류를 만났다. 퍼미션 관련 설정을 해 주었다.

sudo chown [username] /usr/local/lib/pkgconfig

다시 certbot을 실행하여 인증서 생성을 시도하였다.

sudo certbot certonly --manual -d mydomain.org

접속할 수 있는 IP인지 물어본다. y로 대답한다.

Are you OK with your IP being logged?
----------------
(Y)es/(N)o:

생성할 파일의 내용과 경로를 알려준다. 준비가 되면 엔터를 치라고 한다.

Create a file containing just this data: 293487987fd9s87s98fa798s7df7sadf987saf79dsa97afsd897dsaf987 And make it available on your web server at this URL: http://mydomain.org/.well-known/acme-challenge/fas89adfs87dasf9asdf78

-----------------------------
Press Enter to Continue

해당 경로에 파일을 만들어주어야 하기 때문에 gitlab.rb를 편집한다.

vi /Users/[username]/apps/gitlab/config/gitlab.rb

다음 줄을 추가해 준다.

nginx['custom_gitlab_server_config'] = "location ^~ /.well-known { alias /etc/gitlab/www; }"

해당 내용을 적용해 준다.

docker exec -it gitlab /bin/bash gitlab-ctl reconfigure

그리고 아래의 경로에 해당 파일을 위에서 알려준 내용으로 만들어 주었다.

vi /Users/[username]/apps/gitlab/config/www/acme-challenge/[instructed filename]

파일내용:
293487987fd9s87s98fa798s7df7sadf987saf79dsa97afsd897dsaf987

다시 certbot을 실행한 shell로 돌아가서 Enter를 누른다.

이제 /etc/letsencrypt/live/[mydomain.org]에 인증서 파일들이 생겼다. ssl 디렉토리를 생성하고 인증서를 복사한다.

cd /Users/[username]/apps/gitlab/config
mkdir ssl
cd ssl
sudo cp /etc/letsencrypt/live/[mydomain.org]/fullchain.pem ./
sudo cp /etc/letsencrypt/live/[mydomain.org]/privkey.pem ./

다시 gitrab.rb를 편집하러 간다.

vi /Users/[username]/apps/gitlab/config/gitlab.rb

다음 3개의 줄을 편집해 준다.

external_url 'https://[mydomain.org]'
nginx['ssl_certificate'] = "/etc/gitlab/ssl/fullchain.pem"
nginx['ssl_certificate_key'] = "/etc/gitlab/ssl/privkey.pem"

첫째 줄은 외부 접속 경로를 설정해 주는 것이다. 필자는 외부에서도 접속할 수 있게 하려고 하였기 때문에 개인적으로 사용하는 도메인 이름을 적어 주었다.

둘째, 셋째 줄은 인증서 파일에 대한 경로를 설정해 주는 것이다.

이제 준비가 되었다. 적용해 준다.

docker exec -it gitlab /bin/bash gitlab-ctl reconfigure

웹 브라우저를 띄우고 접속해 본다.

필자는 공유기 – MacOS – docker container(Ubuntu 16.04) 의 구조였고, 포트는 8443:8443:443이었으므로

https://[mydomain.org]:8443

으로 접속하였다. 자물쇠가 나오는 것을 확인하면 SSL이 제대로 설정된 것이다.

두서 없이 썼지만, 기억은 잘 잊혀지므로  기록하였다.

다음엔 letsencrypt 인증서 만료 기간이 3개월이니, 자동으로 갱신되도록 만들어 보아야겠다.

Bitbucket 저장소와 Jenkins Webhook 연동하기

Jenkins의 소스코드 관리에서 Bitbucket 저장소와 연동하여 사용할 수가 있다. 그런데, Webhook을 걸면 브랜치를 가리지 않고 항상 실행된다.

필자는 저장소에서 Webhook을 걸 때마다 개발용 앱과 상용 앱을 모두 빌드하게 하고 싶지 않았다. pull request가 개발 브랜치로 머지될 때에는 테스트 서버에 붙는 테스트용 앱을 빌드하고, 상용 브랜치로 머지될 때에는 실 서버에 붙는 상용 앱을 빌드하고 싶었다. 하지만 기본으로 제공되는 Webhook을 사용하면, 둘을 나누어 실행할 수 없었다.

Jenkins Plugin 중에 Generic Webhook Trigger를 사용하면 이러한 문제를 해결할 수 있다.

우선은 Jenkins Plugin에 Generic Webhook Trigger를 설치한다. 설치 후 설정을 희망하는 프로젝트의 환경설정으로 간 후 Build trigger에 있는 Generic Webhook Trigger를 찾는다. 체크박스를 클릭하면 파라미터 설정 창이 열린다.

Post content parameters에 다음과 같이 적었다.

Variable Name: MERGED_BRANCH
Expression: $.pullrequest.destination.branch.name
Filter: 비워놓음

Variable Name은 Shell에서 사용할 변수명을 의미한다. Expression은 해당하는 변수에 어떤 값을 저장할 것인지 결정한다. Value filter는 Expression으로 얻은 값 중에 필터하고 싶은 것을 정규식으로 표현해 주면 된다.

Bitbucket에서 Webhook을 걸 때 POST로 보내는 메시지는 세팅 후 Webhook이 걸렸을 때 나가는 내용을 확인할 수 있다.

그리고, 젠킨스 설정의 Build 메뉴로 가서 Execute shell에서 $MERGED_BRANCH 변수를 사용하여 처리하면 된다. 필자는 다음과 같이 원하는 브랜치인 경우에만 앱을 빌드하도록 설정해 놓았다.

if [ “$MERGED_BRANCH” = “release”]
  then
    bash ./gradlew clean
    bash ./gradlew assembleProd
  else
    echo “release branch is not updated!”
fi

이제 릴리즈 브랜치가 병합되었을 때에만 릴리즈 앱이 빌드된다.

이를 토대로 하면 개발 브랜치가 병합되었을 때에만 빌드되게 하는 것도 가능하다.

오늘은 요기까지.

똑부 상사에 대한 오해

사람들이 상사와 부하의 조합에 대해, 혹은 어떤 상사가 좋은 상사라고 생각하는가에 대한 질문에 똑똑함/멍청함, 게으름/부지런함의 네 가지 형용사를 조합하여 4가지로 표현하곤 한다.

사람들은 대체로 똑똑하고 게으른 상사를 원하는 경우가 많았다. 일에 대한 전략과 전술에는 똑똑하기를 바라고 있으며, 부하 직원에 대한 감시나 일에 대한 간섭 등 부하직원의 자율성을 침해하는 행동의 측면에서 게으른 상사를 원하고 있었다.

똑부를 싫어하는 이유 중 하나는 너무 부지런하고 일을 벌리기 쉬워서 부하직원들의 업무가 과중해질 수 있다는 것이었다. 사실 너무 부지런해서 일을 벌리는 스타일은 사실 똑부가 아니고 멍부로 보는 게 더 적합할 것이다. 똑똑하다면 자신이 하고 싶은 일과 할 수 있는 일 사이에서 명확한 경계를 세우고 일을 계획하므로 과도하게 일을 추진하지 않을 것이다.

뭐 개인적으로는 똑부가 제일 낫다고 생각한다. 때때로 적확한 지적은 개인의 역량을 보완하는데에는 최소한 보탬이 되기 때문이다.

똑부든 똑게든 간에 사람들이 싫어하는 지점은 “자율성”이 침해되는 지점에 대한 지적이었다. 우리 말에 “평양감사도 제 싫으면 그만”이라는 말이 있다. 아무리 연봉을 많이 줘도 자율성이 침해당한다면 조직몰입도와 직무몰입의 수준이 낮아진 결과 이직율 증가나 조직 생산성의 저하로 이어지는 것은 필연적인 결과이다.

부하 직원의 자율성을 존중하고, 믿고 기다려주는 것은 사실 쉬운 일이 아니지만 쉬울 수도 있다. 조직의 상황에 따라 일에 치여서 빨리 일을 처리해야 하는 상황이라면 쉽지 않을 것이다. 하지만 심사숙고한다면, 지금 재촉하는 것이 장기적으로도 일을 빨리하는 길이 아닐 수도 있다는 지점은 고려할 필요가 있다. 현명한 선택은 항상 쉽지 않다. 자신이 감내해야 할 분량이 분명이 있기 때문이다. 어떤 선택을 할 것인지는 자신의 몫으로 남아있다.