From 6dd6ead1c9123565fb7a6986f28f557ec31200f6 Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Fri, 9 Jan 2026 14:34:51 +0000 Subject: [PATCH] feat(daemon): add serial console reader and UI tab for serial logs; add version propagation and CI/release workflows --- .gitea/workflows/ci.yml | 26 +++++ .gitea/workflows/release.yml | 108 ++++++++++++++++++ changelog.md | 16 +++ ecoos_daemon/ts/daemon/index.ts | 36 ++++++ ecoos_daemon/ts/ui/server.ts | 73 +++++++++++- ecoos_daemon/ts/version.ts | 2 +- .../includes.chroot/opt/eco/bin/eco-daemon | Bin 86940210 -> 86948075 bytes package.json | 8 +- 8 files changed, 262 insertions(+), 7 deletions(-) create mode 100644 .gitea/workflows/ci.yml create mode 100644 .gitea/workflows/release.yml create mode 100644 changelog.md diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..a35d348 --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,26 @@ +name: CI + +on: + push: + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Deno + uses: denoland/setup-deno@v1 + with: + deno-version: v2.x + + - name: Install pnpm + run: npm install -g pnpm + + - name: Typecheck + run: pnpm run daemon:typecheck + + - name: Bundle + run: pnpm run daemon:bundle diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000..269def5 --- /dev/null +++ b/.gitea/workflows/release.yml @@ -0,0 +1,108 @@ +name: Release + +on: + push: + tags: ['v*'] + +jobs: + release: + if: github.ref_type == 'tag' + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Deno + uses: denoland/setup-deno@v1 + with: + deno-version: v2.x + + - name: Install pnpm + run: npm install -g pnpm + + - name: Get version from tag + id: version + run: | + VERSION=${GITHUB_REF#refs/tags/} + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "version_number=${VERSION#v}" >> $GITHUB_OUTPUT + + - name: Set version in package.json and version.ts + run: | + npm version ${{ steps.version.outputs.version_number }} --no-git-tag-version --allow-same-version + echo "export const VERSION = \"${{ steps.version.outputs.version_number }}\";" > ecoos_daemon/ts/version.ts + + - name: Build daemon binary + run: pnpm run daemon:bundle + + - name: Build ISO with Docker + run: | + cp ecoos_daemon/bundle/eco-daemon isobuild/config/includes.chroot/opt/eco/bin/ + mkdir -p .nogit/iso + docker build -t ecoos-builder -f isobuild/Dockerfile . + docker run --rm --privileged -v $(pwd)/.nogit/iso:/output ecoos-builder + + - name: Prepare release assets + run: | + VERSION="${{ steps.version.outputs.version }}" + mkdir -p dist + cp .nogit/iso/ecoos.iso "dist/ecoos-${VERSION}.iso" + cp ecoos_daemon/bundle/eco-daemon "dist/eco-daemon-${VERSION}" + cd dist && sha256sum * > SHA256SUMS.txt + ls -lh + + - name: Delete existing release if exists + run: | + VERSION="${{ steps.version.outputs.version }}" + EXISTING=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + "https://code.foss.global/api/v1/repos/${{ gitea.repository }}/releases/tags/$VERSION" | jq -r '.id // empty') + if [ -n "$EXISTING" ]; then + echo "Deleting existing release $EXISTING" + curl -X DELETE -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + "https://code.foss.global/api/v1/repos/${{ gitea.repository }}/releases/$EXISTING" + sleep 2 + fi + + - name: Create Release and upload assets + run: | + VERSION="${{ steps.version.outputs.version }}" + + # Create release + RELEASE_ID=$(curl -X POST -s \ + -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + -H "Content-Type: application/json" \ + "https://code.foss.global/api/v1/repos/${{ gitea.repository }}/releases" \ + -d "{ + \"tag_name\": \"$VERSION\", + \"name\": \"EcoOS $VERSION\", + \"body\": \"## EcoOS $VERSION\n\n### Assets\n- **ecoos-${VERSION}.iso** - Full bootable ISO image\n- **eco-daemon-${VERSION}** - Daemon binary for in-place upgrades\n\n### Checksums\nSHA256 checksums in SHA256SUMS.txt\", + \"draft\": false, + \"prerelease\": false + }" | jq -r '.id') + + echo "Created release with ID: $RELEASE_ID" + + # Upload assets + for asset in dist/*; do + filename=$(basename "$asset") + echo "Uploading $filename..." + curl -X POST -s \ + -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + -H "Content-Type: application/octet-stream" \ + --data-binary "@$asset" \ + "https://code.foss.global/api/v1/repos/${{ gitea.repository }}/releases/$RELEASE_ID/assets?name=$filename" + done + + - name: Cleanup old releases (keep 3 latest) + run: | + echo "Checking for old releases to clean up..." + RELEASES=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + "https://code.foss.global/api/v1/repos/${{ gitea.repository }}/releases" | \ + jq -r 'sort_by(.created_at) | reverse | .[3:] | .[].id') + + for id in $RELEASES; do + echo "Deleting old release $id" + curl -X DELETE -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ + "https://code.foss.global/api/v1/repos/${{ gitea.repository }}/releases/$id" + done + echo "Cleanup complete" diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..af6b86c --- /dev/null +++ b/changelog.md @@ -0,0 +1,16 @@ +# Changelog + +## 2026-01-09 - 0.2.0 - feat(daemon) +add serial console reader and UI tab for serial logs; add version propagation and CI/release workflows + +- Start a background serial reader that reads /dev/ttyS0, retains up to 1000 lines and exposes serial logs via the daemon API +- Add a Serial Console tab in the management UI to view serial logs and a tab switcher; UI will auto-reload when daemon version changes +- Expose VERSION from ecoos_daemon and include it in status responses +- Bump package version to 0.1.3 and update daemon version constant +- Add .gitea workflows for CI (typecheck + bundle) and Release (build daemon, build ISO via Docker, upload releases to Gitea), and add a daemon:typecheck npm script; update test/clean scripts + +## 2026-01-09 - 0.1.1 - initial project setup & minor update +Consolidated initial project creation and a follow-up update into the initial release (0.1.1). + +- 2026-01-08: initial commit — project scaffold and first files added. +- 2026-01-09: minor update and version bump to 0.1.1 — small edits and housekeeping. \ No newline at end of file diff --git a/ecoos_daemon/ts/daemon/index.ts b/ecoos_daemon/ts/daemon/index.ts index e2b051d..c648f5c 100644 --- a/ecoos_daemon/ts/daemon/index.ts +++ b/ecoos_daemon/ts/daemon/index.ts @@ -8,6 +8,7 @@ import { ProcessManager } from './process-manager.ts'; import { SystemInfo } from './system-info.ts'; import { UIServer } from '../ui/server.ts'; import { runCommand } from '../utils/command.ts'; +import { VERSION } from '../version.ts'; export interface DaemonConfig { uiPort: number; @@ -29,6 +30,7 @@ export class EcoDaemon { private systemInfo: SystemInfo; private uiServer: UIServer; private logs: string[] = []; + private serialLogs: string[] = []; private swayStatus: ServiceStatus = { state: 'stopped' }; private chromiumStatus: ServiceStatus = { state: 'stopped' }; private manualRestartUntil: number = 0; // Timestamp until which auto-restart is disabled @@ -62,15 +64,21 @@ export class EcoDaemon { return [...this.logs]; } + getSerialLogs(): string[] { + return [...this.serialLogs]; + } + async getStatus(): Promise> { const systemInfo = await this.systemInfo.getInfo(); return { + version: VERSION, sway: this.swayStatus.state === 'running', swayStatus: this.swayStatus, chromium: this.chromiumStatus.state === 'running', chromiumStatus: this.chromiumStatus, systemInfo, logs: this.logs.slice(-50), + serialLogs: this.serialLogs.slice(-50), }; } @@ -131,6 +139,9 @@ export class EcoDaemon { await this.uiServer.start(); this.log('Management UI started successfully'); + // Start serial console reader in the background + this.startSerialReader(); + // Start the Sway/Chromium initialization in the background // This allows the UI server to remain responsive even if Sway fails this.startServicesInBackground(); @@ -302,6 +313,31 @@ export class EcoDaemon { return parseInt(result.stdout.trim(), 10); } + private startSerialReader(): void { + (async () => { + try { + const file = await Deno.open('/dev/ttyS0', { read: true }); + this.log('Serial console reader started on /dev/ttyS0'); + const reader = file.readable.getReader(); + const decoder = new TextDecoder(); + + while (true) { + const { value, done } = await reader.read(); + if (done) break; + const text = decoder.decode(value); + for (const line of text.split('\n').filter((l) => l.trim())) { + this.serialLogs.push(line); + if (this.serialLogs.length > 1000) { + this.serialLogs = this.serialLogs.slice(-1000); + } + } + } + } catch (error) { + this.log(`Serial reader not available: ${error}`); + } + })(); + } + private async runForever(): Promise { // Monitor processes and restart if needed while (true) { diff --git a/ecoos_daemon/ts/ui/server.ts b/ecoos_daemon/ts/ui/server.ts index 468c206..64a4cf5 100644 --- a/ecoos_daemon/ts/ui/server.ts +++ b/ecoos_daemon/ts/ui/server.ts @@ -249,6 +249,27 @@ export class UIServer { background: var(--success); color: white; } + .tabs { + display: flex; + border-bottom: 1px solid var(--border); + margin-bottom: 12px; + } + .tab { + padding: 8px 16px; + cursor: pointer; + color: var(--text-dim); + border-bottom: 2px solid transparent; + margin-bottom: -1px; + font-size: 12px; + text-transform: uppercase; + } + .tab:hover { color: var(--text); } + .tab.active { + color: var(--accent); + border-bottom-color: var(--accent); + } + .tab-content { display: none; } + .tab-content.active { display: block; } @@ -339,8 +360,16 @@ export class UIServer {
-

Logs

-
+
+
Daemon Logs
+
Serial Console
+
+
+
+
+
+
+
@@ -362,7 +391,20 @@ export class UIServer { return mins + 'm'; } + let initialVersion = null; + function updateStatus(data) { + // Check for version change and reload if needed + if (data.version) { + if (initialVersion === null) { + initialVersion = data.version; + } else if (data.version !== initialVersion) { + console.log('Server version changed from ' + initialVersion + ' to ' + data.version + ', reloading...'); + location.reload(); + return; + } + } + // Services document.getElementById('sway-status').className = 'status-dot ' + (data.sway ? 'running' : 'stopped'); @@ -471,7 +513,7 @@ export class UIServer { } } - // Logs + // Daemon Logs if (data.logs) { const logsEl = document.getElementById('logs'); logsEl.innerHTML = data.logs.map(l => @@ -479,6 +521,31 @@ export class UIServer { ).join(''); logsEl.scrollTop = logsEl.scrollHeight; } + + // Serial Logs + if (data.serialLogs) { + const serialEl = document.getElementById('serial-logs'); + if (data.serialLogs.length === 0) { + serialEl.innerHTML = '
No serial data available
'; + } else { + serialEl.innerHTML = data.serialLogs.map(l => + '
' + l + '
' + ).join(''); + serialEl.scrollTop = serialEl.scrollHeight; + } + } + } + + function switchTab(tab) { + document.querySelectorAll('.tab').forEach(t => t.classList.remove('active')); + document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active')); + if (tab === 'daemon') { + document.querySelector('.tab:first-child').classList.add('active'); + document.getElementById('daemon-tab').classList.add('active'); + } else { + document.querySelector('.tab:last-child').classList.add('active'); + document.getElementById('serial-tab').classList.add('active'); + } } function setControlStatus(msg, isError) { diff --git a/ecoos_daemon/ts/version.ts b/ecoos_daemon/ts/version.ts index 6fa18df..782835e 100644 --- a/ecoos_daemon/ts/version.ts +++ b/ecoos_daemon/ts/version.ts @@ -1 +1 @@ -export const VERSION = "0.1.1"; +export const VERSION = "0.1.3"; diff --git a/isobuild/config/includes.chroot/opt/eco/bin/eco-daemon b/isobuild/config/includes.chroot/opt/eco/bin/eco-daemon index ceb084a50f2d8f6a63b102d306492fae8b34d373..ba03775e80b1ba7dd3191f03b5c42493545a111c 100755 GIT binary patch delta 9384 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 DY;I;y delta 4526 zcmb`Dci7i+)W@CiZE9%mbZhs!@9y!tSE*E5iqepklu|-yP!ZwaRxf*`(62JeNXdwd zAK48ODtnWVvbX2%8P{{Uo`0Xu^|{Vq(% zQ9Wuz%{VY>MeV2)b>pC@7xkk-G>k^kIGRM$Xco<*MYN1o(K-%}HjxvDMB8W=?W03< zj84%xxbdN)$NA!$daai<@KG8Q0kABfV2E@P^ z6i3A17!pUuQ86@z#nCZ5M#RV%701NrI5v)pd(88I`?jq_qw%#Jy6eq0c9ZjU9AiKVeDmd71&XWSKc z$BI}P_r$$%U)&$7;(=HlYvRFJ8xO_9@kl%x>*BF^Jl4k(@nk#|Pe(SMiDzR&JQvT$ z3-MyS6fegsu`xEq=GYRi#%r-PUXN|@M!Xqs#rD_{JLBzmC*F# zjnCrq_#(cHUGY`yj<4gJ_%`;$cdp}EjPXeqQ3 zS_=mYZG;@*5TUKmPG~Q55IPE-gw8@2AtmGrc|unqUnmd?g(4v>6bmInsZb`A3*Ch7 z!l6PBp{LMGI85j*^bz_BhYS6L{=xuZpfE@{LKrLz5snm&5{3%HgrkMw!U$ocFiJQ^ z7%dzt948zvoFJSij1f)}#tJ735H1rg7p@R0ge!&l!U6%| zD&cD38sS>uI^lZZ2H{5GCgEmbp>T_^NLVb~D%>XAE-Vo;!ct+Guw1x9xKp@GxLa5u ztQ77M?iKD6?iW@G4+yJ;HNu0!THzt#Vc`+sQDL3%nDDr;UU))yQg}*uTF45|2+s-| zgy)3kg%^Yug_nevg;#`)!X{y}utj)Pcum+Uye@1L-Vojt-V(M8JA|FW+rm4-yTW_I z`@#pphr&m~$HFJVr^08#=fW4lm%=XLD`B_rweXGbt*}SdIZ&yk)K=;!b(MpZdP;qz zfznWEq%>BVC{2}SN^_-!(o$)qv{nvQ+9)~7Axc}Nozh!rN=nI9@|3Ph zzEYqRDn&|KDOO69Ql(5OSGp8Pia+uOv>7(>j4p;gq{gnaAKxL3}gfdte zq8zClr3_VuDMu^Al@ZEFWt4J^GFmxSIZioVIYBv58Kaz}j8#rn#wp{KQtd3<|!8| zmnfGipitWw~;Pa;I{aa<{TVS*hHk+^gKD+^?)s9#B>*Ym^6-waP=v!^$Jdqsltv zG39Y(z4C(ow8Tir+lycp!}%(r2MS>qWr4-ru?q_q5P@*rTne@qZNi2YM9|hVpK7z8r6*I zMh&B;aiCGlsBP3S>KX?b^^E#P1EZnQ$Y^XdF`639jOIoQqovWxXl)#9v@vpwLyWdY zJEOhP!RTmoGCCVwjFgdUVM0QEZeLrAC=iZgexc8;2S_jGjg><1nMQ z(Z}d(9B%Y8`Wpj`fyN-?2xG7@#5mG8${1=4GmbWf8zYR7#wg<$W3+Lsah!3yae{H8 zF~&H_7;Bttj5Ed?rx+8AiN>kMBxAC1nlZ&V-8jQI)0k?UWt?rCV@xxq8#9cV#<|9M z#w=sDF~>OHxWJfeTxeWm%rh=FE-@}O!nn-1+_=K1Fs?M_8w(7KtBk9SYm94+>x}D- z8;l!`n~a-{g~lz$B4e>}t8trgyRpQ`7)y<1#&Y8h<4)r)<8EVxvC_E5xYxMPxZhZ1 zJYcLg)))^OYmJADhmA*!M~!vHW5(mgdgBS>N#iNwX(MYqV?1kYFrG7>H(oGaG+r`Z zHeN9{8k>yG#unpM<27Te@w&0ic*A(pc+1#s>@ap3ZyWCz?;7tJ?;9T&9~vJS9~++- zpBkSTpBrBoUmClNuZ-Qs*Ty%-x5gghJ7cf0&-mW>!T8bm$@tm$#rW0u&G_B;!}!zq z%lO;)$0{6g)G^1M#Hr#`b*eelof=L}=Rl{HQ`@QI)O8MW>N)kD22Mk#k<-{|;xu)d zInA9GPD`hi)7m-MY2)NLhd6DWc20YzgVWLJz^mhh01D!$65zb&|h;yWKlrz*B<{a$| zcSblPol(v)&S>XY=Q!th=LF|OXN+@_GuAoT8Rv|5PH`qU6P;6?NzP>FG-rx)x^sqe zrZd$!%Q@RQ$C>6#cV;*Mb2X9R_8Y7c4vu`ah5vEoaN3P z&YjL(&fU%mXQgwGbFXusbHB67dB9oitZ^Q6);bS44?B-Ik2>p|$DGHV_0AK{lg?Al z(@xfT#(CD+;5_F%@4Vo==)B~-?7ZS^bT&Dgoh{C*&TGzA=XGbB^M>=L^Om#S+2QPT z-ge$`-gVw{-giE5K6E~EK6XBFK6O5GK6k!wzI1juUpc#-ubpq4Z=F5Pcg|jCpYy%* zgY%>Flk>Cli}S1VoAbN#hx4cNm-Dytk5?o}f+kpkCnO0~5~?OtOQ@buBcW!(feEz| zYA4i5sGD$5LcN6g2@Mh&CNxTDoX{kpX+pDv<_RqlS|+qgXq|9yLYst~ghLYACbUav zpU@$pV?w8d&Iw(TCsWD14fP93N{dTM%8H8e3k!>i(&==0S@wnvsbqYW%&iHy zg&8^B3Q9{#%hTogrKLs1MVURXq>?UO^Ycp!Q|0M`{Vo5JD=JTyrBh|a<>mjamM+UL zE6NPqm`Zx(7Zs*UD@T=ndd8MJyHc_g#{(4qJJ&@zY|KziYqTPckYC$?(-5Rz}OTO>&d5|H=L=yQ)fV(xh5;KYL+= z?2h)i$J%^k%DKl<%UeY|XEAo<-nZpY6 zlA76h<$1|c&5W$bOFCq$&d*C0)y=M0oR^4X7Wi1HnO!p?FBzQk|D)5YdiIl*c}cVC z$$0~McNvszv^Fp4BR;hE^pV;559KBOk`@Iy-D^xJnwoz`dg_E$!wxuLg&uIg?j3T# G{`Vijj7ISQ diff --git a/package.json b/package.json index a9db80d..933ea40 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,18 @@ { "name": "@ecobridge/eco-os", - "version": "0.1.1", + "version": "0.1.3", "private": true, "scripts": { "build": "npm version patch --no-git-tag-version && node -e \"const v=require('./package.json').version; require('fs').writeFileSync('ecoos_daemon/ts/version.ts', 'export const VERSION = \\\"'+v+'\\\";\\n');\" && pnpm run daemon:bundle && cp ecoos_daemon/bundle/eco-daemon isobuild/config/includes.chroot/opt/eco/bin/ && mkdir -p .nogit/iso && docker build --no-cache -t ecoos-builder -f isobuild/Dockerfile . && docker run --rm --privileged -v $(pwd)/.nogit/iso:/output ecoos-builder", "daemon:dev": "cd ecoos_daemon && deno run --allow-all --watch mod.ts", "daemon:start": "cd ecoos_daemon && deno run --allow-all mod.ts", + "daemon:typecheck": "cd ecoos_daemon && deno check mod.ts", "daemon:bundle": "cd ecoos_daemon && deno compile --allow-all --output bundle/eco-daemon mod.ts", - "test": "cd isotest && ./run-test.sh", + "test": "pnpm run test:clean && cd isotest && ./run-test.sh", "test:screenshot": "cd isotest && ./screenshot.sh", "test:screenshot:loop": "while true; do pnpm run test:screenshot; sleep 5; done", "test:stop": "cd isotest && ./stop.sh", - "clean": "rm -rf .nogit/iso/*.iso .nogit/vm/*.qcow2 .nogit/screenshots/*" + "test:clean": "pnpm run test:stop && rm -rf .nogit/vm/*.qcow2 .nogit/screenshots/*", + "clean": "rm -rf .nogit/iso/*.iso && pnpm run test:clean" } }