How to Use Version Management in the Fabrica-Kit: Parsing and Validating Service Versions

Fabrica-Kit centralizes version handling in the version package, where GetSubVersion parses zone-prefixed strings like "us-v1.20230428_153224" into availability zones and numeric components for reliable service identification.

Fabrica-Kit provides a robust version management system through its dedicated version package and global profile state. This system allows services to parse, validate, and propagate standardized version strings across distributed deployments. According to the go-pantheon/fabrica-kit source code, version strings follow a strict zone-v<major>.<minor> pattern that enables precise service identification and compatibility checks.

Understanding the Version String Format

Fabrica-Kit expects version strings to follow the exact pattern zone-v<major>.<minor>. This format encodes both geographic deployment information and semantic versioning data in a single identifier.

The parser enforces these rules:

  • Zone prefix: Any non-empty identifier representing the availability zone or region (e.g., "us", "eu", "asia")
  • Major version: A decimal integer following the literal "v" character
  • Minor version: A decimal integer that may contain underscores which are automatically stripped (e.g., 20230428_153224 becomes 20230428153224)

Valid examples include "us-v1.20230428_153224" and "eu-v2.0". Invalid strings that lack the "v" prefix, contain wrong section counts, or include extra components will fail validation.

Parsing Versions with GetSubVersion

The version package exposes GetSubVersion in version/version.go as the primary mechanism for decomposing version strings into structured data.

Function Signature and Return Values

Call GetSubVersion with a version string to receive three values:

az, sv, ok := version.GetSubVersion(v)
  • az (string): The availability-zone or region prefix (the part before the hyphen)
  • sv ([]int64): A two-element slice containing the major and minor numbers as integers
  • ok (bool): true only if the input matches the required zone-vX.Y pattern

When parsing "us-v1.20230428_153224", the function returns "us" for the zone, []int64{1, 20230428153224} for the versions, and true for success.

Handling Invalid Versions

If the string does not conform to the expected pattern, GetSubVersion returns defensive empty values. The function provides false for the ok boolean, an empty string for az, and nil for sv. This design allows safe error handling without panic risks.

Integrating Version Management with the Global Profile

During service startup, the profile.Init function stores the version string in global state accessible via profile.Version(). This integration lives in profile/vars.go, where the package maintains a private _version variable and exposes it through the getter function.

Typical initialization looks like this:

profile.Init("my-service", profile.ProfileProd, "blue", 2, "eu-v2.0", "node-42")

After initialization, profile.Version() returns "eu-v2.0", which you can then pass to version.GetSubVersion for parsing. This pattern ensures version metadata propagates consistently across logging, metrics, and compatibility checks.

Practical Implementation Examples

The version package includes comprehensive unit tests in version/version_test.go demonstrating expected behaviors. These examples show common production usage patterns.

Parsing a Valid Version String

Extract zone and version components from a properly formatted service identifier:

package main

import (
	"fmt"

	"github.com/go-pantheon/fabrica-kit/version"
)

func main() {
	v := "us-v1.20230428_153224"
	az, sv, ok := version.GetSubVersion(v)
	if !ok {
		fmt.Println("invalid version")
		return
	}
	fmt.Printf("zone: %s, major: %d, minor: %d\n", az, sv[0], sv[1])
	// Output: zone: us, major: 1, minor: 20230428153224
}

Detecting Invalid Formats

Validate user input or configuration values before processing:

az, sv, ok := version.GetSubVersion("invalid-format")
if !ok {
    // sv is nil and az is ""
    fmt.Println("Version string does not follow zone-vX.Y pattern")
}

Accessing Version Data from the Global Profile

Combine profile initialization with version parsing for runtime service identification:

package main

import (
	"github.com/go-pantheon/fabrica-kit/profile"
	"github.com/go-pantheon/fabrica-kit/version"
)

func initService() {
	// Example: service is started with version "eu-v2.0"
	profile.Init("my-service", profile.ProfileProd, "blue", 2, "eu-v2.0", "node-42")

	ver := profile.Version() // "eu-v2.0"
	az, sv, ok := version.GetSubVersion(ver)
	if ok {
		// Use az and sv for logging, metrics, or compatibility checks
		_ = az   // e.g., "eu"
		_ = sv[0] // major version 2
	}
}

Summary

  • Fabrica-Kit version management relies on the version package and profile integration for standardized service identification.
  • Strict format compliance is required: version strings must follow zone-v<major>.<minor> where underscores in the minor version are ignored.
  • GetSubVersion in version/version.go provides safe parsing with boolean validation to prevent runtime errors from malformed strings.
  • Global state management occurs through profile.Init and profile.Version() in profile/vars.go, making version data accessible throughout the service lifecycle.
  • Comprehensive testing in version/version_test.go validates both valid patterns and edge cases for reliable production deployment.

Frequently Asked Questions

What format does Fabrica-Kit require for version strings?

Fabrica-Kit requires the format zone-v<major>.<minor>, where zone is a non-empty identifier, major is a decimal integer, and minor is a decimal integer that may contain underscores. The parser ignores underscores in the minor component, allowing timestamps like 20230428_153224 to be treated as 20230428153224.

How does GetSubVersion handle timestamps in version minors?

The function automatically strips underscores from the minor version component before converting it to an integer. This allows version strings like "us-v1.20230428_153224" to parse correctly, returning 20230428153224 as the minor version number without requiring pre-processing.

Where is the service version stored after calling profile.Init?

The version string is stored in the private _version variable within profile/vars.go. The package exposes this value through the profile.Version() getter function, making it accessible to any package that imports github.com/go-pantheon/fabrica-kit/profile.

What happens when GetSubVersion receives an invalid version?

When the input string fails to match the zone-vX.Y pattern, GetSubVersion returns an empty string for the zone, nil for the version slice, and false for the boolean ok flag. This defensive return pattern allows callers to implement explicit error handling without risking nil pointer dereferences.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →