プライベートリポジトリのモジュールをgo getするための設定(https)
社内のプライベートリポジトリをgo getする際にしばしば混乱するのでメモ。httpsでのアクセスが必要な環境なので、https前提の話となっている。
何も設定していない場合に発生するエラー
前提:
- go version go1.15.6 linux/amd64 (ちょっと古い…)
- GOPRIVATEを設定していない
- httpsの認証情報を設定してない
- キャッシュクリア
- go.modがあるディレクトリで実行
go get, go get ${モジュール名}
- go.modに記載のモジュールをインストールする。
- ①プライベートリポジトリの認証を突破できない
❯ go get
①go: github.com/Sho372/mysecret@v0.0.0-20221015173609-50bc2589408e: invalid version: git fetch -f origin refs/heads/*:refs/heads/* refs/tags/*:refs/tags/* in /home/sho/goworkspace/pkg/mod/cache/vcs/f7c95e78ccfc05412466703c9dfe4d96cfb78fa98dc272d0d7347bff3f468e2d: exit status 128:
fatal: could not read Username for 'https://github.com': terminal prompts disabled
ちなみに、go.modがない環境で実行すると…
❯ go get github.com/Sho372/go-const
①go get github.com/Sho372/go-const: module github.com/Sho372/go-const: git ls-remote -q origin in /home/sho/goworkspace/pkg/mod/cache/vcs/1213af4aff3f33e0fc4e0690d9630417ffc2fcdd363e78fe9cf3cf41f1e5a64c: exit status 128:
fatal: could not read Username for 'https://github.com': terminal prompts disabled
②Confirm the import path was entered correctly.
If this is a private repository, see https://golang.org/doc/faq#git_https for additional information.
1. GOPRIVAETを設定
今回はモジュール名を直接指定する。モジュール名はモジュール側のgo.modに書いてある。
❯ export GOPRIVATE=github.com/Sho372/mysecret
❯ env | grep GOPRIVATE
GOPRIVATE=github.com/Sho372/mysecret
指定するもジュルー名がわからない時はモジュール側のgo.modを確認する
❯ cat go.mod
module github.com/Sho372/mysecret
go 1.15
上記のexportで設定してもいいが、goの設定なので、go env -wで設定するようにしている。
go env -w GOPRIVATE=github.com/Sho372/mysecret
2. httpsの認証情報を設定に追加して、認証情報入力をスキップする
- .netrcまたはgit configに設定する
- パスワードはgithubから取得したaccess tokenを使用する
.netrc
Frequently Asked Questions (FAQ) - The Go Programming Language
git confg
プライベートリポジトリをgo getする方法 - 尋常でないもふもふ
bitbucket, gitlab
Today I Learned - Fix: go get private repository return error terminal prompts disabled
こちらも.netrcで設定してもいいが、.gitconfigで設定がまとまっている方がいいので、gitの設定で解決するようにしている。
git config --global url."https://${githubのaccess token}:x-oauth-basic@github.com/".insteadOf "https://github.com/"
❯ cat ~/.gitconfig
[user]
email = 32non23ca@gmail.com
name = Sho372
[url "https://${githubのaccess token}:x-oauth-basic@github.com/"]
insteadOf = https://github.com/
3. go get
設定が完了したら、欲しいプライベートモジュールをgo getする
❯ go get [github.com/Sho372/mysecret](http://github.com/Sho372/mysecret)
go: downloading [github.com/Sho372/mysecret](http://github.com/Sho372/mysecret) v0.0.0-20221015173609-50bc2589408e
go: [github.com/Sho372/mysecret](http://github.com/Sho372/mysecret) upgrade => v0.0.0-20221015173609-50bc2589408e
❯ cat go.mod
module go-import-package
go 1.15
require github.com/Sho372/mysecret v0.0.0-20221015173609-50bc2589408e // indirect
go getが成功すると、GOMODCACHE配下にread onlyで格納される
❯ go env | grep GOMODCACHE
GOMODCACHE="/home/sho/goworkspace/pkg/mod"
❯ pwd
/home/sho/goworkspace/pkg/mod/github.com/!sho372
❯ ll
total 16
drwxr-xr-x 4 sho sho 4096 Oct 16 02:41 .
drwxr-xr-x 40 sho sho 4096 Oct 16 04:43 ..
dr-x------ 2 sho sho 4096 Oct 16 02:41 mysecret@v0.0.0-20221015173609-50bc2589408e
❯ go env | grep GOCACHE
GOCACHE="/home/sho/.cache/go-build"
4. ソース上で取得したモジュールをimportして使う
最後にソース上でimportする
import (
"fmt"
"log"
"github.com/Sho372/mysecret" ★
"github.com/shopspring/decimal"
)
go mod vendor (vendoring)
go mod vendorを実行すると、vendorディレクトリが生成され、ソースコードが格納される。
- vendorディレクトリが生成され、この配下に依存モジュールのソースがダウンロードされる
- vendorがある場合は、そこにあるモジュールで依存が解決されるらしい
- GOMODCACHE配下とは異なり、修正可能なのでデバッグコードを差し込むことができる
❯ ll
total 2368
drwxrwxrwx 1 sho sho 512 Oct 17 04:49 .
drwxrwxrwx 1 sho sho 512 Oct 16 03:31 ..
-rwxrwxrwx 1 sho sho 148 Oct 16 05:41 go.mod
-rwxrwxrwx 1 sho sho 404 Oct 16 04:54 go.sum
-rwxrwxrwx 1 sho sho 2421984 Oct 16 05:33 main
-rwxrwxrwx 1 sho sho 261 Oct 16 04:57 main.go
❯ go mod vendor
❯ ll
total 2368
drwxrwxrwx 1 sho sho 512 Oct 17 04:49 .
drwxrwxrwx 1 sho sho 512 Oct 16 03:31 ..
-rwxrwxrwx 1 sho sho 148 Oct 16 05:41 go.mod
-rwxrwxrwx 1 sho sho 404 Oct 16 04:54 go.sum
-rwxrwxrwx 1 sho sho 2421984 Oct 16 05:33 main
-rwxrwxrwx 1 sho sho 261 Oct 16 04:57 main.go
drwxrwxrwx 1 sho sho 512 Oct 17 04:49 vendor ★
❯ ll vendor/github.com/Sho372
total 0
drwxrwxrwx 1 sho sho 512 Oct 17 04:49 .
drwxrwxrwx 1 sho sho 512 Oct 17 04:49 ..
drwxrwxrwx 1 sho sho 512 Oct 17 04:49 mysecret ★
キャッシュクリア実験
上記の手順でプライベートパッケージからパッケージを取得したあとに、以下を実施してキャッシュクリアの挙動を確かめた
1 go clean -modcache
- GOMODCACHE="/home/sho/goworkspace/pkg/mod" ディレクトリが削除される
- このあとにgo buildを実行してもまだ通る
2 go clean --cache
- GOCACHE="/home/sho/.cache/go-build"配下のキャッシュが削除される
- このあとにgo buildを実行してもまだ通る
3 rm -rf vendor
,go clean -modcache
,go clean --cache
- vendorディレクトリを削除
- go buildするとGOCACHEにキャッシュが残るので再度これもクリア
- 念のためGOMODCACHEもクリア
- これで完全にローカルからパッケージが消え去ったはず
4 go build
- パッケージのダウンロードが開始した。(ただし、Go 16ではgo build時の自動ダウンロードはなくなったらしいので、go get or go mod tidyを実行)
❯ go build
go: downloading github.com/shopspring/decimal v1.3.1
go: downloading github.com/Sho372/mysecret v0.0.0-20221015173609-50bc2589408e
キャッシュクリアまとめ
つまり、ローカルのパッケージを完全に削除して、再ダウンロードしたい場合は以下ぽい
- もしvendorディレクトリがあるなら、
rm -rf vendor
go clean --cache
go clean -modcache
go get
or go mod tidy
- もしvendorディレクトリが必要なら、
go mod vendor
プライベートモジュールの改修
- プライベートパッケージ側でブランチを切って改修
- そのブランチ版をインポートして使ってみる
1. プライベートモジュールで改修
feature
ブランチを作成して改修し、push
- 新たに
pokemons
パッケージを作成
2. featureブランチ版をgo get
- @${ブランチ名}で指定できる
- go get -uだとさらにモジュールが依存するモジュールの最新も取得してくれるらしい。こっちが適切?
❯ go get github.com/Sho372/mysecret@feature
go: github.com/Sho372/mysecret feature => v0.0.0-20221016202503-eb4c4bc6b253
go: downloading github.com/Sho372/mysecret v0.0.0-20221016202503-eb4c4bc6b253
❯ cat go.mod
module go-import-package
go 1.15
require (
github.com/Sho372/mysecret v0.0.0-20221016202503-eb4c4bc6b253
github.com/shopspring/decimal v1.3.1
)
3. 使ってみる
- 今回は、「モジュール名」と「パッケージ名」が異なるから?、${モジュール名}/${パッケージ名}で指定するとimportできた
import (
"fmt"
"log"
"github.com/Sho372/mysecret"
"github.com/Sho372/mysecret/pokemons" ★
"github.com/shopspring/decimal"
)
func main() {
mysecret.SecretProcess()
fmt.Println(pokemons.PIKACHU) ★
amount, err := decimal.NewFromString("1.23")
if err != nil {
log.Fatal(err)
}
fmt.Println(amount.String())
}
4. 元のmainブランチ版に戻す
- go get ${モジュール名}@latestでも、元のmasterブランチの最新に戻った
- go get ${モジュール名}@latestはgo get ${モジュール名}と同じ意味らしい
❯ go get github.com/Sho372/mysecret@latest
go: github.com/Sho372/mysecret latest => v0.0.0-20221015173609-50bc2589408e
❯ cat go.mod
module go-import-package
go 1.15
require (
github.com/Sho372/mysecret v0.0.0-20221015173609-50bc2589408e
github.com/shopspring/decimal v1.3.1
)
❯ go build
go: finding module for package github.com/Sho372/mysecret/pokemons
main.go:8:2: module github.com/Sho372/mysecret@latest found (v0.0.0-20221015173609-50bc2589408e), but does not contain package github.com/Sho372/mysecret/pokemons
masterブランチ指定でもいける
❯ go get github.com/Sho372/mysecret@master
go: github.com/Sho372/mysecret master => v0.0.0-20221015173609-50bc2589408e
Modules · golang/go Wiki
goコマンド
公式ドキュメント
Go Modules Reference - The Go Programming Language
go.modで定義された、プロジェクトの依存モジュールを取得したい時
- go get or go mod tidy
- 格納先:GOMODCACHE="/home/sho/goworkspace/pkg/mod"
cd ${go.modがあるディレクトリ}
go get or go mod tidy
プロジェクトに新しいモジュールを追加したい時(go.modへの追記)
- go get ${モジュール名}
- 格納先:GOMODCACHE="/home/sho/goworkspace/pkg/mod"
cd ${go.modがあるディレクトリ}
go get ${モジュール名}
cat go.mod //取得したモジュール名が追記されている