version-management

Technology-agnostic version management system with Git tags as source of truth

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "version-management" with this command: npx skills add hitoshura25/claude-devtools/hitoshura25-claude-devtools-version-management

Version Management

A technology-agnostic version management system using Git tags as the source of truth, with platform-specific adapters.

Overview

Design Philosophy:

  • Git tags are the source of truth for versions
  • Committed version files (version.properties, package.json, etc.) cache the version for fast builds
  • Release workflows update both git tags and version files
  • Supports semantic versioning (major.minor.patch)

Prerequisites

  • Git repository initialized
  • Git tags enabled
  • Bash shell available
  • Write access to project directory

Inputs

InputRequiredDefaultDescription
project_pathYes.Project root directory
platformYesgradlePlatform adapter: gradle, npm, python

Process

Step 1: Create Core Version Manager Script

Create scripts/version-manager.sh (technology-agnostic):

#!/bin/bash
# Core version manager - technology agnostic
# Handles: tag parsing, semver calculation, version bumping

set -euo pipefail

# === CONFIGURATION ===
BASE_VERSION="${BASE_VERSION:-1.0}"
TAG_PREFIX="${TAG_PREFIX:-v}"

# === CORE FUNCTIONS ===

get_latest_version() {
    local prefix="${1:-$TAG_PREFIX}"
    git tag -l "${prefix}*" 2>/dev/null |
        sed "s/^${prefix}//" |
        sort -V |
        tail -1 || echo "0.0.0"
}

bump_version() {
    local version="$1"
    local bump_type="${2:-patch}"

    IFS='.' read -r major minor patch <<< "$version"
    major="${major:-0}"; minor="${minor:-0}"; patch="${patch:-0}"

    case "$bump_type" in
        major) major=$((major + 1)); minor=0; patch=0 ;;
        minor) minor=$((minor + 1)); patch=0 ;;
        patch) patch=$((patch + 1)) ;;
    esac

    echo "${major}.${minor}.${patch}"
}

generate_version() {
    local bump_type="${1:-patch}"
    local latest
    latest=$(get_latest_version)

    if [[ "$latest" == "0.0.0" ]]; then
        echo "${BASE_VERSION}.0"
    else
        bump_version "$latest" "$bump_type"
    fi
}

output_version() {
    local version="$1"
    local is_prerelease="${2:-false}"

    if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
        echo "version=$version" >> "$GITHUB_OUTPUT"
        echo "is-prerelease=$is_prerelease" >> "$GITHUB_OUTPUT"
        echo "tag=${TAG_PREFIX}${version}" >> "$GITHUB_OUTPUT"
    fi

    echo "$version"
}

main() {
    local command="${1:-generate}"
    local arg="${2:-patch}"

    case "$command" in
        generate) output_version "$(generate_version "$arg")" "false" ;;
        latest)   get_latest_version ;;
        bump)     bump_version "$(get_latest_version)" "$arg" ;;
        *)        echo "Usage: $0 {generate|latest|bump} [patch|minor|major]" >&2; exit 1 ;;
    esac
}

main "$@"

Make it executable:

chmod +x scripts/version-manager.sh

Step 2: Create Platform Adapter

For Gradle/Android Projects

Create scripts/gradle-version.sh:

#!/bin/bash
# Gradle/Android version adapter

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/version-manager.sh"

# Convert semver to Android versionCode: "1.2.34" → 1002034
semver_to_version_code() {
    local version="$1"
    IFS='.' read -r major minor patch <<< "$version"
    echo $((major * 1000000 + minor * 1000 + patch))
}

# Update version.properties
update_version_properties() {
    local version="$1"
    local version_code
    version_code=$(semver_to_version_code "$version")

    cat > version.properties << VERSIONEOF
# Auto-generated by release workflow - do not edit manually
VERSION_NAME=$version
VERSION_CODE=$version_code
VERSIONEOF
    echo "Updated version.properties: VERSION_NAME=$version, VERSION_CODE=$version_code"
}

# Output Android-specific values to GitHub Actions
output_android_version() {
    local version="$1"
    local version_code
    version_code=$(semver_to_version_code "$version")

    if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
        echo "version-code=$version_code" >> "$GITHUB_OUTPUT"
    fi
}

