or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

caching.mddiscovery.mddownload.mdextraction.mdindex.mdmanifest.mdversions.md
tile.json

versions.mddocs/

Version Utilities

Semantic version evaluation and validation utilities for working with version specifications, ranges, and version resolution in tool management workflows.

Capabilities

Version Specification Validation

Determines if a version specification is explicit (exact version) rather than a range or pattern.

/**
 * Determines if a version spec is explicit (exact version) rather than a range
 * @param versionSpec - Version specification to check
 * @returns True if the version specification is an exact version, false for ranges
 */
function isExplicitVersion(versionSpec: string): boolean;

Usage Examples:

import { isExplicitVersion } from "@actions/tool-cache";

// Explicit versions
console.log(isExplicitVersion("1.2.3"));     // true
console.log(isExplicitVersion("2.0.0"));     // true
console.log(isExplicitVersion("1.0.0-beta")); // true
console.log(isExplicitVersion("v3.1.4"));    // false (has 'v' prefix)

// Non-explicit (range) versions
console.log(isExplicitVersion("1.x"));       // false
console.log(isExplicitVersion(">=1.0.0"));   // false
console.log(isExplicitVersion("~1.2.0"));    // false
console.log(isExplicitVersion("^2.0.0"));    // false
console.log(isExplicitVersion("1.2.*"));     // false

// Use in conditional logic
const version = "3.11.x";
if (isExplicitVersion(version)) {
  console.log("Using exact version:", version);
} else {
  console.log("Using version range:", version);
}

Version Evaluation

Gets the highest satisfying semantic version from a list that matches the specified version range.

/**
 * Gets the highest satisfying semantic version that satisfies the version spec
 * @param versions - Array of version strings to evaluate
 * @param versionSpec - Semantic version specification to satisfy
 * @returns Highest matching version string, or empty string if no match found
 */
function evaluateVersions(
  versions: string[],
  versionSpec: string
): string;

Usage Examples:

import { evaluateVersions } from "@actions/tool-cache";

// Find best matching version
const availableVersions = ["1.0.0", "1.1.0", "1.2.0", "2.0.0", "2.1.0"];

const match1 = evaluateVersions(availableVersions, "1.x");
console.log(match1); // "1.2.0" (highest 1.x version)

const match2 = evaluateVersions(availableVersions, ">=1.1.0 <2.0.0");
console.log(match2); // "1.2.0" (highest version in range)

const match3 = evaluateVersions(availableVersions, "^1.0.0");
console.log(match3); // "1.2.0" (compatible with 1.0.0)

const match4 = evaluateVersions(availableVersions, "~2.0.0");
console.log(match4); // "2.0.0" (reasonably close to 2.0.0)

// No match found
const noMatch = evaluateVersions(availableVersions, "3.x");
console.log(noMatch); // "" (empty string)

Complete Version Resolution Workflows

Tool Version Resolution

import { evaluateVersions, isExplicitVersion, findAllVersions } from "@actions/tool-cache";

function resolveToolVersion(toolName: string, versionSpec: string): string {
  // Get all cached versions
  const cachedVersions = findAllVersions(toolName);
  
  if (cachedVersions.length === 0) {
    throw new Error(`No cached versions found for ${toolName}`);
  }
  
  // Check if we need exact match or can use range
  if (isExplicitVersion(versionSpec)) {
    // Look for exact match
    const exactMatch = cachedVersions.find(v => v === versionSpec);
    if (!exactMatch) {
      throw new Error(`Exact version ${versionSpec} not found for ${toolName}`);
    }
    return exactMatch;
  } else {
    // Use semantic version resolution
    const resolvedVersion = evaluateVersions(cachedVersions, versionSpec);
    if (!resolvedVersion) {
      throw new Error(`No version matching ${versionSpec} found for ${toolName}`);
    }
    return resolvedVersion;
  }
}

// Usage
try {
  const nodeVersion = resolveToolVersion("node", "18.x");
  console.log(`Resolved Node.js version: ${nodeVersion}`);
} catch (error) {
  console.error(error.message);
}

Version Compatibility Check

import { evaluateVersions, isExplicitVersion } from "@actions/tool-cache";

interface VersionRequirement {
  tool: string;
  versionSpec: string;
  required: boolean;
}

