Skip to content

s41r4j/s4vs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 

Repository files navigation

S4 Versioning System


Table of Contents

  1. Introduction
  2. Format Specification
  3. Component Definitions
  4. PRERELEASE Tags
  5. Version Ordering
  6. Use Cases and Examples
  7. Best Practices
  8. Implementation Guidelines
  9. Comparison with Other Systems

Introduction

S4 Versioning System is a comprehensive versioning scheme that combines semantic versioning principles with additional metadata to provide complete traceability and context for software releases.

What S4 Stands For

  • Semantic: MAJOR.MINOR.PATCH versioning
  • Stage: PRERELEASE stage identifier
  • Stamp: YYYYMMDD.HHMM timestamp
  • Sequence: BUILD number and COMMIT hash

Design Goals

  • Traceability: Every version can be traced to exact source code
  • Chronology: Clear temporal ordering of releases
  • Context: Understand the stage and purpose of each release
  • Automation: Easy to generate and parse programmatically
  • Standards Compliance: Follows ISO 8601 for dates and SemVer conventions

Format Specification

Complete Format

MAJOR.MINOR.PATCH-PRERELEASE.BUILD+YYYYMMDD.HHMM.COMMIT.BRANCH

Format Components

1.0.0-stable.1+20250127.2145.a3f5b2c.main
│ │ │    │    │  │        │    │       │
│ │ │    │    │  │        │    │       └─ BRANCH: Git branch name
│ │ │    │    │  │        │    └───────── COMMIT: Git commit hash (7 chars)
│ │ │    │    │  │        └────────────── HHMM: Time in 24-hour format
│ │ │    │    │  └─────────────────────── YYYYMMDD: Date (ISO 8601)
│ │ │    │    └────────────────────────── + : Metadata separator
│ │ │    └─────────────────────────────── BUILD: Sequential build number
│ │ └──────────────────────────────────── - : Prerelease separator
│ └────────────────────────────────────── MINOR: Minor version
└──────────────────────────────────────── MAJOR: Major version

Syntax Rules

  1. Components are separated by . (dot)
  2. PRERELEASE is preceded by - (hyphen)
  3. Metadata section starts with + (plus sign)
  4. All components are mandatory
  5. No whitespace allowed
  6. Case-sensitive for PRERELEASE and BRANCH

Component Definitions

1. MAJOR (Required)

  • Type: Non-negative integer
  • Range: 0 to ∞
  • Purpose: Incompatible API changes or breaking changes
  • Initial Value: 0 for development, 1 for first stable release

When to Increment:

  • Breaking changes to public API
  • Major architecture changes
  • Removal of deprecated features
  • Incompatible database schema changes

Rules:

  • Reset MINOR and PATCH to 0 when MAJOR is incremented
  • Example: 1.5.32.0.0

2. MINOR (Required)

  • Type: Non-negative integer
  • Range: 0 to ∞
  • Purpose: New features added in backwards-compatible manner
  • Initial Value: 0

When to Increment:

  • New functionality added
  • Significant improvements
  • Deprecation of features (not removal)
  • Large internal changes that don't break compatibility

Rules:

  • Reset PATCH to 0 when MINOR is incremented
  • Example: 1.2.51.3.0

3. PATCH (Required)

  • Type: Non-negative integer
  • Range: 0 to ∞
  • Purpose: Backwards-compatible bug fixes
  • Initial Value: 0

When to Increment:

  • Bug fixes
  • Security patches
  • Performance improvements
  • Documentation updates (in some cases)

Rules:

  • Increment for each bug fix release
  • Example: 1.2.31.2.4

4. PRERELEASE (Required)

  • Type: Lowercase alphanumeric string
  • Purpose: Indicates the release stage
  • Format: [a-z]+ (lowercase letters only)

Standard Values:

  • dev - Active development
  • alpha - Alpha testing
  • beta - Beta testing
  • rc - Release candidate
  • stable - Production release
  • hotfix - Emergency fix
  • patch - Maintenance patch
  • lts - Long-term support

See PRERELEASE Tags section for complete list.

5. BUILD (Required)

  • Type: Positive integer
  • Range: 1 to ∞
  • Purpose: Sequential counter for builds on the same day
  • Initial Value: 1

When to Increment:

  • Each new build of the same version on the same day
  • Resets to 1 when date changes or version changes

Example:

1.0.0-stable.1+20250127.1200.a3f5b2c.main  ← First build
1.0.0-stable.2+20250127.1530.b4c8e3d.main  ← Second build (same day)
1.0.0-stable.1+20250128.0900.c5d9f4e.main  ← Next day (reset to 1)

