2021-09-15 15:42:12 +08:00
|
|
|
import { isValidUrl } from "../http/validate_url"
|
2021-09-15 16:35:19 +08:00
|
|
|
import semverCompare from "semver/functions/compare"
|
2021-12-07 16:46:07 +08:00
|
|
|
import semverCoerce from "semver/functions/coerce"
|
|
|
|
import semverValid from "semver/functions/valid"
|
2021-09-15 16:35:19 +08:00
|
|
|
import { getExecOutput } from "@actions/exec"
|
2021-09-15 15:42:12 +08:00
|
|
|
|
2021-09-15 15:12:01 +08:00
|
|
|
/**
|
2021-09-15 15:42:12 +08:00
|
|
|
* Gets the specific versions supported by this action compatible with the supplied (specific or minimum) version in
|
|
|
|
* descending order of release (e.g., `5.0.2`, `5.0.1`, and `5.0.0` for `5`).
|
2021-09-15 15:12:01 +08:00
|
|
|
*/
|
|
|
|
export function getSpecificVersions(versions: Set<string>, semversion: string): string[] {
|
|
|
|
return Array.from(versions)
|
|
|
|
.filter((v) => /^\d+\.\d+\.\d+$/.test(v) && v.startsWith(semversion))
|
|
|
|
.sort()
|
|
|
|
.reverse()
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-09-15 15:42:12 +08:00
|
|
|
* Gets the specific and minimum versions that can be used to refer to the supplied specific versions (e.g., `3`, `3.5`,
|
|
|
|
* `3.5.2` for `3.5.2`).
|
2021-09-15 15:12:01 +08:00
|
|
|
*/
|
|
|
|
export function getVersions(specific: string[]): Set<string> {
|
|
|
|
const versions = new Set(specific)
|
|
|
|
|
|
|
|
for (const version of specific) {
|
|
|
|
versions.add(/^\d+/.exec(version)![0])
|
|
|
|
versions.add(/^\d+\.\d+/.exec(version)![0])
|
|
|
|
}
|
|
|
|
|
|
|
|
return versions
|
|
|
|
}
|
2021-09-15 15:42:12 +08:00
|
|
|
|
|
|
|
/** Gets the most recent specific version for which there is a valid download URL. */
|
|
|
|
export async function getSpecificVersionAndUrl(
|
|
|
|
versions: Set<string>,
|
|
|
|
platform: string,
|
|
|
|
version: string,
|
|
|
|
getUrl: (platform: string, version: string) => string | null | Promise<string | null>
|
|
|
|
): Promise<[string, string]> {
|
|
|
|
if (!versions.has(version)) {
|
|
|
|
throw new Error(`Unsupported target! (platform='${platform}', version='${version}')`)
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const specificVersion of getSpecificVersions(versions, version)) {
|
|
|
|
// eslint-disable-next-line no-await-in-loop
|
|
|
|
const url = await getUrl(platform, specificVersion)
|
|
|
|
// eslint-disable-next-line no-await-in-loop
|
|
|
|
if (url !== null && (await isValidUrl(url))) {
|
|
|
|
return [specificVersion, url]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new Error(`Unsupported target! (platform='${platform}', version='${version}')`)
|
|
|
|
}
|
2021-09-15 16:35:19 +08:00
|
|
|
|
2021-09-15 16:50:26 +08:00
|
|
|
export const defaultVersionRegex = /v?(\d\S*)/
|
2021-09-15 16:35:19 +08:00
|
|
|
|
|
|
|
/** Get the version of a binary */
|
2021-09-15 16:50:26 +08:00
|
|
|
export async function getBinVersion(file: string, versionRegex: RegExp = defaultVersionRegex) {
|
2021-09-15 16:35:19 +08:00
|
|
|
try {
|
|
|
|
const { stderr, stdout } = await getExecOutput(file, ["--version"])
|
|
|
|
const version = stdout.match(versionRegex)?.[1] ?? stderr.match(versionRegex)?.[1]
|
|
|
|
return version
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e)
|
|
|
|
return undefined
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Check if the given bin is up to date against the target version */
|
2021-09-15 16:50:26 +08:00
|
|
|
export async function isBinUptoDate(
|
|
|
|
givenFile: string,
|
|
|
|
targetVersion: string,
|
|
|
|
versionRegex: RegExp = defaultVersionRegex
|
|
|
|
) {
|
|
|
|
const givenVersion = await getBinVersion(givenFile, versionRegex)
|
2021-09-15 16:35:19 +08:00
|
|
|
if (
|
|
|
|
typeof givenVersion === "string" &&
|
|
|
|
typeof targetVersion === "string" &&
|
|
|
|
givenVersion !== "" &&
|
|
|
|
targetVersion !== ""
|
|
|
|
) {
|
|
|
|
return semverCompare(givenVersion, targetVersion) !== -1
|
|
|
|
} else {
|
|
|
|
// assume given version is old
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
2021-12-07 16:46:07 +08:00
|
|
|
|
|
|
|
/** Coerce the given version if it is invalid */
|
|
|
|
export function semverCoerceIfInvalid(version: string) {
|
|
|
|
if (semverValid(version) === null) {
|
|
|
|
// version coercion
|
|
|
|
try {
|
|
|
|
// find the semver version of an integer
|
|
|
|
const coercedVersion = semverCoerce(version)
|
|
|
|
if (coercedVersion !== null) {
|
|
|
|
return coercedVersion.version
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
// handled below
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return version
|
|
|
|
}
|