main() {
    local command="${1:-generate}"
    shift || true

    case "$command" in
        generate)
            local version
            version=$(generate_version "${1:-patch}")
            output_version "$version" "false"
            output_android_version "$version"
            ;;
        update)
            local version="${1:-}"
            [[ -z "$version" ]] && version=$(get_latest_version)
            update_version_properties "$version"
            ;;
        version-code)
            local version="${1:-}"
            [[ -z "$version" ]] && version=$(get_latest_version)
            semver_to_version_code "$version"
            ;;
        *)
            # Delegate to core
            source "$SCRIPT_DIR/version-manager.sh"
            main "$command" "$@"
            ;;
    esac
}

main "$@"

Make it executable:

chmod +x scripts/gradle-version.sh

Step 3: Create Initial Version File

For Gradle projects, create version.properties:

cat > version.properties << 'EOF'
# Auto-generated by release workflow - do not edit manually
VERSION_NAME=1.0.0
VERSION_CODE=1000000
EOF

Step 4: Update Build Configuration

For Gradle Projects

Update app/build.gradle.kts to read from version.properties:

import java.util.Properties

// Read version from version.properties (fast, no git commands)
val versionProps = Properties().apply {
    val versionFile = rootProject.file("version.properties")
    if (versionFile.exists()) {
        versionFile.inputStream().use { load(it) }
    }
}

android {
    defaultConfig {
        versionName = versionProps.getProperty("VERSION_NAME", "0.0.1-dev")
        versionCode = versionProps.getProperty("VERSION_CODE", "1")?.toIntOrNull() ?: 1
    }
}

Detection logic:

  • Check if versionName/versionCode already set in build.gradle.kts
  • If using a different version scheme, ask user if they want to migrate

Step 5: Commit Version File

git add version.properties scripts/
git commit -m "chore: add version management system"

Usage Examples

Local Development

# Get current version
./scripts/version-manager.sh latest

# Generate next patch version
./scripts/version-manager.sh generate patch

# Generate next minor version
./scripts/version-manager.sh generate minor

# Generate next major version
./scripts/version-manager.sh generate major

For Gradle Projects

# Generate version and update version.properties
./scripts/gradle-version.sh generate patch

# Update version.properties with specific version
./scripts/gradle-version.sh update 1.2.3

# Get version code for a version
./scripts/gradle-version.sh version-code 1.2.3

In GitHub Actions

See the release workflow created by android-playstore-setup skill for full integration example.

Verification

MANDATORY: Run these commands:

# Verify scripts exist
test -f scripts/version-manager.sh && echo "✓ Core script exists"
test -f scripts/gradle-version.sh && echo "✓ Gradle adapter exists"

# Verify scripts are executable
test -x scripts/version-manager.sh && echo "✓ Core script is executable"
test -x scripts/gradle-version.sh && echo "✓ Gradle adapter is executable"

# Test version generation
./scripts/version-manager.sh latest
./scripts/version-manager.sh generate patch

Expected output:

  • ✓ Core script exists
  • ✓ Gradle adapter exists
  • ✓ Core script is executable
  • ✓ Gradle adapter is executable
  • Version numbers displayed

Outputs

OutputLocationDescription
Core scriptscripts/version-manager.shTechnology-agnostic version logic
Gradle adapterscripts/gradle-version.shAndroid-specific version handling
Version cacheversion.propertiesCached version for fast builds
Build configapp/build.gradle.ktsUpdated to read from version file

Troubleshooting

"No tags found"

Cause: No git tags exist yet Fix: First version will be 1.0.0 (or BASE_VERSION.0)

"version.properties not found"

Cause: File not created or committed Fix: Run ./scripts/gradle-version.sh update 1.0.0 to create it

"Permission denied"

Cause: Scripts not executable Fix: chmod +x scripts/*.sh

Platform Adapters

NPM (Future)

For npm projects, create scripts/npm-version.sh that updates package.json:

# Updates package.json with new version
update_package_json() {
    local version="$1"
    npm version "$version" --no-git-tag-version
}

Python (Future)

For Python projects, create scripts/python-version.sh that updates __version__:

# Updates __init__.py with new version
update_python_version() {
    local version="$1"
    sed -i "s/__version__ = .*/__version__ = \"$version\"/" src/__init__.py
}

Completion Criteria

  • scripts/version-manager.sh exists and is executable
  • Platform adapter script exists and is executable
  • Version file created (e.g., version.properties)
  • Build configuration updated to read from version file
  • Scripts can generate and bump versions correctly
  • git tag -l shows version tags (after first release)

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

android-playstore-setup

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

android-proguard-setup

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

android-playstore-scan

No summary provided by upstream source.

Repository SourceNeeds Review