6. YYYYMMDD (Required)

  • Type: 8-digit date
  • Format: ISO 8601 basic format
  • Purpose: Date of build/release
  • Range:
    • YYYY: 1000-9999
    • MM: 01-12
    • DD: 01-31

Example: 20250127 = January 27, 2025

7. HHMM (Required)

  • Type: 4-digit time
  • Format: 24-hour time
  • Purpose: Time of build/release
  • Range:
    • HH: 00-23
    • MM: 00-59

Example: 2145 = 21:45 (9:45 PM)

8. COMMIT (Required)

  • Type: 7-character hexadecimal string
  • Format: Short Git commit hash
  • Purpose: Exact source code identifier
  • Character Set: [0-9a-f] (lowercase)

How to Generate:

git rev-parse --short=7 HEAD

Example: a3f5b2c

9. BRANCH (Required)

  • Type: String
  • Format: Valid Git branch name
  • Purpose: Identifies the source branch
  • Allowed Characters: [a-zA-Z0-9._/-]

Common Values:

  • main - Main production branch
  • develop - Development branch
  • feature-<name> - Feature branches
  • hotfix-<name> - Hotfix branches
  • release - Release preparation branch

Example: main, feature-auth, hotfix-security


PRERELEASE Tags

Standard Release Stages

Tag Stage Stability Purpose Audience
dev Development Unstable Active development Developers
alpha Alpha Unstable Early testing Internal testers
beta Beta Moderate Feature testing External testers
rc Release Candidate Stable Pre-release QA team
stable Stable Stable Production Public

Special Release Types

Tag Purpose Use Case
hotfix Emergency fixes Critical bugs in production
patch Maintenance Minor updates
lts Long-term support Maintained versions

Experimental & Preview

Tag Purpose Use Case
canary Bleeding edge Experimental features
preview Public preview Early access features
nightly Nightly builds Automated daily builds
snapshot Point-in-time Development snapshots
experimental Experimental Unstable features

Release Stage Progression

Development Flow:
dev → alpha → beta → rc → stable

Maintenance Flow:
stable → hotfix → stable
stable → patch → stable

Experimental Flow:
dev → canary → dev → alpha

Version Ordering

Primary Ordering Rules

Versions are ordered by the following hierarchy:

  1. MAJOR (numerical, ascending)
  2. MINOR (numerical, ascending)
  3. PATCH (numerical, ascending)
  4. PRERELEASE (stage precedence)
  5. TIMESTAMP (chronological)
  6. BUILD (numerical, ascending)

PRERELEASE Precedence

dev < alpha < beta < rc < stable

Special tags follow alphabetical ordering relative to standard tags.

Comparison Examples

# Version ordering (ascending):
0.1.0-dev.1+20250127.1200.a1b2c3d.main
0.1.0-alpha.1+20250128.0900.b2c3d4e.main
0.1.0-beta.1+20250130.1000.c3d4e5f.main
0.1.0-rc.1+20250201.1200.d4e5f6a.main
0.1.0-stable.1+20250205.1500.e5f6a7b.main
0.2.0-stable.1+20250210.0900.f6a7b8c.main
1.0.0-stable.1+20250215.1000.a7b8c9d.main

Comparison Algorithm

def compare_versions(v1, v2):
    # Compare MAJOR.MINOR.PATCH
    if v1.major != v2.major:
        return v1.major - v2.major
    if v1.minor != v2.minor:
        return v1.minor - v2.minor
    if v1.patch != v2.patch:
        return v1.patch - v2.patch
    
    # Compare PRERELEASE
    stage_order = ['dev', 'alpha', 'beta', 'rc', 'stable']
    if v1.prerelease != v2.prerelease:
        return stage_order.index(v1.prerelease) - stage_order.index(v2.prerelease)
    
    # Compare TIMESTAMP (YYYYMMDD.HHMM)
    if v1.timestamp != v2.timestamp:
        return v1.timestamp - v2.timestamp
    
    # Compare BUILD
    return v1.build - v2.build

Use Cases and Examples

Initial Development

0.1.0-dev.1+20250110.1000.a1b2c3d.develop
0.1.0-dev.2+20250110.1430.b2c3d4e.develop
0.1.0-dev.3+20250111.0900.c3d4e5f.develop

Feature Development

0.2.0-dev.1+20250115.1200.d4e5f6a.feature-auth
0.2.0-dev.2+20250115.1600.e5f6a7b.feature-auth
0.2.0-dev.1+20250116.1000.f6a7b8c.feature-api

