What is semantic versioning and why must I use it in EK9 packages?

← Getting Started · Ref: Q15

EK9 enforces semantic versioning (semver) for all packages. This is not optional: the compiler and dependency resolver rely on version numbers to make safe decisions about compatibility.

Version format: MAJOR.MINOR.PATCH-BUILD

  version as Version: 2.1.3-0

What each part means:

  MAJOR  breaking API changes (consumers must update their code)
  MINOR  new features, backwards compatible (safe to upgrade)
  PATCH  bug fixes, backwards compatible (safe to upgrade)
  BUILD  auto-incremented on every build attempt

Feature branch format: MAJOR.MINOR.PATCH-FEATURE-BUILD

  version as Version: 2.1.3-beta-5
  Used for pre-release or experimental work.

Why EK9 ENFORCES this:
- The dependency resolver auto-selects the highest compatible PATCH version. If two of your dependencies require the same library at 1.2.0-0 and 1.2.3-0, the resolver picks 1.2.3-0 because same MAJOR.MINOR means compatible.
- Different MAJOR versions cause the build to FAIL. This protects you from silently using an incompatible API.
- Without enforced semver, automatic version rationalization would be unsafe.

CLI commands for version management:

  ek9 -IV major app.ek9     increment major (resets minor, patch, build)
  ek9 -IV minor app.ek9     increment minor (resets patch, build)
  ek9 -IV patch app.ek9     increment patch (resets build)
  ek9 -IV build app.ek9     increment build number only
  ek9 -SV 2.0.0 app.ek9    set version explicitly (zeros build)
  ek9 -SF 2.0.0-rc app.ek9  set feature version
  ek9 -PV app.ek9           print current version

Common workflow:

  1. Develop and test
  2. ek9 -IV patch app.ek9   bump patch for bug fix release
  3. ek9 -P app.ek9          package (uses -O3)
  4. ek9 -D app.ek9          deploy

Related questions:
- How do I manage dependencies? (Q7)
- How do I see resolved dependencies? (Q14)

See Q7 for managing dependencies. See Q14 for listing resolved dependencies. See Q270 for supply chain security.

Example

defines module qa.getting.started.semantic.versioning

  defines package

    version as Version: 2.1.3-0
    description as String = "Demonstrates semantic versioning in EK9"
    license <- "MIT"
    publicAccess <- true

    tags <- [
      "example",
      "versioning"
    ]

    applyStandardIncludes <- true

  defines program
    SemanticVersioning()
      stdout <- Stdout()

      stdout.println("Package version: 2.1.3-0")
      stdout.println("MAJOR=2 MINOR=1 PATCH=3 BUILD=0")
      stdout.println("Run: ek9 -PV thisFile.ek9 to see current version")
      stdout.println("Run: ek9 -IV minor thisFile.ek9 to bump to 2.2.0-0")

Common mistakes

E01040 — Defining two constructs with the same name in the same module triggers E01040 — duplicate construct. Each program or function name must be unique. See ek9 -h E01040 for details.

Incorrect:

defines program
    SemanticVersioning()
      stdout <- Stdout()
    SemanticVersioning()
      stdout <- Stdout()

Correct:

defines program
    SemanticVersioning()
      stdout <- Stdout()
Other ways to ask this
  • Why does EK9 enforce semantic versioning?
  • How does version numbering work in EK9?
  • What do the version numbers mean in defines package?
  • I use Maven versions or npm version, how does EK9 handle versioning?
  • How do I version my EK9 package?

Coming from another language?

Java: Maven versions are conventions not enforced (versions-maven-plugin for management). npm: semver by convention, npm version command. Rust: Cargo.toml version field, cargo semver-checks for enforcement. Go: module versions with /v2 path suffix for major. Python: PEP 440 versioning, not enforced. EK9 enforces semver at the compiler level: the dependency resolver depends on it for safe version rationalization.

Keywords: beginner, start, versioning, major, semantic, npm, compatibility, patch, cargo, breaking, build, mvn, intro, maven, first, semver, minor, version, increment, package