steps

package
v1.6.6-rc.153 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 16, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package steps implements the scaffold pipeline steps.

Index

Constants

This section is empty.

Variables

View Source
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

func ApplyTemplate(cfg *config.Config)

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

func Cleanup(cfg *config.Config)

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

func CloneRepos(cfg *config.Config, gh *shell.GitHub)

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

func CloneShopTemplate(cfg *config.Config)

CloneShopTemplate clones the optivem/shop template repository pinned to cfg.ShopRef into cfg.ShopPath (pre-computed during ParseAndValidate).

func CommitAndPush

func CommitAndPush(cfg *config.Config, failureNote string)

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

func CreateRepos(cfg *config.Config, gh *shell.GitHub)

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

func EnsureProjectBoard(cfg *config.Config, gh *shell.GitHub)

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

func Expand(tmpl string, vars map[string]string) string

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

func ExpandRef(tmpl string, vars map[string]string) string

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

func MergeVars(base, override map[string]string) map[string]string

MergeVars returns a new map with base entries overridden by override entries.

func PrintRegistration

func PrintRegistration(cfg *config.Config)

PrintRegistration outputs structured project registration info that can be copy-pasted into the course registration form or tracking sheet.

func ReplaceNamespaces

func ReplaceNamespaces(cfg *config.Config)

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

func ReplaceRepoReferences(cfg *config.Config)

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

func ReplaceSystemName(cfg *config.Config)

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

func SeedSubtypeLabels(cfg *config.Config, gh *shell.GitHub)

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

func SetupEnvironments(cfg *config.Config, gh *shell.GitHub)

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

func SetupVariablesAndSecrets(cfg *config.Config, gh *shell.GitHub)

SetupVariablesAndSecrets sets GitHub Actions variables and secrets.

func UpdateReadme

func UpdateReadme(cfg *config.Config)

UpdateReadme generates README.md for the repo(s).

func ValidateNoLeftoverTemplateRefs added in v1.3.9

func ValidateNoLeftoverTemplateRefs(cfg *config.Config)

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

func VarsForCfg(cfg *config.Config) map[string]string

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

func VerifyAcceptanceStages(cfg *config.Config, gh *shell.GitHub)

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

func VerifyBuildSystem(cfg *config.Config)

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

func VerifyCleanSystem(cfg *config.Config)

VerifyCleanSystem removes the locally-built images + volumes from the stacks. Mirrors `gh optivem system clean`.

func VerifyCleanup added in v1.3.20

func VerifyCleanup(cfg *config.Config, gh *shell.GitHub)

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

func VerifyCommitStage(cfg *config.Config, gh *shell.GitHub)

VerifyCommitStage waits for commit stage workflow to pass.

func VerifyCompileSystem added in v1.6.1

func VerifyCompileSystem(cfg *config.Config)

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

func VerifyCompileTests(cfg *config.Config)

VerifyCompileTests compiles the system-test/ tier in cfg.TestLang.

func VerifyLocalSonar added in v1.3.14

func VerifyLocalSonar(cfg *config.Config)

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

func VerifyProdStage(cfg *config.Config, gh *shell.GitHub)

VerifyProdStage triggers and verifies production stage.

func VerifyQA added in v1.3.8

func VerifyQA(cfg *config.Config, gh *shell.GitHub)

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

func VerifyQASignoff(cfg *config.Config, gh *shell.GitHub)

VerifyQASignoff triggers and verifies QA signoff.

func VerifyQAStage

func VerifyQAStage(cfg *config.Config, gh *shell.GitHub)

VerifyQAStage triggers and verifies QA stage.

func VerifyRunTests added in v1.6.1

func VerifyRunTests(cfg *config.Config, testsFile string)

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

func VerifyScaffoldWorkflows(cfg *config.Config)

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

func VerifySetupTests(cfg *config.Config)

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

func VerifyStartSystem(cfg *config.Config)

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

func VerifyStopSystem(cfg *config.Config)

VerifyStopSystem tears down the docker stacks. Mirrors `gh optivem system stop`.

func WriteLicense added in v1.3.20

func WriteLicense(cfg *config.Config)

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

func WriteOptivemYAML(cfg *config.Config)

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

func WriteOptivemYAMLToFilePath(cfg *config.Config, yamlPath string) error

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

func WriteOptivemYAMLToFilePathWithBanner(cfg *config.Config, yamlPath, banner string) error

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

func WriteOptivemYAMLToPath(cfg *config.Config, dir string) error

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL