Обновления из файла для закрытого контура: пакет с портала → проверка подписи → ядро, потом модули

- release: пакет обновления (ExtractBundle/ReadStagedManifest/WriteBundle), Artifact.MinCore,
  план блокирует модуль, которому нужно ядро новее, чем будет после установки
- bj-release: модули получают min_core = версия релиза
- настройки → Обновления: «Обновить из файла» (zip до 2 ГБ), фон как у сетевого обновления,
  причина блокировки в таблице компонентов

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q4YVo4UMopqT5DzicqpPjL
This commit is contained in:
zuevav
2026-09-18 11:27:23 +03:00
parent 5bafd60df6
commit 17d8ec3988
8 changed files with 443 additions and 2 deletions
+27 -1
View File
@@ -100,12 +100,33 @@ type ComponentState struct {
SameFile bool // установленный файл совпадает с файлом релиза
Update bool // можно обновить
New bool // модуль выделен из ядра и ставится впервые (FromCore)
// Blocked — почему обновлять нельзя: модулю нужно более новое ядро, чем будет после установки.
Blocked string
}
// Plan — что можно обновить. m == nil — только состояние установленного (без сети).
// selfVersion — версия работающего bj-server, если записи об установке ещё нет.
func Plan(root string, m *Manifest, installed map[string]Installed, selfVersion string) []ComponentState {
var out []ComponentState
// Версия ядра после установки: если ядро тоже обновляется этим релизом — его новая версия,
// иначе — установленная. С ней сверяются требования модулей (Artifact.MinCore).
coreAfter := selfVersion
if inst, ok := installed["bj-server"]; ok && inst.Version != "" {
coreAfter = inst.Version
}
if m != nil {
for _, a := range m.Artifacts {
if a.Name == "bj-server" {
v := a.Version
if v == "" {
v = m.Version
}
if coreAfter == "" || IsNewer(v, coreAfter) {
coreAfter = v
}
}
}
}
for _, c := range Components {
st := ComponentState{Component: c}
sha := ""
@@ -130,6 +151,11 @@ func Plan(root string, m *Manifest, installed map[string]Installed, selfVersion
}
st.SameFile = sha != "" && a.SHA256 == sha
st.Update = (st.Present || c.Core) && !st.SameFile && (st.Installed == "" || IsNewer(st.Available, st.Installed))
if !c.Core && a.MinCore != "" && coreAfter != "" && IsNewer(a.MinCore, coreAfter) {
// Модулю нужно ядро новее, чем будет на сервере: сначала обновляется ядро.
st.Blocked = "нужно ядро не ниже " + a.MinCore + " (будет " + coreAfter + ") — сначала обновите ядро"
st.Update = false
}
}
}
out = append(out, st)
@@ -142,7 +168,7 @@ func Plan(root string, m *Manifest, installed map[string]Installed, selfVersion
func MarkSplitModules(states []ComponentState, allowed func(feature string) bool) {
for i := range states {
s := &states[i]
if s.FromCore && !s.Present && s.Available != "" && allowed(s.Feature) {
if s.FromCore && !s.Present && s.Available != "" && s.Blocked == "" && allowed(s.Feature) {
s.Update, s.New = true, true
}
}