[FEATURE] /* Description: */ Also moves all nodejs stuff into `tools` package. Also adds a basic `CONTRIBUTING.md` file. Superseeds https://github.com/Nomi-CEu/Nomi-CEu/pull/431, which was closed as the branch needed to be renamed, due to the last two items on this list. TODO: - [x] Make it only run on master repo. - [x] Remove qb-lang-revamp branch from the events - [x] Allow workflow to run on all branches starting with test_buildscript? /* Commits: */ * Buildscript Changes * Make Contributing Docs a .md file * updateqb.yml v1 * Test QB change * Add lang file to commit file list * Another Test Change * Test with only lang path, + `./` at beginning of path * Test QB change * updateqb.yml v3 * Test QB Change * Add some debug settings * Remove debug, branch input. Switch to auto-commit action * Make activate: branches prefix `test_buildscript`, commit author GHA bot * Add branch prefix note into CONTRIBUTING.md * Make workflow only run if on master repo
168 lines
4.6 KiB
TypeScript
168 lines
4.6 KiB
TypeScript
import { modpackManifest, sharedDestDirectory } from "../../globals";
|
|
|
|
import request from "requestretry";
|
|
import fs from "fs";
|
|
import log from "fancy-log";
|
|
import upath from "upath";
|
|
import buildConfig from "../../buildConfig";
|
|
import { makeArtifactNameBody } from "../../util/util";
|
|
import sanitize from "sanitize-filename";
|
|
|
|
const CURSEFORGE_LEGACY_ENDPOINT = "https://minecraft.curseforge.com/";
|
|
const variablesToCheck = ["CURSEFORGE_API_TOKEN", "CURSEFORGE_PROJECT_ID"];
|
|
|
|
interface CFUploadOptions {
|
|
releaseType?: "release" | "beta";
|
|
}
|
|
|
|
/**
|
|
* Uploads beta artifacts to CurseForge.
|
|
*/
|
|
export async function deployCurseForgeBeta(): Promise<void> {
|
|
/**
|
|
* Obligatory variable check.
|
|
*/
|
|
["RC_VERSION", ...variablesToCheck].forEach((vari) => {
|
|
if (!process.env[vari]) {
|
|
throw new Error(`Environmental variable ${vari} is unset.`);
|
|
}
|
|
});
|
|
|
|
const version = process.env.RC_VERSION;
|
|
const flavorTitle = process.env.BUILD_FLAVOR_TITLE;
|
|
const displayName = [modpackManifest.name, [version.replace(/^v/, ""), "Release Candidate"].join(" "), flavorTitle]
|
|
.filter(Boolean)
|
|
.join(" - ");
|
|
|
|
const files = [
|
|
{
|
|
name: sanitize((makeArtifactNameBody(modpackManifest.name) + "-client.zip").toLowerCase()),
|
|
displayName: displayName,
|
|
},
|
|
{
|
|
name: sanitize((makeArtifactNameBody(modpackManifest.name) + "-server.zip").toLowerCase()),
|
|
displayName: `${displayName} Server`,
|
|
},
|
|
];
|
|
|
|
/**
|
|
* Obligatory file check.
|
|
*/
|
|
await upload(files, {
|
|
releaseType: "beta",
|
|
});
|
|
}
|
|
|
|
async function upload(files: { name: string; displayName: string }[], opts?: CFUploadOptions) {
|
|
opts = opts || {};
|
|
|
|
files.forEach((file) => {
|
|
const path = upath.join(buildConfig.buildDestinationDirectory, file.name);
|
|
if (!fs.existsSync(path)) {
|
|
throw new Error(`File ${path} doesn't exist!`);
|
|
}
|
|
});
|
|
|
|
// Since we've built everything beforehand, the changelog must be available in the shared directory.
|
|
const changelog = await (await fs.promises.readFile(upath.join(sharedDestDirectory, "CHANGELOG.md")))
|
|
.toString()
|
|
.replace(/\n/g, " \n")
|
|
.replace(/\n\*/g, "\n•");
|
|
|
|
const tokenHeaders = {
|
|
"X-Api-Token": process.env.CURSEFORGE_API_TOKEN,
|
|
};
|
|
|
|
// Fetch the list of Minecraft versions from CurseForge.
|
|
log("Fetching CurseForge version manifest...");
|
|
const versionsManifest =
|
|
(await request({
|
|
uri: CURSEFORGE_LEGACY_ENDPOINT + "api/game/versions",
|
|
headers: tokenHeaders,
|
|
method: "GET",
|
|
json: true,
|
|
fullResponse: false,
|
|
maxAttempts: 5,
|
|
})) || [];
|
|
|
|
if (!versionsManifest) {
|
|
throw new Error("Failed to fetch CurseForge version manifest.");
|
|
}
|
|
|
|
const version = versionsManifest.find((m) => m.name == modpackManifest.minecraft.version);
|
|
|
|
if (!version) {
|
|
throw new Error(`Version ${modpackManifest.minecraft.version} not found on CurseForge.`);
|
|
}
|
|
|
|
let clientFileID: number | null;
|
|
|
|
// Upload artifacts.
|
|
for (const file of files) {
|
|
const options = {
|
|
uri: CURSEFORGE_LEGACY_ENDPOINT + `api/projects/${process.env.CURSEFORGE_PROJECT_ID}/upload-file`,
|
|
method: "POST",
|
|
headers: {
|
|
...tokenHeaders,
|
|
"Content-Type": "multipart/form-data",
|
|
},
|
|
formData: {
|
|
metadata: JSON.stringify({
|
|
changelog: changelog,
|
|
changelogType: "markdown",
|
|
releaseType: opts.releaseType || "release",
|
|
parentFileID: clientFileID,
|
|
gameVersions: clientFileID ? undefined : [version.id],
|
|
displayName: file.displayName,
|
|
}),
|
|
file: fs.createReadStream(upath.join(buildConfig.buildDestinationDirectory, file.name)),
|
|
},
|
|
json: true,
|
|
fullResponse: false,
|
|
};
|
|
|
|
log(`Uploading ${file.name} to CurseForge...` + (clientFileID ? `(child of ${clientFileID})` : ""));
|
|
|
|
const response = await request(options);
|
|
|
|
if (response && response.id) {
|
|
if (!clientFileID) {
|
|
clientFileID = response.id;
|
|
}
|
|
} else {
|
|
throw new Error(`Failed to upload ${file.name}: Invalid Response.`);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Uploads build artifacts to CurseForge.
|
|
*/
|
|
export async function deployCurseForge(): Promise<void> {
|
|
/**
|
|
* Obligatory variable check.
|
|
*/
|
|
["GITHUB_TAG", ...variablesToCheck].forEach((vari) => {
|
|
if (!process.env[vari]) {
|
|
throw new Error(`Environmental variable ${vari} is unset.`);
|
|
}
|
|
});
|
|
|
|
const tag = process.env.GITHUB_TAG;
|
|
const flavorTitle = process.env.BUILD_FLAVOR_TITLE;
|
|
const displayName = [modpackManifest.name, tag.replace(/^v/, ""), flavorTitle].filter(Boolean).join(" - ");
|
|
|
|
const files = [
|
|
{
|
|
name: sanitize((makeArtifactNameBody(modpackManifest.name) + "-client.zip").toLowerCase()),
|
|
displayName: displayName,
|
|
},
|
|
{
|
|
name: sanitize((makeArtifactNameBody(modpackManifest.name) + "-server.zip").toLowerCase()),
|
|
displayName: `${displayName} Server`,
|
|
},
|
|
];
|
|
|
|
upload(files);
|
|
}
|