feat: GiteaHubSync v1.0.0 — fnOS 原生应用:Gitea→GitHub 镜像同步
- 每次推送到飞牛 Gitea(3000 端口)的代码 10 秒内自动镜像到 GitHub 7 个私有仓库 (SMB_Android / DCU_APP / GD32E50X_BOOT / DCU_DesktopController / Motor_v2 / DCU_ECAT_Master / GD32_BOOT),真镜像语义(删分支/标签同步删) - 标准 .fpk 原生应用:不进 Docker,依赖 python312,安装后进入应用中心已安装列表 和桌面启动台,支持启动/停止/重启/卸载,NAS 重启自动恢复 - 控制面板(:8899):自动同步开关、立即同步、仓库状态、同步日志、打开 Gitea - GitHub 推送走 SSH 22 端口直连(HTTPS 443 本地网络被断),部署私钥随应用本地分发 - 附 fnos-install.js(命令行自动安装)、build.sh(重新构建 fpk)、genicon.py(图标生成) 注意:GitHub 部署私钥(GiteaHubSync/app/ssh/id_ed25519)与打包产物 .fpk 按 .gitignore 规则不进仓库,仅保留在工作目录本地分发。
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
exit 0
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
exit 0
|
||||
@@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
# GiteaHubSync 安装后初始化:建数据目录、默认开启自动同步、落一份 SSH 密钥、清理旧面板
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
APPDEST="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
DATA_DIR="${TRIM_PKGVAR:-}"
|
||||
if [ -n "$DATA_DIR" ] && [ -d "$DATA_DIR" ]; then
|
||||
mkdir -p "${DATA_DIR}/repos" "${DATA_DIR}/logs"
|
||||
[ -f "${DATA_DIR}/state.json" ] || printf '{"enabled":true}\n' > "${DATA_DIR}/state.json"
|
||||
# 把内置 GitHub 密钥复制到数据目录,属主跟随数据目录(应用用户),保证守护进程可读
|
||||
if [ -f "${APPDEST}/ssh/id_ed25519" ] && [ ! -f "${DATA_DIR}/id_ed25519" ]; then
|
||||
cp "${APPDEST}/ssh/id_ed25519" "${DATA_DIR}/id_ed25519" 2>/dev/null
|
||||
chmod 600 "${DATA_DIR}/id_ed25519" 2>/dev/null
|
||||
chown --reference="${DATA_DIR}" "${DATA_DIR}/id_ed25519" 2>/dev/null
|
||||
fi
|
||||
fi
|
||||
# 停掉占用 8899 端口的旧面板进程(早期原生版或本应用旧实例),避免端口冲突
|
||||
pkill -f 'panel\.py$' 2>/dev/null
|
||||
exit 0
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
exit 0
|
||||
@@ -0,0 +1,103 @@
|
||||
#!/bin/bash
|
||||
# GiteaHubSync service control(由 fnOS 应用中心在 启动/停止/查询状态 时调用)
|
||||
# 守护进程以 setsid nohup 方式后台运行,pidfile 位于持久数据目录(@appdata/GiteaHubSync)
|
||||
|
||||
PYBIN=""
|
||||
for candidate in \
|
||||
/var/apps/python312/target/bin/python3 \
|
||||
/vol1/@appcenter/python312/target/bin/python3 \
|
||||
/var/apps/python311/target/bin/python3 \
|
||||
/var/apps/python310/target/bin/python3 \
|
||||
/usr/bin/python3 \
|
||||
/usr/local/bin/python3; do
|
||||
if [ -x "$candidate" ]; then PYBIN="$candidate"; break; fi
|
||||
done
|
||||
|
||||
# TRIM_APPDEST 由 fnOS 注入;若缺失或指向其他应用,则回退到脚本自身位置
|
||||
APPDEST="${TRIM_APPDEST:-}"
|
||||
if [ -z "$APPDEST" ] || [ ! -d "$APPDEST/cmd" ]; then
|
||||
APPDEST="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
fi
|
||||
BACKEND_DIR="${APPDEST}/backend"
|
||||
[ -d "$BACKEND_DIR" ] || BACKEND_DIR="${APPDEST}/target/backend"
|
||||
[ -d "$BACKEND_DIR" ] || BACKEND_DIR="${APPDEST}/app/backend"
|
||||
DAEMON="${BACKEND_DIR}/panel.py"
|
||||
|
||||
# 持久数据目录(TRIM_PKGVAR 由 fnOS 注入,通常为 /vol{n}/@appdata/GiteaHubSync)
|
||||
if [ -n "${TRIM_PKGVAR}" ] && [ -d "${TRIM_PKGVAR}" ]; then
|
||||
DATA_DIR="${TRIM_PKGVAR}"
|
||||
else
|
||||
DATA_DIR=""
|
||||
for candidate in \
|
||||
"${APPDEST}/../../@appdata/GiteaHubSync" \
|
||||
"${APPDEST}/var" \
|
||||
"/var/apps/GiteaHubSync/var" \
|
||||
"/vol1/@appdata/GiteaHubSync" \
|
||||
"/vol2/@appdata/GiteaHubSync"; do
|
||||
if [ -d "$candidate" ]; then DATA_DIR="$candidate"; break; fi
|
||||
done
|
||||
if [ -z "$DATA_DIR" ]; then
|
||||
DATA_DIR="${APPDEST}/../../@appdata/GiteaHubSync"
|
||||
fi
|
||||
fi
|
||||
PIDFILE="${DATA_DIR}/daemon.pid"
|
||||
|
||||
daemon_alive() {
|
||||
[ -f "$PIDFILE" ] || return 1
|
||||
local pid
|
||||
pid="$(cat "$PIDFILE" 2>/dev/null)"
|
||||
[ -n "$pid" ] || return 1
|
||||
kill -0 "$pid" 2>/dev/null
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
if daemon_alive; then
|
||||
echo "GiteaHubSync daemon already running (pid $(cat "$PIDFILE"))"
|
||||
exit 0
|
||||
fi
|
||||
if [ -z "$PYBIN" ]; then
|
||||
echo "python3 runtime not found (install_dep_apps=python312)" > "${TRIM_TEMP_LOGFILE:-/dev/stderr}"
|
||||
exit 1
|
||||
fi
|
||||
mkdir -p "$DATA_DIR"
|
||||
# fnOS 解包可能放宽密钥权限,ssh 会拒绝;启动前收紧
|
||||
[ -f "${APPDEST}/ssh/id_ed25519" ] && chmod 600 "${APPDEST}/ssh/id_ed25519" 2>/dev/null
|
||||
[ -f "${DATA_DIR}/id_ed25519" ] && chmod 600 "${DATA_DIR}/id_ed25519" 2>/dev/null
|
||||
GHS_DATA_DIR="$DATA_DIR" setsid nohup "$PYBIN" "$DAEMON" >> "${DATA_DIR}/daemon.out" 2>&1 &
|
||||
for _ in 1 2 3 4 5 6 7 8 9 10; do
|
||||
if daemon_alive; then
|
||||
echo "GiteaHubSync daemon started (pid $(cat "$PIDFILE"))"
|
||||
exit 0
|
||||
fi
|
||||
sleep 0.5
|
||||
done
|
||||
echo "GiteaHubSync daemon failed to start; see ${DATA_DIR}/daemon.out" > "${TRIM_TEMP_LOGFILE:-/dev/stderr}"
|
||||
exit 1
|
||||
;;
|
||||
stop)
|
||||
if daemon_alive; then
|
||||
pid="$(cat "$PIDFILE")"
|
||||
kill "$pid" 2>/dev/null
|
||||
for _ in 1 2 3 4 5 6 7 8 9 10; do
|
||||
kill -0 "$pid" 2>/dev/null || break
|
||||
sleep 0.5
|
||||
done
|
||||
kill -9 "$pid" 2>/dev/null
|
||||
echo "GiteaHubSync daemon stopped (pid $pid)"
|
||||
else
|
||||
echo "GiteaHubSync daemon not running"
|
||||
fi
|
||||
rm -f "$PIDFILE"
|
||||
exit 0
|
||||
;;
|
||||
status)
|
||||
if daemon_alive; then
|
||||
exit 0
|
||||
fi
|
||||
exit 3
|
||||
;;
|
||||
*)
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
exit 0
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
exit 0
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
exit 0
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
exit 0
|
||||
Reference in New Issue
Block a user