function checkVersionCompatibility(
  requirements: VersionRequirement[],
  availableVersions: Record<string, string[]>
): { compatible: boolean; issues: string[] } {
  const issues: string[] = [];
  
  for (const req of requirements) {
    const versions = availableVersions[req.tool] || [];
    
    if (versions.length === 0) {
      if (req.required) {
        issues.push(`Required tool ${req.tool} has no available versions`);
      }
      continue;
    }
    
    if (isExplicitVersion(req.versionSpec)) {
      if (!versions.includes(req.versionSpec)) {
        const message = `Exact version ${req.versionSpec} not available for ${req.tool}`;
        if (req.required) {
          issues.push(message);
        } else {
          console.warn(message);
        }
      }
    } else {
      const resolved = evaluateVersions(versions, req.versionSpec);
      if (!resolved) {
        const message = `No version matching ${req.versionSpec} available for ${req.tool}`;
        if (req.required) {
          issues.push(message);
        } else {
          console.warn(message);
        }
      }
    }
  }
  
  return {
    compatible: issues.length === 0,
    issues
  };
}

Upgrade Strategy Resolution

import { evaluateVersions } from "@actions/tool-cache";

function findUpgradeCandidate(
  currentVersion: string,
  availableVersions: string[],
  upgradeStrategy: "patch" | "minor" | "major"
): string {
  let versionSpec: string;
  
  switch (upgradeStrategy) {
    case "patch":
      versionSpec = `~${currentVersion}`;  // Same minor, newer patch
      break;
    case "minor":
      versionSpec = `^${currentVersion}`;  // Same major, newer minor
      break;
    case "major":
      versionSpec = "*";                   // Any newer version
      break;
  }
  
  const candidate = evaluateVersions(availableVersions, versionSpec);
  
  // Make sure we're actually upgrading
  if (candidate && candidate !== currentVersion) {
    return candidate;
  }
  
  return "";
}

// Usage
const currentPython = "3.10.5";
const availablePythonVersions = ["3.10.5", "3.10.12", "3.11.5", "3.12.0"];

const patchUpgrade = findUpgradeCandidate(currentPython, availablePythonVersions, "patch");
console.log(`Patch upgrade: ${patchUpgrade}`); // "3.10.12"

const minorUpgrade = findUpgradeCandidate(currentPython, availablePythonVersions, "minor");
console.log(`Minor upgrade: ${minorUpgrade}`); // "3.11.5"

Implementation Details

Semantic Version Support

  • Full semver compatibility: Uses the semver library for all version operations
  • Range operators: Supports >=, <=, >, <, =, ~, ^, ||, -, and x patterns
  • Pre-release versions: Handles alpha, beta, rc, and custom pre-release identifiers
  • Build metadata: Properly handles version build metadata

Version Sorting

  • Descending order: evaluateVersions sorts versions from highest to lowest
  • Semantic ordering: Uses proper semantic version comparison, not string comparison
  • Pre-release handling: Pre-release versions are ordered correctly relative to stable versions

Error Handling

  • Invalid versions: Malformed version strings are handled gracefully
  • Empty arrays: Returns empty string when no versions match or no versions provided
  • Non-semantic versions: Falls back to string comparison for non-semantic version strings

Performance Considerations

  • Lazy evaluation: Version parsing occurs only when needed
  • Sorting overhead: Large version arrays may have performance impact due to sorting
  • Memory efficiency: Doesn't cache results; performs fresh evaluation each call

Version Specification Examples

Exact Versions

isExplicitVersion("1.2.3");        // true
isExplicitVersion("2.0.0-alpha");  // true
isExplicitVersion("1.0.0+build1"); // true

Range Specifications

evaluateVersions(versions, "1.x");           // Latest 1.x
evaluateVersions(versions, ">=1.2.0");       // 1.2.0 or higher
evaluateVersions(versions, "~1.2.0");        // >=1.2.0 <1.3.0
evaluateVersions(versions, "^1.2.0");        // >=1.2.0 <2.0.0
evaluateVersions(versions, "1.2.0 - 1.5.0"); // Between 1.2.0 and 1.5.0
evaluateVersions(versions, "1.2.0 || 2.0.0"); // Either 1.2.0 or 2.0.0