diff --git a/index.js b/index.js index 1dc62d7..1ad3d0e 100644 --- a/index.js +++ b/index.js @@ -1,48 +1,66 @@ const { ScreepsAPI } = require("screeps-api"); const core = require("@actions/core"); const fs = require("fs"); -const { glob } = require("glob"); +const glob = require("glob"); const path = require("path"); +/** + * Replaces specific placeholder strings within the provided content with corresponding dynamic values. + * + * This function targets: + * - {{gitHash}} -> GITHUB_SHA + * - {{gitRef}} -> GITHUB_REF + * - {{deployTime}} -> ISO timestamp + * - {{hostname}} -> hostname + * + * @param {string} content + * @param {string} hostname + * @returns {string} + */ function replacePlaceholders(content, hostname) { const deployTime = new Date().toISOString(); - core.debug( - `Replacing placeholders with: GITHUB_SHA=${process.env.GITHUB_SHA}, GITHUB_REF=${process.env.GITHUB_REF}, deployTime=${deployTime}, hostname=${hostname}`, - ); + const gitHash = process.env.GITHUB_SHA; + const gitRef = process.env.GITHUB_REF; + + core.info("Replacing placeholders:"); + core.info(` GITHUB_SHA: ${gitHash}`); + core.info(` GITHUB_REF: ${gitRef}`); + core.info(` deployTime: ${deployTime}`); + core.info(` hostname: ${hostname}`); + return content - .replace(/{{gitHash}}/g, process.env.GITHUB_SHA) - .replace(/{{gitRef}}/g, process.env.GITHUB_REF) + .replace(/{{gitHash}}/g, gitHash) + .replace(/{{gitRef}}/g, gitRef) .replace(/{{deployTime}}/g, deployTime) .replace(/{{hostname}}/g, hostname); } +/** + * Replaces placeholders in files matching a glob pattern. + * + * @param {string} pattern + * @param {string} [prefix] + * @param {string} hostname + * @returns {Promise} + */ async function readReplaceAndWriteFiles(pattern, prefix, hostname) { return new Promise((resolve, reject) => { const globPattern = prefix ? path.join(prefix, pattern) : pattern; - core.info(`Searching files with glob pattern: ${globPattern}`); glob(globPattern, async (err, files) => { if (err) { - core.error(`Glob error: ${err}`); return reject(err); } - if (files.length === 0) { - core.warning("No files matched the glob pattern."); - } - let processPromises = []; files.forEach((file) => { - core.debug(`Processing file: ${file}`); + core.info(`Replacing placeholders in file: ${file}`); let processPromise = fs.promises .readFile(file, "utf8") .then((content) => { content = replacePlaceholders(content, hostname); return fs.promises.writeFile(file, content); - }) - .then(() => { - core.info(`Replaced and wrote file: ${file}`); }); processPromises.push(processPromise); @@ -50,24 +68,26 @@ async function readReplaceAndWriteFiles(pattern, prefix, hostname) { try { await Promise.all(processPromises); - core.info(`Successfully processed ${files.length} files.`); resolve(files); } catch (processError) { - core.error(`Error during file processing: ${processError}`); reject(processError); } }); }); } +/** + * Reads files matching a glob pattern into a dictionary. + * @param {string} pattern + * @param {string} prefix + * @returns {Promise} + */ function readFilesIntoDict(pattern, prefix) { const globPattern = prefix ? path.join(prefix, pattern) : pattern; - core.info(`Reading files into dict with glob: ${globPattern}`); return new Promise((resolve, reject) => { glob(globPattern, (err, files) => { if (err) { - core.error(`Glob error: ${err}`); return reject(err); } @@ -75,7 +95,6 @@ function readFilesIntoDict(pattern, prefix) { let readPromises = []; files.forEach((file) => { - core.debug(`Reading file: ${file}`); let readPromise = fs.promises.readFile(file, "utf8").then((content) => { let key = file; if (prefix && file.startsWith(prefix)) { @@ -89,54 +108,70 @@ function readFilesIntoDict(pattern, prefix) { }); Promise.all(readPromises) - .then(() => { - core.debug(`Read ${files.length} files into dictionary.`); - resolve(fileDict); - }) - .catch((readErr) => { - core.error(`Error reading files: ${readErr}`); - reject(readErr); - }); + .then(() => resolve(fileDict)) + .catch(reject); }); }); } +/** + * Validates the provided authentication credentials. + * @param {string} token + * @param {string} username + * @param {string} password + * @returns {string|null} + */ function validateAuthentication(token, username, password) { - if (token && (username || password)) { - return "Token is defined along with username and/or password."; - } - if (!token && (!username || !password)) { - return "Username and password must both be defined if token is not used."; + if (token) { + if (username || password) { + return "Token is defined along with username and/or password."; + } + } else { + if (!username && !password) { + return "Neither token nor password and username are defined."; + } + if (username && !password) { + return "Username is defined but no password is provided."; + } + if (!username && password) { + return "Password is defined but no username is provided."; + } } return null; } +/** + * Posts code to Screeps server. + */ async function postCode() { const protocol = core.getInput("protocol") || "https"; const hostname = core.getInput("hostname") || "screeps.com"; const port = core.getInput("port") || "443"; const path = core.getInput("path") || "/"; + const token = core.getInput("token") || undefined; const username = core.getInput("username") || undefined; const password = core.getInput("password") || undefined; const prefix = core.getInput("source-prefix"); const pattern = core.getInput("pattern") || "*.js"; const branch = core.getInput("branch") || "default"; + const gitReplace = core.getInput("git-replace") || null; - core.info("Starting Screeps code upload action..."); - if (gitReplace) { - core.info(`Replacing placeholders in files matching: ${gitReplace}`); await readReplaceAndWriteFiles(gitReplace, prefix, hostname); } const files_to_push = await readFilesIntoDict(pattern, prefix); + core.info( - `Preparing to upload ${ + `Uploading ${ Object.keys(files_to_push).length - } files to branch: ${branch}`, + } file(s) to branch '${branch}':`, ); + Object.keys(files_to_push).forEach((key) => { + core.info(` File: ${key}`); + }); const login_arguments = { token, @@ -147,34 +182,35 @@ async function postCode() { port, path, }; - core.debug(`Login arguments: ${JSON.stringify(login_arguments, null, 2)}`); + + core.info("Authentication arguments:"); + core.info(JSON.stringify(login_arguments, null, 2)); const errorMessage = validateAuthentication(token, username, password); if (errorMessage) { - core.setFailed(errorMessage); + core.error(errorMessage); return; } let api = new ScreepsAPI(login_arguments); - try { - if (token) { - const response = await api.code.set(branch, files_to_push); - core.info( - `Code uploaded via token. Response: ${JSON.stringify( - response, - null, - 2, - )}`, - ); - } else { - core.info(`Logging in with username/password for user ${username}`); - await api.auth(username, password, login_arguments); - await api.code.set(branch, files_to_push); - core.info("Code uploaded via basic auth."); - } - } catch (err) { - core.setFailed(`Upload failed: ${err.message || err}`); + if (token) { + const response = await api.code.set(branch, files_to_push); + core.info(JSON.stringify(response, null, 2)); + console.log(`Code set successfully to ${branch}`); + } else { + core.info(`Logging in as user ${username}`); + await Promise.resolve() + .then(() => api.auth(username, password, login_arguments)) + .then(() => { + return api.code.set(branch, files_to_push); + }) + .then(() => { + console.log(`Code set successfully to ${branch}`); + }) + .catch((err) => { + console.error("Error:", err); + }); } }