본문 바로가기

Tip

[gitlab-ci] (주먹구구식) 수정된 파일만 maven build (docker)

기존 운영되던 프로젝트에 소스파일 전체를 빌드해서 올리는 것은 문제가 있다고 판단하였다..

한개씩 파일을 고쳤을수도 있으니깐..

 

그래서 내가 수정한 파일만 gitlab-ci로 빌드해서 artifact로 뽑아내야겠다고 생각했다.

 

이미 docker기반 gitlab-ci.yml 운영하던터라 yml만 잘하면 되겠지라고 넘겨버렸다..

 

포괄적으로 구현순서는 

1) 전체 소스를 빌드

2) 내가 수정한 파일만 추출

3) artifact.zip으로 gitlab에서 다운로드

 

첫번째 문제, 전체 소스를 빌드

 

처음 gitlab-ci.yml를 사용해보았고 다른 프로젝트에 있는 yml을 많이 참고하였다..

새로 gitlab project를 생성하여 진행하였다. 허나 gitlab에서 편하게 제공해주는 autoDevOps가 문제였다..

 

물론 job이 많아 테스트가 좋아보였다.. 그냥 수정한 파일만 추출하고 싶었다.

autoDevOps를 off하니 gitlab-ci를 푸쉬해도 job이 생성되지 않았다.

 

그래서 결국 autoDevOps없이 진행하기 위해서 gitlab root로 접속해 생성되는 프로젝트에 default autoDevOps를 disable해버렸다..

 

결국, 

docker기반으로 maven image를 통해 빌드하고 artifact를 뽑아내는 것은 생각보다 편안하게 되었다.

 

 

두번째 문제, 수정된 파일의 디렉토리+파일명 형태로 목록이 필요하다.

 

gitlab api를 보면 웬만한 걸 지원해주어서 수정목록을 어떤 형식으로든지 가져올 수 있을지 알았다..

역시나 모든 일을 쉽게 보아선 안된다..

 

일단 docker 컨테이너 안에서 이루어진다는 것을 역시나 잊고 있었다..

local에도 git이 있으니 git명령어를 통해 현재 commit된 수정 목록을 가져올 수 있었다.

 

git diff-tree --no-commit-id --name-only -r [commitId]

 

따라서, gitlab-runner라고 해야할지 gitlab-ci라할지 아무튼 컨테이너 안에서도 git 동작하는 것을 확인했다..

 

 

세번째 문제, 쉘스크립트

 

전체소스를 빌드하고 수정된 파일의 목록을 통해 추출하는 것인데..

스크립트를 모른다. 구글링해서 배열에 넣고 for문을 찾아가면서 했다.

.yml after_script에 넣기전에 sample로 스크립트를 만들고 실행권한 주어서 실행해보면서 테스트를 했다.

 

수정된 파일 목록이 text로 된 것을 배열로 변경하고

파일 목록은 원래소스디렉토리 경로이기에 exploded된 폴더의 경로로 변경해주어야 했다..

 

src/main/~~~ >> WEB-INF/classes~ 

.java 는 .class로 변경 등등

 

자체서버에서 curl --output artifacts.zip ~~ (gitlab api 참조) 하면 artifact.zip을 받을 수 있다.

받은 zip파일로 테스트를 해보니 추출하는 것까지 확인!

 

네번째 문제, 추출한 파일을 디렉토리 포함한 상태의 artifact.zip 다운로드

 

처음에는 전체 빌드한 zip도 필요하니 놔두고 별도로 추출한 zip을 내 서버로 옮겨야겠다 생각했다..

하지만 docker기반이라 package를 설치해야했다. gitlab-ci & gitlab-runner에 zip, unzip, vi, jq등등...

 

참고:

jq 리눅스에서 curl로 response 받은 json을 다룰 수 있다.

gitlab api를 통해서 받은 json을 가공해서 원하는 값(수정 목록, commitId)만 추출하려고 했었다.

 

container안에서는 jq가 동작 안하는 것이다..

정확히는 모르겠지만 maven image가 빌드 후 gitlab 어느 repository로 마운팅 된다고 생각했다.

그러니 maven이 아닌 컨테이너에 pack을 설치해도 안되네?하면서 결론냈다..

 

