diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 6ac1cf88..68d74530 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -22,7 +22,7 @@ jobs: node-version: 24.x registry-url: https://registry.npmjs.org - run: pnpm install --no-frozen-lockfile - - run: pnpm -r --filter='./{plugins,packages}/*' publish --no-git-checks + - run: pnpm -r --filter='./packages/*' --filter='./plugins/*' --fail-if-no-match publish --no-git-checks - uses: softprops/action-gh-release@v3 with: files: pnpm-lock.yaml @@ -37,7 +37,7 @@ jobs: with: node-version: 24.x - run: pnpm install --no-frozen-lockfile - - run: pnpm -r --filter='./{plugins,packages}/*' run build-mod --output-dir ../../dist + - run: pnpm -r --filter='./packages/*' --filter='./plugins/*' --fail-if-no-match run build-mod --output-dir ../../dist - run: node ./publish.js factorio ./dist env: FACTORIO_TOKEN: ${{ secrets.FACTORIO_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 52c13d77..a18c744c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,127 @@ Many thanks to the following for contributing to this release: [@username](https://github.com/username) --> +## Version 2.0.0 + +### Features + +- Mod packs now show informational notices for disabled recommended mods and available compatible updates. [#949]() +- Added host, server name, save copy and start options to the create instance dialog in the web UI. [#405]() +- Added `InstanceSaveGameRequest` and `clusterioctl instance save-game` to save the running game of an instance. [#405]() +- Added `permissions` to `PluginDeclaration` and a `Permissions` type registry so plugin permission names are checked at compile time. [#987]() +- Added Update All to the web interface and `--all` to the ctl update commands, updating the core package and all npm installed plugins in one npm call. [#910]() +- Added typed hook system for plugin registration. ([#730]()) +- Added `plugin install ` command to controller, host and ctl which installs a plugin from npm and adds it to the plugin list. [#1008]() +- Added a guard that prevents controller and host restart requests from unintentionally downgrading Clusterio. [#950]() +- Added option to load static assets from a separate URL from where the controller's web API is hosted at. [#983]() +- Added `clusteriocontroller copy-static` command to copy static web assets to a folder to ease hosting assets on a separate server. [#983]() +- Added Mark Restart Required to the host and controller pages and matching ctl commands, for plugins installed by other means than the install request. [#1043]() +- Added the RoleViewPageBeforePermissions web extension slot for plugin components above the permissions on the role page. [#1045]() +- Added a list of permission groups to the role page, highlighting groups with granted permissions. [#1044]() +- Added `clusteriohost create-scenario` to create a scenario with the Clusterio modules patched in for use outside of Clusterio. [#1014]() +- Plugins can declare a `migrationEntrypoint` to migrate the config fields and role permissions core stores for them. Configs track the plugin version they were last loaded with in a hidden `.version` field. [#1073]() + +### Fixes + +- Deprecation warning DEP0190 is no longer printed when installing. [#851]() +- Events sent to subscribers are no longer addressed to the request id of the request that created the subscription. [#847]() +- Factorio account token no longer written to the log when a mod download fails. [#795]() +- Failed downloads no longer leave a temporary file and an open file handle behind, which could shift the file names used by later downloads. [#957]() +- Requests that could not be forwarded to the next hop are no longer answered a second time when the link disconnects. [#650]() +- Events broadcast from an instance to all hosts are now delivered to every host instead of only the one running the instance. [#575]() +- Web interface now asks to be reloaded when the controller's plugins change, instead of continuing against plugins that are no longer loaded. [#804]() +- Plugin list no longer reports a plugin added since the page was opened as having failed to load. [#729]() +- Instance console no longer hides the Factorio server's replies to console commands, or Factorio's own errors, when filtering to game activity. [#853]() +- Allow player online autosave slots to be disabled while autosaves are enabled. [#966]() +- Plugin web bundles are now loaded relative to `staticRoot` instead of `webRoot`. [#980]() +- Fixed inventory_sync not preserving the personal roboport toggle, the equipment movement bonus toggle, game view settings such as alt mode, and toggleable mod shortcuts between instances. [#898]() +- Schema validation errors are now included when an InvalidMessage is logged from IPC and event handlers. [#986]() +- Fixed clusterioctl not being able to reference hosts, instances, mod packs and roles by an integer like name. [#886]() +- Fixed the web-only plugin template referencing a permission that was never defined. [#987]() +- Config files are no longer world readable by default. [#1005]() +- Fixed failed recipe notification names being duplicated on every upload from the same instance in inventory sync. [#964]() +- Instances refuse to start with a mod pack for a newer Factorio version than the instance runs, instead of Factorio silently loading default mod settings. [#1006]() +- Documented the config options missing from configuration.md, marked the internal ones and noted the validation rules. [#985]() +- Fixed concurrent saves of the same file racing on a shared temporary file. [#1026]() +- Fixed control connections leaving their log subscription and debug dump listeners attached after closing. [#1027]() +- Fixed the Load Scenario modal reading the wrong field for map settings. [#1032]() +- Fixed the controller exiting when a control message's permission check threw an unexpected error. [#1033]() +- Fixed the host exiting on server log lines that look like actions but do not match the expected format. [#1034]() +- Fixed the controller crashing when a control connection with the WebSocket debug dump active was resumed. [#1035]() +- Fixed deleted users keeping their permissions on any open connection until they disconnected. [#1030]() +- Restored pagination on the instance save list. [#967]() +- Mod dependency resolution now only picks releases made for the mod pack's Factorio version. [#965]() +- Inventory sync no longer uploads an empty inventory over the stored one after a failed download. [#912]() +- Inventory sync now releases players who leave while using a temporary inventory, instead of showing them as busy until the instance stops. [#975]() +- Fixed reading map exchange strings from Factorio 2.1.13 and later, which broke `instance load-scenario --map-exchange-string` on current Factorio. [#977]() +- Fixed instances getting stuck on a host after a failed assign, and instance create requests no longer accept `instance.assigned_host`. [#1029]() +- Fixed the host exiting when an instance's whitelist or server settings config changed while it was starting, or when tags contained non-string values. [#1028]() +- Fixed a host being able to modify the controller's stored save list for, or forge log messages attributed to, instances assigned to other hosts. [#1036]() +- Fixed a stop request or RCON command hanging when the Factorio process exited before its RCON connection was established. [#1031]() +- Fixed core plugins needlessly installing the web_ui, controller, host and ctl packages. [#1021]() +- Installing a plugin on a host or the controller now marks it as needing a restart. [#1042]() +- Fixed plugin manifest path resolution when loading web assets. [#1046]() +- A plugin whose web build is expected but missing is reported again: `Controller.loadJsonObject(path, true)` throws on a missing file instead of returning `{}`, and a malformed JSON file always throws. [#1046]() +- Preserve full configuration field names when using the CLI config editor. [#796]() +- Plugin metrics hook handlers may return nothing. [#1052]() +- Fixed save names given when starting an instance or creating a save not being checked, allowing files outside the instance directory to be written or modified. [#1053]() +- Fixed access tokens from request headers being written to the controller and cluster logs. [#1054]() +- Fixed subscriptions and log following continuing after the user lost permission for them. [#1056]() +- Fixed web interface data staying marked as up to date after the user lost permission to view it, and not loading after permission was granted. [#1058]() +- Fixed ctl config edit showing fields that cannot be edited and leaving out field descriptions. [#1051]() +- Fixed the reason an instance failed to start being logged as "undefined". [#1065]() +- Fixed subspace inventory combinators missing items after instance startup. [#1069]() +- Fixed the controller crashing when a WebSocket client sent an invalid frame before completing the handshake. [#1063]() +- Fixed an instance reusing a stored game port that another process holds, which made it fail to start until the port was freed. [#1065]() +- Fixed credentials in request query parameters, such as OAuth codes, being written to the controller's HTTP log. [#1074]() +- Fixed plugin `ctlConfigFields` not being registered in the clusterioctl config. [#1075]() +- Fixed startup failures and plugin loading when installing Clusterio from published npm packages after the ES module migration. [#1070]() + +### Changes + +- Global chat now filters server-specific GPS, blueprint, train, and train-stop rich-text tags before relaying messages between instances. [#593]() +- Instance console filter is now a labelled Game/Instance control instead of a single-label toggle, and Factorio's output in the log consoles is prefixed with `[server]` like every other log level. [#853]() +- Inventory sync sends only the recipe notifications that differ from the destination instance's state on download. [#964]() +- Log the source of responses received without a pending request, the peer of timed out connections and the number of messages resent on session resume. [#1007]() +- Plugins that are not expected to have a web build are no longer shown with an error in the plugins page. [#1004]() +- Plugins should now return a function to register handlers via hooks. ([#730]()) +- Plugin templates from `@clusterio/create` use entrypoint functions and hooks. ([#730]()) +- Improved typing for plugin APIs and webui extension points. ([#730]()) +- Plugin hooks run concurrently instead of one plugin at a time. ([#730]()) +- Access tokens are also accepted as an `Authorization: Bearer` header on HTTP API endpoints. [#1009]() +- `plugin install` and `plugin add` with a package name now check that they are run from a Clusterio installation directory. [#1008]() +- Bumped pnpm to 12, the GitHub Actions used by CI to their current majors, and the CI Factorio version to 2.1.17. [#1022]() +- Bumped dependencies, including eslint 10, yargs 18, chalk 6, @types/express 5 and @types/node 24. [#1023]() +- Plugin discovery now traverses dependencies only after confirming the parent package is a Clusterio plugin. [#963]() +- Converted the project to using ES Modules. [#984]() +- Converted the bundled plugins to entrypoint functions. [#1052]() +- Added `controller.max_subscription_filters` config to limit the number of filters a connection can subscribe with for one event. [#1055]() +- Added `controller.max_send_buffer_size` config to limit how much the controller buffers for a connection that does not acknowledge messages. [#1057]() +- Added links to the ExpCluster and Chat Relay community plugins in the README. [#1062]() + +### Breaking Changes + +- `staticRoot` in the web interface now includes the `static/` prefix. Plugins that fetch assets with `${staticRoot}static/...` should drop the `static/` part. [#980]() +- `checkPermission` and the web UI `hasPermission` helpers take `PermissionName`; TypeScript plugins must augment the `Permissions` interface. [#987]() +- Replaced `plugins` map with `loadedPlugins` set across core classes (except WebUi). ([#730]()) +- The `/metrics` endpoint requires a user token with the new `core.controller.metrics` permission. Concurrent scrapes share a single gather from the hosts. [#1009]() +- Config files now have to be explicitly created. Use the `--create-config` flag to get the old behaviour of creating it if missing. [#548]() +- Renamed clusterioctl's config-control subcommand to config. [#1039]() +- Renamed clusterioctl's main class from Control to Ctl. [#1039]() +- Renamed clusterioctl's config entries from control.[name] to ctl.[name]. [#1039]() +- Plugin entrypoints must now specify the full filename including the `.js` extension. [#984]() +- Renamed the inventory_sync plugin to player_sync, published as `@clusterio/plugin-player_sync`. Config fields, the inventory view permission, the controller database file and save data are migrated on load. Uninstall `@clusterio/plugin-inventory_sync` before installing the new package. [#1072]() + +### Meta + +- Added a `NO_EXTERNAL_TEST` flag to skip tests that use external APIs. [#976]() +- Added a CI check that the controller and host stay compatible with the latest published release. [#978]() +- Added a Lua lint CI job using emmylua_check. [#979]() +- Added a plugin migration guide for 2.0 and documented that minor versions may contain breaking changes for the plugin API. [#1050]() + +Many thanks to the following for contributing to this release: +[@bbassie](), [@lntutor](), [@ColumbusLabs](), [@floze-the-genius](), [@Cooldude2606](), [@solarcloud7](), [@Hornwitser](), [@ILLISIS](), [@Danielv123](), [@PHIDIAS0303]() + ## Version 2.0.0-alpha.27 ### Features @@ -47,14 +168,12 @@ Many thanks to the following for contributing to this release: ### Fixes -- Allow player online autosave slots to be disabled while autosaves are enabled. [#966]() - Silenced two Ant Design console warnings in the Web UI: the deprecated Modal `destroyOnClose` prop, and a duplicate-value warning from the instance version selector. [#940]() - Surface the mod portal's own error when downloading mods for an unsupported Factorio version. [#941]() - Instances always create their config file on assignment preventing duplicate folder creation. [#945]() ### Changes -- Global chat now filters server-specific GPS, blueprint, train, and train-stop rich-text tags before relaying messages between instances. [#593]() - Reworked the site layout into a fixed sidebar with a top bar. [#924]() - The builtin "recycler" mod is now included correctly as builtin. [#925]() - Mod `info.json` versions (a mod's version and its `factorio_version`) are now parsed leniently, matching how the game reads them, instead of being validated against a fixed list of Factorio versions. [#941]() diff --git a/README.md b/README.md index 1f803461..15425bf8 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,10 @@ Discord for development/support/play: https://discord.gg/5XuDkje ## Important notice -Clusterio 2.0 is still in alpha, however the previous stable has been abandoned and is no longer supported. -Despite being alpha it's reasonably stable now and there's no major breakages expected before a stable release of 2.0. -If you are starting a new cluster, it's highly recommended to use the 2.0 alpha. +Clusterio 2.0 is the current stable release and requires Node.js 22 or newer. +The previous stable series is no longer supported. +If you are upgrading from a 2.0 alpha, review the [changelog](CHANGELOG.md) before upgrading. +Plugin authors should also follow the [2.0 migration guide](docs/devs/plugin-migration-to-2.0.md). ### Ways to support me/the project: diff --git a/docs/release-workflow.md b/docs/release-workflow.md index 691afec2..188a5f6e 100644 --- a/docs/release-workflow.md +++ b/docs/release-workflow.md @@ -11,6 +11,12 @@ If the script fails due to GitHub's 60/hour public access rate limit, you can se ## Packages +The [Publish workflow](../.github/workflows/publish.yml) publishes npm packages and Lua mods when a GitHub release is published. +For this workflow, first merge the changelog and package version updates into `master`, then create and push the release tag on that merged commit. +Create a draft GitHub release for the existing tag and use the GitHub Release Markdown from `scripts/pr_to_changelog.mts` as its notes. +Publishing the draft triggers the workflow; pushing a tag alone does not. +The steps below describe publishing npm packages manually instead. + > [!NOTE] > You will need commit access to the repository as well publish access to the @clusterio org on npm to do this. @@ -40,7 +46,7 @@ If the script fails due to GitHub's 60/hour public access rate limit, you can se ```sh pnpm clean - pnpm -r --filter='./{plugins,packages}/*' publish + pnpm -r --filter='./packages/*' --filter='./plugins/*' --fail-if-no-match publish ``` ## Plugins diff --git a/packages/controller/package.json b/packages/controller/package.json index 041ce483..ac3bec78 100644 --- a/packages/controller/package.json +++ b/packages/controller/package.json @@ -1,6 +1,6 @@ { "name": "@clusterio/controller", - "version": "2.0.0-alpha.27", + "version": "2.0.0", "description": "Implementation of Clusterio controller", "homepage": "https://github.com/clusterio/clusterio#readme", "author": "Hornwitser ", diff --git a/packages/create/package.json b/packages/create/package.json index 85a50e44..3d4ab2a9 100644 --- a/packages/create/package.json +++ b/packages/create/package.json @@ -1,6 +1,6 @@ { "name": "@clusterio/create", - "version": "2.0.0-alpha.27", + "version": "2.0.0", "description": "Installer for clusterio", "homepage": "https://github.com/clusterio/clusterio#readme", "author": "Hornwitser ", diff --git a/packages/ctl/package.json b/packages/ctl/package.json index 0d73a9a4..37ff79af 100644 --- a/packages/ctl/package.json +++ b/packages/ctl/package.json @@ -1,6 +1,6 @@ { "name": "@clusterio/ctl", - "version": "2.0.0-alpha.27", + "version": "2.0.0", "description": "Clusterio command line management tool", "homepage": "https://github.com/clusterio/clusterio#readme", "author": "Hornwitser ", diff --git a/packages/host/package.json b/packages/host/package.json index 70dc3a3f..09f47512 100644 --- a/packages/host/package.json +++ b/packages/host/package.json @@ -1,6 +1,6 @@ { "name": "@clusterio/host", - "version": "2.0.0-alpha.27", + "version": "2.0.0", "description": "Implementation of Clusterio host server", "homepage": "https://github.com/clusterio/clusterio#readme", "author": "Hornwitser ", diff --git a/packages/lib/package.json b/packages/lib/package.json index 5f6f94b3..2c0d447c 100644 --- a/packages/lib/package.json +++ b/packages/lib/package.json @@ -1,6 +1,6 @@ { "name": "@clusterio/lib", - "version": "2.0.0-alpha.27", + "version": "2.0.0", "description": "Shared library for Clusterio", "homepage": "https://github.com/clusterio/clusterio#readme", "author": "Hornwitser ", diff --git a/packages/web_ui/package.json b/packages/web_ui/package.json index 93c2aad8..340f55dc 100644 --- a/packages/web_ui/package.json +++ b/packages/web_ui/package.json @@ -1,6 +1,6 @@ { "name": "@clusterio/web_ui", - "version": "2.0.0-alpha.27", + "version": "2.0.0", "description": "Clusterio web interface implementation", "homepage": "https://github.com/clusterio/clusterio#readme", "author": "Hornwitser", diff --git a/plugins/global_chat/package.json b/plugins/global_chat/package.json index 6947e542..2928100a 100644 --- a/plugins/global_chat/package.json +++ b/plugins/global_chat/package.json @@ -1,6 +1,6 @@ { "name": "@clusterio/plugin-global_chat", - "version": "2.0.0-alpha.27", + "version": "2.0.0", "description": "Clusterio plugin forwarding between Factorio servers", "homepage": "https://github.com/clusterio/clusterio#readme", "author": "Hornwitser ", diff --git a/plugins/player_auth/package.json b/plugins/player_auth/package.json index a2535d16..425e0830 100644 --- a/plugins/player_auth/package.json +++ b/plugins/player_auth/package.json @@ -1,6 +1,6 @@ { "name": "@clusterio/plugin-player_auth", - "version": "2.0.0-alpha.27", + "version": "2.0.0", "description": "Clusterio plugin authenticating logged in players to the web interface", "homepage": "https://github.com/clusterio/clusterio#readme", "author": "Hornwitser ", diff --git a/plugins/player_sync/package.json b/plugins/player_sync/package.json index c20697f7..74d35039 100644 --- a/plugins/player_sync/package.json +++ b/plugins/player_sync/package.json @@ -1,6 +1,6 @@ { "name": "@clusterio/plugin-player_sync", - "version": "2.0.0-alpha.27", + "version": "2.0.0", "description": "Clusterio plugin forwarding between Factorio servers", "homepage": "https://github.com/clusterio/clusterio#readme", "author": "Danielv ", diff --git a/plugins/research_sync/package.json b/plugins/research_sync/package.json index e491db89..3281b4ba 100644 --- a/plugins/research_sync/package.json +++ b/plugins/research_sync/package.json @@ -1,6 +1,6 @@ { "name": "@clusterio/plugin-research_sync", - "version": "2.0.0-alpha.27", + "version": "2.0.0", "description": "Clusterio plugin for synchronizing research between Factorio servers", "homepage": "https://github.com/clusterio/clusterio#readme", "author": "Hornwitser ", diff --git a/plugins/statistics_exporter/package.json b/plugins/statistics_exporter/package.json index 05276508..d7f2f900 100644 --- a/plugins/statistics_exporter/package.json +++ b/plugins/statistics_exporter/package.json @@ -1,6 +1,6 @@ { "name": "@clusterio/plugin-statistics_exporter", - "version": "2.0.0-alpha.27", + "version": "2.0.0", "description": "Clusterio plugin for gathering statistics from Factorio servers", "homepage": "https://github.com/clusterio/clusterio#readme", "author": "Hornwitser ", diff --git a/plugins/subspace_storage/package.json b/plugins/subspace_storage/package.json index 2ddaa3f9..00005313 100644 --- a/plugins/subspace_storage/package.json +++ b/plugins/subspace_storage/package.json @@ -1,6 +1,6 @@ { "name": "@clusterio/plugin-subspace_storage", - "version": "2.0.0-alpha.27", + "version": "2.0.0", "description": "Clusterio plugin for sharing storage between Factorio servers", "homepage": "https://github.com/clusterio/clusterio#readme", "author": "Hornwitser ",