Compare commits
2
Commits
1fdd0cc162
...
810cf44d3d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
810cf44d3d | ||
|
|
0c569b0b31 |
No files matched your search
@@ -8,6 +8,8 @@
|
|||||||
ESA 只代理 80/443 vhost,该端口不对公网;HMAC 是硬门槛。
|
ESA 只代理 80/443 vhost,该端口不对公网;HMAC 是硬门槛。
|
||||||
|
|
||||||
触发链:gitea push(main) → 本接收器验签 → build.sh → www-staging 更新。
|
触发链:gitea push(main) → 本接收器验签 → build.sh → www-staging 更新。
|
||||||
|
部署形态:systemd 运行副本 ~/docker_apps/blog/webhook_receiver.py——改本文件
|
||||||
|
必须同步两份(仓内源 + 运行副本)并 restart 单元,漂移即事故。
|
||||||
常驻方式:systemd --user(blog-webhook.service);reboot 自启需一次性
|
常驻方式:systemd --user(blog-webhook.service);reboot 自启需一次性
|
||||||
`sudo loginctl enable-linger wait4x`(已列入上线检查单)。
|
`sudo loginctl enable-linger wait4x`(已列入上线检查单)。
|
||||||
"""
|
"""
|
||||||
@@ -21,9 +23,21 @@ from pathlib import Path
|
|||||||
|
|
||||||
PORT = 13021
|
PORT = 13021
|
||||||
SECRET_FILE = Path.home() / "docker_apps/gitea/webhook-secret.txt"
|
SECRET_FILE = Path.home() / "docker_apps/gitea/webhook-secret.txt"
|
||||||
BUILD = Path.home() / "Code/Github/my-blog/infra/deploy/build.sh"
|
BUILD_REPO = Path.home() / "docker_apps/blog/build-repo"
|
||||||
BUILD_LOCK = threading.Lock()
|
BUILD_LOCK = threading.Lock()
|
||||||
|
|
||||||
|
# 构建脚本 = 构建仓自己的 origin/main 版本(架构修正 2026-10-25:此前指向
|
||||||
|
# 工作树副本,车道在途半成品状态会断生产链——20:31 事故实锤)。构建仓缺失时
|
||||||
|
# 首克引导(blog 仓公开,匿名 clone)。
|
||||||
|
def build_script() -> Path:
|
||||||
|
s = BUILD_REPO / "infra/deploy/build.sh"
|
||||||
|
if not s.exists():
|
||||||
|
subprocess.run(
|
||||||
|
["git", "clone", "https://git.wait4x.online/wait4x/blog.git", str(BUILD_REPO)],
|
||||||
|
check=True, capture_output=True,
|
||||||
|
)
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
def read_secret() -> bytes:
|
def read_secret() -> bytes:
|
||||||
return SECRET_FILE.read_text().strip().encode()
|
return SECRET_FILE.read_text().strip().encode()
|
||||||
@@ -72,9 +86,9 @@ class Handler(BaseHTTPRequestHandler):
|
|||||||
def _run_build(self) -> None:
|
def _run_build(self) -> None:
|
||||||
with BUILD_LOCK:
|
with BUILD_LOCK:
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
["bash", str(BUILD)],
|
["bash", str(build_script())],
|
||||||
capture_output=True, timeout=1200,
|
capture_output=True, timeout=1200,
|
||||||
cwd=str(BUILD.parent),
|
cwd=str(BUILD_REPO),
|
||||||
)
|
)
|
||||||
|
|
||||||
def log_message(self, fmt: str, *args: object) -> None:
|
def log_message(self, fmt: str, *args: object) -> None:
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
---
|
---
|
||||||
// 键盘层(极客层 P0):? 帮助 / t 主题 / g-chords 导航
|
// 键盘层(极客层 P0):? 帮助 / t 主题 / g-chords 导航
|
||||||
// 惯例来源:GitHub 键位(g+N、? 帮助);每项能力都有可视入口(触屏等价物原则)
|
// 惯例来源:GitHub 键位(g+N、? 帮助);每项能力都有可视入口(触屏等价物原则)
|
||||||
|
// 文案全部 ui.ts 词条:locale 构建期按页面 URL 自推断(BaseLayout 不透传,同 Footer 模式)
|
||||||
|
import { t } from '../../i18n/ui';
|
||||||
|
import { localeOf } from '../../lib/locale';
|
||||||
|
const locale = localeOf(Astro.url.pathname);
|
||||||
const routes: Record<string, string> = {
|
const routes: Record<string, string> = {
|
||||||
h: '/',
|
h: '/',
|
||||||
a: '/archives/',
|
a: '/archives/',
|
||||||
@@ -11,21 +15,21 @@ const routes: Record<string, string> = {
|
|||||||
---
|
---
|
||||||
|
|
||||||
<dialog id="kbd-help" class="kbd-help" data-routes={JSON.stringify(routes)}>
|
<dialog id="kbd-help" class="kbd-help" data-routes={JSON.stringify(routes)}>
|
||||||
<h2>键盘快捷键</h2>
|
<h2>{t('kbd_title', locale)}</h2>
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr><td><kbd>Ctrl</kbd> <kbd>K</kbd></td><td>命令面板</td></tr>
|
<tr><td><kbd>Ctrl</kbd> <kbd>K</kbd></td><td>{t('kbd_palette', locale)}</td></tr>
|
||||||
<tr><td><kbd>t</kbd></td><td>切换明暗</td></tr>
|
<tr><td><kbd>t</kbd></td><td>{t('kbd_theme_toggle', locale)}</td></tr>
|
||||||
<tr><td><kbd>?</kbd></td><td>本帮助</td></tr>
|
<tr><td><kbd>?</kbd></td><td>{t('kbd_this_help', locale)}</td></tr>
|
||||||
<tr><td><kbd>g</kbd> <kbd>h</kbd></td><td>首页</td></tr>
|
<tr><td><kbd>g</kbd> <kbd>h</kbd></td><td>{t('kbd_gh_home', locale)}</td></tr>
|
||||||
<tr><td><kbd>g</kbd> <kbd>a</kbd></td><td>文章</td></tr>
|
<tr><td><kbd>g</kbd> <kbd>a</kbd></td><td>{t('kbd_ga_posts', locale)}</td></tr>
|
||||||
<tr><td><kbd>g</kbd> <kbd>g</kbd></td><td>图库</td></tr>
|
<tr><td><kbd>g</kbd> <kbd>g</kbd></td><td>{t('kbd_gg_gallery', locale)}</td></tr>
|
||||||
<tr><td><kbd>g</kbd> <kbd>m</kbd></td><td>瞬间</td></tr>
|
<tr><td><kbd>g</kbd> <kbd>m</kbd></td><td>{t('kbd_gm_moments', locale)}</td></tr>
|
||||||
<tr><td><kbd>/terminal</kbd></td><td class="k-term-desc">终端彩蛋</td></tr>
|
<tr><td><kbd>/terminal</kbd></td><td>{t('kbd_terminal', locale)}</td></tr>
|
||||||
<tr><td><kbd>Esc</kbd></td><td>关闭浮层</td></tr>
|
<tr><td><kbd>Esc</kbd></td><td>{t('kbd_esc_close', locale)}</td></tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<p class="hint">提示:试试终端彩蛋(Phase 4 上线 <code>~</code>)</p>
|
<p class="hint">{t('kbd_hint', locale)}</p>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -33,10 +37,6 @@ const routes: Record<string, string> = {
|
|||||||
// 路由表由 data-routes 注入(module 脚本里 currentScript 恒为 null,不能走内联取参)
|
// 路由表由 data-routes 注入(module 脚本里 currentScript 恒为 null,不能走内联取参)
|
||||||
const helpEl = document.getElementById('kbd-help') as HTMLElement & { dataset: { routes?: string } };
|
const helpEl = document.getElementById('kbd-help') as HTMLElement & { dataset: { routes?: string } };
|
||||||
const routes: Record<string, string> = JSON.parse(helpEl?.dataset.routes ?? '{}');
|
const routes: Record<string, string> = JSON.parse(helpEl?.dataset.routes ?? '{}');
|
||||||
// en 轨仅切换终端行词条(帮助表其余文案的双语化另行车道)
|
|
||||||
if (location.pathname === '/en' || location.pathname.startsWith('/en/')) {
|
|
||||||
document.querySelector('.k-term-desc')?.replaceChildren(document.createTextNode('terminal'));
|
|
||||||
}
|
|
||||||
let chord = '';
|
let chord = '';
|
||||||
let chordTimer: number | undefined;
|
let chordTimer: number | undefined;
|
||||||
|
|
||||||
|
|||||||
@@ -78,6 +78,19 @@ const dict = {
|
|||||||
footer_stack: { zh: '装备', en: 'stack' },
|
footer_stack: { zh: '装备', en: 'stack' },
|
||||||
footer_colophon: { zh: '制作', en: 'colophon' },
|
footer_colophon: { zh: '制作', en: 'colophon' },
|
||||||
|
|
||||||
|
// ===== C 车道:Keyboard 帮助表全量词条(组件 Astro.url 构建期自推断 locale) =====
|
||||||
|
kbd_title: { zh: '键盘快捷键', en: 'Keyboard shortcuts' },
|
||||||
|
kbd_palette: { zh: '命令面板', en: 'Command palette' },
|
||||||
|
kbd_theme_toggle: { zh: '切换明暗', en: 'Toggle light / dark' },
|
||||||
|
kbd_this_help: { zh: '本帮助', en: 'This help' },
|
||||||
|
kbd_gh_home: { zh: '首页', en: 'Home' },
|
||||||
|
kbd_ga_posts: { zh: '文章', en: 'Posts' },
|
||||||
|
kbd_gg_gallery: { zh: '图库', en: 'Gallery' },
|
||||||
|
kbd_gm_moments: { zh: '瞬间', en: 'Moments' },
|
||||||
|
kbd_terminal: { zh: '终端彩蛋', en: 'Terminal easter egg' },
|
||||||
|
kbd_esc_close: { zh: '关闭浮层', en: 'Close dialogs' },
|
||||||
|
kbd_hint: { zh: '提示:/terminal 终端彩蛋等你探索', en: 'Tip: the /terminal easter egg awaits' },
|
||||||
|
|
||||||
// ===== 命令面板(Phase 4 T1 车道):动作/导航/分组与键位提示 =====
|
// ===== 命令面板(Phase 4 T1 车道):动作/导航/分组与键位提示 =====
|
||||||
nav_home: { zh: '首页', en: 'Home' },
|
nav_home: { zh: '首页', en: 'Home' },
|
||||||
nav_moments: { zh: '瞬间', en: 'Moments' },
|
nav_moments: { zh: '瞬间', en: 'Moments' },
|
||||||
|
|||||||
Reference in new issue
Block a user