重建个人应用入口与静态博客,保留旧文章并支持本地发布
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
"""Ship locally built static output, preserving TLS, ingress and other services."""
|
||||
from pathlib import Path
|
||||
import datetime
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import urllib.request
|
||||
import time
|
||||
import shlex
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
HOST = os.environ.get('DEPLOY_HOST', 'fzc')
|
||||
def run(*args, capture=False):
|
||||
return subprocess.run(args, check=True, text=True, capture_output=capture).stdout
|
||||
def ssh(*args, capture=False):
|
||||
return run('ssh', HOST, shlex.join(args), capture=capture)
|
||||
def kube(*args, capture=False):
|
||||
return ssh('kubectl', '-n', 'gnoc-hugo', *args, capture=capture)
|
||||
|
||||
def main():
|
||||
release = datetime.datetime.now(datetime.timezone.utc).strftime('%Y%m%dT%H%M%SZ') + '-' + run('git','rev-parse','--short','HEAD',capture=True).strip()
|
||||
target = '/var/gnoc/site-releases/' + release
|
||||
deployment = json.loads(kube('get','deployment','hugo','-o','json',capture=True))
|
||||
volumes = deployment['spec']['template']['spec']['volumes']
|
||||
current = next(v for v in volumes if v['name']=='site')
|
||||
previous = current['hostPath']['path']
|
||||
assert previous == '/var/gnoc/hugo-public' or previous.startswith('/var/gnoc/site-releases/'), 'Unexpected production mount'
|
||||
ssh('mkdir','-p',target)
|
||||
run('rsync','-az','--chmod=D755,F644',str(ROOT/'public')+'/',f'{HOST}:{target}/')
|
||||
def point(path):
|
||||
patch={'spec':{'template':{'spec':{'volumes':[{'name':'site','hostPath':{'path':path,'type':'Directory'}}]}}}}
|
||||
kube('patch','deployment','hugo','--type=strategic','-p',json.dumps(patch))
|
||||
kube('rollout','status','deployment/hugo','--timeout=120s')
|
||||
try:
|
||||
point(target)
|
||||
for _ in range(10):
|
||||
try:
|
||||
with urllib.request.urlopen('https://famzheng.me/release.json',timeout=15) as response:
|
||||
actual=json.load(response)
|
||||
expected=json.loads((ROOT/'public/release.json').read_text())
|
||||
if actual == expected: break
|
||||
except Exception: pass
|
||||
time.sleep(2)
|
||||
else: raise RuntimeError('Public release smoke test failed')
|
||||
except Exception:
|
||||
print('Restoring previous site:',previous)
|
||||
point(previous)
|
||||
raise
|
||||
print('Published https://famzheng.me/ →', target)
|
||||
print('Previous release retained:', previous)
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
Reference in New Issue
Block a user