Контрибьютинг¶
Спасибо за интерес к contribution. srekit — маленький, со своей позицией, и стремится таким и остаться — пожалуйста открой issue перед PR, который добавляет новую команду, новую third-party зависимость или меняет имя флага.
Локальная установка¶
Требуется:
- Go 1.26.4 (должен совпадать с CI; см. урок про расхождение версий ниже)
- GNU Make 3.81+ — системный
makeна macOS и в любом Linux-дистрибутиве подходит, ставить нечего - git, bash и обычные POSIX-утилиты
Всё остальное Makefile ставит сам при первом использовании, версии запинены в нём же:
golangci-lintиgovulncheck→./bin(черезgo install,go.modпри этом не трогается)- MkDocs и плагины →
./.venv(нужен Python 3 сvenv)
Опционально: goreleaser для make release-dry, tokei для pre-commit хука с LoC-бейджем.
Цели Make¶
make без аргументов печатает этот список. CI зовёт ровно эти же цели, поэтому зелёный make ci локально и зелёный пайплайн означают одно и то же.
| Цель | Что делает |
|---|---|
make run ARGS="<args>" |
go run . <args> |
make build |
Билдит ./dist/srekit |
make install |
go install |
make test |
go test --short -coverprofile=cover.out -v ./... |
make test-race |
go test -race -coverprofile=cover.out -v ./... (что запускает CI) |
make lint |
golangci-lint run на запиненной версии |
make lint-fix |
То же с --fix |
make govulncheck |
Скан уязвимостей (что запускает CI) |
make ci |
lint + test-race — one-shot pre-push check |
make ci-full |
lint + test-race + govulncheck + docs-build |
make release-check |
goreleaser check — валидирует .goreleaser.yaml |
make release-dry |
goreleaser release --clean --snapshot --skip=publish,sign — билдит в ./dist без публикации |
make docs-install |
Создаёт ./.venv и ставит docs/requirements.txt |
make docs-serve |
Сервит docs-сайт на http://127.0.0.1:8000 |
make docs-build |
Билдит docs в ./site (strict mode) |
make docs-deploy |
mkdocs gh-deploy — зовётся из CI, не руками |
make tools |
Ставит запиненные golangci-lint и govulncheck в ./bin |
make fmt |
gofmt -s -w . |
make vet |
go vet ./... |
make tidy |
go mod tidy |
make clean |
Убирает dist/, site/, bin/, cover.out |
Makefile написан под GNU Make 3.81 — это системный make на macOS, и новее Apple не поставит. При правке не используй .ONESHELL и .SHELLFLAGS (3.82+), != и $(file ...) (4.0+), $(intcmp) и $(let) (4.4+), и проверяй на 3.81 до пуша: раннер на 4.x проглотит несовместимость молча.
Стиль кода¶
- Никаких
Co-Authored-By-маркеров в коммитах — пиши коммиты от своего лица. - Conventional-commit префиксы (
feat:,fix:,chore:,docs:,refactor:,test:). Для удобства changelog scan'а. - Добавляй smoke-тест на каждую новую генератор-команду и unit-тест на каждую новую internal-функцию. См.
cmd/cmd_test.goдля smoke- паттерна иinternal/*/для unit-тестов. - Не глушить lint-находки без обоснования — используй формат
//nolint:<linter> // <code>: <reason>, как мы делаем дляgosecG306. - Держи публичные CLI-флаги минимальными. Новый флаг — PR-worthy change.
Чек-лист перед пушем¶
Если трогаешь cmd/templates.go, прогони и полный набор тестов templates руками — у 3-way merge тонкие инварианты:
Релизный процесс¶
(Для мейнтейнеров.)
- Убедиться что
mainчистый и CI зелёный. -
Проверить токен от tap'а — это единственный credential в пайплайне, который не является встроенным в workflow
GITHUB_TOKEN, и падает он после публикации релиза:401 Bad credentialsозначает ротацию fine-grained PAT (jtprogru/homebrew-tap,Contents: Read and write) иgh secret set HOMEBREW_TAP_GITHUB_TOKEN --repo jtprogru/srekit. -
Отрезать changelog:
srekit changelog release --version X.Y.Zлибо руками переместить[Unreleased]в[X.Y.Z] - YYYY-MM-DD. git commit -m "release: X.Y.Z"+git push.git tag -a vX.Y.Z -m vX.Y.Z+git push origin vX.Y.Z.- Подождать
goreleaserworkflow — ~90 секунд. - Проверить GitHub Release страницу и
jtprogru/homebrew-tapcask.
Если пуш в cask всё же упал, перезапуск job'а не помогает: rerun проигрывает тот же ref, поэтому фикс, приехавший в main, не подхватится, а повторная заливка существующих артефактов падает с 422. Почини токен, потом удали релиз и тег и запушь тег заново на том же коммите (gh release delete vX.Y.Z --yes, git push origin :refs/tags/vX.Y.Z, git push origin vX.Y.Z). Пересборка не byte-identical — таймстемпы в архивах двигают checksums, — так что всё, что записало sha256 первого прогона, протухает.
make release-dry локально билдит без публикации — полезно отловить .goreleaser.yaml-баги до тегирования.
Известные нюансы¶
Расхождение версий¶
golangci-lint запинен в Makefile (GOLANGCI_LINT_VERSION) и ставится в ./bin, поэтому make lint резолвится в один и тот же бинарь локально и в CI. Запуск системного golangci-lint напрямую обходит пин — на старой версии gosec правила G703 (path traversal taint) и G705 (XSS taint) дают false positive на коде config init. Используй make lint.
Go-тулчейн Makefile не пиннит — сверяйся с go.mod и GO_VERSION в workflow'ах.
Глобальное состояние в тестах¶
Загрузчик шаблонов собирается на каждое дерево команд в configureTemplates и пробрасывается в команды через cobra command context (loaderFrom), поэтому тесты на --templates-dir спокойно живут с t.Parallel(). Не возвращай package-level загрузчик: gochecknoglobals включён, а прежний глобал (tmpl.Default) убрали именно потому, что он трипал race-детектор.
Единственное оставшееся глобальное состояние — конфиг-синглтон за config.Global(). Тесты, которые его засеивают, используют хелпер withConfig(t, kv) из cmd/cmd_test.go: он сбрасывает конфиг и регистрирует cleanup. Такие тесты не должны вызывать t.Parallel().
См. также¶
- Архитектура — карта кода и ключевые абстракции.
- GitHub issues — открой одну перед нетривиальной работой.