Архитектура¶
Карта кода для контрибьюторов и любопытных пользователей.
Раскладка пакетов¶
srekit/
├── main.go # точка входа: cobra.Execute()
├── cmd/ # один .go на команду + общий root
│ ├── root.go # cobra root + viper init + persistent --templates-dir / --config
│ ├── <command>.go # один файл на генератор + группы templates / config
│ └── cmd_test.go # smoke-тесты через cobra (SetArgs + capture stdout)
├── internal/
│ ├── ids/ # UUID v4 + slug
│ ├── clock/ # var Now = time.Now (overridable в тестах)
│ ├── meta/ # Author.Resolve + DetectRepo (парсинг git remote)
│ ├── cliflags/ # общий бандл --out / --stdout / --force / --dry-run / --json (--template через BindTemplateFlag, только license)
│ ├── tmpl/ # //go:embed templates/*.yaml + Funcs + Source/Loader + Samples + Validate + DocsMD
│ │ └── templates/ # v1 single-file YAML артефакты, по одному на генератор
│ ├── sections/ # Artifact (v1 single-file) + Section/Manifest + Merge + RenderArtifact + JSONSchema
│ ├── migrate/ # `srekit templates migrate` — heuristic .tmpl → .yaml конвертер
│ └── render/ # Render() — buildBody/writeBody + JSON short-circuit + artifact branch
├── docs/ # этот сайт (MkDocs Material с i18n)
├── .github/
│ ├── workflows/ # tests / lint / goreleaser / docs
│ └── dependabot.yml
├── .goreleaser.yaml
├── .golangci.yaml
└── Taskfile.yml
Ключевые абстракции¶
internal/tmpl.Source и Loader¶
Шаблоны могут приходить из binary (embedded) или из директории пользователя. Source — интерфейс:
EmbedSource читает из //go:embed templates/*.yaml. DirSource{Dir} читает с диска. Loader{Sources} идёт по ним по порядку с fs.ErrNotExist-as-fallthrough семантикой — отсутствующий файл в user dir прозрачно фолбэчится на embedded.
Каждая команда строит *tmpl.Loader через configureTemplates и кладёт его в cmd.Context(); downstream код достаёт через loaderFrom(cmd). Никакого package-level mutable state — loader scoped per command tree, и --templates-dir тесты остаются parallel-safe.
internal/sections¶
Runtime v1 артефакта. Artifact — это распаршенный <name>.yaml: frontmatter (yaml.Node для сохранения порядка), title, meta_bullets, header_body, список секций. ParseArtifact валидирует структурные инварианты; Merge накладывает per-section override'ы и template-evaluate'ит section titles; RenderArtifact собирает markdown (frontmatter блок → H1 → meta_bullets → header_body → ## section блоки).
Генераторы передают Options.RenderArtifact = true и реализуют ArtifactPayload() на data-структуре, чтобы отдать merged section list + ctx обратно в RenderArtifact.
internal/render.Render()¶
Общий рендеринг-пайплайн. Берёт имя шаблона, data-структуру и render.Options{Out, Stdout, Force, DryRun, TemplatePath, JSON, Default, BootstrapJSON, RenderArtifact}. Три ветки:
--jsonshort-circuit:MarshalIndentdata (structured pass-through).RenderArtifact = true: загрузить<name>.yaml, распарсить, отдать вsections.RenderArtifact.- Иначе: legacy
text/templateexecution. Ни один shipped-генератор не использует эту ветку с v0.20; оставлено для--template FILEнаlicenseи для external tooling.
internal/cliflags.Output¶
Каждый генератор-cmd содержит Output и зовёт .Bind(cmd, "default-path-description"). Это шипит общие флаги (--out / --stdout / --force / --dry-run / --json). Флаг --template FILE — opt-in через BindTemplateFlag(cmd); зовёт только cmd/license.go, потому что все остальные генераторы идут через artifact path и игнорируют TemplatePath. RenderOptions(def) превращает значения флагов в render.Options; RenderOptionsStructured(def) чистит BootstrapJSON для artifact-path команд.
internal/meta.Resolve и DetectRepo¶
Resolve идёт flag → viper → git config для author и email. DetectRepo regex-парсит git config remote.origin.url против GitHub SSH и HTTPS паттернов.
internal/clock.Now¶
var Now func() time.Time = time.Now indirection. Позволяет тестам пиннить wall clock (например regression-тест Sunday on-call boundary).
Snapshot'ы шаблонов: .srekit-embedded/¶
3-way merge в templates upgrade использует per-template снапшот "embedded content на момент последнего sync" как merge base. Снапшоты лежат в <user-templates-dir>/.srekit-embedded/<name> — отдельная служебная директория, которая дописывается в .gitignore user dir, чтобы не загрязнять templates-репо. См. cmd/templates.go — snapshotPath, readSnapshot, writeSnapshot, ensureSnapshotIgnored, threeWayMerge.
Релизный конвейер¶
| Тул | Назначение |
|---|---|
goreleaser |
Билдит linux/darwin/freebsd × arm64/x86_64 бинари; подписывает checksums GPG; обновляет homebrew tap. |
GitHub Actions goreleaser.yaml |
Триггерится на tag push (v*), импортит GPG-ключ, запускает goreleaser. |
crazy-max/ghaction-import-gpg@v7 |
Импортит signing key. |
HOMEBREW_TAP_GITHUB_TOKEN secret |
Fine-grained PAT с Contents:read+write на jtprogru/homebrew-tap. |
Flow релиза:
- Bump
CHANGELOG.md— переместить[Unreleased]контент в[X.Y.Z]. - Commit
release: X.Y.Zвmain. git tag -a vX.Y.Z -m vX.Y.Zиgit push origin vX.Y.Z.- goreleaser билдит 8 артефактов + checksums + GPG sig.
- Cask в
jtprogru/homebrew-tap/Casks/srekit.rbпереписывается.
Стратегия тестирования¶
| Слой | Что тестируется | Файл |
|---|---|---|
| Unit | ids.UUID/Slug, meta.Resolve/DetectRepo, tmpl.Funcs/Loader, sections.*, cliflags, render (file/stdout/dry-run/JSON/artifact) |
internal/*/*_test.go |
| Integration | Smoke через cobra.Command.SetArgs + captured stdout для каждой команды, включая templates pull/validate/diff/upgrade/list/migrate и config init |
cmd/cmd_test.go |
| Race | go test -race ./... на CI |
.github/workflows/tests.yaml |
| Lint | golangci-lint v2.12 с ~50 линтерами |
.golangci.yaml, .github/workflows/lint.yaml |
Render/tmpl unit-тесты строят loader через newFixtureLoader(t) helper, который пишет per-test .tmpl fixture во временную dir — они не зависят от того, что лежит в embed, что и удержало suite стабильным через v0.14–v0.20 миграционный churn.
Что трогать по фиче¶
| Если хочешь... | Старт здесь |
|---|---|
| Добавить новый SRE-артефакт | cmd/<name>.go (скопируй существующий генератор) + internal/tmpl/templates/<name>.yaml (v1 артефакт) |
| Добавить флаг существующему генератору | Соответствующий cmd/<name>.go; для общих output-флагов — internal/cliflags/cliflags.go |
| Изменить контент шаблона | Правь internal/tmpl/templates/<name>.yaml |
| Подкрутить layout rendered markdown (frontmatter, H1, section composition) | internal/sections/render_artifact.go |
| Добавить helper-функцию шаблонов | internal/tmpl/funcs.go |
| Модифицировать жизненный цикл шаблонов | cmd/templates.go |
См. также¶
- Контрибьютинг — local dev, Taskfile, release process.
- GitHub source — читай код напрямую, он небольшой.