Alpha Testing

0.3.0-alpha.1+20250120.0900.a7b8c9d.main
0.3.0-alpha.2+20250120.1400.b8c9d0e.main
0.3.0-alpha.3+20250121.1000.c9d0e1f.main

Beta Testing

0.4.0-beta.1+20250125.1000.d0e1f2a.release
0.4.0-beta.2+20250126.1500.e1f2a3b.release

Release Candidate

1.0.0-rc.1+20250128.1200.f2a3b4c.release
1.0.0-rc.2+20250129.0900.a3b4c5d.release

Stable Release

1.0.0-stable.1+20250201.1000.b4c5d6e.main

Bug Fix Release

1.0.1-stable.1+20250205.1400.c5d6e7f.main

Hotfix Release

1.0.2-hotfix.1+20250206.1800.d6e7f8a.hotfix-critical

Feature Release

1.1.0-stable.1+20250210.0900.e7f8a9b.main

Breaking Change Release

2.0.0-stable.1+20250220.1000.f8a9b0c.main

Best Practices

1. Version Progression

DO:

  • Follow the standard progression: dev → alpha → beta → rc → stable
  • Increment BUILD for same-day releases of same version
  • Use meaningful branch names
  • Tag releases in Git

DON'T:

  • Skip stages arbitrarily
  • Go backwards in stages (e.g., stable → beta)
  • Reuse version numbers
  • Change COMMIT or BRANCH in same version

2. Branch Naming

DO:

  • Use main for production releases
  • Use develop for development
  • Use descriptive feature branch names (feature-auth, feature-api)
  • Use specific hotfix names (hotfix-security, hotfix-memory-leak)

DON'T:

  • Use generic branch names (fix, test, new)
  • Include spaces or special characters
  • Use uppercase letters inconsistently

3. PRERELEASE Selection

DO:

  • Use dev for daily development work
  • Use alpha for internal testing
  • Use beta for external testing
  • Use rc for release candidates
  • Use stable for production releases
  • Use hotfix for emergency fixes

DON'T:

  • Mix prerelease meanings
  • Create custom tags without documentation
  • Use stable for untested code

4. Build Numbering

DO:

  • Start BUILD at 1 for each new day
  • Increment BUILD for each same-day release
  • Reset BUILD to 1 when version changes

DON'T:

  • Skip build numbers
  • Use BUILD as a global counter
  • Reuse build numbers on different days

5. Timestamp Accuracy

DO:

  • Use actual build/release time
  • Use UTC or document timezone
  • Ensure clocks are synchronized in CI/CD

DON'T:

  • Use arbitrary timestamps
  • Mix timezones
  • Backdate releases

6. Git Integration

DO:

  • Tag each release in Git
  • Use annotated tags: git tag -a v1.0.0-stable.1+20250127.2145.a3f5b2c.main
  • Include release notes in tag messages
  • Push tags to remote: git push --tags

DON'T:

  • Forget to tag releases
  • Delete or modify existing tags
  • Use lightweight tags

Implementation Guidelines

1. Automation Requirements

A proper S4 implementation should:

  1. Read current version from a version file or Git tags
  2. Determine version bump (major/minor/patch)
  3. Select appropriate PRERELEASE tag
  4. Auto-increment BUILD for same-day releases
  5. Generate timestamp automatically
  6. Extract COMMIT hash from Git
  7. Detect BRANCH from Git
  8. Update version files in the project
  9. Create Git tag with the new version
  10. Commit changes to version control

2. Required Files

project/
├── VERSION               # Contains current S4 version
├── version.json          # Machine-readable version info
├── CHANGELOG.md          # Version history
└── .version-history/     # Optional: detailed logs

VERSION file example:

1.0.0-stable.1+20250127.2145.a3f5b2c.main

version.json example:

{
  "version": "1.0.0-stable.1+20250127.2145.a3f5b2c.main",
  "major": 1,
  "minor": 0,
  "patch": 0,
  "prerelease": "stable",
  "build": 1,
  "date": "20250127",
  "time": "2145",
  "commit": "a3f5b2c",
  "branch": "main"
}

3. Version Bump Commands

Recommended CLI interface:

# Bump patch version
s4 bump patch

# Bump minor version
s4 bump minor

# Bump major version
s4 bump major

# Change prerelease stage
s4 stage alpha
s4 stage beta
s4 stage rc
s4 stage stable

# Manual version set
s4 set 2.0.0-stable

# Show current version
s4 current

# Show version history
s4 history

4. CI/CD Integration

