mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-15 15:24:52 +09:00
Add publish workflow (#798)
* Change build-mod to belong to packages * Add publish script and workflow * Fix typo in variable name
This commit is contained in:
1 parent
3fbd9a995d
commit
41151d47f0
6 files changed
+201
-6
No files matched your search
@@ -0,0 +1,48 @@
|
||||
|
||||
name: Publish
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- released
|
||||
|
||||
jobs:
|
||||
npm:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22.x
|
||||
registry-url: https://registry.npmjs.org
|
||||
- run: pnpm install --no-frozen-lockfile
|
||||
- run: pnpm -r --filter='./{plugins,packages}/*' publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: $${{ secrets.NPM_TOKEN }}
|
||||
- uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: pnpm-lock.yaml
|
||||
|
||||
factorio:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22.x
|
||||
- run: pnpm install --no-frozen-lockfile
|
||||
- run: pnpm -r --filter='./{plugins,packages}/*' run build-mod --output-dir ../../dist
|
||||
- run: node ./publish.js factorio ./dist
|
||||
env:
|
||||
FACTORIO_TOKEN: ${{ secrets.FACTORIO_TOKEN }}
|
||||
- uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: ./dist/*
|
||||
@@ -86,8 +86,8 @@ async function removeExecutionArtifacts() {
|
||||
async function main() {
|
||||
await yargs(process.argv.slice(2))
|
||||
.scriptName("clean")
|
||||
.usage("$0 <command> [options]")
|
||||
.option("dry", {
|
||||
.option("dry-run", {
|
||||
alias: "dry",
|
||||
nargs: 0,
|
||||
describe: "Will not delete any files",
|
||||
default: false,
|
||||
@@ -108,7 +108,7 @@ async function main() {
|
||||
DRY = argv.dry;
|
||||
removeBuildArtifacts();
|
||||
})
|
||||
.demandCommand(1, "You need to specify a command to run")
|
||||
.demandCommand(1, "A command must be specified")
|
||||
.strict()
|
||||
.parse();
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
"scripts": {
|
||||
"build": "tsc --build",
|
||||
"watch": "tsc --build --watch",
|
||||
"build-mod": "node ./packages/lib/build_mod.js --source-dir ./packages/host/lua/clusterio_lib",
|
||||
"build-mod": "pnpm run -r build-mod --output-dir ../../dist",
|
||||
"test": "pnpm run build && mocha --enable-source-maps --check-leaks -R spec --recursive test \"plugins/*/test/**\" --exclude \"test/manual/**\"",
|
||||
"silent-test": "SILENT_TEST=y pnpm test",
|
||||
"fast-test": "FAST_TEST=y pnpm test",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"main": "dist/node/index.js",
|
||||
"scripts": {
|
||||
"prepare": "tsc --build",
|
||||
"build-mod": "node ../lib/build_mod.js --source-dir ./lua/clusterio_lib",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"bin": {
|
||||
|
||||
@@ -115,9 +115,21 @@ async function main() {
|
||||
"clean": { describe: "Remove previous builds", type: "boolean", default: false },
|
||||
"build": { describe: "Build mod(s)", type: "boolean", default: true },
|
||||
"pack": { describe: "Pack into zip file", type: "boolean", default: true },
|
||||
"source-dir": { describe: "Path to mod source files", nargs: 1, type: "string", demandOption: true },
|
||||
"output-dir": { describe: "Path to output built mod(s)", nargs: 1, type: "string", default: "dist" },
|
||||
"factorio-version": { describe: "Override factorio_version", type: "string" },
|
||||
"source-dir": {
|
||||
describe: "Path to mod source files",
|
||||
type: "string",
|
||||
nargs: 1,
|
||||
normalize: true,
|
||||
demandOption: true,
|
||||
},
|
||||
"output-dir": {
|
||||
describe: "Path to output built mod(s)",
|
||||
type: "string",
|
||||
nargs: 1,
|
||||
normalize: true,
|
||||
default: "dist/factorio",
|
||||
},
|
||||
})
|
||||
.strict()
|
||||
.argv
|
||||
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* Publish any mods that need to be published
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
const FormData = require("form-data");
|
||||
const fs = require("fs-extra");
|
||||
const yargs = require("yargs");
|
||||
|
||||
let DRY = false;
|
||||
|
||||
const modReleaseCache = new Map();
|
||||
/**
|
||||
* Gets a list of all releases for a mod
|
||||
*/
|
||||
async function requestModReleases(mod) {
|
||||
const cache = modReleaseCache.get(mod);
|
||||
if (cache) {
|
||||
return cache;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Requesting current releases of ${mod}`);
|
||||
|
||||
const response = await fetch(`https://mods.factorio.com/api/mods/${mod}`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed request to mod portal api: ${response.statusText}\n${await response.text()}`);
|
||||
}
|
||||
|
||||
const json = await response.json();
|
||||
modReleaseCache.set(mod, json.releases);
|
||||
return json.releases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload a mod to the mod portal
|
||||
*/
|
||||
async function uploadModRelease(file, name) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Uploading new release ${file}`);
|
||||
if (DRY) {
|
||||
return;
|
||||
}
|
||||
|
||||
const headers = {
|
||||
Authorization: `Bearer ${process.env.FACTORIO_TOKEN}`,
|
||||
};
|
||||
|
||||
// Start the upload process by requesting an upload url
|
||||
const initFormData = new FormData();
|
||||
initFormData.append("mod", name);
|
||||
|
||||
const initResponse = await fetch("https://mods.factorio.com/api/v2/mods/releases/init_upload", {
|
||||
method: "POST",
|
||||
headers: headers,
|
||||
body: initFormData,
|
||||
});
|
||||
if (!initResponse.ok) {
|
||||
throw new Error(`Failed init mod upload: ${initResponse.statusText}\n${await initResponse.text()}`);
|
||||
}
|
||||
|
||||
// Upload the new version of the mod
|
||||
const uploadUrl = (await initResponse.json()).upload_url;
|
||||
const uploadFormData = new FormData();
|
||||
uploadFormData.append("file", fs.createReadStream(file));
|
||||
|
||||
const uploadResponse = await fetch(uploadUrl, {
|
||||
method: "POST",
|
||||
headers: headers,
|
||||
body: uploadFormData,
|
||||
});
|
||||
if (!uploadResponse.ok) {
|
||||
throw new Error(`Failed mod upload: ${uploadResponse.statusText}\n${await uploadResponse.text()}`);
|
||||
}
|
||||
}
|
||||
|
||||
const regexModZip = /(\w+)_\d+.\d+.\d+\.zip/;
|
||||
/**
|
||||
* Publishes all mods that require publishing
|
||||
*/
|
||||
async function publishMods(dir) {
|
||||
const files = await fs.readdir(dir);
|
||||
const mods = files
|
||||
.map(file => regexModZip.exec(file))
|
||||
.filter(file => Boolean(file));
|
||||
|
||||
const uploading = [];
|
||||
for (const mod of mods) {
|
||||
const [file, name] = mod;
|
||||
const releases = await requestModReleases(name);
|
||||
if (!releases.some(release => release.file_name === file)) {
|
||||
uploading.push(uploadModRelease(file, name));
|
||||
} else {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Skipped ${file}`);
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(uploading);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main function for this script
|
||||
*/
|
||||
async function main() {
|
||||
await yargs(process.argv.slice(2))
|
||||
.scriptName("publish")
|
||||
.option("dry-run", {
|
||||
alias: "dry",
|
||||
nargs: 0,
|
||||
describe: "Will not publish anything",
|
||||
default: false,
|
||||
type: "boolean",
|
||||
})
|
||||
.command(["factorio <mods-dir>", "$0 <mods-dir>"], "Publish factorio mods", yargs => {
|
||||
yargs
|
||||
.positional("mods-dir", {
|
||||
describe: "Path to packed mods to publish",
|
||||
normalize: true,
|
||||
type: "string",
|
||||
})
|
||||
.demandOption("mods-dir", "A path to the mods dir must be specified");
|
||||
}, async argv => {
|
||||
DRY = argv.dry;
|
||||
publishMods(argv.modsDir);
|
||||
})
|
||||
.strict()
|
||||
.parse();
|
||||
}
|
||||
|
||||
// Run main if started from command line
|
||||
if (module === require.main) {
|
||||
main();
|
||||
}
|
||||
Reference in new issue
Block a user