@wellsite/version-generator
TypeScript icon, indicating that this package has built-in type declarations

1.0.32-main.32ea8149 • Public • Published

Below is an updated version of your README in markdown that reintroduces the details on how CFBundleVersion and versionCode are determined, along with the improvements made earlier. Let me know if you need any further adjustments.


Version Generator

A tool that generates package versions based on Git information. It can be used as a CLI, a GitHub Action, or as a direct dependency in your code.


Overview

The version generator creates version strings using Git data following the schema:

<major>.<minor>.<patch>-<branch-name>.<commit-hash>

For example:

v1.2-feature-branch.4-g5678abc

The tool extracts the version components as follows:

Component Description Source
major Major version number Extracted from the latest Git tag (e.g., v1.21)
minor Minor version number Extracted from the latest Git tag (e.g., v1.22)
patch Patch version number Number of commits since the latest tag
branch-name Current branch name Git branch name (cleaned of special characters)
commit-hash Short commit hash Short hash of the current commit

Important: The tool requires at least one Git tag (formatted as v<major>.<minor>) to exist in your repository. Without a tag, the action will fail with an error message.

This approach automatically creates versions based on commit history and allows you to quickly trace back any commit from a version string. It also helps identify which branch the code originates from.


Version Tagging

To update the major or minor version, create a new tag in the format:

v<major>.<minor>

For example:

git tag -a v1.2 -m "Release version 1.2"
git push origin v1.2

Typical Uses

  • Service Versioning: Embed the version string in your service (e.g., under /version.json) to quickly identify the deployed version.
  • Artifact Versioning: Use the version string to tag deployment artifacts, ensuring clarity on which package version is being deployed.

Mobile App Version Considerations

For app packages, both iOS and Android have specific versioning requirements.

iOS Versioning

  • CFBundleShortVersionString: Represents the version of the app in the store. The App Store uses this string (formatted as <major>.<minor>.<patch>) to determine release ordering. Use the appReleaseVersion produced by the tool.
  • CFBundleVersion: Ensures uniqueness between builds with identical version strings. This string can consist of up to three integers separated by periods.

Android Versioning

  • Android version strings are public and ideally follow the <major>.<minor>.<patch> format. Use the appReleaseVersion produced by the tool.
  • Android does not use the version string for release ordering. Instead, it relies on a monotonically increasing integer called versionCode.

Detailed Mobile Versioning

  • iOS:
    The tool queries App Store Connect to determine the current build number for the given version string. If that version string does not yet exist in the App Store or TestFlight, the build number defaults to 1. The commit hash is then encoded as an integer, and these two values are combined into an iosBuildNumberString using the format:

    <buildNumber>.<encoded-commitHash>
    

    The first value ensures monotonically increasing build numbers for release ordering, while the second value allows you to decode and retrieve the commit hash. This iosBuildNumberString is used to set the CFBundleVersion.

  • Android:
    The tool queries the Google Play Store API to retrieve the latest build version code used across all tracks and then increments it by one. Additionally, if the major version of the package in the store is different from the package being built, the version code is increased by a configurable increment (default: 10). The resulting androidVersionCode is used to set the versionCode in your Android app.

Note: To generate values specific to iOS or Android, use the appropriate CLI flags or GitHub Action inputs.


Environment Variables

The version generator normalizes environment variables from different CI/CD systems to ensure consistent behavior. You can explicitly set these variables or let the tool automatically detect them from your CI environment.

Normalized Environment Variables

Variable Description Sources (in priority order)
TOKEN GitHub access token GITHUB_TOKEN, TRAVIS_TOKEN
REPOSITORY_OWNER Repository owner/organization GITHUB_REPOSITORY_OWNER, VERCEL_GIT_REPO_OWNER, TRAVIS_REPO_SLUG (parsed)
REPOSITORY_NAME Repository name (without owner) GITHUB_REPOSITORY (parsed), VERCEL_GIT_REPO_SLUG, TRAVIS_REPO_SLUG (parsed)
SHA Commit hash GITHUB_SHA, VERCEL_GIT_COMMIT_SHA, TRAVIS_COMMIT
BRANCH_NAME Current branch name GITHUB_HEAD_REF (PR source), GITHUB_REF_NAME, TRAVIS_PULL_REQUEST_BRANCH (PR source), TRAVIS_BRANCH, VERCEL_GIT_COMMIT_REF
CI Indicates running in CI environment GITHUB_ACTIONS, VERCEL, TRAVIS, CI

