Files
autodeploy/main.lua
2026-03-25 20:32:01 +00:00

206 lines
5.8 KiB
Lua

-- ============================================================
-- startup.lua - Auto-updater pour repo Gitea privé
-- ============================================================
-- ============================================================
-- Chargement de la configuration
-- ============================================================
local function loadConfig(path)
if not fs.exists(path) then
error("[Config] Fichier '" .. path .. "' introuvable !")
end
local config = {}
local f = fs.open(path, "r")
local line = f.readLine()
while line do
-- Ignorer les lignes vides et les commentaires (#)
if line ~= "" and not line:match("^%s*#") then
local key, value = line:match("^([^=]+)=(.+)$")
if key and value then
config[trim(key)] = trim(value)
end
end
line = f.readLine()
end
f.close()
return config
end
local function validateConfig(cfg)
local required = { "gitea_base", "user", "repo", "branch", "program", "remote_ver", "check_interval" }
for _, key in ipairs(required) do
if not cfg[key] then
error("[Config] Clé manquante dans config.cfg : '" .. key .. "'")
end
end
cfg.check_interval = tonumber(cfg.check_interval)
if not cfg.check_interval then
error("[Config] 'check_interval' doit être un nombre.")
end
end
-- ============================================================
-- Utilitaires fichiers
-- ============================================================
local function readFile(path)
if not fs.exists(path) then return nil end
local f = fs.open(path, "r")
local content = f.readAll()
f.close()
return content
end
local function writeFile(path, content)
local f = fs.open(path, "w")
f.write(content)
f.close()
end
function trim(s)
return s:gsub("%s+", "")
end
-- ============================================================
-- Gestion du token
-- ============================================================
local function loadToken(path)
local token = readFile(path or ".token")
if not token then
error("[Updater] Fichier '.token' introuvable !\n"
.. "Crée-le avec : echo 'ton_token' > .token")
end
return trim(token)
end
-- ============================================================
-- HTTP avec auth Gitea
-- ============================================================
local function buildRawUrl(cfg, filepath)
return cfg.gitea_base
.. "/" .. cfg.user
.. "/" .. cfg.repo
.. "/raw/branch/" .. cfg.branch
.. "/" .. filepath
end
local function fetchWithToken(url, token)
local ok, res = pcall(function()
return http.get(url, {
["Authorization"] = "token " .. token,
["Accept"] = "application/json",
})
end)
if not ok or not res then
return nil, "Requête échouée vers : " .. url
end
local code = res.getResponseCode()
if code == 401 then
res.close()
return nil, "Token invalide ou expiré (401)"
elseif code == 404 then
res.close()
return nil, "Fichier introuvable sur le repo (404)"
elseif code ~= 200 then
res.close()
return nil, "Erreur HTTP " .. code
end
local content = res.readAll()
res.close()
return content, nil
end
-- ============================================================
-- Logique de mise à jour
-- ============================================================
local function checkAndUpdate(cfg, token)
print("[Updater] Vérification des mises à jour...")
local remoteVersion, err = fetchWithToken(buildRawUrl(cfg, cfg.remote_ver), token)
if not remoteVersion then
print("[Updater] " .. err)
return false
end
remoteVersion = trim(remoteVersion)
local localVersion = readFile(".version")
if localVersion then localVersion = trim(localVersion) end
if remoteVersion == localVersion then
print("[Updater] Déjà à jour (v" .. remoteVersion .. ").")
return false
end
local prevVersion = localVersion or "aucune"
print("[Updater] Mise à jour : v" .. prevVersion .. " → v" .. remoteVersion)
local newProgram, dlErr = fetchWithToken(buildRawUrl(cfg, cfg.program), token)
if not newProgram then
print("[Updater] Échec du téléchargement : " .. dlErr)
return false
end
writeFile(cfg.program, newProgram)
writeFile(".version", remoteVersion)
print("[Updater] Mise à jour appliquée (v" .. remoteVersion .. ").")
return true
end
-- ============================================================
-- Programme principal
-- ============================================================
local function runProgram(cfg)
print("[Updater] Lancement de " .. cfg.program .. "...")
shell.run(cfg.program)
print("[Updater] Le programme s'est arrêté.")
end
local function watcherLoop(cfg, token)
while true do
sleep(cfg.check_interval)
local updated = checkAndUpdate(cfg, token)
if updated then
print("[Updater] Redémarrage dans 2 secondes...")
sleep(2)
return
end
end
end
local function main()
print("=== Auto-updater Gitea ===")
local cfg = loadConfig("config.cfg")
validateConfig(cfg)
print("[Config] Configuration chargée.")
local token = loadToken(".token")
print("[Updater] Token chargé.")
checkAndUpdate(cfg, token)
if not fs.exists(cfg.program) then
print("[Updater] Aucun programme disponible. Abandon.")
return
end
parallel.waitForAny(
function() runProgram(cfg) end,
function() watcherLoop(cfg, token) end
)
print("[Updater] Redémarrage du système...")
sleep(1)
os.reboot()
end
main()