Added version-resolver input

This commit is contained in:
Kir_Antipov 2021-10-01 16:13:08 +03:00
parent bc45e09dbd
commit fcfbc7c0f9
7 changed files with 174 additions and 2 deletions

View file

@ -66,6 +66,7 @@ jobs:
| changelog-file | A glob of the changelog file | ❌ | `CHANGELOG.md` |
| loaders | A list of supported mod loaders | `fabric` | `fabric` <br> `forge` <br> `rift` |
| game-versions | A list of supported Minecraft versions | Will be parsed from the `version` value (e.g., `0.40.0+1.18_experimental` results in `21w37a` and `21w38a` at the moment) | `21w37a` <br> `1.17` |
| version-resolver | Determines the way automatic `game-versions` resolvement works | `releasesIfAny` | `exact` - exact game version *(`1.16` -> `1.16`)* <br><br> `latest` - the latest release of the given minor *(`1.16` -> `1.16.5`)* <br><br> `all` - all versions of the given minor starting with the specified build <br><br> `releases` - all releases of the given minor starting with the specified build *(`1.16.3` -> `[1.16.3, 1.16.4, 1.16.5]`)* <br><br> `releasesIfAny` - all releases of the given minor starting with the specified build, if any; otherwise, all versions |
| java | A list of supported Java versions | *empty string* | `Java 8` <br> `Java 1.8` <br> `8` |
### Minimalistic Example

View file

@ -59,6 +59,9 @@ inputs:
game-versions:
description: A list of supported Minecraft versions
required: false
version-resolver:
description: Determines the way automatic game-versions resolvement works
required: false
java:
description: A list of supported Java versions
required: false

View file

