Add build script (#989)

* make build script

* fix formating

* Add newline

* test action

* debug

* tag logic

* that would do it

* GITHUB_ENV

* NODE_AUTH_TOKEN

* update version

* change order

* setup cores

* it works now
This commit is contained in:
Allan Niles 2025-04-23 17:08:30 -06:00 committed by GitHub
parent 8dbf1cff29
commit bd26e754d9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 381 additions and 9 deletions

View File

@ -34,5 +34,5 @@ jobs:
- name: Clean Up Minify
run: |
cd /mnt/HDD/public/.EmulatorJS/
rm "minify/package-lock.json"
rm -f "minify/package-lock.json"
rm -rf "minify/node_modules/"

View File

@ -13,8 +13,55 @@ jobs:
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
- name: Get latest release tag (if workflow_dispatch)
if: ${{ github.event_name == 'workflow_dispatch' }}
run: |
LATEST_TAG=$(curl -s https://api.github.com/repos/${{ github.repository }}/releases/latest | jq -r '.tag_name')
echo "LATEST_TAG=$LATEST_TAG" >> $GITHUB_ENV
- name: Download cores
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG_NAME=${{ github.event.release.tag_name || env.LATEST_TAG }}
TRIMMED_TAG=${TAG_NAME#v}
echo "TRIMMED_TAG=$TRIMMED_TAG" >> $GITHUB_ENV
gh release download "$TAG_NAME" \
--repo ${{ github.repository }} \
--pattern "$TRIMMED_TAG.7z"
- name: Extract cores
run: |
7z x -y "$TRIMMED_TAG.7z" "data/cores/*" -o./
rm "$TRIMMED_TAG.7z"
- run: npm i
- run: npm ci
- run: npm publish --access public
- name: Make @emulatorjs/emulatorjs
run: |
node build.js --npm=emulatorjs
npm ci
npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Get cores list
run: |
echo "CORES=$(node build.js --npm=get-cores | jq -r '. | join(" ")')" >> $GITHUB_ENV
- name: Setup cores
run: |
node build.js --npm=cores
- name: Publish each core
run: |
cd data/cores
for core in $CORES; do
echo "Processing core: $core"
cd $core
npm publish --access public
cd ..
done
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Make @emulatorjs/cores
run: |
cd data/cores
npm i
npm ci
npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

11
.gitignore vendored
View File

@ -1,10 +1,15 @@
**/node_modules/
*.db
node_modules/
package-lock.json
yarn.lock
roms/
data/emulator.min.js
data/emulator.min.css
data/cores
data/cores/*
!data/cores/README.md
!data/cores/core-README.md
!data/cores/package.json
!data/cores/.npmignore
.DS_Store
.vscode/*
*.tgz
dist/

15
.npmignore Normal file
View File

@ -0,0 +1,15 @@
.git
dist/
node_modules/
package-lock.json
.github/
*.tgz
update.js
build.js
data/localization/translate.html
data/cores/*
!data/cores/README.md
!data/cores/package.json
minify/
.npmignore
.gitignore

183
build.js Normal file
View File

@ -0,0 +1,183 @@
import fs from 'fs';
import path from 'path';
import Seven from 'node-7z';
let version;
try {
const packageJsonPath = path.resolve('package.json');
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
version = packageJson.version;
} catch (error) {
console.error("Error reading version from package.json:", error.message);
process.exit(1);
}
const args = process.argv.slice(2);
const npmArg = args.find(arg => arg.startsWith('--npm='));
const build_type = npmArg ? npmArg.split('=')[1] : process.env.npm;
if (!build_type) {
const progressData = {
'7z': 0,
'zip': 0
};
const progressInterval = setInterval(() => {
process.stdout.clearLine();
process.stdout.cursorTo(0);
if (progressData['7z'] < 100 && progressData['zip'] < 100) {
process.stdout.write(`7z Progress: ${progressData['7z']}% | Zip Progress: ${progressData['zip']}%`);
} else if (progressData['7z'] === 100) {
console.log(`${version}.7z created successfully!`);
process.stdout.write(`Zip Progress: ${progressData['zip']}%`);
progressData['7z'] = 101;
} else if (progressData['zip'] === 100) {
console.log(`${version}.zip created successfully!`);
process.stdout.write(`7z Progress: ${progressData['7z']}%`);
progressData['zip'] = 101;
} else if (progressData['zip'] >= 100 && progressData['7z'] >= 100) {
process.stdout.write(`All archives for EmulatorJS version: ${version} created successfully!`);
clearInterval(progressInterval);
console.log('\nArchives are in the dist/ folder.');
} else if (progressData['7z'] >= 100) {
process.stdout.write(`Zip Progress: ${progressData['zip']}%`);
} else if (progressData['zip'] >= 100) {
process.stdout.write(`7z Progress: ${progressData['7z']}%`);
}
}, 100);
console.log(`Creating archives for EmulatorJS version: ${version}`);
const npmIgnorePath = path.resolve('.npmignore');
if (!fs.existsSync('dist')) {
fs.mkdirSync('dist');
}
const distNpmIgnorePath = path.resolve('dist', '.ignore');
fs.copyFileSync(npmIgnorePath, distNpmIgnorePath);
const npmIgnoreContent = fs.readFileSync(npmIgnorePath, 'utf8');
const updatedNpmIgnoreContent = npmIgnoreContent.replace('data/cores/*', 'data/cores/core-README.md\ndata/cores/package.json');
fs.writeFileSync(distNpmIgnorePath, updatedNpmIgnoreContent, 'utf8');
Seven.add(`dist/${version}.7z`, './', {
$raw: ['-xr@dist/.ignore'],
$progress: true
}).on('progress', function (progress) {
progressData['7z'] = progress.percent;
}).on('end', function () {
progressData['7z'] = 100;
});
Seven.add(`dist/${version}.zip`, './', {
$raw: ['-xr@dist/.ignore'],
$progress: true
}).on('progress', function (progress) {
progressData['zip'] = progress.percent;
}).on('end', function () {
progressData['zip'] = 100;
});
} else if (build_type !== "emulatorjs" && build_type !== "cores" && build_type !== "get-cores") {
console.log("Invalid argument. Use --npm=emulatorjs, --npm=cores or --npm=get-cores.");
process.exit(1);
} else {
const removeLogo = () => {
const readmePath = path.resolve('README.md');
const readmeContent = fs.readFileSync(readmePath, 'utf8');
const updatedContent = readmeContent
.split('\n')
.filter(line => !line.includes('docs/Logo-light.png#gh-dark-mode-only>'))
.join('\n');
fs.writeFileSync(readmePath, updatedContent, 'utf8');
};
const getCores = async () => {
const coresJsonPath = path.resolve('data', 'cores', 'cores.json');
if (!fs.existsSync(coresJsonPath)) {
console.error(`Cores JSON file not found at ${coresJsonPath}`);
return;
}
return JSON.parse(fs.readFileSync(coresJsonPath, 'utf8'));
};
if (build_type === "emulatorjs") {
console.log(`Current EmulatorJS Version: ${version}`);
removeLogo();
console.log("Ready to build EmulatorJS!");
} else if (build_type === "get-cores") {
const cores = await getCores();
console.log(JSON.stringify(cores.map(coreName => coreName.name)));
} else if (build_type === "cores") {
console.log(`Current EmulatorJS Version: ${version}`);
console.log("Building cores...");
const allCores = await getCores();
console.log("Building EmulatorJS cores:");
const coreNames = allCores.map(coreName => coreName.name);
console.log(coreNames.join(', '));
if (!coreNames) {
console.error("No cores found.");
process.exit(1);
}
const coresPath = path.resolve('data', 'cores');
const coresFiles = fs.readdirSync(coresPath);
const dataFiles = coresFiles.filter(file => file.endsWith('.data') || file.endsWith('.zip'));
const cores = {};
for (const core of coreNames) {
const coreFiles = dataFiles.filter(file => file.startsWith(core + '-'));
if (!cores[core]) {
cores[core] = [];
}
cores[core].push(...coreFiles);
}
const packagePath = path.resolve('data', 'cores', 'package.json');
const packageContent = fs.readFileSync(packagePath, 'utf8');
const packageJson = JSON.parse(packageContent);
packageJson.dependencies = {
"@emulatorjs/emulatorjs": "latest"
};
fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 4), 'utf8');
for (const core in cores) {
if (!fs.existsSync(path.resolve('data', 'cores', core))) {
fs.mkdirSync(path.resolve('data', 'cores', core));
}
for (const file of cores[core]) {
const sourcePath = path.resolve('data', 'cores', file);
const destPath = path.resolve('data', 'cores', core, file);
fs.copyFileSync(sourcePath, destPath);
const reportsPath = path.resolve('data', 'cores', core, 'reports');
if (!fs.existsSync(reportsPath)) {
fs.mkdirSync(reportsPath);
}
}
const coreReportPath = path.resolve('data', 'cores', 'reports', `${core}.json`);
const coreReportDestPath = path.resolve('data', 'cores', core, 'reports', `${core}.json`);
fs.copyFileSync(coreReportPath, coreReportDestPath);
const corePackagePath = path.resolve('data', 'cores', 'package.json');
const corePackageDestPath = path.resolve('data', 'cores', core, 'package.json');
const corePackageContent = fs.readFileSync(corePackagePath, 'utf8');
const corePackageJson = JSON.parse(corePackageContent);
corePackageJson.name = `@emulatorjs/core-${core}`;
corePackageJson.description = `EmulatorJS Core: ${core}`;
corePackageJson.license = allCores.find(c => c.name === core).license;
corePackageJson.repository.url = allCores.find(c => c.name === core).repo + '.git';
corePackageJson.bugs.url = allCores.find(c => c.name === core).repo + '/issues';
corePackageJson.dependencies = {
"@emulatorjs/emulatorjs": "latest"
};
fs.writeFileSync(corePackageDestPath, JSON.stringify(corePackageJson, null, 4), 'utf8');
const coreReadmePath = path.resolve('data', 'cores', 'core-README.md');
const coreReadmeDestPath = path.resolve('data', 'cores', core, 'README.md');
const coreReadmeContent = fs.readFileSync(coreReadmePath, 'utf8');
const updatedCoreReadmeContent = coreReadmeContent
.replace(/<!-- EJS_CORE_NAME -->/g, `${core}`)
.replace(/<!-- EJS_CORE_REPO -->/g, allCores.find(c => c.name === core).repo);
fs.writeFileSync(coreReadmeDestPath, updatedCoreReadmeContent, 'utf8');
packageJson.dependencies[`@emulatorjs/core-${core}`] = "latest";
fs.writeFileSync(packagePath, JSON.stringify(packageJson, null, 4), 'utf8');
}
console.log("EmulatorJS cores built successfully!");
console.log("Ready to build EmulatorJS!");
}
}

3
data/cores/.npmignore Normal file
View File

@ -0,0 +1,3 @@
*
!README.md
!package.json

22
data/cores/README.md Normal file
View File

@ -0,0 +1,22 @@
# EmulatorJS Cores
This package contains the stable cores for EmulatorJS.
Lean more about EmulatorJS at https://emulatorjs.org
Cores are build using this repository:
https://github.com/EmulatorJS/build
## How to install
To install all cores, run the following command:
```bash
npm install @emulatorjs/cores
```
To install a specific core, run the following command:
```bash
npm install @emulatorjs/core-<core-name>
```

25
data/cores/core-README.md Normal file
View File

@ -0,0 +1,25 @@
# EmulatorJS Core: <!-- EJS_CORE_NAME -->
This package contains the stable EmulatorJS core: <!-- EJS_CORE_NAME -->
Lean more about EmulatorJS at https://emulatorjs.org
Core repository:
<!-- EJS_CORE_REPO -->
Core is build using this repository:
https://github.com/EmulatorJS/build
## How to install
To install core, run the following command:
```bash
npm install @emulatorjs/core-<!-- EJS_CORE_NAME -->
```
To install all cores, run the following command:
```bash
npm install @emulatorjs/cores
```

65
data/cores/package.json Normal file
View File

@ -0,0 +1,65 @@
{
"name": "@emulatorjs/cores",
"version": "4.2.1",
"type": "module",
"description": "EmulatorJS Cores",
"homepage": "https://emulatorjs.org",
"license": "GPL-3.0",
"repository": {
"type": "git",
"url": "https://github.com/EmulatorJS/EmulatorJS.git"
},
"bugs": {
"url": "https://github.com/EmulatorJS/EmulatorJS/issues"
},
"sideEffects": true,
"dependencies": {
"@emulatorjs/emulatorjs": "latest",
"@emulatorjs/core-81": "latest",
"@emulatorjs/core-mame2003": "latest",
"@emulatorjs/core-vice_x64": "latest",
"@emulatorjs/core-vice_x64sc": "latest",
"@emulatorjs/core-vice_x128": "latest",
"@emulatorjs/core-vice_xpet": "latest",
"@emulatorjs/core-vice_xplus4": "latest",
"@emulatorjs/core-vice_xvic": "latest",
"@emulatorjs/core-fceumm": "latest",
"@emulatorjs/core-nestopia": "latest",
"@emulatorjs/core-snes9x": "latest",
"@emulatorjs/core-gambatte": "latest",
"@emulatorjs/core-mgba": "latest",
"@emulatorjs/core-beetle_vb": "latest",
"@emulatorjs/core-mupen64plus_next": "latest",
"@emulatorjs/core-melonds": "latest",
"@emulatorjs/core-desmume2015": "latest",
"@emulatorjs/core-desmume": "latest",
"@emulatorjs/core-a5200": "latest",
"@emulatorjs/core-fbalpha2012_cps1": "latest",
"@emulatorjs/core-fbalpha2012_cps2": "latest",
"@emulatorjs/core-prosystem": "latest",
"@emulatorjs/core-stella2014": "latest",
"@emulatorjs/core-opera": "latest",
"@emulatorjs/core-genesis_plus_gx": "latest",
"@emulatorjs/core-yabause": "latest",
"@emulatorjs/core-handy": "latest",
"@emulatorjs/core-virtualjaguar": "latest",
"@emulatorjs/core-pcsx_rearmed": "latest",
"@emulatorjs/core-picodrive": "latest",
"@emulatorjs/core-fbneo": "latest",
"@emulatorjs/core-mednafen_psx_hw": "latest",
"@emulatorjs/core-mednafen_pce": "latest",
"@emulatorjs/core-mednafen_pcfx": "latest",
"@emulatorjs/core-mednafen_ngp": "latest",
"@emulatorjs/core-mednafen_wswan": "latest",
"@emulatorjs/core-gearcoleco": "latest",
"@emulatorjs/core-parallel_n64": "latest",
"@emulatorjs/core-mame2003_plus": "latest",
"@emulatorjs/core-puae": "latest",
"@emulatorjs/core-smsplus": "latest",
"@emulatorjs/core-fuse": "latest",
"@emulatorjs/core-cap32": "latest",
"@emulatorjs/core-crocods": "latest",
"@emulatorjs/core-prboom": "latest",
"@emulatorjs/core-ppsspp": "latest"
}
}

View File

@ -1,10 +1,11 @@
{
"name": "@emulatorjs/emulatorjs",
"version": "4.2.1",
"version": "4.2.1-beta.2",
"type": "module",
"description": "EmulatorJS is a frontend for RetroArch in the web browser.",
"homepage": "https://emulatorjs.org",
"license": "GPL-3.0",
"sideEffects": true,
"repository": {
"type": "git",
"url": "https://github.com/EmulatorJS/EmulatorJS.git"
@ -14,12 +15,18 @@
},
"scripts": {
"start": "http-server",
"minify": "node minify/minify.js"
"minify": "node minify/minify.js",
"build": "node build.js"
},
"dependencies": {
"http-server": "^14.1.1",
"@node-minify/clean-css": "^9.0.1",
"@node-minify/core": "^9.0.2",
"@node-minify/terser": "^9.0.1",
"http-server": "^14.1.1"
"node-7z": "^3.0.0",
"node-fetch": "^3.3.2"
},
"optionalDependencies": {
"@emulatorjs/cores": "latest"
}
}