mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 19:01:54 +00:00
The extension installer returned as soon as an add-on was installed, in whatever version. A new pin in meta/addons/ therefore reached a fresh wiki only, and an existing wiki kept the version it was first deployed with. The installer now skips an add-on only when the installed version equals the pin. Otherwise it calls install(id, version, namespace), which the Extension Manager resolves as an upgrade, and it reports an error when the add-on is not on the pin afterwards. The check that follows the installer compared presence only. It takes the pin as well, so a deploy fails when an add-on is installed in another version. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
57 lines
2.0 KiB
Groovy
57 lines
2.0 KiB
Groovy
// Reads Base64 JSON from placeholder and avoids any quoting issues.
|
|
import groovy.json.JsonSlurper
|
|
import java.util.Base64
|
|
|
|
def ext = services.extension
|
|
def ns = "wiki:xwiki"
|
|
|
|
def b64 = '__WANTED_B64__'
|
|
def json = new String(Base64.decoder.decode(b64), 'UTF-8')
|
|
def wanted = new JsonSlurper().parseText(json) as List<Map>
|
|
|
|
if (!wanted || wanted.isEmpty()) {
|
|
println "SKIP: no extensions requested"
|
|
return
|
|
}
|
|
|
|
wanted.each { e ->
|
|
def id = (e.id ?: "").toString()
|
|
def ver = (e.version ?: "").toString().trim()
|
|
if (!id) { println "ERROR::<missing-id>::Empty extension id in wanted list"; return }
|
|
|
|
def already = ext.getInstalledExtension(id, ns)
|
|
if (already && (!ver || already.id?.version?.toString() == ver)) { println "ALREADY_INSTALLED::${id}::${already.id?.version}"; return }
|
|
|
|
println "INSTALL_START::${id}::${ver ? ver : 'latest'}"
|
|
def job = null
|
|
def caughtErr = null
|
|
try {
|
|
job = ver ? ext.install(id, ver, ns) : ext.install(id, null, ns)
|
|
job?.join()
|
|
} catch (Throwable t) {
|
|
caughtErr = (t?.message ?: t?.toString())
|
|
}
|
|
|
|
def st = job?.status?.state?.name()
|
|
if (st) println "STATE=${st}::${id}"
|
|
|
|
def err = job?.status?.error // singular!
|
|
def errMsg = err ? (err?.message ?: err?.toString()) : null
|
|
|
|
def now = ext.getInstalledExtension(id, ns)
|
|
if (now && (!ver || now.id?.version?.toString() == ver)) {
|
|
// Race-safe: Extension Manager can report "Failed to create install plan"
|
|
// while the extension gets installed by the concurrent distribution job.
|
|
if (caughtErr) println "WARN::${id}::${caughtErr}"
|
|
if (errMsg) println "WARN::${id}::${errMsg}"
|
|
println "INSTALLED_OK::${id}::${now.id?.version}"
|
|
} else {
|
|
if (caughtErr) println "ERROR::${id}::${caughtErr}"
|
|
if (errMsg) println "ERROR::${id}::${errMsg}"
|
|
if (!caughtErr && !errMsg && st && st != 'FINISHED') {
|
|
println "ERROR::${id}::Unexpected install state ${st}"
|
|
}
|
|
println now ? "ERROR::${id}::Still on ${now.id?.version}, wanted ${ver}" : "INSTALLED_MISSING::${id}"
|
|
}
|
|
}
|