CI/CD System Support

The tool automatically detects and normalizes environment variables from:

  1. GitHub Actions: Uses GITHUB_* environment variables
  2. Vercel: Uses VERCEL_* environment variables
  3. Travis CI: Uses TRAVIS_* environment variables
  4. Generic CI: Uses expected environment variable directly

Note: When running in a CI environment, a GitHub token (TOKEN) is required for accessing the GitHub API. This is automatically available in GitHub Actions as GITHUB_TOKEN, but must be manually set in other CI systems.

Direct Usage

You can also set these normalized environment variables directly in your environment, and they will be used as-is without further normalization:

# Example of directly setting normalized variables
export TOKEN="your-github-token"
export REPOSITORY_OWNER="your-username"
export REPOSITORY_NAME="your-repo"
export SHA="abcdef1234567890"
export BRANCH_NAME="main"
export CI="true"

Usage

As a CLI Tool

You can install the version generator globally or as a dev dependency.

Installation

Add the package to your project:

npm add -d @wellsite/version-generator

Running the Tool

To display help:

# npm
npx @wellsite/version-generator --help

# pnpm
pnpm dlx @wellsite/version-generator --help

CLI Options

  • --dir, -d: Directory to use for command execution and output file path (defaults to current working directory)
  • --output-file: Output file path (relative to --dir if not absolute) where the version file should be written. Can be specified multiple times to write to multiple locations.
  • --format, -f: Output format: string or json (default: string)
  • --android: Enable Android version code generation
  • --android-package: Android package name for the Play Store API
  • --android-service-account-key: Service account key for the Play Store API (JSON string or base64-encoded)
  • --android-track: Track for the Play Store API (production, beta, alpha; default: production)
  • --android-major-increment: Increment for major version changes (default: 10)
  • --ios: Enable iOS build number generation
  • --ios-bundle-id: iOS bundle ID for the App Store Connect API
  • --ios-api-key-id: App Store Connect API Key ID
  • --ios-api-issuer-id: App Store Connect API Issuer ID
  • --ios-api-private-key: App Store Connect API Private Key (can be base64-encoded)

Local Usage: The tool uses local Git commands and does not require a GITHUB_TOKEN.
GitHub Actions: When running in a GitHub Actions environment (GITHUB_ACTIONS=true), the tool uses the GitHub API and requires GITHUB_TOKEN.

Examples

Basic usage to output version to console:

npx @wellsite/version-generator

Write version to a file:

npx @wellsite/version-generator --output-file version.json --format json

Write version to multiple files:

npx @wellsite/version-generator --output-file version.json --output-file public/version.json --format json

JSON Output Format

When using the JSON format, the output includes additional metadata:

{
  "version": "1.2.4-g5678abc",
  "major": "1",
  "minor": "2",
  "patch": 4,
  "branchName": "main",
  "commitHash": "5678abc",
  "appReleaseVersion": "1.2.4",
  "androidVersionCode": 15, 
  "iosBuildNumberString": "1.23234323"
}

In GitHub Actions

Here’s an example workflow step:

- name: Generate version
  uses: wellsite/version-generator@v1
  with:
    outputFilePath: 'version.json'
    format: 'json'
    android: 'true'
    android-package: 'com.example.app'
    android-service-account-key: ${{ secrets.PLAY_STORE_SERVICE_ACCOUNT_KEY_BASE64 }}
    android-track: 'production'
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

GitHub Action Inputs

Input Description Required Default
dir Directory to use for command execution and output file path No Current dir
destination Destination path (relative to dir if not absolute) No
format Output format (string or json) No string
android Enable Android version code generation No false
android-package Android package name for the Play Store API No
android-service-account-key Service account key for the Play Store API (as JSON string) No
android-track Track for the Play Store API (production, beta, alpha) No production
android-major-increment Increment for major version changes No 10
ios Enable iOS build number generation No false
ios-bundle-id iOS bundle ID for the App Store Connect API No
ios-api-key-id App Store Connect API Key ID No
ios-api-issuer-id App Store Connect API Issuer ID No
ios-api-private-key App Store Connect API Private Key (can be base64-encoded) No

