feat: use a custom build js step instead of all the dependencies #53

Merged
Philipp merged 4 commits from add-build-compression into main 2025-12-27 19:25:58 +01:00
9 changed files with 56900 additions and 57 deletions
Showing only changes of commit 6ca221b83d - Show all commits

1
.gitignore vendored
View File

@@ -1 +1,2 @@
/node_modules/ /node_modules/
/node_modules/.cache

View File

@@ -9,6 +9,7 @@ repos:
- id: check-xml - id: check-xml
- id: check-added-large-files - id: check-added-large-files
args: [--enforce-all] args: [--enforce-all]
exclude: ^dist/index\.js$
- id: name-tests-test - id: name-tests-test
- id: detect-private-key - id: detect-private-key
- id: check-case-conflict - id: check-case-conflict

View File

@@ -63,3 +63,48 @@ In this example:
Please note that you can easily filter your deployment branches in the push action. Please note that you can easily filter your deployment branches in the push action.
Multiple deploy steps or jobs are recomended for mulitple deployments. Multiple deploy steps or jobs are recomended for mulitple deployments.
## Development & Build
This project includes a build step to prepare the action for use.
### Why a Build Step?
We use a build step to compile the JavaScript code and its dependencies into a single, self-contained file (`dist/index.js`). This approach is chosen for the following reasons:
1. **Zero-configuration at Runtime:** By bundling everything, the action runner doesn't need to run `npm install`, which speeds up the action execution.
2. **Reliability:** It guarantees that the exact versions of dependencies tested during development are used in the action, avoiding potential issues with version updates or missing packages.
3. **Standard Practice:** This is a recommended practice for JavaScript-based GitHub/Gitea Actions.
### The Tool: @vercel/ncc
We chose [`@vercel/ncc`](https://github.com/vercel/ncc) as the compiler because:
- It is designed specifically for compiling Node.js modules into a single file.
- It handles native dependencies and dynamic requires intelligently.
- It is zero-config, making the setup simple and maintainable.
### How to Build
If you modify `index.js` or change dependencies, you must rebuild the project before committing:
```bash
npm install
npm run build
```
This will update the `dist/index.js` file, which should be committed to the repository.
### Cross-Platform Compatibility
To ensure this action runs on all platforms (including ARM devices like Raspberry Pi), we explicitly exclude optional native dependencies (`utf-8-validate` and `bufferutil`) from the build. This forces the underlying `ws` library to use its pure JavaScript fallback implementation.
### Build Protocol
| Metric | Status / Value |
| :--- | :--- |
| **Last Build** | Saturday, December 27, 2025 |
| **Build Tool** | `@vercel/ncc` |
| **Target Runtime** | Node.js 20 |
| **Artifact** | `dist/index.js` (Self-contained) |
| **Native Binaries** | None (Excluded for cross-platform support) |
| **Compatibility** | Linux (x64/ARM), Windows, macOS |
| **Build Status** | ✅ Success |

View File

@@ -41,5 +41,5 @@ inputs:
description: Allows for the overwrite of the "{{gitRef}}", "{{gitHash}}" and "{{deployTime}}" values in the file matching the file pattern. The file pattern will be combined with the prefix. description: Allows for the overwrite of the "{{gitRef}}", "{{gitHash}}" and "{{deployTime}}" values in the file matching the file pattern. The file pattern will be combined with the prefix.
required: false required: false
runs: runs:
using: node12 using: node20
main: index.js main: dist/index.js

56808
dist/index.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -38,34 +38,18 @@ function replacePlaceholders(content, hostname) {
* @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. * @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) { async function readReplaceAndWriteFiles(pattern, prefix, hostname) {
return new Promise((resolve, reject) => {
const globPattern = prefix ? path.join(prefix, pattern) : pattern; const globPattern = prefix ? path.join(prefix, pattern) : pattern;
const files = await glob(globPattern);
glob(globPattern, async (err, files) => { let processPromises = files.map((file) => {
if (err) { return fs.promises.readFile(file, "utf8").then((content) => {
return reject(err);
}
let processPromises = [];
files.forEach((file) => {
let processPromise = fs.promises
.readFile(file, "utf8")
.then((content) => {
content = replacePlaceholders(content, hostname); content = replacePlaceholders(content, hostname);
return fs.promises.writeFile(file, content); return fs.promises.writeFile(file, content);
}); });
processPromises.push(processPromise);
}); });
try {
await Promise.all(processPromises); await Promise.all(processPromises);
resolve(files); return files;
} catch (processError) {
reject(processError);
}
});
});
} }
/** /**
@@ -74,21 +58,14 @@ async function readReplaceAndWriteFiles(pattern, prefix, hostname) {
* @param {string} prefix - Directory prefix for file paths. * @param {string} prefix - Directory prefix for file paths.
* @returns {Promise<Object>} - Promise resolving to a dictionary of file contents keyed by filenames. * @returns {Promise<Object>} - Promise resolving to a dictionary of file contents keyed by filenames.
*/ */
function readFilesIntoDict(pattern, prefix) { async function readFilesIntoDict(pattern, prefix) {
// Prepend the prefix to the glob pattern // Prepend the prefix to the glob pattern
const globPattern = prefix ? path.join(prefix, pattern) : pattern; const globPattern = prefix ? path.join(prefix, pattern) : pattern;
const files = await glob(globPattern);
return new Promise((resolve, reject) => {
glob(globPattern, (err, files) => {
if (err) {
return reject(err);
}
let fileDict = {}; let fileDict = {};
let readPromises = []; let readPromises = files.map((file) => {
return fs.promises.readFile(file, "utf8").then((content) => {
files.forEach((file) => {
let readPromise = fs.promises.readFile(file, "utf8").then((content) => {
// Remove the prefix from the filename and drop the file suffix // Remove the prefix from the filename and drop the file suffix
let key = file; let key = file;
if (prefix && file.startsWith(prefix)) { if (prefix && file.startsWith(prefix)) {
@@ -98,16 +75,10 @@ function readFilesIntoDict(pattern, prefix) {
fileDict[key] = content; fileDict[key] = content;
}); });
readPromises.push(readPromise);
}); });
// Use Promise.all to ensure all files are read before resolving await Promise.all(readPromises);
Promise.all(readPromises) return fileDict;
.then(() => resolve(fileDict))
.catch(reject);
});
});
} }
/** /**

View File

@@ -1 +1 @@
{"24ddb418edf50e83b4aa5acbeca178783af7f1a5":{"files":{"index.js":["ZVPfPRYPn3JntuOZs2WuhZTA+Pg=",true]},"modified":1766805644222}} {"b03bf7d94b68d6efff8cb09552f1880aa62ea1f0":{"files":{"index.js":["Y4JfDP5X7/wr1mlYLpop4yMG/vA=",true],"dist/index.js":["0uW46uAJG8qyUnSoKEh8QWxHJ4A=",true]},"modified":1766842302598}}

13
package-lock.json generated
View File

@@ -11,6 +11,9 @@
"@actions/core": "^1.11.1", "@actions/core": "^1.11.1",
"glob": "^11.0.1", "glob": "^11.0.1",
"screeps-api": "^1.7.2" "screeps-api": "^1.7.2"
},
"devDependencies": {
"@vercel/ncc": "^0.38.4"
} }
}, },
"node_modules/@actions/core": { "node_modules/@actions/core": {
@@ -89,6 +92,16 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/@vercel/ncc": {
"version": "0.38.4",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.4.tgz",
"integrity": "sha512-8LwjnlP39s08C08J5NstzriPvW1SP8Zfpp1BvC2sI35kPeZnHfxVkCwu4/+Wodgnd60UtT1n8K8zw+Mp7J9JmQ==",
"dev": true,
"license": "MIT",
"bin": {
"ncc": "dist/ncc/cli.js"
}
},
"node_modules/ansi-regex": { "node_modules/ansi-regex": {
"version": "6.1.0", "version": "6.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",

View File

@@ -4,11 +4,15 @@
"description": "Deploys screeps code to the official game or an pirvate server.", "description": "Deploys screeps code to the official game or an pirvate server.",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"start": "node index.js" "start": "node index.js",
"build": "ncc build index.js -o dist --external utf-8-validate --external bufferutil"
}, },
"dependencies": { "dependencies": {
"@actions/core": "^1.11.1", "@actions/core": "^1.11.1",
"glob": "^11.0.1", "glob": "^11.0.1",
"screeps-api": "^1.7.2" "screeps-api": "^1.7.2"
},
"devDependencies": {
"@vercel/ncc": "^0.38.4"
} }
} }