import fs from "fs"; import upath from "upath"; import { configFolder, rootDirectory, templatesFolder } from "#globals"; import mustache from "mustache"; import gulp from "gulp"; import dedent from "dedent-js"; import { isEnvVariableSet } from "#utils/util.ts"; import { BuildData } from "#types/transformFiles.ts"; import { logWarn } from "#utils/log.ts"; import sortKeysRecursive from "sort-keys-recursive"; // This updates all the files, for a release. // If it is not a release or build, and thus no changes to versions need to be made. // This occurs when the files are to be updated from the templates outside of a release or a build. let updateFiles: boolean; let updateFileVersion: string; let updateFileTransformedVersion: string; let buildData: BuildData; async function updateFilesSetup(): Promise { updateFiles = false; // See if current run is to update files if (isEnvVariableSet("UPDATE_FILES")) { try { updateFiles = JSON.parse( (process.env.UPDATE_FILES ?? "false").toLowerCase(), ); } catch (err) { throw new Error("Update Files Env Variable set to Invalid Value."); } } buildData = new BuildData(); const versionsFilePath: string = upath.join(templatesFolder, "versions.txt"); updateFileVersion = ""; if (!buildData.isVersionBuild() && !updateFiles) return; // Versions.txt handling if (!fs.existsSync(versionsFilePath)) { if (updateFiles) { if (!buildData.isVersionBuild()) throw new Error( "In order to update files, needs versions.txt to exist and have values, or the version to be set via the GITHUB_TAG environmental variable.", ); updateFileVersion = buildData.rawVersion; updateFileTransformedVersion = buildData.transformedVersion; return; } logWarn( "Version.txt does not exist. Creating empty file. This may be an error.", ); // Create Versions.txt fs.closeSync(fs.openSync(versionsFilePath, "w")); } else { const versionList = await fs.promises.readFile(versionsFilePath, "utf8"); if (updateFiles) { if (!versionList) { if (!buildData.isVersionBuild()) throw new Error( "In order to update files, needs versions.txt to exist and have values, or the version to be set via the GITHUB_TAG environmental variable.", ); updateFileVersion = buildData.rawVersion; updateFileTransformedVersion = buildData.transformedVersion; return; } updateFileVersion = versionList.split("\n")[0].replace("-", "").trim(); updateFileTransformedVersion = `v${updateFileVersion}`; return; } // Duplicate Key if (versionList.includes(`${buildData.rawVersion}\n`)) { throw new Error("Version already exists in version.txt. Exiting..."); } } } export async function updateFilesBuildSetup() { updateFiles = true; buildData = new BuildData(); updateFileVersion = buildData.rawVersion; updateFileTransformedVersion = buildData.transformedVersion; } /** * @param readPath The filepath to read from. (Template) * @param writePath The filepath to write to. * @param replacementObject A record, of type string to type unknown, containing the keys, and replacement for those keys * @param addWarning whether to add warning not to edit file *

*

* A warning not to edit the file will also be added to the start of the file. */ async function modifyFile( readPath: string, writePath: string, replacementObject: Record, addWarning = true, ) { // Read the file content const data: string = await fs.promises.readFile(readPath, "utf8"); // Moustache Render let modifiedData: string = mustache.render(data, replacementObject); // Add warning to not edit file if (addWarning) modifiedData = dedent`# FOR DEVELOPMENT, DO NOT EDIT THIS FILE! EDIT THE TEMPlATES INSTEAD! # See https://github.com/Nomi-CEu/Nomi-CEu/wiki/Part-1:-Contributing-Information#section-5-template-information! ${modifiedData}`; // Write the modified content back to the file return fs.promises.writeFile(writePath, modifiedData, "utf8"); } /* Functions NOT Used in Build Process */ async function updateIssueTemplates(): Promise { // Filenames const fileNames: string[] = ["001-bug-report.yml", "002-feature-request.yml"]; const versionsFilePath: string = upath.join(templatesFolder, "versions.txt"); let versionList: string = await fs.promises.readFile( versionsFilePath, "utf8", ); if (!updateFiles) { if (!buildData.isVersionBuild()) throw new Error( "In order to update Issue Templates, the version must be set via the GITHUB_TAG environmental variable.", ); // Add new version to list, with indent versionList = ` - ${buildData.rawVersion}\n${versionList}`; // Write updated Version List await fs.promises.writeFile(versionsFilePath, versionList); } // Replacement Object const replacementObject: Record = { versions: versionList, }; const issueTemplatesFolder: string = upath.join( rootDirectory, ".github", "ISSUE_TEMPLATE", ); // Write to issue templates for (const fileName of fileNames) { const readPath = upath.join(templatesFolder, fileName); const writePath = upath.join(issueTemplatesFolder, fileName); await modifyFile(readPath, writePath, replacementObject); } } async function updateMainMenuConfig(): Promise { // Filename & paths const fileName = "mainmenu.json"; const readPath: string = upath.join(templatesFolder, fileName); const writePath: string = upath.join( rootDirectory, configFolder, "CustomMainMenu", fileName, ); if (!updateFiles && !buildData.isVersionBuild()) throw new Error( "The main menu should only be updated if the version is set via the GITHUB_TAG environmental variable.", ); // Replacement object const replacementObject: Record = { version: updateFiles ? updateFileVersion : buildData.rawVersion, }; // Read file const data: string = await fs.promises.readFile(readPath, "utf8"); // Moustache Render let modifiedData = JSON.parse(mustache.render(data, replacementObject)); // Add warning to not edit file modifiedData["_comment"] = "FOR DEVELOPMENT, DO NOT EDIT THIS FILE! EDIT THE TEMPlATES INSTEAD! See https://github.com/Nomi-CEu/Nomi-CEu/wiki/Part-1:-Contributing-Information#section-5-template-information!"; // Sort keys so that comment appears first modifiedData = sortKeysRecursive(modifiedData); return await fs.promises.writeFile( writePath, JSON.stringify(modifiedData, null, 2), "utf8", ); } /* Functions USED in Build Process */ export async function updateLabsVersion(rootDir: string): Promise { const fileName = "nomilabs-version.cfg"; const readPath: string = upath.join(templatesFolder, fileName); const writePath = upath.join(rootDir, configFolder, fileName); const replacementObject: Record = { version: updateFiles ? updateFileTransformedVersion : buildData.transformedVersion, }; return modifyFile(readPath, writePath, replacementObject); } // Main Closures const updateFilesLabsVersion = async () => { await updateLabsVersion(rootDirectory); }; export const updateFilesIssue = gulp.series( updateFilesSetup, updateIssueTemplates, ); export const updateFilesVersion = gulp.series( updateFilesSetup, updateFilesLabsVersion, ); export const updateFilesMainMenu = gulp.series( updateFilesSetup, updateMainMenuConfig, ); export const updateAll = gulp.series( updateFilesSetup, gulp.parallel( updateIssueTemplates, updateFilesLabsVersion, updateMainMenuConfig, ), );