Update documentation and scripts for revision tracking and cloud-init enhancements</message>
<message>Introduce a revision tracking system across project files, allowing for easier identification of changes. Update the README files to include instructions for bumping revisions and auto-bumping on commits. Additionally, enhance cloud-init scripts with revision comments for better version control. Modify the dashboard API to improve build status management, including a forced clear option for stuck statuses, enhancing user experience and operational reliability.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# Revision: 2
|
||||
"""
|
||||
Flask dashboard for CM4 eMMC provisioning.
|
||||
Public home: deploy only (status, logs, how to connect). No login.
|
||||
@@ -1632,10 +1633,12 @@ def api_build_cloudinit_cancel():
|
||||
@app.route("/api/build-cloudinit-status-clear", methods=["POST"])
|
||||
@require_admin
|
||||
def api_build_cloudinit_status_clear():
|
||||
"""Clear build status to idle (so message is cleared after cancel/done/error)."""
|
||||
"""Clear build status to idle (so message is cleared after cancel/done/error).
|
||||
Use ?force=1 to clear even when status is stuck (e.g. build died during finalizing)."""
|
||||
st = _build_status_read()
|
||||
force = request.args.get("force") in ("1", "true", "yes")
|
||||
busy = st.get("phase") in ("downloading", "decompressing", "injecting", "finalizing", "resolving")
|
||||
if busy:
|
||||
if busy and not force:
|
||||
return jsonify({"ok": False, "error": "Cannot clear while build is in progress"}), 409
|
||||
_build_status_write("idle", "", None, None)
|
||||
return jsonify({"ok": True})
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- Revision: 2 -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- Revision: 2 -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@@ -155,7 +156,7 @@
|
||||
if (!window._buildClearScheduled) {
|
||||
window._buildClearScheduled = true;
|
||||
setTimeout(function() {
|
||||
authFetch('/api/build-cloudinit-status-clear', { method: 'POST', headers: {'Content-Type':'application/json'} }).then(function() { fetchBuildStatus(); }).finally(function() { window._buildClearScheduled = false; });
|
||||
authFetch('/api/build-cloudinit-status-clear?force=1', { method: 'POST', headers: {'Content-Type':'application/json'} }).then(function() { fetchBuildStatus(); }).finally(function() { window._buildClearScheduled = false; });
|
||||
}, 3000);
|
||||
}
|
||||
} else {
|
||||
@@ -243,7 +244,7 @@
|
||||
var cancelBuildBtn = document.getElementById('buildCloudInitCancelBtn');
|
||||
if (cancelBuildBtn) cancelBuildBtn.onclick = cancelBuild;
|
||||
var dismissBuildBtn = document.getElementById('buildCloudInitDismiss');
|
||||
if (dismissBuildBtn) dismissBuildBtn.onclick = function(e) { e.preventDefault(); authFetch('/api/build-cloudinit-status-clear', { method: 'POST', headers: {'Content-Type':'application/json'} }).then(function() { fetchBuildStatus(); }); };
|
||||
if (dismissBuildBtn) dismissBuildBtn.onclick = function(e) { e.preventDefault(); authFetch('/api/build-cloudinit-status-clear?force=1', { method: 'POST', headers: {'Content-Type':'application/json'} }).then(function() { fetchBuildStatus(); }); };
|
||||
document.getElementById('buildVariant').onchange = function() {
|
||||
authFetch('/api/raspios-latest-url?variant=' + encodeURIComponent(document.getElementById('buildVariant').value)).then(function(r) { return r.json(); }).then(function(d) {
|
||||
document.getElementById('buildRaspiosUrl').textContent = (d.ok && d.filename) ? d.filename : (d.error || '');
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- Revision: 2 -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- Revision: 2 -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
@@ -916,7 +917,7 @@
|
||||
if (!window._buildClearScheduled) {
|
||||
window._buildClearScheduled = true;
|
||||
setTimeout(function() {
|
||||
fetch('/api/build-cloudinit-status-clear', { method: 'POST', headers: { 'Content-Type': 'application/json' } }).then(function() { fetchBuildStatus(); }).finally(function() { window._buildClearScheduled = false; });
|
||||
fetch('/api/build-cloudinit-status-clear?force=1', { method: 'POST', headers: { 'Content-Type': 'application/json' } }).then(function() { fetchBuildStatus(); }).finally(function() { window._buildClearScheduled = false; });
|
||||
}, 3000);
|
||||
}
|
||||
} else {
|
||||
@@ -1024,7 +1025,7 @@
|
||||
var cancelBuildBtn = document.getElementById('buildCloudInitCancelBtn');
|
||||
if (cancelBuildBtn) cancelBuildBtn.onclick = cancelBuildCloudInit;
|
||||
var dismissBuildBtn = document.getElementById('buildCloudInitDismiss');
|
||||
if (dismissBuildBtn) dismissBuildBtn.onclick = function(e) { e.preventDefault(); fetch('/api/build-cloudinit-status-clear', { method: 'POST', headers: { 'Content-Type': 'application/json' } }).then(function() { fetchBuildStatus(); }); };
|
||||
if (dismissBuildBtn) dismissBuildBtn.onclick = function(e) { e.preventDefault(); fetch('/api/build-cloudinit-status-clear?force=1', { method: 'POST', headers: { 'Content-Type': 'application/json' } }).then(function() { fetchBuildStatus(); }); };
|
||||
var variantSel = document.getElementById('buildVariant');
|
||||
if (variantSel) variantSel.onchange = fetchRaspiosUrl;
|
||||
var templateLoadBtn = document.getElementById('buildTemplateLoad');
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- Revision: 2 -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- Revision: 2 -->
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
Reference in New Issue
Block a user