Slide 1

Slide 1 text

OZON Использование go modules в бою

Slide 2

Slide 2 text

Ivan Korolev TeamLead @ Logistics [email protected]
 
 github.com/mwf Слайды: ozon.ru/t/39 Прошлый доклад: ozon.ru/t/38

Slide 3

Slide 3 text

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

Slide 20

Slide 20 text

go.mod - псевдоверсии $ cat /home/gopher/foo/bar/go.mod module github.com/foo/bar go 1.12 require ( github.com/kr/pretty v0.1.0 github.com/sirupsen/logrus v1.4.1 github.com/utrack/clay/v2 v2.3.9 github.com/go-chi/chi v4.0.2+incompatible golang.org/x/tools v0.0.0-20190511041617-99f201b6807e // indirect github.com/foo/buz v0.18.1-0.20190717141926-407f5697e69d )

Slide 21

Slide 21 text

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) • общий интерфейс + разделение зависимостей • микросервис + клиентская либа

Slide 36

Slide 36 text

Vault module github.com/hashicorp/vault go 1.12 replace github.com/hashicorp/vault/api => ./api // Клиент replace github.com/hashicorp/vault/sdk => ./sdk // Плагины require ( cloud.google.com/go v0.39.0 github.com/Azure/azure-sdk-for-go v29.0.0+incompatible github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect github.com/Azure/go-autorest v11.7.1+incompatible ... )

Slide 37

Slide 37 text

Разделение зависимостей

Slide 38

Slide 38 text

handler.go type Handler interface { http.Handler AddLivenessCheck(name string, check Check) AddReadinessCheck(name string, check Check) // ... } // Check is a liveness/readiness check. type Check func() error

Slide 39

Slide 39 text

postgres go.mod module gitlab.ozon.ru/platform/healthcheck-go/checker/db/postgres replace gitlab.ozon.ru/platform/healthcheck-go => ../../../ require ( github.com/lib/pq v0.0.0-20180523175426-90697d60dd84 gitlab.ozon.ru/platform/healthcheck-go v0.4.0 )

Slide 40

Slide 40 text

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

Slide 45

Slide 45 text

GitLab - кэширование сборок .gitlab-ci.yml build: cache: key: "go-modules-cache" paths: - .cache/go/pkg/mod/cache/download - .cache/gocache/*/* - .cache/gocache/trim.txt before_script: - export GOPATH=${CI_PROJECT_DIR}/.cache/go - export GOCACHE=${CI_PROJECT_DIR}/.cache/gocache #25323, fixed in go1.13 - $GOCACHE/log.txt рос бесконтрольно

Slide 46

Slide 46 text

GitLab subgroups Репозиторий нормального человека gitlab.ozon.ru/platform/scratch

Slide 47

Slide 47 text

GitLab subgroups Репозиторий нормального человека gitlab.ozon.ru/platform/scratch Репозиторий курильщика gitlab.ozon.ru/lms/go/service/platform/tsmr

Slide 48

Slide 48 text

GitLab subgroups $ curl -s https://gitlab.com/group/sub-group/repo?go-get=1 https://gitlab.com/gitlab-org/gitlab-ce/issues/30785

Slide 49

Slide 49 text

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

Slide 55

Slide 55 text

GOSUMDB Ложка дёгтя: verifying gitlab.ozon.ru/platform/[email protected]/go.mod: gitlab.ozon.ru/platform/[email protected]/go.mod: reading https://sum.golang.org/lookup/gitlab.ozon.ru/ platform/[email protected]: 410 Gone

Slide 56

Slide 56 text

Proxy Альтернативные публичные прокси - https://goproxy.io/ Коробочные решения: • Athens - https://docs.gomods.io/ • Artifactory - https://jfrog.com/artifactory/ • github.com/goproxy/goproxy

Slide 57

Slide 57 text

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]

Slide 62

Slide 62 text

Нерешённые проблемы • глобальная установка бинарей - #30515 • tools.go - "официальный костыль" // +build tools package tools import ( _ "golang.org/x/tools/cmd/stringer" )

Slide 63

Slide 63 text

Что на выходе • поддержка в экосистеме • скорость работы • повторяемость сборок • безопасность и контроль • гибкость разработки - вложенные модули • универсальность решения (бинарные зависимости, 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