Documentation
¶
Overview ¶
Package steps implements the scaffold pipeline steps.
Index ¶
- Variables
- func ApplyTemplate(cfg *config.Config)
- func BuildOptivemYAML(cfg *config.Config) *projectconfig.Config
- func Cleanup(cfg *config.Config)
- func CloneRepos(cfg *config.Config, gh *shell.GitHub)
- func CloneShopTemplate(cfg *config.Config)
- func CommitAndPush(cfg *config.Config, failureNote string)
- func CreateRepos(cfg *config.Config, gh *shell.GitHub)
- func CreateSonarCloudProjects(cfg *config.Config, pc *projectconfig.Config, sc *shell.SonarCloud)
- func EnsureProjectBoard(cfg *config.Config, gh *shell.GitHub)
- func EnsureWorkflowDir(repoDir string)
- func Expand(tmpl string, vars map[string]string) string
- func ExpandRef(tmpl string, vars map[string]string) string
- func MergeVars(base, override map[string]string) map[string]string
- func PrintRegistration(cfg *config.Config)
- func ReplaceNamespaces(cfg *config.Config)
- func ReplaceRepoReferences(cfg *config.Config)
- func ReplaceSystemName(cfg *config.Config)
- func SeedSubtypeLabels(cfg *config.Config, gh *shell.GitHub)
- func SetupEnvironments(cfg *config.Config, gh *shell.GitHub)
- func SetupVariablesAndSecrets(cfg *config.Config, gh *shell.GitHub)
- func UpdateReadme(cfg *config.Config)
- func ValidateNoLeftoverTemplateRefs(cfg *config.Config)
- func VarsForCfg(cfg *config.Config) map[string]string
- func VerifyAcceptanceStages(cfg *config.Config, gh *shell.GitHub)
- func VerifyBuildSystem(cfg *config.Config)
- func VerifyCleanSystem(cfg *config.Config)
- func VerifyCleanup(cfg *config.Config, gh *shell.GitHub)
- func VerifyCommitStage(cfg *config.Config, gh *shell.GitHub)
- func VerifyCompileSystem(cfg *config.Config)
- func VerifyCompileTests(cfg *config.Config)
- func VerifyLocalSonar(cfg *config.Config)
- func VerifyProdStage(cfg *config.Config, gh *shell.GitHub)
- func VerifyQA(cfg *config.Config, gh *shell.GitHub)
- func VerifyQASignoff(cfg *config.Config, gh *shell.GitHub)
- func VerifyQAStage(cfg *config.Config, gh *shell.GitHub)
- func VerifyRunTests(cfg *config.Config, testsFile string)
- func VerifyScaffoldWorkflows(cfg *config.Config)
- func VerifySetupTests(cfg *config.Config)
- func VerifyStartSystem(cfg *config.Config)
- func VerifyStopSystem(cfg *config.Config)
- func WriteLicense(cfg *config.Config)
- func WriteOptivemYAML(cfg *config.Config)
- func WriteOptivemYAMLToFilePath(cfg *config.Config, yamlPath string) error
- func WriteOptivemYAMLToFilePathWithBanner(cfg *config.Config, yamlPath, banner string) error
- func WriteOptivemYAMLToPath(cfg *config.Config, dir string) error
Constants ¶
This section is empty.
Variables ¶
var Names = struct { MonolithCommitStageWf string MonolithBumpPatchVersionWf string MonolithPipelineStageWf string MonolithLegacyAcceptWf string MultitierBackendCommitStageWf string MultitierFrontendCommitStageWf string MultitierBumpPatchVersionWf string MultitierBackendBumpPatchWf string MultitierFrontendBumpPatchWf string MultitierPipelineStageWf string MultitierLegacyAcceptWf string BumpPatchVersionMultirepoWf string CleanupWf string DestCommitStageWf string DestBackendCommitStageWf string DestFrontendCommitStageWf string DestPipelineStageWf string DestLegacyAcceptWf string DestBumpPatchVersionWf string ShopSystemMonolithDir string ShopSystemMultitierBackend string ShopSystemMultitierFrontend string ShopSystemTestDir string ShopDockerDir string ShopDocsArchDir string ShopDocsSharedDir string ShopVersionFile string ShopSimulatorsDir string ShopStubsDir string TargetSystemDir string TargetBackendDir string TargetFrontendDir string TargetSystemTestDir string TargetDockerDir string TargetDocsDir string TargetWorkflowsDir string MonolithImageRef string MultitierBackendRef string MultitierFrontendRef string MonolithFlavorPrefix string MultitierFlavorPrefix string }{ MonolithCommitStageWf: "monolith-${lang}-commit-stage.yml", MonolithBumpPatchVersionWf: "monolith-${lang}-bump-patch-version.yml", MonolithPipelineStageWf: "monolith-${testLang}-${stage}${stageSuffix}.yml", MonolithLegacyAcceptWf: "monolith-${testLang}-acceptance-stage-legacy.yml", MultitierBackendCommitStageWf: "multitier-backend-${backendLang}-commit-stage.yml", MultitierFrontendCommitStageWf: "multitier-frontend-${frontendLang}-commit-stage.yml", MultitierBumpPatchVersionWf: "multitier-${backendLang}-bump-patch-version.yml", MultitierBackendBumpPatchWf: "multitier-backend-${backendLang}-bump-patch-version.yml", MultitierFrontendBumpPatchWf: "multitier-frontend-${frontendLang}-bump-patch-version.yml", MultitierPipelineStageWf: "multitier-${testLang}-${stage}${stageSuffix}.yml", MultitierLegacyAcceptWf: "multitier-${testLang}-acceptance-stage-legacy.yml", BumpPatchVersionMultirepoWf: "bump-patch-version-multirepo.yml", CleanupWf: "cleanup.yml", DestCommitStageWf: "commit-stage.yml", DestBackendCommitStageWf: "backend-commit-stage.yml", DestFrontendCommitStageWf: "frontend-commit-stage.yml", DestPipelineStageWf: "${stage}.yml", DestLegacyAcceptWf: "acceptance-stage-legacy.yml", DestBumpPatchVersionWf: "bump-patch-version.yml", ShopSystemMonolithDir: "system/monolith/${lang}", ShopSystemMultitierBackend: "system/multitier/backend-${backendLang}", ShopSystemMultitierFrontend: "system/multitier/frontend-${frontendLang}", ShopSystemTestDir: "system-test/${testLang}", ShopDockerDir: "docker/${testLang}/${arch}", ShopDocsArchDir: "docs/design/${arch}", ShopDocsSharedDir: "docs/design/shared", ShopVersionFile: "system/${arch}/${lang}/VERSION", ShopSimulatorsDir: "external-systems/simulators", ShopStubsDir: "external-systems/stubs", TargetSystemDir: "system", TargetBackendDir: "backend", TargetFrontendDir: "frontend", TargetSystemTestDir: "system-test", TargetDockerDir: "docker", TargetDocsDir: "docs", TargetWorkflowsDir: ".github/workflows", MonolithImageRef: "monolith-system-${lang}", MultitierBackendRef: "multitier-backend-${backendLang}", MultitierFrontendRef: "multitier-frontend-${frontendLang}", MonolithFlavorPrefix: "monolith-${lang}", MultitierFlavorPrefix: "multitier-${lang}", }
Names is the central registry of file and folder name templates produced or consumed by the scaffolder. Each field is a template string with ${...} placeholders. Use Expand(template, vars) to substitute.
Two-step process at every call site:
dst := Expand(Names.MonolithBumpPatchVersionWf, map[string]string{"lang": cfg.Lang})
Keeping every naming convention in one struct lets a maintainer answer "what filenames does the scaffolder emit?" by reading this file alone.
Functions ¶
func ApplyTemplate ¶
ApplyTemplate copies template files into the cloned repo(s).
func BuildOptivemYAML ¶ added in v1.6.2
func BuildOptivemYAML(cfg *config.Config) *projectconfig.Config
BuildOptivemYAML translates the init Config into the projectconfig schema. Kept as a pure function (no I/O) so tests can verify the translation independently of file writing, and so configinit.BuildConfig can reuse it without pulling in the disk-write tail of runWithBanner.
Tier paths are read verbatim from cfg — BuildOptivemYAML does no path derivation. Each call site that produces a Config supplies the paths matching its own on-disk layout (the flat scaffold layout via config.resolvePathFlagsForYAML's defaults, or explicit --*-path flag overrides). This keeps the YAML emitter agnostic to whether it is writing for a scaffolded repo, shop's worktree, or a hand-rolled layout.
func Cleanup ¶
Cleanup deletes the local scaffold dir(s) on success so the user is left with just the remote repo(s) + SonarCloud projects. main.go forces KeepLocal=true on failure so the broken scaffold can be inspected.
func CloneRepos ¶
CloneRepos clones the repository (and component repos for multitier) into the destination dirs pre-computed during ParseAndValidate (cfg.RepoDir etc).
func CloneShopTemplate ¶ added in v1.3.7
CloneShopTemplate clones the optivem/shop template repository pinned to cfg.ShopRef into cfg.ShopPath (pre-computed during ParseAndValidate).
func CommitAndPush ¶
CommitAndPush commits and pushes changes to GitHub.
failureNote is empty on a clean run. When non-empty, earlier scaffold steps failed and this is an intentional partial push for troubleshooting — the note is included in the commit message so git history flags it.
func CreateRepos ¶
CreateRepos creates the GitHub repository (and component repos for multitier).
func CreateSonarCloudProjects ¶
func CreateSonarCloudProjects(cfg *config.Config, pc *projectconfig.Config, sc *shell.SonarCloud)
CreateSonarCloudProjects creates the SonarCloud org and the per-code-tier projects named in gh-optivem.yaml. Walks the loaded projectconfig's sonar_project fields (system or backend+frontend, plus system_test) so the YAML is the single source of truth for which projects exist; an operator hand-edit (or future `config refresh`) propagates here for free. Now creates 3 projects for monolith (system + system_test) and 4 for multitier (backend + frontend + system_test) — up from 1/2 in the pre-materialization world that relied on SonarCloud's auto-provision of the system-test project on first scan.
func EnsureProjectBoard ¶ added in v1.3.31
EnsureProjectBoard creates or verifies the GitHub Project (v2) board the ATDD pipeline depends on. Two sub-paths:
Path A — cfg.ProjectURL == "": list/create a project named cfg.SystemName under cfg.Owner, replace the default Status set with the canonical six, link the scaffolded repo(s), and write the URL back into cfg.ProjectURL so the later WriteOptivemYAML step bakes it into gh-optivem.yaml. When the source gh-optivem.yaml init read at startup had project.url empty, the auto-created URL is also persisted back into that source file (cfg.SourceConfigPath) so re-runs and future commands keyed off it see the URL — reused-by-title runs (source URL already set) leave the source file alone.
Path B — cfg.ProjectURL set: validate the operator-supplied URL exposes every ATDD-required Status option. If any are missing, prompt for confirmation (or honour --yes) and additively add them — existing options on the board are preserved.
Short-circuits to a no-op when cfg.NoProject is true. The gh argument is accepted for signature consistency with sibling Setup* steps but unused — gh project commands take --owner/--repo per-call rather than a Repo binding.
func EnsureWorkflowDir ¶
func EnsureWorkflowDir(repoDir string)
EnsureWorkflowDir creates the .github/workflows directory in a repo.
func Expand ¶ added in v1.3.23
Expand substitutes ${name} placeholders in tmpl using vars. Unknown placeholders panic — the placeholder name must be in recognizedPlaceholders. Missing keys in vars expand to empty string, which is intentional for optional fields (e.g. ${stageSuffix} is "" for docker deploy, "-cloud" for cloud-run).
func ExpandRef ¶ added in v1.3.23
ExpandRef is Expand followed by stripping a trailing ".yml" — the form used in workflow `name:` / `concurrency.group:` / `uses:` substring patterns.
func MergeVars ¶ added in v1.3.23
MergeVars returns a new map with base entries overridden by override entries.
func PrintRegistration ¶
PrintRegistration outputs structured project registration info that can be copy-pasted into the course registration form or tracking sheet.
func ReplaceNamespaces ¶
ReplaceNamespaces swaps the 6 company placeholder forms (MyCompany / myCompany / my-company / mycompany / my_company / MY_COMPANY) for the user's owner-name casings in file content, filenames, and directory names.
func ReplaceRepoReferences ¶
ReplaceRepoReferences rewrites the handful of publisher-real strings that must point at the user's GitHub / GHCR / SonarCloud identity in the scaffolded repo. These stay in the template verbatim so the template's own CI continues to work; the scaffolder rewrites them per user at scaffold time.
Everything else — .sln names, Java packages, compose project names, TS identifiers — is driven by the MyCompany / MyShop generic placeholders handled by ReplaceNamespaces and ReplaceSystemName.
func ReplaceSystemName ¶
ReplaceSystemName swaps the 6 system placeholder forms (MyShop / myShop / my-shop / myshop / my_shop / MY_SHOP) for the user's system-name casings in file content, filenames, and directory names.
func SeedSubtypeLabels ¶ added in v1.3.29
SeedSubtypeLabels creates the three `subtype:*` labels the ATDD runtime reads from task tickets to dispatch the right structural cycle. Idempotent (gh label create --force updates color/description on existing labels).
func SetupEnvironments ¶
SetupEnvironments creates GitHub environments on the main repo.
Scaffolded repos only ever host one arch+lang combination, so the env names drop the arch+lang prefix used inside optivem/shop and are just the bare stage names. The workflow content rewrite in apply_template.go rewrites the template's prefixed "environment:" references to match.
func SetupVariablesAndSecrets ¶ added in v1.3.7
SetupVariablesAndSecrets sets GitHub Actions variables and secrets.
func UpdateReadme ¶
UpdateReadme generates README.md for the repo(s).
func ValidateNoLeftoverTemplateRefs ¶ added in v1.3.9
ValidateNoLeftoverTemplateRefs checks that ApplyTemplate's content replacements covered every case. Each forbidden substring is a literal that the replacement rules promise to rewrite — if any remain anywhere in the scaffolded repo (workflows, source, tests, docs, build files), a replacement rule is missing a case. Fail with the concrete paths so the gap is obvious.
Scanning the whole repo (not just workflows/compose) is intentional: these substrings have no legitimate place in a scaffolded project. A leftover in source or tests is just as much a bug as one in a workflow — it means a user's clone will reference paths or names that don't exist.
Runs after commit+push, following the convention of ValidateNoLeftoverSystemNames (broken output visible in the remote for troubleshooting).
func VarsForCfg ¶ added in v1.3.23
VarsForCfg builds the placeholder map for a Config. Stage and stageSuffix are not set (callers add per-call values).
frontendLang is hardcoded to "react" — the placeholder feeds shop-side paths (system/multitier/frontend-react/, multitier-frontend-react-*.yml) where "react" is the framework directory token, not the source language. cfg.FrontendLang ("typescript") is the user-facing source language and is not used here.
func VerifyAcceptanceStages ¶ added in v1.3.8
VerifyAcceptanceStages triggers the latest and legacy acceptance-stage workflows and watches both runs in parallel. Legacy is skipped when --no-legacy is set. Downstream stages (QA, prod) resolve the latest RC internally when dispatched with an empty version, so no RC lookup is needed here.
func VerifyBuildSystem ¶ added in v1.6.1
VerifyBuildSystem builds the docker images declared in systems.yaml. In multirepo mode it first symlinks the component repos into the root repo so that compose build contexts resolve.
func VerifyCleanSystem ¶ added in v1.6.1
VerifyCleanSystem removes the locally-built images + volumes from the stacks. Mirrors `gh optivem system clean`.
func VerifyCleanup ¶ added in v1.3.20
VerifyCleanup triggers cleanup.yml in dry-run mode in every repo where it was scaffolded. cleanup.yml is otherwise only fired by its nightly schedule, so a syntax error or stale action reference would silently slip past init and surface the next night when the student isn't looking. Dry-run prevents it from touching the freshly published v1.0.0 release. In multirepo setups cleanup.yml is also copied to the sister repos (system / backend+frontend), so each is exercised in turn — apply_template.go writes the same template content to all of them but each repo has its own actions enablement and permissions, so we still verify each.
func VerifyCommitStage ¶
VerifyCommitStage waits for commit stage workflow to pass.
func VerifyCompileSystem ¶ added in v1.6.1
VerifyCompileSystem compiles the system tier(s) locally to catch broken imports, type errors, and case-sensitive path mismatches before pushing.
func VerifyCompileTests ¶ added in v1.6.1
VerifyCompileTests compiles the system-test/ tier in cfg.TestLang.
func VerifyLocalSonar ¶ added in v1.3.14
VerifyLocalSonar runs the per-component run-sonar.sh script against each scaffolded component, pushing analysis to the SonarCloud project created earlier in the same run. The token is picked up from $SONAR_TOKEN by each script (already validated and set on the parent process env). Requires bash on PATH (Git Bash on Windows). Skipped entirely when --no-local-sonar is set (the gate lives in main.go).
func VerifyProdStage ¶
VerifyProdStage triggers and verifies production stage.
func VerifyQA ¶ added in v1.3.8
VerifyQA runs the QA stage followed by the QA signoff. Each workflow resolves the latest relevant RC internally when dispatched with an empty version.
func VerifyQASignoff ¶
VerifyQASignoff triggers and verifies QA signoff.
func VerifyQAStage ¶
VerifyQAStage triggers and verifies QA stage.
func VerifyRunTests ¶ added in v1.6.1
VerifyRunTests runs the suites declared in testsFile against the already- running system. Used twice in the pipeline: once with "tests.yaml" (latest) and once with "tests.legacy.yaml" (legacy, when --no-legacy is unset).
func VerifyScaffoldWorkflows ¶ added in v1.3.21
VerifyScaffoldWorkflows lints the scaffolded workflows with actionlint. Catches broken `uses: ./.github/workflows/*.yml` references, invalid syntax, and other static issues that would otherwise only surface 10+ minutes into the verification pipeline at workflow-dispatch time (HTTP 422 "workflow was not found"). Runs after apply_template has rewritten filenames and content, before any push or workflow trigger.
func VerifySetupTests ¶ added in v1.6.1
VerifySetupTests runs the setupCommands from tests.yaml (npm ci, npx playwright install chromium, ...). Mirrors `gh optivem test setup`.
func VerifyStartSystem ¶ added in v1.6.1
VerifyStartSystem brings up the docker stacks declared in systems.yaml and waits for each to pass its health probe. Mirrors `gh optivem system start --restart`: the verify/init flow always runs immediately after a fresh image build, so any containers still running from a previous scaffold of the same system must be recreated to pick up the new images.
func VerifyStopSystem ¶ added in v1.6.1
VerifyStopSystem tears down the docker stacks. Mirrors `gh optivem system stop`.
func WriteLicense ¶ added in v1.3.20
WriteLicense writes a LICENSE file to the scaffolded repo(s) using the GitHub licenses API. Runs as a regular scaffold step (not part of repo initialization) so it works whether the repo was created by gh-optivem or pre-created by a wrapper script.
func WriteOptivemYAML ¶ added in v1.3.26
WriteOptivemYAML writes <repoRoot>/gh-optivem.yaml in the scaffolded repo(s), translating already-resolved init flags into the projectconfig.Config schema. The file is consumed by the ATDD pipeline at runtime (project URL, repo strategy, system architecture + per-component layout, system_test layout, and external-system stand-in declarations).
Multi-repo: writes the same file to every per-tier repo so `gh optivem implement` can be invoked from any of them.
`cfg.RepoStrategy` arrives in the init flag's spelling (`monorepo` / `multirepo`); this function translates to the schema's spelling (`mono-repo` / `multi-repo`) at write-time so the two surfaces can evolve independently.
System.Config / SystemTest.Config are auto-populated to the paths that copySystemTests just produced (`docker/systems.yaml`, `system-test/tests.yaml`). Without this, a freshly-scaffolded repo wouldn't work with `gh optivem system start` / `gh optivem test run` from repo root — the runner defaults are `./systems.yaml` / `./tests.yaml` in the working directory, which don't resolve from the scaffolded repo root.
func WriteOptivemYAMLToFilePath ¶ added in v1.3.32
WriteOptivemYAMLToFilePath renders cfg as a projectconfig.Config and writes it to an exact yaml file path. Used by `gh optivem config init` when the caller has chosen a non-default filename via the persistent --config flag (e.g. `gh-optivem.monolith-java.yaml`).
func WriteOptivemYAMLToFilePathWithBanner ¶ added in v1.4.0
WriteOptivemYAMLToFilePathWithBanner is the variant used by the interactive `config init` recovery flow: marshals the YAML and prepends a banner comment block so the operator sees which fields were defaulted before running `gh optivem config validate`. The non- interactive command keeps using WriteOptivemYAMLToFilePath (no banner) — operators running that one have supplied every flag and don't need a review checklist.
func WriteOptivemYAMLToPath ¶ added in v1.3.29
WriteOptivemYAMLToPath renders cfg as a projectconfig.Config and writes it to <dir>/gh-optivem.yaml. Single-target sibling of WriteOptivemYAML — used by `gh optivem config init` where the caller knows exactly one directory to write into (CWD or --dir), with no multirepo fan-out.
Types ¶
This section is empty.