Render photos individually, optimize gallery images, and prune old releases

This commit is contained in:
2026-09-19 16:20:07 +03:30
parent e112ed7640
commit 3ec6cdd3ec
210 changed files with 117 additions and 12 deletions
+18 -1
View File
@@ -35,7 +35,7 @@ ssh "${ssh_options[@]}" "$target" "mkdir -p '$release'"
# Checksums and hard links avoid retransmitting existing photos on every build.
printf -v transport 'ssh -i %q -p %q -o BatchMode=yes -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes -o UserKnownHostsFile=%q' \
"$credentials/key" "$DEPLOY_PORT" "$credentials/known_hosts"
rsync -azc --delete --link-dest="$DEPLOY_PATH/current/" -e "$transport" _site/ "$target:$release/"
rsync -azc --no-times --delete --link-dest="$DEPLOY_PATH/current/" -e "$transport" _site/ "$target:$release/"
ssh "${ssh_options[@]}" "$target" "bash -s -- '$DEPLOY_PATH' '$release' '$GITHUB_RUN_NUMBER'" <<'REMOTE'
set -euo pipefail
destination=$1
@@ -58,5 +58,22 @@ chmod -R a+rX "$release"
temporary="$destination/.current-$run-$$"
ln -s "releases/$(basename "$release")" "$temporary"
mv -Tf "$temporary" "$destination/current"
python3 - "$destination" "$run" <<'PRUNE'
from pathlib import Path
import re
import shutil
import sys
root = Path(sys.argv[1])
current = (root / 'current').resolve(strict=True)
run = int(sys.argv[2])
for old in (root / 'releases').iterdir():
if not old.is_dir() or old.is_symlink() or old.resolve() == current:
continue
match = re.fullmatch(r'(\d+)(?:-\d+-[a-f0-9]{40})?', old.name)
# A higher-numbered release may still be transferring; it will prune us later.
if match and int(match.group(1)) <= run:
shutil.rmtree(old)
PRUNE
echo "Deployed $release"
REMOTE
+30
View File
@@ -0,0 +1,30 @@
require 'liquid'
require 'nokogiri'
require_relative '../../_plugins/gallery_items'
require_relative '../../_plugins/lazy_images'
class GalleryRenderer
include GalleryItems
include LazyImages
end
renderer = GalleryRenderer.new
batch = '<div id="photo-batch"></div>' +
'<p><img src="/img/arts/uploads/batch/00.jpg" alt="first"></p>' +
'<p><img src="/img/arts/uploads/batch/01.jpg" alt="second"></p>' +
'<span class="image-details">A &amp; B<br>Caption</span>'
items = renderer.gallery_items(renderer.lazy_images(batch))
raise 'Expected one item per uploaded photo' unless items.length == 2
items.each_with_index do |item, index|
html = Nokogiri::HTML::DocumentFragment.parse(item)
raise 'Each item must contain one photo' unless html.css('img').length == 1
raise 'Photo order changed' unless html.at_css('img')['src'].end_with?("0#{index}.jpg")
raise 'Lazy loading lost' unless html.at_css('img')['loading'] == 'lazy'
raise 'Caption lost' unless html.at_css('.image-details').text == 'A & BCaption'
raise 'Anchor must occur on the first photo only' unless html.css('#photo-batch').length == (index.zero? ? 1 : 0)
end
single = '<p><img src="/img/arts/uploads/batch/00.jpg"></p>'
raise 'Single photo changed' unless renderer.gallery_items(single) == [single]
legacy = '<p><img src="/img/old.jpg"></p><p>Existing artwork content</p>'
raise 'Legacy artwork changed' unless renderer.gallery_items(legacy) == [legacy]
puts 'Gallery item regression checks passed'
+4
View File
@@ -48,6 +48,10 @@ class DeploymentTests(unittest.TestCase):
self.assertEqual((root / 'current/art/index.html').read_text(), '2')
self.assertEqual(activate(4).returncode, 0)
self.assertEqual((root / 'current/art/index.html').read_text(), '4')
self.assertEqual([p.name for p in (root / 'releases').iterdir()], ['4'])
(root / 'releases/6').mkdir() # A newer upload is still transferring.
self.assertEqual(activate(5).returncode, 0)
self.assertEqual(sorted(p.name for p in (root / 'releases').iterdir()), ['5', '6'])
if __name__ == '__main__':