MVS и нововведения тулчейна
Вложенные модули
go modules + GitLab = ...
GOPROXY и Athens
Slide 4
Slide 4 text
SemVer
Slide 5
Slide 5 text
Minimal Version Selection
Скорость работы
Slide 6
Slide 6 text
Minimal Version Selection
Скорость работы
Простота реализации
Slide 7
Slide 7 text
Minimal Version Selection
Скорость работы
Простота реализации
Минимальность вносимых изменений в граф
Slide 8
Slide 8 text
Minimal Version Selection
Скорость работы
Простота реализации
Минимальность вносимых изменений в граф
Воспроизводимость билдов
Slide 9
Slide 9 text
Minimal Version Selection
Скорость работы
Простота реализации
Минимальность вносимых изменений в граф
Воспроизводимость билдов
Локальные replace и exclude
Slide 10
Slide 10 text
go toolchain
Изменения в тулчейне:
- 1.11 внедрение модулей, работа вне GOPATH
изменение get, build, run, test, install, list, ...
Slide 11
Slide 11 text
go toolchain
Изменения в тулчейне:
- 1.11 внедрение модулей, работа вне GOPATH
изменение get, build, run, test, install, list, ...
- 1.12 багфиксы
директива go в go.mod
Slide 12
Slide 12 text
Директива go в go.mod
$ cat < hello.go
package main
import "fmt"
func main() { fmt.Println("hello") }
EOF
Slide 13
Slide 13 text
Директива go в go.mod
$ cat < hello.go
package main
import "fmt"
func main() { fmt.Println("hello") }
EOF
$ go version && go mod init example.com/foo/bar
go version go1.12.1 darwin/amd64
Slide 14
Slide 14 text
Директива go в go.mod
$ cat < hello.go
package main
import "fmt"
func main() { fmt.Println("hello") }
EOF
$ go version && go mod init example.com/foo/bar
go version go1.12.1 darwin/amd64
$ cat go.mod
module example.com/foo/bar
go 1.12
Slide 15
Slide 15 text
Директива go в go.mod
$ gvm use go1.11.3
Now using version go1.11.3
$ go build
go build example.com/foo/bar: module requires Go 1.12
Slide 16
Slide 16 text
Директива go в go.mod
$ gvm use go1.11.3
Now using version go1.11.3
$ go build
go build example.com/foo/bar: module requires Go 1.12
$ gvm use go1.11.4
Now using version go1.11.4
$ go build
Slide 17
Slide 17 text
Директива go в go.mod
$ gvm use go1.11.3
Now using version go1.11.3
$ go build
go build example.com/foo/bar: module requires Go 1.12
$ gvm use go1.11.4
Now using version go1.11.4
$ go build
$ echo "BAD COMPILE" >> hello.go
$ go build
# example.com/foo/bar
.\hello.go:12:1: syntax error: non-declaration statement outside
function body
note: module requires Go 1.12
Slide 18
Slide 18 text
go toolchain
Изменения в тулчейне:
- 1.11 внедрение модулей, работа вне GOPATH
изменение get, build, run, test, install, list, ...
- 1.12 багфиксы
директива go в go.mod
- 1.13 GO111MODULE=auto - модули в GOPATH
Много изменений
Slide 19
Slide 19 text
Переработка go get -u
• go get -u - нет обновлений транзитивных
зависимостей
• go get -u обновляет зависимости текущего пакета
• go get -u all обновляет зависимости модуля
• go get -u -t обновит ещё и тесты
• go get -u @patch обновление до патча
Эквивалентно go get -u=patch
Подробности - #32846
go.mod - псевдоверсии
В go1.13 добавили валидацию псевдоверсий - #27173
Проблема - не было проверки псевдоверсия <-> тэг
require a.com/foo/bar v1.0.0-20180819111657-1c088dc8b6d3
require a.com/foo/bar v1.7.0-alpha.0.20180819111657-1c088dc8b6d3
require a.com/foo/bar v1.9.0-alpha.0.20180819111657-1c088dc8b6d3
Slide 22
Slide 22 text
go.mod - псевдоверсии
Типы псевдоверсий:
• vX.0.0-yyyymmddhhmmss-abcdefabcdef
нет мажора
Slide 23
Slide 23 text
go.mod - псевдоверсии
Типы псевдоверсий:
• vX.0.0-yyyymmddhhmmss-abcdefabcdef
нет мажора
• vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef
в дереве существует vX.Y.Z-pre
Slide 24
Slide 24 text
go.mod - псевдоверсии
Типы псевдоверсий:
• vX.0.0-yyyymmddhhmmss-abcdefabcdef
нет мажора
• vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefabcdef
в дереве существует vX.Y.Z-pre
• vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef
в дереве существует vX.Y.Z
Лучшее средство - указать хэш + go mod tidy
Slide 25
Slide 25 text
go mod
go mod [arguments]
init инициализация модуля
tidy добавление/удаление импортов
vendor копия зависимостей в ./vendor
download скачивает модули в кэш
verify проверка хэш-сумм
edit редактирование go.mod скриптами
why объясняет, откуда та или иная зависимость
graph печатает граф зависимостей
Slide 26
Slide 26 text
go mod why
require github.com/pelletier/go-toml v1.4.0 // indirect
require golang.org/x/text v0.0.0-20190308202827-9d24e82272b4 //
indirect
"Зачем мне эта зависимость?"
Slide 27
Slide 27 text
go mod why
go mod why [-m] [-vendor] packages...
Выдаёт кратчайший путь в графе импортов.
-vendor исключает анализ тестов зависимостей
$ go mod why golang.org/x/text
go: finding golang.org/x/text latest
# golang.org/x/text
(main module does not need package golang.org/x/text)
Slide 28
Slide 28 text
go mod why
$ go mod why -m golang.org/x/text
# golang.org/x/text/language
rsc.io/quote
rsc.io/sampler
golang.org/x/text/language
Slide 29
Slide 29 text
go mod graph
"Зачем мне эта версия?"
go mod graph | grep ...
Slide 30
Slide 30 text
MVS и нововведения тулчейна
Вложенные модули
go modules + GitLab = ...
GOPROXY и Athens
Slide 31
Slide 31 text
Вложенные модули
.
|-- go.mod
|-- b
| |-- go.mod
| `-- b.go
`-- a
|-- go.mod
`-- a.go
git tag a/v1.0.1
git tag b/v1.1.0
Slide 32
Slide 32 text
Использование
• отделить мусорные зависимости (example,
integration)
Slide 33
Slide 33 text
Использование
• отделить мусорные зависимости (example,
integration)
• монорепы
• единый репозиторий библиотек (общий CI)
• библиотека + бинари вокруг неё (etcd, vault)
Slide 34
Slide 34 text
Использование
• отделить мусорные зависимости (example,
integration)
• монорепы
• единый репозиторий библиотек (общий CI)
• библиотека + бинари вокруг неё (etcd, vault)
• общий интерфейс + разделение зависимостей
Slide 35
Slide 35 text
Использование
• отделить мусорные зависимости (example,
integration)
• монорепы
• единый репозиторий библиотек (общий CI)
• библиотека + бинари вокруг неё (etcd, vault)
• общий интерфейс + разделение зависимостей
• микросервис + клиентская либа
postgres.go
package postgres
import (
"context"
"database/sql"
"time"
"gitlab.ozon.ru/platform/healthcheck-go"
"gitlab.ozon.ru/platform/healthcheck-go/checker/db/internal"
"github.com/lib/pq"
)
// PingCheckByDb returns a Check that validates connectivity to a
// database/sql.DB using Ping().
func PingCheckByDb(db *sql.DB, timeout time.Duration) healthcheck.Check {
return internal.DatabasePingCheck(db, timeout)
}
Slide 41
Slide 41 text
Микросервисы
Slide 42
Slide 42 text
Микросервисы
• зависимости сервиса отдельно от клиентских
• тэги либы - SemVer
тэги сервиса - release/2019-07-20
• бонус - версионирование .proto
$GOPATH/pkg/mod/.../pkg/[email protected]/metatarifficator.proto
Slide 43
Slide 43 text
Вложенные модули
Осторожно:
• replace - модификация локального дерева зависимостей
• не забыть про сборку и тестирование всех подмодулей в CI
go test ./... тестирует только текущий модуль
replace github.com/hashicorp/vault/sdk => ./sdk
require github.com/hashicorp/vault/sdk v0.1.12
Slide 44
Slide 44 text
MVS и нововведения тулчейна
Вложенные модули
go modules + GitLab = ...
GOPROXY и Athens
GitLab subgroups
Костыли в go.mod
require gitlab.ozon.ru/lms/go/service/platform/tsmr/pkg/reader v0.0.2
...
replace gitlab.ozon.ru/lms/go/service/platform/tsmr/pkg/reader => gitlab.ozon.ru/
lms/go/service/platform/tsmr.git/pkg/reader v0.0.2
* Уже запилили поддержку .netrc в GitLab и в go 1.13 #29888
Slide 50
Slide 50 text
MVS и нововведения тулчейна
Вложенные модули
go modules + GitLab = ...
GOPROXY и Athens
Slide 51
Slide 51 text
GOPROXY
• Ускорение сборок
• Защита от:
• отключения интернета
• удаления / force push зависимостей
• РКН :)
• Настройка исключений через GOPRIVATE и GONOPROXY
Slide 52
Slide 52 text
GOPROXY
proxy.golang.org - глобальное зеркало
GOPROXY=proxy.example.com,https://proxy.golang.org,direct
Опрос в прямом порядке, пока не ответит 200 или до direct
Если ответил 404 или 410 - идём в следующий proxy
Иначе - ошибка скачивания зависимостей ¯\_(ツ)_/¯
GOPRIVATE=*.corp.example.com,rsc.io/private (или GONOPROXY)
Позволяет настроить исключения для проксирования
Slide 53
Slide 53 text
GOPROXY
Пример из документации:
GOPRIVATE=*.corp.example.com
GOPROXY=proxy.example.com
GONOPROXY=none
Приватные репы - в под-домене corp.example.com
Но GONOPROXY=none магически заставляет использовать
proxy.example.com
Slide 54
Slide 54 text
GOSUMDB
sum.golang.org - глобальная БД чексумм
Защита обновлений через go get -u
GOSUMDB=sum.golang.org
GOSUMDB=off
GONOSUMDB=*.corp.example.com,rsc.io/private
GOPRIVATE - общие исключения для PROXY и SUMDB
Athens
• первый и самый популярный
• настройки приватных репозиториев, доступа наружу и
исключений
• работает поверх go get - имеет все болячки и плюшки
• поддержка .netrc
Slide 58
Slide 58 text
Мифы
• go.sum и GOSUMDB не нужны? - Repeatable build
Slide 59
Slide 59 text
Мифы
• go.sum и GOSUMDB не нужны? - Repeatable build
• сложно откатывать зависимости! - replace и коммуникация
Slide 60
Slide 60 text
Мифы
• go.sum и GOSUMDB не нужны? - Repeatable build
• сложно откатывать зависимости! - replace и коммуникация
• yet another standard? - Смиритесь, за модулями будущее
Slide 61
Slide 61 text
Мифы
• go.sum и GOSUMDB не нужны? - Repeatable build
• сложно откатывать зависимости! - replace и коммуникация
• yet another standard? - Смиритесь, за модулями будущее
• сложность установки бинарей. - Уже стало лучше
GO111MODULE=on go get golang.org/x/tools/[email protected]
Что на выходе
• поддержка в экосистеме
• скорость работы
• повторяемость сборок
• безопасность и контроль
• гибкость разработки - вложенные модули
• универсальность решения (бинарные зависимости, proto-
файлы)
Slide 64
Slide 64 text
Что почитать
• Wiki: https://github.com/golang/go/wiki/Modules
• HowTo: https://github.com/go-modules-by-example/index/
• go help: https://tip.golang.org/cmd/go
Slide 65
Slide 65 text
Спасибо!
Слайды: ozon.ru/t/39
Видео и слайды прошлого доклада: ozon.ru/t/38
habr.com/ru/company/ozontech
github.com/ozonru
Ivan Korolev
Team Lead @ Logistics
[email protected]
github.com/mwf