| Goal | Uniform plugin state in servoy/application_server/plugins across all developers, without touching private / unreleased plugins of individual developers. |
| Platform | V1: Windows · V2: macOS / Linux (already implemented via start-servoy.sh) |
| Servoy version | 2025.12.1.4123 (example) |
Every developer has different plugins locally in:
<SERVOY_HOME>\application_server\plugins
This leads to:
- "works on my machine" / "doesn't work on yours"
- hard-to-reproduce bugs
- tedious onboarding
A central "Gold" plugin baseline lives on a share and is synchronised locally and automatically:
- Managed: team plugins (from the manifest) are installed / updated / removed
- Unmanaged: private / unreleased plugins remain untouched
- Sync errors must warn informatively but still launch Servoy
| Term | Meaning |
|---|---|
| SERVOY_HOME | Folder containing developer/ and application_server/. E.g. C:\servoys\2025.12.1.4123\ |
| Gold Root | Central share folder. E.g. K:\SERVOY_GOLD\ |
| Managed plugin | Any file listed in manifest.json on the share |
| Unmanaged / private plugin | Any file in the local plugins folder that is not (and was never) in the manifest |
| Gold Maintainer | The team member responsible for updating the Gold Share |
The share contains one set of plugins + manifest per Servoy version:
K:\SERVOY_GOLD\
└── plugins\
└── servoy-2025.12.1.4123\
├── manifest.json
└── files\
├── myplugin.jar
└── subfolder\
└── another.jar
Note: V1 uses a versioned folder structure so that updates remain controlled. A
current\symlink can be added later.
plugins_sync.pyreads the config, manifest, and synchronises.- Servoy is launched via a wrapper script (
start-servoy.cmdon Windows,start-servoy.shon macOS / Linux).
- Managed plugins = all files listed in
manifest.json - Unmanaged plugins = everything in the local plugins folder that is not in the manifest
For each managed plugin from the manifest:
| Local state | Action |
|---|---|
| Missing | Copy from share |
| Present, hash matches | Skip (already up to date) |
| Present, hash differs | Replace (atomic: temp copy → rename) |
For local plugins that were previously managed but are no longer in the manifest: → move to quarantine (never hard-delete)
Removed managed plugins are moved to:
<SERVOY_HOME>\application_server\plugins__quarantine\YYYY-MM-DD\
This allows rollback if the manifest was wrong. Old quarantine folders can be
cleaned up with clean_quarantine.py.
Private / unreleased plugins may exist locally and are never removed or modified.
manifest.json contains:
| Field | Type | Description |
|---|---|---|
servoy_version |
string | Servoy version this manifest targets |
generated_at |
string (YYYY-MM-DD) | Generation date |
files |
array | One entry per plugin file |
files[].path |
string | Relative path from files/, forward slashes |
files[].sha256 |
string | SHA-256 hex hash |
files[].size |
integer | File size in bytes |
Minimal example:
{
"servoy_version": "2025.12.1.4123",
"generated_at": "2026-03-02",
"files": [
{ "path": "myplugin.jar", "sha256": "…", "size": 12345 },
{ "path": "subfolder/another.jar", "sha256": "…", "size": 999 }
]
}Identity check is done via sha256. size is used as a fast pre-check to
avoid unnecessary hashing.
Because every developer installs Servoy in a different location, a local config file is required per user. It is never committed to Git.
Default location:
- Windows:
%USERPROFILE%\.servoy-plugin-sync.json - macOS / Linux:
~/.servoy-plugin-sync.json
Example:
{
"gold_root": "K:\\SERVOY_GOLD\\",
"servoy_home": "C:\\servoys\\2025.12.1.4123\\",
"servoy_version": "2025.12.1.4123",
"mode": "quarantine"
}| Field | Description |
|---|---|
gold_root |
Path to the share |
servoy_home |
Local Servoy installation folder |
servoy_version |
Selects the manifest folder on the share (servoy-<version>) |
mode |
quarantine (default, safe) or delete (permanent) |
The fastest way to create this file is the interactive wizard:
python plugins_sync.py --init-configEclipse / Servoy's servoy.ini / eclipse.ini is not designed to reliably run
external scripts at startup. A wrapper script is the clean solution:
- Run
python plugins_sync.py - On error: show warning
- Always launch Servoy (
servoy.exe/Servoy.app) regardless
- Create the folder structure on the share:
K:\SERVOY_GOLD\plugins\servoy-<VERSION>\files\ - Copy all intended team plugins into
files\. - Generate the manifest:
python build_manifest.py --files-dir "K:\...\files" --out "K:\...\manifest.json" --servoy-version "2025.12.1.4123"
- Optional: create a
CHANGELOG.mdon the share for change tracking.
- Create local config (
--init-configor manually). - Use
start-servoy.cmd(Windows) orstart-servoy.sh(macOS / Linux) instead of launching Servoy directly.
For every plugin change:
- Update plugin files in
files\. - Regenerate the manifest with
build_manifest.py. - Optional: update
CHANGELOG.md(what changed and why). - All developers receive the new state automatically on their next launch.
| Error | Sync behaviour | Servoy |
|---|---|---|
| Share not accessible | Clear warning, exit code ≠ 0 | Launches anyway |
| File locked (Servoy open) | Warning, name the file, suggest "close Servoy and retry" | Launches anyway |
| Manifest parse error | Fatal error, exit code 1 | Launches anyway |
- Optional HTTP server instead of SMB (only the transport changes, sync logic stays the same)
current\symlink on the share for the latest version- Webhook notification when the Gold Maintainer publishes a new manifest