HeadVer Versioning Specification

repository·main·Indexed 43 days ago

https://github.com/line/headver

A versioning specification using the format {head}.{yearweek}.{build} to simplify release management. It combines a manually modifiable major version ({head}) with automatic ISO-8601 time-based increments ({yearweek}) and build-server increments ({build}). Includes implementation examples for Bash, Elixir, Fastlane, Gradle, PowerShell, TypeScript, and GitHub Actions.

Tokens
5.6K
Snippets
17
Records
25
Agent score
52%

What's inside HeadVer

  1. HeadVer Tagging Variables and Components

    main

    When constructing a HeadVer tag in a workflow, the following variables and components are used to form the {head}.{yearweek}.{build} pattern:

    • VERSION_PREFIX: A string prefix (commonly v).
    • VERSION_HEAD: The first digit of the version extracted from package.json (e.g., if version is 0.1.0, head is 0).
    • VERSION_YEAR: The last two digits of the year of the ISO week number (calculated via date +%g).
    • VERSION_WEEK: The ISO week number, where Monday is the first day of the week (01..53) (calculated via date +%V).
    • VERSION_BUILD: A unique number for each execution of a specific workflow (typically using ${{ github.run_number }}).
  2. Configure the {build} component

    main

    The {build} is the final part of the HeadVer version and is intended to be an automatically incremental number.

    • Automation: It is strongly recommended to use a build server with an auto-incremental counter to stamp this value.
    • Purpose: Guarantees that every release binary is unique and distinguishable.
    • Notation: Can be written as b59 or b.59.
  3. Understand the HeadVer versioning system

    main

    HeadVer is a versioning specification using the format {head}.{yearweek}.{build}. It is designed to simplify version management by only requiring one manual number ({head}), while the rest are automatically generated. This system is compatible with Semantic Versioning (SemVer) and ensures every release is distinguishable and incremental.

    Version Components:

    • {head}: A zero-based, manually modifiable number. It represents major version shifts (e.g., when a new AppStore release occurs).
    • {yearweek}: An automatic 4-digit number consisting of a 2-digit year and a 2-digit week number (e.g., 2134 for the 34th week of 2021).
    • {build}: An automatic, incremental number typically provided by a build server to distinguish specific release binaries.
  4. Configure the {head} component

    main

    The {head} is the first part of the HeadVer version. It is a zero-based number that you must update manually.

    • Manual Control: You decide when to increment this number.
    • Migration Tip: If migrating from a software version like v2.1.0, it is recommended to start your HeadVer {head} at 3.
    • Notation: Can be written as v3 or v.3.
  5. Configure the {yearweek} component

    main

    The {yearweek} is the second part of the HeadVer version and is automatically generated. It must always be a 4-digit number.

    • Format: YYWW (2-digit year + 2-digit week).
    • Standard: It follows the ISO-8601 week date system.
    • Example: The 34th week of 2021 is represented as 2134.
    • Sprint Alignment: If your team uses weekly or bi-weekly sprints, this number can serve as a sprint identifier.
  6. Apply HeadVer to Android builds using Gradle

    main

    To use HeadVer versioning in an Android project, pass the head and build values as project properties via the command line. You can then access these properties in your build.gradle file to construct a versionName following the {head}.{yearweek}.{build} pattern.

    Run the Gradle command with -P flags: gradlew assembleRelease -Pversion.head=1 -Pversion.build=67

    ext {
        head = (rootProject.properties.get("version.head") as Integer)
        build = (rootProject.properties.get("version.build") as Integer)
    }
    
    android {
        defaultConfig {
            versionName "${project.head}.${new version().getYearWeek()}.${project.build}"
            // ...
        }
    }
  7. Set up HeadVer for NodeJS

    main

    To use HeadVer in a NodeJS environment, follow these two steps:

    1. Add date-fns and semver to your package.json dependencies.
    2. Use standard module imports instead of URL imports.
    {
      "dependencies": {
        "date-fns": "2.30.0",
        "semver": "7.5.4"
      }
    }
    import * as semver from 'semver'
    import { format } from 'date-fns'
  8. Set up HeadVer for Deno

    main

    To use HeadVer in a Deno environment, import the required dependencies using Deno's standard URL-based imports. You will need semver from the Deno standard library and date-fns via the npm: specifier.

    import * as semver from 'https://deno.land/std@0.195.0/semver/mod.ts'
    import { format } from 'npm:date-fns@2.30.0'
  9. Configure GitHub Actions for HeadVer auto-tagging

    main

    To implement HeadVer auto-tagging in a Node.js project using GitHub Actions, follow these steps:

    1. Set Repository Permissions: Ensure your repository has Read and write permissions enabled. Navigate to Settings > Actions > General in your GitHub repository to verify this.
    2. Prepare package.json: Ensure your package.json contains a version field (e.g., "version": "0.1.0"). The HeadVer logic uses the first digit of this version as the {head} component.
    3. Create Workflow File: Create a .yml file in the .github/workflows directory.
    4. Implement Tagging Job: Include a job that reads the package.json, calculates the HeadVer components, and pushes the new Git tag.
    # Example of the Tagging job logic
    jobs:
      tag:
        runs-on: ubuntu-latest
        steps:
          - name: Checkout repository
            uses: actions/checkout@v2
            with:
              fetch-depth: "0"
          - name: Read packages.json
            run: |
              echo "PACKAGE_JSON=$(jq -c . < package.json)" >> $GITHUB_ENV
          - name: Generate tag version (headver)
            run: |
              VERSION_PREFIX="v"
              VERSION_HEAD=$(cut -d '.' -f 1 <<< ${{ fromJson(env.PACKAGE_JSON).version }})
              VERSION_YEAR=$(date +%g)
              VERSION_WEEK=$(date +%V)
              VERSION_BUILD=${{github.run_number}}
              NEW_TAG="${VERSION_PREFIX}${VERSION_HEAD}.${VERSION_YEAR}${VERSION_WEEK}.${VERSION_BUILD}"
              echo "NEW_TAG=$NEW_TAG" >> $GITHUB_ENV
          - name: Push Git Tag
            run: |
              git config user.name "GitHub Actions"
              git config user.email "github-actions@users.noreply.github.com"
              git tag $NEW_TAG
              git push origin $NEW_TAG
  10. Apply HeadVer to various build environments

    main

    HeadVer can be implemented in various environments. The repository provides specific examples for the following:

    • Bash (examples/bash.md)
    • Elixir (examples/elixir.md)
    • Fastlane (examples/fastlane.md)
    • Gradle (examples/gradle.md)
    • PowerShell (examples/powershell.md or examples/headver.ps1)
    • TypeScript (examples/typescript.md)
  11. Use the headver.ps1 PowerShell script

    main

    The headver.ps1 script generates a version string based on a head number, a year-week identifier, and a build number. It is compatible with PowerShell 7.1+ on Windows, Linux, and macOS.

    To see all available parameters and detailed documentation, run:

    Get-Help -Detailed ./headver.ps1
    Get-Help -Detailed ./headver.ps1
  12. Use the HeadVer Bash script

    main

    The HeadVer Bash script generates a version string based on a {head}.{yearweek}.{build} format. It accepts up to 5 optional arguments passed as key=value pairs.

    Arguments:

    • head: The first component of the version. Defaults to 0.
    • build: The last component of the version. Defaults to 0.
    • suffix: A string appended to the end of the version with a + separator (e.g., +qa).
    • date: Forces the yearweek calculation to use a specific date instead of the current system date.
    • override_version: If provided, this value is used directly as the version, and all other parameters (head, yearweek, build, suffix) are ignored.
    # Standard usage
    ./script.sh head=15 build=383 suffix=qa
    
    # Overriding the entire version
    ./script.sh override_version=15.1827.383