GitHub Action Outputs

  • version: The generated version string.
  • major: Major version number.
  • minor: Minor version number.
  • patch: Patch version number (commit count since the last tag).
  • branchName: Current branch name.
  • commitHash: Current commit hash.
  • appReleaseVersion: App release version (only major.minor.patch) for mobile apps.
  • androidVersionCode: Android version code (if Android input is enabled).
  • iosBuildNumber: iOS build number (if iOS input is enabled).

As a Dependency

You can also use the version generator directly in your code.

Installation

pnpm add @wellsite/version-generator

Example Usage in JavaScript

const { generatePackageVersion, generateAndWriteVersion } = require('@wellsite/version-generator');

// Generate version information without writing to a file
const versionInfo = await generatePackageVersion('.');
console.log(versionInfo);

// Generate version information with Android version code
const versionInfoWithAndroid = await generatePackageVersion('.', {
  android: {
    enabled: true,
    packageName: 'com.example.app',
    serviceAccountKey: '{ ... }', // Service account key JSON
    track: 'production',
    majorVersionIncrement: 10
  }
});
console.log(versionInfoWithAndroid);

// Generate version information with iOS build number
const versionInfoWithIos = await generatePackageVersion('.', {
  ios: {
    enabled: true,
    bundleId: 'com.example.app',
    apiKeyId: 'XXXXXXXXXX',
    apiIssuerId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx',
    apiPrivateKey: '-----BEGIN PRIVATE KEY-----\n...', // Can also be base64-encoded
  }
});
console.log(versionInfoWithIos);

// Alternatively, generate and write to a file
const writtenVersionInfo = await generateAndWriteVersion('.', 'version.json');
console.log(writtenVersionInfo);

The returned object includes properties such as:

{
  "version": "1.0.0-main.12345abc",
  "appReleaseVersion": "1.0.0",
  "iosBuildNumberString": "42",
  "iosBuildNumber": 42,
  // ...other properties
}

Mobile Setup Details

Android Setup

The tool can automatically generate Android version codes by:

  1. Creating a Service Account: In the Google Cloud Console with access to the Google Play Android Developer API.
  2. Downloading the Service Account Key JSON.
  3. Encoding the Key: For GitHub Actions, encode the JSON as base64:
    cat service-account-key.json | base64
  4. Storing the Key: Add the base64-encoded string as a GitHub secret.
  5. Inviting the Service Account: Invite the service account (via its email) to your Google Play Console.

iOS App Store Setup

The tool automatically generates iOS build numbers by:

  1. Creating an API Key in App Store Connect.
  2. Collecting Credentials:
    • Key ID: Displayed after generating the key (e.g., ABC1234567).
    • Issuer ID: Found at the top of the Keys page.
    • Private Key: Download the .p8 file (downloadable only once).
    • Bundle ID: Your app's bundle identifier (e.g., com.example.app).
  3. Preparing the Private Key: Encode it as base64:
    cat AuthKey_XXXXXXXX.p8 | base64
  4. Storing Securely: For GitHub Actions, store the Key ID, Issuer ID, and base64-encoded private key as secrets. Never commit these values to your repository.

Troubleshooting

Error: "No git tags found"

If you see the error:

No git tags found fatal: No names found, cannot describe anything

It means your repository lacks any Git tags. The version generator requires at least one tag to function.

Solution:

Create an initial tag manually:

git tag -a v0.0.0 -m "Initial version"
git push origin v0.0.0

Error: "Failed to get commit count from tag"

Ensure that your repository has at least one tag. Note that the action is configured to work with shallow clones (e.g., fetch-depth: 1), which may affect commit count retrieval.


Development

For more information on contributing and developing this project, please see DEVELOPMENT.md.


GitHub Action Versioning

This project uses tags to version the Github Action. Although we use our own version generator to version the published artifacts, we also tag the commit in the main branch with the major version during the build. This enables users of our GitHub Action to pin the version of the action to the latest major version of the build. For example:

uses: Wellsite-Navigator/version-generator@v1  # Uses the latest v1.x.x-main.xxx release via the v1 tag

The @v1 syntax is shorthand for always using the latest release in the v1 major version series from the main branch.


License

This project is licensed under the MIT License.


Package Sidebar

Install

npm i @wellsite/version-generator

Weekly Downloads

222

Version

1.0.32-main.32ea8149

License

MIT

Unpacked Size

380 kB

Total Files

23

Last publish

Collaborators

  • sarhan-wellsite
  • ali-wellsite