release: harden plugin deployment and recovery
Business Plugins CI / check (plugin-admin) (push) Successful in 1m37s
Business Plugins CI / check (subscription-admin) (push) Successful in 1m31s

This commit is contained in:
Qiufeng
2026-08-30 13:14:22 +08:00
parent ada4ab3c21
commit d3ff9be315
16 changed files with 259 additions and 50 deletions
+8 -6
View File
@@ -24,12 +24,14 @@ PLUGIN_CONFIG_KEY=local-development-secret-at-least-32-chars \
go run .
```
`PLUGIN_ALLOW_UNSIGNED=true` is a development-only switch. Production
packages must contain `signature.json`, use Ed25519, and match a trusted key
from `PLUGIN_TRUSTED_PUBLISHERS` (a JSON object of key ID to base64 public
key). `PLUGIN_CONFIG_KEY` is required in every environment; use a randomly
generated secret in production and keep it stable across restarts so encrypted
plugin configuration remains decryptable.
`PLUGIN_ALLOW_UNSIGNED=true` is a development-only switch for business package
uploads. Production `.s2plugin` packages must contain `signature.json`, use
Ed25519, and match a trusted key from `PLUGIN_TRUSTED_PUBLISHERS` (a JSON
object of key ID to base64 public key). Plugin Admin itself is deployed as a
pinned source checkout and binary, not as a `.s2plugin` package. `PLUGIN_CONFIG_KEY`
is required in every environment; use a randomly generated secret in production
and keep it stable across restarts so encrypted plugin configuration remains
decryptable.
When the optional subscription module is enabled, set `PLUGIN_PUBLIC_URL` to
the externally reachable Plugin Admin base URL (without `/admin`), for example
@@ -2,7 +2,7 @@
"schema_version": 1,
"plugin_id": "qiu.plugin-admin",
"name": "Business Plugin Control Plane",
"version": "1.1.0",
"version": "1.1.1",
"core_api_baseline": "sub2api-0.1.183",
"tested_core_versions": ["0.1.183"],
"capabilities": ["plugin.admin.v1"],
+13 -6
View File
@@ -44,7 +44,7 @@ import (
const (
pluginID = "qiu.plugin-admin"
subscriptionPluginID = "qiu.subscription-admin"
pluginVersion = "1.1.0"
pluginVersion = "1.1.1"
sessionCookieName = "plugin_admin_session"
maxJSONBytes = 2 << 20
maxPackageBytes = 128 << 20
@@ -2668,18 +2668,25 @@ func (a *app) startRevision(p *pluginRecord, revisionID, processKey string) (str
probe.Endpoint = endpoint
var probeErr error
attempts := 1
probeDelay := 50 * time.Millisecond
var startupDeadline time.Time
if pluginManifest.Backend.Command != "" {
// A freshly spawned process can need a short interval before binding its
// port. Retry the probe within the bounded startup window.
attempts = 20
// A freshly spawned interpreter-backed process can need several seconds
// before binding its port (notably on macOS under concurrent test load).
// Keep the window bounded while avoiding a fixed one-second flake.
attempts = 100
startupDeadline = time.Now().Add(5 * time.Second)
}
for attempt := 0; attempt < attempts; attempt++ {
if !startupDeadline.IsZero() && time.Now().After(startupDeadline) {
break
}
probeErr = a.checkPluginHealth(&probe)
if probeErr == nil {
break
}
if attempt+1 < attempts {
time.Sleep(50 * time.Millisecond)
if attempt+1 < attempts && (startupDeadline.IsZero() || time.Now().Add(probeDelay).Before(startupDeadline)) {
time.Sleep(probeDelay)
}
}
if probeErr != nil {
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "@awaioi/plugin-admin-ui",
"version": "1.1.0",
"version": "1.1.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@awaioi/plugin-admin-ui",
"version": "1.1.0",
"version": "1.1.1",
"dependencies": {
"echarts": "^6.1.0",
"pinia": "^3.0.4",
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@awaioi/plugin-admin-ui",
"private": true,
"version": "1.1.0",
"version": "1.1.1",
"type": "module",
"scripts": {
"dev": "vite --host 127.0.0.1 --port 3002",
@@ -25,7 +25,7 @@
</t-menu>
<div class="aside-footer">
<t-tag theme="success" variant="light" class="status-tag"><CheckCircleIcon size="14px" /> Core 会话正常</t-tag>
<span class="version-text">Plugin Admin v1.1.0</span>
<span class="version-text">Plugin Admin v1.1.1</span>
</div>
</t-aside>
<t-layout class="main-layout">
File diff suppressed because one or more lines are too long