TL;DR
-
read_api
とread_repository
権限のついた、gitlab Personal Access Tokenを作る -
~/.netrc
を作成~/.netrcmachine gitlab.com login yourname@gitlab.com password yourpersonalaccesstoken
-
go get
するGO111MODULE=on GOPRIVATE=gitlab.com/group go get gitlab.com/group/subgroup/hoge.git@v1.0.0
-
container image や CI 内でやりたい場合ば、
.netrc
をgo get
する環境に渡してあげる
Private repository の go get
go module が導入され、モジュールの依存関係を go.mod で管理することもメジャーになってきました。そんな中、自チームで作成した private な git repository を go get
して、他のアプリでも使いたいという場面もあるかと思います。Github で管理された priavte repository でこれを実現する方法は、ググればたくさん出てくるのですが、GitLab でやる方法はまだまだマイナーです。
そこで、gitlab.com で管理している go の private git repository を go get
する方法をご紹介します!
Local環境に go get
する
まず、 private repository を手元のローカル環境に go get
することを考えます。が、その前に目的のモジュールがgitlabのsubgroup配下にあるかどうか確認してください。
対象モジュール(hoge)が、例えばgitlab.com/group/subgroup/hoge
のように、subgroupに属している場合、go get
対象となるパッケージ名はgitlab.com/group/subgroup/hoge.git
になります。
go get gitlab.com/group/subgroup/hoge.git
これを.git
無しで実行すると、gitlab.com/group/subgroup.git
というリポジトリが見つからないというエラーが発生します。
githubだとgroupまたはユーザの階層の直下がリポジトリ階層になるので、subgroup
の部分がリポジトリ扱いされるのではないかと推測しています。明示的に.git
とすると、そこをリポジトリとして認識してくれます。
次に、gitlab private repositoryをgo get
する方法ですが、公式にissueが切られているので、まずはこれをチェック。
注目すべきは最後のコメントで、
-
read_api
とread_repository
権限のついた、gitlab Personal Access Tokenを作る -
~/.netrc
を下記の内容で作るmachine gitlab.com login yourname@gitlab.com password yourpersonalaccesstoken
-
go get --insecure
を使って対象のモジュールをダウンロードする -
.gitconfig
のinsteadOf
は使わない
とのこと。
なおGo 1.13以降の場合、GOPRIVATE
という変数が追加されており、3番目の--insecure
オプションではなく、こちらを用いた方が良さそうです。
ここまでで、privateなgo git repositoryをlocalにgo get
できたことかと思います。go get
したモジュールは$GOPATH/pkg/mod/gitlab.com/group/subgroup
配下に指定したバージョンごとにhoge.git@v1.0.0
のようなディレクトリ名で格納されているはずです。
Container image 内で go get
する
続いて、Container image内でgo get
する場合を考えます。この場合、実際に実行するコマンドはgo get
ではなく、go build
やgo test
かもしれませんが、やりたいことはモジュールのダウンロードなのでgo get
と同じです。
goで開発している場合、マルチステージビルドをすることが一般的かと思います。そうなると、マルチステージビルドの、ビルド環境側で下記のように.netrc
を設定してあげる必要があります。
FROM golang:1.14 AS builder
ENV GO111MODULE=on
ENV GOPRIVATE=gitlab.com/group
ADD . /go/src/gitlab.com/group/subgroup/fuga
WORKDIR /go/src/gitlab.com/group/subgroup/fuga
ARG NETRC
RUN echo "${NETRC}" > /root/.netrc
RUN go build -o /bin/fuga .
## Product
FROM alpine:3.12
COPY --from=builder /bin/fuga /bin/
CMD [ "/bin/fuga" ]
.netrc
ファイルをボリュームマウントやADD
、COPY
などして渡してあげることも可能ですが、今回はARG
でNETRC
変数にファイルの中身を渡しています。従って、docker build
コマンドは下記のようになります。
docker build -t fuga --build-arg NETRC="$(cat ~/.netrc)" .
GitLab CI環境で go get
する
では、CIでimageをビルドする際にはどのように.netrc
を渡せばいいでしょうか。個人のアクセストークンを使用したくはありません。
こちらも、gitlabの公式に答えが用意されていました。gitlabにはCI内で使用できるトークンが用意されており、下記の形で.netrc
も設定できます。
echo -e "machine gitlab.com\nlogin gitlab-ci-token\npassword ${CI_JOB_TOKEN}" > ~/.netrc
これを応用してあげれば、CI内でgo get
したい場合には上記のトークンでモジュールをダウンロードできます。また、docker-in-dockerなど、CIのなかでdocker build
したい場合や、/kaniko/executor
したい場合には、下記のようにして--build-arg
に渡すことができます。
--build-arg NETRC="$(echo -e "machine gitlab.com\n login gitlab-ci-token\n password ${CI_JOB_TOKEN}")"
まとめ
gitlabの、subgroupを持つgoのprivate repositoryで、publicなモジュール同様にgo get
する方法をご紹介しました。あくまで、2020/09/01
時点(go 1.14)で調べたものですので、今後また変わってくると思います。なかなか面倒くさいですもんね