pack 설치를 위해서 maven image를 새로운 img로 빌드해서 하면 될 것 같았지만 하지 않았다..

 

결국,

temp_target 폴더를 생성, 전체 소스 target 폴더 삭제

temp_target을 target으로 이름 바꿔주고

artifact는 기존 기능이니 경로만 맞추어주면 동작할 것으로 판단

 

몇일 고생했다.. 기존 선임자는 svn을 통해 추출하는 애플리케이션을 만들었다(대단..)

하지만 난 gitlab에서 통합관리를 위해(프로젝트 별도 2개) 시작했다..

 

개선해야할 점은 아직 남아있는 것 같다..

큰 비즈니스로직 수정요청이 없어서 한동안은 사용하다가 점점 개선해야겠다..

수정사항이 없을시에는 전체소스파일로 대체한다던지 추가해야함..

 

gitlab-ci.yml

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
image: docker:latest
 
stages:
- build
 
maven-build:
stage: build
image: maven:3.6.3-openjdk-8
tags:
- builder
except:
- production
before_script:
- echo "Hello Maven!"
script:
- mvn package -Dmaven.repo.local=$CI_PROJECT_DIR/.m2/repository -Dmaven.test.skip=true
cache:
key: binaries-cache-$CI_COMMIT_REF_SLUG-$CI_COMMIT_REF_SLUG
paths:
- $CI_PROJECT_DIR/.m2
after_script:
- recentCommitId=$(git log --pretty=format:"%h" -1)
- filesDirArr=$(git diff-tree --no-commit-id --name-only -r $recentCommitId)
- DIRLIST=( ${filesDirArr} )
- echo "Target Modified files >>> ${DIRLIST[*]}"
- mkdir temp_target
- echo ">>>>>>>>>>>>>>>>>>>>>>>>> create Temp folder"
- ls -l
- >
for item in ${DIRLIST[*]}
do
if [[ "${item}" == *"src/main/java"* ]]; then
convertDir=${item/src\/main\/java/target\/[project name]\/WEB-INF\/classes}
baseDir=./${convertDir/.java/.class}
fileName=$(basename $baseDir)
copyDir=./${baseDir%%$fileName*}
tempDir=${copyDir/target/temp_target}
 
echo "baseDir >>> ${baseDir}"
echo "fileName >>> ${fileName}"
echo "copyDir >>> ${copyDir}"
echo "tempDir >>> ${tempDir}"
 
mkdir -p ${baseDir%%$fileName*} ${tempDir}
cp ${baseDir} ${tempDir}
elif [[ "${item}" == *"src/main/resources"* ]]; then
baseDir=${item/src\/main\/resources/target\/[project name]\/WEB-INF\/classes}
fileName=$(basename $baseDir)
copyDir=./${baseDir%%$fileName*}
tempDir=${copyDir/target/temp_target}
 
echo "baseDir >>> ${baseDir}"
echo "fileName >>> ${fileName}"
echo "copyDir >>> ${copyDir}"
echo "tempDir >>> ${tempDir}"
 
mkdir -p ${baseDir%%$fileName*} ${tempDir}
cp ${baseDir} ${tempDir}
elif [[ "${item}" == *"src/main/webapp"* ]]; then
baseDir=${item/src\/main\/webapp/target\/[project name]}
fileName=$(basename $baseDir)
copyDir=./${baseDir%%$fileName*}
tempDir=${copyDir/target/temp_target}
 
echo "baseDir >>> ${baseDir}"
echo "fileName >>> ${fileName}"
echo "copyDir >>> ${copyDir}"
echo "tempDir >>> ${tempDir}"
 
mkdir -p ${baseDir%%$fileName*} ${tempDir}
cp ${baseDir} ${tempDir}
else
echo "File's Directiry Not found >>> ${item}"
fi
done
- echo ">>>>>>>>>>>>>>>>>>>>>>>>> Before Modify folder name"
- ls -l
- rm -rf target
- mv temp_target target
- echo ">>>>>>>>>>>>>>>>>>>>>>>>> After Modified folder name"
- ls -l
artifacts:
paths:
- $CI_PROJECT_DIR/target/[project name]
expire_in: 1 week
 
 
cs