import semver from "semver"; type CompatibilityPolicy = /** * Strict policy: the action must support the same features as the payload version declares * @example Payload version 1.2.3 => ^1.2.0 range of action versions supported * @example Payload version 0.1.55 => ^0.1.55 range of action versions supported */ | "same-features" /** * Loose policy: the action must have no breaking changes compared to the payload version * @example Payload version 1.2.3 => ^1.0.0 range of action versions supported * @example Payload version 0.1.55 => ^0.1.0 range of action versions supported */ | "non-breaking"; const COMPATIBILITY_POLICY: CompatibilityPolicy = "non-breaking"; /** * @throws Error if the action can't process payload * The compatibility is determined according to the COMPATIBILITY_POLICY above. * @param payloadVersion the version of the payload * @param actionVersion the version of the action (recipient) */ export function validateCompatibility(payloadVersion: string, actionVersion: string): void { const payloadSemVer = semver.parse(payloadVersion); if (!payloadSemVer) throw new Error(`Payload version ${payloadVersion} is not a valid semantic version.`); const major = payloadSemVer.major; const minor = payloadSemVer.minor; const patch = payloadSemVer.patch; const compatibilityRange = COMPATIBILITY_POLICY === "same-features" ? `^${major}.${minor}.${major === 0 ? patch : 0}` : `^${major}.${major === 0 ? minor : 0}.${major === 0 ? "x" : 0}`; // non-breaking if (!semver.satisfies(actionVersion, compatibilityRange)) { throw new Error( `Payload version ${payloadVersion} is incompatible with action version ${actionVersion}. ` + `Please update your workflow to use at least ${semver.minVersion(compatibilityRange)} version of the action.` ); } }