Matheus Sampaio Queiroga
bfe21134a7
All checks were successful
Spigot Build / build (push) Successful in 10s
Reviewed-on: #1 Co-authored-by: Matheus Sampaio Queiroga <srherobrine20@gmail.com> Co-committed-by: Matheus Sampaio Queiroga <srherobrine20@gmail.com>
135 lines
5.6 KiB
JavaScript
135 lines
5.6 KiB
JavaScript
#!/usr/bin/env node
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import stream from "node:stream";
|
|
import os from "node:os";
|
|
import { finished } from "node:stream/promises";
|
|
import { execFileSync } from "node:child_process";
|
|
|
|
const rootURL = process.env.GITHUB_SERVER_URL || "https://sirherobrine23.org"
|
|
function concat(...args) {
|
|
return String.prototype.concat(...args)
|
|
}
|
|
|
|
/**
|
|
* get release
|
|
* @param {string} token
|
|
* @param {string} version
|
|
*
|
|
* @returns {{ tag_name: string; assets: { id: number; name: string; browser_download_url: string; }[]; }}
|
|
*/
|
|
async function getRelease(token, version) {
|
|
const rel = await fetch(concat(rootURL, "/api/v1/repos/Minecraft-Server/Spigot/releases/tags/", version), { headers: {"Authorization": ("token ").concat(token)} });
|
|
const data = await rel.json();
|
|
if (data.id === undefined) throw new Error("Tag not exists!");
|
|
return data;
|
|
}
|
|
|
|
function semverSort(a, b) {
|
|
if (!(typeof a === "number" || typeof a === "string" || typeof a === "bigint")) throw new TypeError("Require string, number or bigint");
|
|
if (!(typeof b === "number" || typeof b === "string" || typeof b === "bigint")) throw new TypeError("Require string, number or bigint");
|
|
if ((typeof a === "number" && typeof b === "number") || (typeof a === "bigint" && typeof b === "bigint")) {
|
|
if (a > b) return 1;
|
|
else if (a < b) return -1;
|
|
return 0;
|
|
}
|
|
|
|
if (!(typeof a === "string" && typeof b === "string")) throw new TypeError("The paraments have to be the same type!");
|
|
const partsA = a.split("."), partsB = b.split(".");
|
|
for (let i = 0; i < Math.max(partsA.length, partsB.length); i++) {
|
|
const numA = parseInt(partsA[i] || "0"), numB = parseInt(partsB[i] || "0");
|
|
if (numA > numB) return 1;
|
|
if (numA < numB) return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* Upload file to release
|
|
* @param {string} token
|
|
* @param {boolean} prerelease
|
|
* @param {string} version
|
|
* @param {...{name: string, size: number, fileStream: Blob}} files
|
|
*/
|
|
async function uploadToRelease(token, prerelease, version, ...files) {
|
|
const exist = await fetch(concat(rootURL, "/api/v1/repos/Minecraft-Server/Spigot/releases/tags/", version), { headers: {"Authorization": ("token ").concat(token)} });
|
|
if (!exist.ok || (await exist.json()).id === undefined) {
|
|
const status = await fetch(concat(rootURL, "/api/v1/repos/Minecraft-Server/Spigot/releases"), {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"Authorization": ("token ").concat(token),
|
|
},
|
|
body: JSON.stringify({
|
|
tag_name: version,
|
|
name: version,
|
|
prerelease: !!prerelease,
|
|
}),
|
|
});
|
|
if (status.status !== 201) throw new Error("Cannot create release, check token", { cause: { createRelease: status } });
|
|
}
|
|
const { upload_url } = (await (await fetch(concat(rootURL, "/api/v1/repos/Minecraft-Server/Spigot/releases/tags/", version))).json());
|
|
|
|
return Promise.all(Array.from(files).filter(Boolean).map(async ({ name, fileStream }) => {
|
|
const to = new URL(upload_url);
|
|
to.searchParams.set("name", name);
|
|
const form = new FormData;
|
|
form.set("attachment", fileStream);
|
|
const status = await fetch(to, {
|
|
method: "POST",
|
|
headers: { "Authorization": ("token ").concat(token) },
|
|
body: form,
|
|
});
|
|
|
|
if (status.status !== 201) throw new Error("Cannot upload file, check token", { cause: { name, blobUpload: await status.json(), status: { code: status.status, message: status.statusText } } });
|
|
return status.json();
|
|
}));
|
|
}
|
|
|
|
const { GH_TOKEN } = process.env;
|
|
|
|
/** @type {{ versions: {type: string, id: string}[] }} */
|
|
const dataHtml = await (await fetch("https://hub.spigotmc.org/versions/")).text();
|
|
const mcVersions = Array.from(dataHtml.match(/href=["'](.*)["']/g)).map(s => s.slice(6, -1)).filter(s => s.endsWith(".json") && s.slice(0, 2) === "1.").map(s => s.slice(0, -5)).sort(semverSort);
|
|
const versionsUpload = (await Promise.all(mcVersions.map(async ver => getRelease(GH_TOKEN, ver).then(() => ({exist: true, ver}), () => ({exist: false, ver}))))).filter(s => semverSort(s.ver, "1.8") >= 0 && !s.exist);
|
|
|
|
if (versionsUpload.length === 0) {
|
|
console.log("Servers are updated");
|
|
process.exit(0);
|
|
}
|
|
|
|
const builderPath = path.join(os.tmpdir(), "build.jar");
|
|
await finished(stream.Readable.fromWeb((await fetch("https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar")).body).pipe(fs.createWriteStream(builderPath)), { error: true });
|
|
|
|
for (const { ver: version } of versionsUpload) {
|
|
console.log("\n\n------- %s -------\n\n", version);
|
|
const buildFolder = path.join(process.cwd(), version);
|
|
await fs.promises.rm(buildFolder, { recursive: true }).catch(() => {});
|
|
await fs.promises.mkdir(buildFolder, { recursive: true });
|
|
try {
|
|
execFileSync("java", [
|
|
"-jar",
|
|
builderPath,
|
|
"--rev",
|
|
version
|
|
], {
|
|
cwd: buildFolder,
|
|
stdio: "inherit",
|
|
});
|
|
const files = (await fs.promises.readdir(buildFolder, { recursive: true })).filter(s => s.endsWith(".jar"));
|
|
if (files.length === 0) {
|
|
console.warn("No files to upload in ver %s", version);
|
|
continue;
|
|
}
|
|
const craftbukkit = files.find(s => s.toLowerCase().startsWith("craftbukkit"));
|
|
await uploadToRelease(GH_TOKEN, false, version,
|
|
{ name: "server.jar", fileStream: await fs.openAsBlob(path.join(buildFolder, files.find(s => s.toLowerCase().startsWith("spigot")))) },
|
|
craftbukkit ? { name: path.basename(craftbukkit), fileStream: await fs.openAsBlob(path.join(buildFolder, craftbukkit)) } : null,
|
|
);
|
|
} catch (err) {
|
|
console.error(err);
|
|
process.exit(-1);
|
|
} finally {
|
|
await fs.promises.rm(buildFolder, { recursive: true });
|
|
}
|
|
} |