@ -1,8 +1,9 @@
import { context } from "@actions/github";
import { getCompatibleBuilds, parseVersionNameFromFileVersion } from "../utils/minecraft-utils";
import { parseVersionNameFromFileVersion } from "../utils/minecraft-utils";
import { File, getFiles, parseVersionFromFilename, parseVersionTypeFromFilename } from "../utils/file-utils";
import Publisher from "./publisher";
import PublisherTarget from "./publisher-target";
import MinecraftVersionResolver from "../utils/minecraft-version-resolver";
interface ModPublisherOptions {
id: string;
@ -12,6 +13,7 @@ interface ModPublisherOptions {
name?: string;
version?: string;
changelog?: string | { file?: string };
versionResolver?: string;
gameVersions?: string | string[];
java?: string | string[];
files?: string | { primary?: string, secondary?: string };
@ -67,7 +69,8 @@ export default abstract class ModPublisher extends Publisher<ModPublisherOptions
if (!gameVersions.length) {
const minecraftVersion = parseVersionNameFromFileVersion(version);
if (minecraftVersion) {
gameVersions.push(...(await getCompatibleBuilds(minecraftVersion)).map(x => x.id));
const resolver = options.versionResolver && MinecraftVersionResolver.byName(options.versionResolver) || MinecraftVersionResolver.releasesIfAny;
gameVersions.push(...(await resolver.resolve(minecraftVersion)).map(x => x.id));
}
if (!gameVersions.length) {
throw new Error("At least one game version should be specified");

View file

@ -0,0 +1,19 @@
import Version from "./version";
export default abstract class GameVersionResolver<TGameVersion> {
private readonly _filter: (version: string | Version, versions: TGameVersion[]) => TGameVersion[];
protected constructor(filter?: (version: string | Version, versions: TGameVersion[]) => TGameVersion[]) {
this._filter = filter || ((_, x) => x);
}
public async resolve(version: string | Version): Promise<TGameVersion[]> {
return this.filter(version, await this.getCompatibleVersions(version));
}
public filter(version: string | Version, versions: TGameVersion[]): TGameVersion[] {
return this._filter(version, versions);
}
public abstract getCompatibleVersions(version: string | Version): Promise<TGameVersion[]>;
}

View file

@ -0,0 +1,24 @@
import GameVersionResolver from "./game-version-resolver";
import { getCompatibleBuilds, MinecraftVersion } from "./minecraft-utils";
import Version from "./version";
export default class MinecraftVersionResolver extends GameVersionResolver<MinecraftVersion> {
public static readonly exact = new MinecraftVersionResolver((n, v) => [v.find(x => x.version.equals(n))].filter(x => x));
public static readonly latest = new MinecraftVersionResolver((_, v) => v.find(x => x.isRelease) ? [v.find(x => x.isRelease)] : v.length ? [v[0]] : []);
public static readonly all = new MinecraftVersionResolver((_, v) => v);
public static readonly releases = new MinecraftVersionResolver((_, v) => v.filter(x => x.isRelease));
public static readonly releasesIfAny = new MinecraftVersionResolver((_, v) => v.find(x => x.isRelease) ? v.filter(x => x.isRelease) : v);
public static byName(name: string): MinecraftVersionResolver | null {
for (const [key, value] of Object.entries(MinecraftVersionResolver)) {
if (value instanceof MinecraftVersionResolver && key.localeCompare(name, undefined, { sensitivity: "accent" }) === 0) {
return value;
}
}
return null;
}
public getCompatibleVersions(version: string | Version): Promise<MinecraftVersion[]> {
return getCompatibleBuilds(version);
}
}

View file

@ -16,4 +16,11 @@ export default class Version {
this.build = build || 0;
}
}
public equals(version: unknown): boolean {
if (version instanceof Version) {
return this.major === version.major && this.minor === version.minor && this.build === version.build;
}
return typeof version === "string" && this.equals(new Version(version));
}
}

View file

@ -0,0 +1,115 @@
import { describe, test, expect } from "@jest/globals";
import MinecraftVersionResolver from "../src/utils/minecraft-version-resolver";
describe("MinecraftVersionResolver.byName", () => {
test("every predefined MinecraftVersionResolver can be resolved", () => {
for (const [key, value] of Object.entries(MinecraftVersionResolver).filter(([_, x]) => x instanceof MinecraftVersionResolver)) {
expect(MinecraftVersionResolver.byName(key)).toStrictEqual(value);
}
});
test("null is returned if MinecraftVersionResolver with the given name doesn't exist", () => {
expect(MinecraftVersionResolver.byName("non-existing-resolver")).toBeNull();
});
test("name of MinecraftVersionResolver is case insensitive", () => {
expect(MinecraftVersionResolver.byName("latest")).toStrictEqual(MinecraftVersionResolver.latest);
expect(MinecraftVersionResolver.byName("Latest")).toStrictEqual(MinecraftVersionResolver.latest);
expect(MinecraftVersionResolver.byName("LATEST")).toStrictEqual(MinecraftVersionResolver.latest);
expect(MinecraftVersionResolver.byName("LatesT")).toStrictEqual(MinecraftVersionResolver.latest);
});
});
describe("MinecraftVersionResolver.exact", () => {
test("the exact version is returned", async () => {
const _1_17 = (await MinecraftVersionResolver.exact.resolve("1.17")).map(x => x.id);
expect(_1_17).toHaveLength(1);
expect(_1_17).toContain("1.17");
const _1_17_1 = (await MinecraftVersionResolver.exact.resolve("1.17.1")).map(x => x.id);
expect(_1_17_1).toHaveLength(1);
expect(_1_17_1).toContain("1.17.1");
});
test("empty array is returned if no versions were found", async () => {
expect(await MinecraftVersionResolver.exact.resolve("42.0")).toHaveLength(0);
});
});
describe("MinecraftVersionResolver.latest", () => {
test("the latest version of the given minor is returned", async () => {
const versions = (await MinecraftVersionResolver.latest.resolve("1.17")).map(x => x.id);
expect(versions).toHaveLength(1);
expect(versions).toContain("1.17.1");
});
test("empty array is returned if no versions were found", async () => {
expect(await MinecraftVersionResolver.latest.resolve("42.0")).toHaveLength(0);
});
});
describe("MinecraftVersionResolver.all", () => {
test("all versions of the given minor are returned", async () => {
const versions = (await MinecraftVersionResolver.all.resolve("1.17")).map(x => x.id);
expect(versions).toHaveLength(31);
expect(versions).toContain("1.17");
expect(versions).toContain("1.17.1");
expect(versions).toContain("1.17.1-rc2");
expect(versions).toContain("1.17.1-rc1");
expect(versions).toContain("1.17.1-pre3");
expect(versions).toContain("1.17.1-pre2");
expect(versions).toContain("1.17.1-pre1");
expect(versions).toContain("21w03a");
});
test("all versions of the given minor starting with the given build are returned", async () => {
const versions = (await MinecraftVersionResolver.all.resolve("1.17.1")).map(x => x.id);
expect(versions).toHaveLength(6);
expect(versions).toContain("1.17.1");
expect(versions).toContain("1.17.1-rc2");
expect(versions).toContain("1.17.1-rc1");
expect(versions).toContain("1.17.1-pre3");
expect(versions).toContain("1.17.1-pre2");
expect(versions).toContain("1.17.1-pre1");
});
test("empty array is returned if no versions were found", async () => {
expect(await MinecraftVersionResolver.all.resolve("42.0")).toHaveLength(0);
});
});
describe("MinecraftVersionResolver.releases", () => {
test("all releases of the given minor are returned", async () => {
const versions = (await MinecraftVersionResolver.releases.resolve("1.17")).map(x => x.id);
expect(versions).toHaveLength(2);
expect(versions).toContain("1.17");
expect(versions).toContain("1.17.1");
});
test("all releases of the given minor starting with the given build are returned", async () => {
const versions = (await MinecraftVersionResolver.releases.resolve("1.16.1")).map(x => x.id);
expect(versions).toHaveLength(5);
expect(versions).toContain("1.16.1");
expect(versions).toContain("1.16.2");
expect(versions).toContain("1.16.3");
expect(versions).toContain("1.16.4");
expect(versions).toContain("1.16.5");
});
test("an empty array is returned if no versions were found", async () => {
expect(await MinecraftVersionResolver.releases.resolve("42.0")).toHaveLength(0);
});
});
describe("MinecraftVersionResolver.releasesIfAny", () => {
test("all releases of the given minor are returned", async () => {
const versions = (await MinecraftVersionResolver.releasesIfAny.resolve("1.17")).map(x => x.id);
expect(versions).toHaveLength(2);
expect(versions).toContain("1.17");
expect(versions).toContain("1.17.1");
});
test("empty array is returned if no versions were found", async () => {
expect(await MinecraftVersionResolver.releasesIfAny.resolve("42.0")).toHaveLength(0);
});
});