Здравейте всички!

В тази статия искам да покажа как можем да създадем monorepo с Golang и Bazel.

Изисквания:

  1. Go Modules — искаме да използваме go mod за управление на зависимости
  2. Споделена кодова база — искаме да използваме повторно нашия код в друго приложение
  3. Тест — искаме да проведем тестове на едно/всички приложения
  4. Изграждане — искаме да изграждаме всяко приложение отделно

Тези изисквания надхвърлят определението за monorepo. Добре, да започваме.

1. Init go модули

Трябва да създадем go mod в нашата папка:

go mod init monorepo

След тази команда можем да получим зависимост от нашия проект.

2. Създайте например две приложения

Нека създадем папка packages, която ще съдържа всички наши приложения.

mkdir packages
cd packages
mkdir main_app
mkdir second_app
cd main_app && touch main.go && cd ../
cd second_app && touch main.go && cd ../
mkdir shared && touch shared.go - that file for shared code

Например, нашето приложение ще използва gin като HTTP сървър:

go get github.com/gin-gonic/gin

3. Създайте работно пространство за нашето monorepo

В главната папка трябва да създадем файл WORKSPACE със съдържание:

И BUILD файл със съдържание:

След като имаме нужда от настройка на Bazel да използва зависимост от go.mod с команда:

bazel run //:gazelle -- update-repos -from_file=go.mod

Тази команда ще актуализира нашия файл WORKSPACE със зависимости от go.mod

Завършваме настройката на нашето работно пространство, след което трябва да настроим нашите приложения.

4. Създайте компилация за приложения

Всяко приложение в папката на приложението трябва да има BUILD като входна точка за Bazel

Тук имаме два раздела:

  1. go_binary
  2. go_test

Секция go_binary

Този раздел има пълен списък с полета, който можете да намерите във връзката. Ще опиша само някои от тях:

„name“ — името за Bazel, за deps и Bazel resolver

“srcs” — входни точки за модули, ще бъдат като артефакти

“importpath” — как трябва да импортираме този модул в нашите приложения

“deps” — масив от зависимости

Раздел go_test

„име“ — за теста за изпълнение

“srcs” — входни точки за тестове

Нека добавим малко споделено съдържание

За създаване на приложение като в реалния живот добавям рутер и в двете приложения с подобно съдържание

Ако видите, че този пакет използва някои зависимости от споделена папка.

И нека създадем BUILD файл за този пакет:

Този файл има раздел „go_library“

Секция go_library

„име“ — името за Bazel, за използване в dep

“srcs” — входната точка за lib

„importpath“ — път за импортиране извън (Bazel ще бъде разрешен този псевдоним като webpack в nodejs)

“visibility” — видимост на модула в Bazel

„deps“ — зависимости, в този пример имаме dep от „@com_github_gin_gonic_gin“ — това е вътрешното име на gin, което можете да получите от файла WORKSPACE и от нашия споделен манипулатор.

5. Създайте споделена папка и компилирайте

В предишната стъпка имаме препратка към споделена папка.

Създавам споделен манипулатор за джин като този:

И компилирайте за пакет:

Както виждаме и джин в деп.

Ще пропусна частта в създаването на код за второто приложение, защото е напълно същото. Пълният код можете да намерите тук



6. Нека изградим и тестваме нашите приложения

За изграждане на основно приложение можем да използваме командата:

bazel build //packages/main_app:main_app

Тази команда ще бъде приложение за изграждане и ще покаже пътя до bin файла

За изграждане на второ приложение можете да използвате:

bazel build //packages/second_app:second_app

Тест

Тест за едно приложение:

bazel test //packages/second_app/...:all

Всички приложения тестват:

bazel test //packages/...:all

Dep графика

Bazel може да създаде dep графика с командата:

bazel query 'allpaths(packages/...,//packages/shared/handlers/health:health)' --output graph | dot -Tpng > dep.png

Тази команда ще покаже всички пакети, които зависят от модула здраве.

7. Насладете се!

В този пример показах основата за създаване на monorepo в Go, ако се интересувате, ще продължа статията и ще кажа как да използвате например protobuf или общи статични файлове в monorepo.