Example GitHub Actions workflow:

name: Version and Release

on:
  push:
    branches: [ main ]

jobs:
  version:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      
      - name: Bump version
        run: |
          ./scripts/s4-bump.sh patch stable
          
      - name: Create release
        run: |
          VERSION=$(cat VERSION)
          gh release create "v$VERSION" --notes "Release $VERSION"

5. Programming Language Support

The S4 system should have parsers/generators for:

  • Python
  • JavaScript/Node.js
  • Go
  • Rust
  • Java
  • C/C++
  • Shell (Bash/Zsh)

Comparison with Other Systems

S4 vs Semantic Versioning (SemVer)

Feature SemVer S4
Format MAJOR.MINOR.PATCH MAJOR.MINOR.PATCH-PRERELEASE.BUILD+YYYYMMDD.HHMM.COMMIT.BRANCH
Prerelease Optional Required
Metadata Optional Required
Traceability Low High
Chronology No Yes
Git Integration No Yes

When to use SemVer: Simple libraries, minimal requirements
When to use S4: Complex projects, need for traceability

S4 vs Calendar Versioning (CalVer)

Feature CalVer S4
Date-based Yes Partial (metadata)
Semantic No Yes
Flexibility High Medium
Meaning Date = importance Version = compatibility

When to use CalVer: Time-based releases (Ubuntu, etc.)
When to use S4: API versioning, libraries, applications

S4 vs Git Commit Hash

Feature Git Hash S4
Uniqueness Perfect High
Readability Poor Good
Meaning None Full context
Ordering No Yes

When to use Git Hash: Internal references
When to use S4: User-facing versions, releases


Appendix A: Regular Expression

Complete S4 version regex:

^([0-9]+)\.([0-9]+)\.([0-9]+)-([a-z]+)\.([0-9]+)\+([0-9]{8})\.([0-9]{4})\.([0-9a-f]{7})\.([a-zA-Z0-9._/-]+)$

Capture Groups:

  1. MAJOR
  2. MINOR
  3. PATCH
  4. PRERELEASE
  5. BUILD
  6. DATE (YYYYMMDD)
  7. TIME (HHMM)
  8. COMMIT
  9. BRANCH

Appendix B: Validation Rules

A valid S4 version must satisfy:

  1. ✅ MAJOR, MINOR, PATCH are non-negative integers
  2. ✅ PRERELEASE contains only lowercase letters
  3. ✅ BUILD is a positive integer (≥ 1)
  4. ✅ DATE is valid (YYYYMMDD format, valid calendar date)
  5. ✅ TIME is valid (HHMM format, HH: 00-23, MM: 00-59)
  6. ✅ COMMIT is 7 lowercase hexadecimal characters
  7. ✅ BRANCH is a valid Git branch name
  8. ✅ All components are present (no optional parts)

Appendix C: Migration Guide

From SemVer to S4

SemVer: 1.2.3-beta

S4: 1.2.3-beta.1+20250127.2145.a3f5b2c.main

Migration steps:

  1. Keep MAJOR.MINOR.PATCH unchanged
  2. Normalize PRERELEASE tag (lowercase)
  3. Add BUILD number (start with 1)
  4. Add current timestamp
  5. Add current Git commit hash
  6. Add current Git branch

From CalVer to S4

CalVer: 2025.01.3

S4: 0.1.3-stable.1+20250127.2145.a3f5b2c.main

Migration steps:

  1. Decide on MAJOR.MINOR.PATCH mapping
  2. Add PRERELEASE tag (likely stable)
  3. Add BUILD, timestamp, commit, branch

Appendix D: FAQ

Q: Can I use S4 for libraries?

A: Yes! S4 is perfect for libraries that need traceability.

Q: Is BUILD necessary if I only release once per day?

A: Yes, BUILD is always required (use 1 if only one build).

Q: Can I customize PRERELEASE tags?

A: Yes, but document them clearly and keep lowercase.

Q: What if my branch name has special characters?

A: Use only alphanumeric, dots, underscores, hyphens, and slashes.

Q: How do I handle parallel development branches?

A: Use different branch names in the version string.

Q: Can I omit the commit hash if not using Git?

A: No, all components are required. Use a dummy hash like 0000000 if needed.

Q: Should I use UTC or local time?

A: Document your choice, but UTC is recommended for consistency.


License

This versioning system is released into the public domain.


Changes and Contributions

This is a living document. Suggestions and improvements are welcome.

Repository: (s41r4j/s4vs)[https://github.com/s41r4j/s4vs]

About

S4 Versioning System

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors