This commit is contained in:
parent
6f0f75d7ad
commit
705d67adec
169
index.js
169
index.js
@ -4,21 +4,11 @@ const fs = require("fs");
|
||||
const { glob } = require("glob");
|
||||
const path = require("path");
|
||||
|
||||
/**
|
||||
* Replaces specific placeholder strings within the provided content with corresponding dynamic values.
|
||||
*
|
||||
* This function specifically targets three placeholders:
|
||||
* - {{gitHash}} is replaced with the current Git commit hash, obtained from the GITHUB_SHA environment variable.
|
||||
* - {{gitRef}} is replaced with the Git reference (branch or tag) that triggered the workflow, obtained from the GITHUB_REF environment variable.
|
||||
* - {{deployTime}} is replaced with the current ISO timestamp.
|
||||
*
|
||||
* Note: This function is designed for use within a GitHub Actions workflow where GITHUB_SHA and GITHUB_REF environment variables are automatically set.
|
||||
*
|
||||
* @param {string} content - The string content in which placeholders are to be replaced.
|
||||
* @returns {string} The content with placeholders replaced by their respective dynamic values.
|
||||
*/
|
||||
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}`,
|
||||
);
|
||||
return content
|
||||
.replace(/{{gitHash}}/g, process.env.GITHUB_SHA)
|
||||
.replace(/{{gitRef}}/g, process.env.GITHUB_REF)
|
||||
@ -26,33 +16,33 @@ function replacePlaceholders(content, hostname) {
|
||||
.replace(/{{hostname}}/g, hostname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all files matching a specified pattern, replaces certain placeholders in their content, and writes the updated content back to the files.
|
||||
*
|
||||
* This function searches for files in the filesystem using the provided glob pattern, optionally prefixed. It reads each file,
|
||||
* uses the `replacePlaceholders` function to replace specific placeholders in the file's content, and then writes the modified content
|
||||
* back to the original file. This is useful for dynamically updating file contents in a batch process, such as during a build or deployment.
|
||||
*
|
||||
* @param {string} pattern - The glob pattern used to find files. Example: '*.js' for all JavaScript files.
|
||||
* @param {string} [prefix] - An optional directory prefix to prepend to the glob pattern. This allows searching within a specific directory.
|
||||
* @returns {Promise<string[]>} A promise that resolves with an array of file paths that were processed, or rejects with an error if the process fails.
|
||||
*/
|
||||
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}`);
|
||||
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);
|
||||
@ -60,27 +50,24 @@ 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 - Glob pattern to match files.
|
||||
* @param {string} prefix - Directory prefix for file paths.
|
||||
* @returns {Promise<Object>} - Promise resolving to a dictionary of file contents keyed by filenames.
|
||||
*/
|
||||
function readFilesIntoDict(pattern, prefix) {
|
||||
// Prepend the prefix to the glob pattern
|
||||
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);
|
||||
}
|
||||
|
||||
@ -88,119 +75,107 @@ function readFilesIntoDict(pattern, prefix) {
|
||||
let readPromises = [];
|
||||
|
||||
files.forEach((file) => {
|
||||
core.debug(`Reading file: ${file}`);
|
||||
let readPromise = fs.promises.readFile(file, "utf8").then((content) => {
|
||||
// Remove the prefix from the filename and drop the file suffix
|
||||
let key = file;
|
||||
if (prefix && file.startsWith(prefix)) {
|
||||
key = key.slice(prefix.length);
|
||||
}
|
||||
key = path.basename(key, path.extname(key)); // Drop the file suffix
|
||||
|
||||
key = path.basename(key, path.extname(key));
|
||||
fileDict[key] = content;
|
||||
});
|
||||
|
||||
readPromises.push(readPromise);
|
||||
});
|
||||
|
||||
// Use Promise.all to ensure all files are read before resolving
|
||||
Promise.all(readPromises)
|
||||
.then(() => resolve(fileDict))
|
||||
.catch(reject);
|
||||
.then(() => {
|
||||
core.debug(`Read ${files.length} files into dictionary.`);
|
||||
resolve(fileDict);
|
||||
})
|
||||
.catch((readErr) => {
|
||||
core.error(`Error reading files: ${readErr}`);
|
||||
reject(readErr);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the provided authentication credentials.
|
||||
* @param {string} token - The authentication token.
|
||||
* @param {string} username - The username.
|
||||
* @param {string} password - The password.
|
||||
* @returns {string|null} - Returns an error message if validation fails, otherwise null.
|
||||
*/
|
||||
function validateAuthentication(token, username, password) {
|
||||
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.";
|
||||
}
|
||||
if (token && (username || password)) {
|
||||
return "Token is defined along with username and/or password.";
|
||||
}
|
||||
return null; // No errors found
|
||||
if (!token && (!username || !password)) {
|
||||
return "Username and password must both be defined if token is not used.";
|
||||
}
|
||||
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(`Trying to upload the following files to ${branch}:`);
|
||||
Object.keys(files_to_push).forEach((key) => {
|
||||
core.info(`Key: ${key}`);
|
||||
});
|
||||
core.info(
|
||||
`Preparing to upload ${
|
||||
Object.keys(files_to_push).length
|
||||
} files to branch: ${branch}`,
|
||||
);
|
||||
|
||||
const login_arguments = {
|
||||
token: token,
|
||||
username: username,
|
||||
password: password,
|
||||
protocol: protocol,
|
||||
hostname: hostname,
|
||||
port: port,
|
||||
path: path,
|
||||
token,
|
||||
username,
|
||||
password,
|
||||
protocol,
|
||||
hostname,
|
||||
port,
|
||||
path,
|
||||
};
|
||||
|
||||
core.info("login_arguments:");
|
||||
core.info(JSON.stringify(login_arguments, null, 2));
|
||||
core.debug(`Login arguments: ${JSON.stringify(login_arguments, null, 2)}`);
|
||||
|
||||
const errorMessage = validateAuthentication(token, username, password);
|
||||
if (errorMessage) {
|
||||
core.error(errorMessage);
|
||||
core.setFailed(errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
let api = new ScreepsAPI(login_arguments);
|
||||
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(() => {
|
||||
api.code.set(branch, files_to_push);
|
||||
})
|
||||
.then(() => {
|
||||
console.log(`Code set successfully to ${branch}`);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Error:", err);
|
||||
});
|
||||
|
||||
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}`);
|
||||
}
|
||||
}
|
||||
|
||||
postCode();
|
||||
|
Loading…
x
Reference in New Issue
Block a user