Documentation
¶
Overview ¶
Package release provides the helper logic the release workflow invokes via cmd/mdsmith-release/. The package was originally a set of bash scripts under scripts/, but JSON/TOML editing in perl regex and indirect testing through `bash <script>` made them brittle. The Go port runs under one toolchain, has direct tests, and reports actionable errors without shelling out.
Production code constructs a Toolkit via New(); tests can substitute a fake FS via NewWithFS to exercise IO error branches the real OS cannot reliably trigger.
Index ¶
- Constants
- Variables
- func BuildNpmPlatforms(rootDir, artifactsDir, outDir string) error
- func BuildWheels(rootDir, artifactsDir, outDir string) error
- func Check(root string) error
- func Stamp(root, version string) error
- func ValidateSemver(v string) error
- type FS
- type Manifest
- type ManifestKind
- type Runner
- type Toolkit
- func (t *Toolkit) BuildNpmPlatforms(rootDir, artifactsDir, outDir string) error
- func (t *Toolkit) BuildWheels(rootDir, artifactsDir, outDir string) error
- func (t *Toolkit) Check(root string) error
- func (t *Toolkit) Stamp(root, version string) error
- func (t *Toolkit) TrackedManifests(root string) []Manifest
Constants ¶
const DevSentinel = "0.0.0-dev"
DevSentinel is the version every tracked manifest carries between releases. Stamp rewrites it to the cleaned tag during release; Check fails the version-guard CI job when a hand-edit pushes anything else to main.
Variables ¶
var PlatformPackages = []string{
"@mdsmith/linux-x64",
"@mdsmith/linux-arm64",
"@mdsmith/darwin-x64",
"@mdsmith/darwin-arm64",
"@mdsmith/win32-x64",
}
PlatformPackages enumerates the @mdsmith/<platform> optional- dependency keys the npm root must list. Stays in lock-step with the build matrix in .github/workflows/release.yml.
Functions ¶
func BuildNpmPlatforms ¶
BuildNpmPlatforms delegates to a default-OS Toolkit (see Stamp).
func BuildWheels ¶
BuildWheels delegates to a default-OS Toolkit (see Stamp).
func Stamp ¶
Stamp delegates to a default-OS Toolkit so callers without an explicit Toolkit (for example, the cmd binary) can stay terse. Tests that need fault injection construct a Toolkit via NewWithFS instead.
func ValidateSemver ¶
ValidateSemver rejects empty strings, leading-v tags ("v1.2.3"), and any version that isn't conforming SemVer.
Types ¶
type FS ¶
type FS interface {
// Stat returns the FileInfo for the named file, mirroring
// os.Stat.
Stat(name string) (os.FileInfo, error)
// ReadFile reads the named file, mirroring os.ReadFile.
ReadFile(name string) ([]byte, error)
// WriteFile writes data to the named file, mirroring
// os.WriteFile.
WriteFile(name string, data []byte, perm fs.FileMode) error
// ReadDir reads the named directory, mirroring os.ReadDir.
ReadDir(name string) ([]os.DirEntry, error)
// MkdirAll creates name and any parents, mirroring
// os.MkdirAll.
MkdirAll(path string, perm fs.FileMode) error
// MkdirTemp creates a new temporary directory, mirroring
// os.MkdirTemp.
MkdirTemp(dir, pattern string) (string, error)
// Rename renames (moves) oldpath to newpath, mirroring
// os.Rename.
Rename(oldpath, newpath string) error
// RemoveAll removes path and any children, mirroring
// os.RemoveAll.
RemoveAll(path string) error
}
FS is the small filesystem surface the release toolkit uses. Production paths use osFS (delegating to the real syscalls); tests inject a fault-injecting fake to exercise IO error branches that real filesystems don't reliably trigger (mid-pipeline mkdir failure, rename target on a non-directory, disk-full WriteFile, etc.).
We intentionally keep this independent of stdlib's read-only `io/fs.FS`. The release toolkit needs Mkdir/Write/Rename alongside Read/Stat, and stdlib's interface only covers reads.
type Manifest ¶
type Manifest struct {
Path string
Kind ManifestKind
OptionalDeps bool
}
Manifest is one tracked file. OptionalDeps marks the npm root — only that file carries @mdsmith/* pins.
func TrackedManifests ¶
TrackedManifests is a thin wrapper over the default Toolkit so callers without an explicit Toolkit can still introspect the tracked set.
type ManifestKind ¶
type ManifestKind int
ManifestKind tells the rewrite/check helpers which syntax to expect: JSON for npm package manifests, TOML for pyproject.
const ( // ManifestJSON marks JSON manifests (npm package.json files). ManifestJSON ManifestKind = iota // ManifestTOML marks TOML manifests (python pyproject.toml). ManifestTOML )
type Runner ¶
type Runner interface {
// RunCommand executes name+args in dir, with stdout/stderr
// inherited from the calling process. Mirrors exec.Cmd.Run
// semantics: a non-zero exit returns *exec.ExitError; other
// failures (binary not found, IO) return their underlying
// error.
RunCommand(dir, name string, args ...string) error
}
Runner runs an external command. The release toolkit shells out to `python -m build` and `python -m wheel tags` for the PyPI publish path; tests inject a fake Runner to cover those branches without putting python on PATH.
type Toolkit ¶
type Toolkit struct {
// contains filtered or unexported fields
}
Toolkit owns a configured FS and Runner and exposes the release helpers (Stamp, Check, BuildNpmPlatforms, BuildWheels) as methods. `New()` returns a Toolkit backed by the real OS for both; tests can use `NewWithFS(fakeFS)` or `NewWithDeps` to drive error paths that the OS does not expose.
func New ¶
func New() *Toolkit
New returns a Toolkit backed by the real OS filesystem and command runner.
func NewWithDeps ¶
NewWithDeps returns a Toolkit with custom FS and Runner. Used by tests that exercise both IO and command-execution faults.
func NewWithFS ¶
NewWithFS returns a Toolkit with a custom FS and the OS-backed Runner. Convenience helper for tests that only need IO faults.
func (*Toolkit) BuildNpmPlatforms ¶
BuildNpmPlatforms emits one ready-to-publish npm sub-package directory per supported platform under outDir, copying the matching release artifact from artifactsDir. Stamp must run first because the version is taken from rootDir/npm/mdsmith/package.json.
func (*Toolkit) BuildWheels ¶
BuildWheels builds one platform-tagged wheel per supported host from prebuilt binaries in artifactsDir, writing the wheels to outDir. The python source tree at rootDir/python is staged per build with the matching binary embedded under mdsmith/_bin/, then `python -m build` produces a py3-none-any wheel which `python -m wheel tags` retags to the correct platform tag (in both the filename and the dist-info/WHEEL metadata).
Requires `python -m build`, `python -m wheel`, and the hatchling build backend on PATH. Stamp must run first so pyproject.toml carries the published version.
func (*Toolkit) Check ¶
Check accumulates every problem with the tracked manifests (missing file, missing field, drifted version, missing or drifted @mdsmith/* pin) into one multi-line error. The version-guard CI job uses Check; reporting all problems at once is more useful than failing on the first.
func (*Toolkit) Stamp ¶
Stamp rewrites every tracked manifest under root from the dev sentinel to version. Idempotent: running with the same version twice produces no further change. A required manifest that's missing a version field — or, for the npm root, missing the @mdsmith/* optionalDependencies block — is a hard error.
func (*Toolkit) TrackedManifests ¶
TrackedManifests returns the set of manifests Stamp rewrites and Check verifies via the Toolkit's FS. The npm/platforms/ directory is not in source control — BuildNpmPlatforms emits the platform sub-packages under its own outDir argument (npm/dist in the release workflow). Anything that has already materialised npm/platforms/<plat>/package.json (a previous local Stamp+BuildNpmPlatforms invocation, a custom staging step) is stamped here too; if the directory is absent the helper just returns the four checked-in manifests.