Semantic version evaluation and validation utilities for working with version specifications, ranges, and version resolution in tool management workflows.
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);
}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)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);
}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
};
}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"semver library for all version operations>=, <=, >, <, =, ~, ^, ||, -, and x patternsevaluateVersions sorts versions from highest to lowestisExplicitVersion("1.2.3"); // true
isExplicitVersion("2.0.0-alpha"); // true
isExplicitVersion("1.0.0+build1"); // trueevaluateVersions(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