mirror of
https://github.com/CyC2018/Interview-Notebook.git
synced 2026-10-31 19:13:42 +00:00
85 lines
4.4 KiB
Python
85 lines
4.4 KiB
Python
"""Exercise repeat builds, article/image updates, and failed-build preservation locally."""
|
|
import hashlib
|
|
import json
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
from urllib.parse import unquote
|
|
|
|
from check import check
|
|
|
|
BASE = Path(__file__).resolve().parents[1]
|
|
SOURCE = BASE / 'upstream'
|
|
OUTPUT = BASE / 'dist'
|
|
|
|
|
|
def digest(path):
|
|
return hashlib.sha256(path.read_bytes()).hexdigest()
|
|
|
|
|
|
def build(source, output, *extra):
|
|
return subprocess.run([sys.executable, str(BASE / 'builder/build.py'),
|
|
'--source', str(source), '--output', str(output), *extra], capture_output=True, text=True)
|
|
|
|
|
|
first_manifest = digest(OUTPUT / 'asset-manifest.json')
|
|
result = build(SOURCE, OUTPUT)
|
|
assert result.returncode == 0, result.stderr
|
|
assert digest(OUTPUT / 'asset-manifest.json') == first_manifest, '相同输入的两次构建不一致'
|
|
|
|
report = json.loads((BASE / 'dist-report.json').read_text())
|
|
url, image = next((url, path) for url, path in report['imageReplacements'].items()
|
|
if path.startswith('/notes/pics/') and path.endswith('.png'))
|
|
image_name = unquote(image).lstrip('/')
|
|
note = next(path for path in (SOURCE / 'notes').glob('*.md') if url in path.read_text())
|
|
note_name = note.relative_to(SOURCE)
|
|
original_note = digest(note)
|
|
original_image = digest(SOURCE / image_name)
|
|
|
|
with tempfile.TemporaryDirectory(prefix='.update-check-', dir=BASE) as temp:
|
|
root = Path(temp)
|
|
source, output = root / 'source', root / 'dist'
|
|
shutil.copytree(SOURCE, source)
|
|
with (source / note_name).open('a') as handle:
|
|
handle.write('\n\n## 本地验证更新\n\n本地同步验证示例词:这是未上传的更新测试。\n')
|
|
replacement = next(path for path in (SOURCE / 'notes/pics').glob('*.png') if digest(path) != original_image)
|
|
shutil.copyfile(replacement, source / image_name)
|
|
shutil.copyfile(replacement, source / 'notes/pics/local-validation-new.png')
|
|
(source / 'notes/本地新增验证.md').write_text('# 本地新增验证\n\n仅在测试副本中生成。\n\n\n')
|
|
result = build(source, output, '--no-optimize-images', '--source-commit', 'local-update-check')
|
|
assert result.returncode == 0, result.stderr
|
|
assert '本地同步验证示例词' in (output / note_name).read_text()
|
|
assert digest(output / image_name) == digest(replacement)
|
|
assert digest(output / image_name) != original_image
|
|
assert (output / 'notes/本地新增验证.md').is_file()
|
|
assert (output / 'notes/pics/local-validation-new.png').is_file()
|
|
validation = check(source, output)
|
|
assert not validation['errors'], validation['errors']
|
|
subprocess.run(['node', str(BASE / 'builder/test_search.cjs'), str(output), '--updated'], check=True)
|
|
|
|
successful_manifest = digest(output / 'asset-manifest.json')
|
|
with (source / note_name).open('a') as handle:
|
|
handle.write('\n\n\n')
|
|
failed = build(source, output, '--no-optimize-images', '--source-commit', 'local-failure-check')
|
|
assert failed.returncode != 0, '缺少必须图片时构建应失败'
|
|
assert digest(output / 'asset-manifest.json') == successful_manifest, '失败的构建覆盖了上次产物'
|
|
|
|
text = (source / note_name).read_text()
|
|
(source / note_name).write_text(text.replace('',
|
|
'[故障模拟](/notes/local-validation-missing.md)'))
|
|
failed = build(source, output, '--no-optimize-images', '--source-commit', 'local-link-failure-check')
|
|
assert failed.returncode != 0, '站内链接校验失败时构建应失败'
|
|
assert digest(output / 'asset-manifest.json') == successful_manifest, '校验失败覆盖了上次产物'
|
|
|
|
assert digest(note) == original_note and digest(SOURCE / image_name) == original_image
|
|
result = {'sameInputRebuildIdentical': True, 'articleUpdatePickedUp': True,
|
|
'repositoryImageUpdatePickedUp': True, 'newArticleAndImageIncluded': True,
|
|
'updatedSearchIndexPassed': True, 'failedBuildPreservesPreviousOutput': True,
|
|
'failedValidationPreservesPreviousOutput': True,
|
|
'upstreamSnapshotUnchanged': True, 'testFixtureRemoved': True,
|
|
'sourceCommit': report['sourceCommit'], 'manifestSha256': first_manifest}
|
|
(BASE / 'update-validation.json').write_text(json.dumps(result, ensure_ascii=False, indent=2) + '\n')
|
|
print(json.dumps(result, ensure_ascii=False, indent=2))
|