Rewrite CI to lint/typecheck/audit/test only; add HPC deployment path
- Replace the Docker build/publish CI stages with ruff (lint + format check), ty (type check), pip-audit, and pytest run directly against python:3.11-slim; Docker remains for manual/server deployment only. - Swap black/pylint/mypy for ruff/ty across pyproject.toml, and fix every resulting lint, format, and type diagnostic in gallery/ and plotstyle/. - Fix tests broken/stale from before the package restructuring: wrong `utils.*` import paths, mock patch targets pointed at the wrong module, and PDF-conversion tests still assuming ImageMagick instead of the current PyMuPDF-first path. Drop test_container.py (obsolete Docker-container smoke tests, fully superseded elsewhere). - Add a plain-venv + systemd --user timer deployment path (deploy/systemd/) for HPC login nodes without a Docker daemon, where public_html is already served by existing infrastructure. - Document both in CLAUDE.md, including running CI's checks locally before committing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+76
-153
@@ -1,214 +1,137 @@
|
||||
import zipfile
|
||||
import datetime
|
||||
import zipfile
|
||||
from unittest.mock import patch
|
||||
from utils import backup
|
||||
|
||||
from gallery.utils.backup import create_backup
|
||||
|
||||
|
||||
def test_backup_creates_zip(tmp_path, monkeypatch):
|
||||
# Setup fake web folder
|
||||
web_folder = tmp_path / 'plots'
|
||||
def test_backup_creates_zip(tmp_path):
|
||||
web_folder = tmp_path / "plots"
|
||||
web_folder.mkdir()
|
||||
(web_folder / 'file1.txt').write_text('abc')
|
||||
(web_folder / 'file2.txt').write_text('def')
|
||||
backup_folder = tmp_path / 'backups'
|
||||
(web_folder / "file1.txt").write_text("abc")
|
||||
(web_folder / "file2.txt").write_text("def")
|
||||
backup_folder = tmp_path / "backups"
|
||||
backup_folder.mkdir()
|
||||
|
||||
# Patch the module variables
|
||||
monkeypatch.setattr(backup, 'WEB_FOLDER', web_folder)
|
||||
monkeypatch.setattr(backup, 'BACKUP_FOLDER', backup_folder)
|
||||
assert create_backup(web_folder, backup_folder) is True
|
||||
|
||||
# Call the backup function
|
||||
backup.create_backup()
|
||||
|
||||
# Check that backup was created
|
||||
today = datetime.date.today().strftime('%Y%m%d')
|
||||
backup_name = f'backup-{today}.zip'
|
||||
backup_path = backup_folder / backup_name
|
||||
today = datetime.date.today().strftime("%Y%m%d")
|
||||
backup_path = backup_folder / f"backup-{today}.zip"
|
||||
|
||||
assert backup_path.exists()
|
||||
with zipfile.ZipFile(backup_path, 'r') as z:
|
||||
with zipfile.ZipFile(backup_path, "r") as z:
|
||||
names = z.namelist()
|
||||
assert any('file1.txt' in n for n in names)
|
||||
assert any('file2.txt' in n for n in names)
|
||||
|
||||
# Cleanup: remove the backup file after test
|
||||
backup_path.unlink()
|
||||
assert any("file1.txt" in n for n in names)
|
||||
assert any("file2.txt" in n for n in names)
|
||||
|
||||
|
||||
def test_backup_with_subdirectories(tmp_path, monkeypatch):
|
||||
# Setup fake web folder with subdirectories
|
||||
web_folder = tmp_path / 'plots'
|
||||
def test_backup_with_subdirectories(tmp_path):
|
||||
web_folder = tmp_path / "plots"
|
||||
web_folder.mkdir()
|
||||
(web_folder / 'file1.txt').write_text('content1')
|
||||
|
||||
subdir = web_folder / 'subdir'
|
||||
(web_folder / "file1.txt").write_text("content1")
|
||||
|
||||
subdir = web_folder / "subdir"
|
||||
subdir.mkdir()
|
||||
(subdir / 'file2.txt').write_text('content2')
|
||||
|
||||
nested_subdir = subdir / 'nested'
|
||||
(subdir / "file2.txt").write_text("content2")
|
||||
|
||||
nested_subdir = subdir / "nested"
|
||||
nested_subdir.mkdir()
|
||||
(nested_subdir / 'file3.txt').write_text('content3')
|
||||
|
||||
backup_folder = tmp_path / 'backups'
|
||||
(nested_subdir / "file3.txt").write_text("content3")
|
||||
|
||||
backup_folder = tmp_path / "backups"
|
||||
backup_folder.mkdir()
|
||||
|
||||
# Patch the module variables
|
||||
monkeypatch.setattr(backup, 'WEB_FOLDER', web_folder)
|
||||
monkeypatch.setattr(backup, 'BACKUP_FOLDER', backup_folder)
|
||||
assert create_backup(web_folder, backup_folder) is True
|
||||
|
||||
# Call the backup function
|
||||
backup.create_backup()
|
||||
|
||||
# Check that backup was created with all files
|
||||
today = datetime.date.today().strftime('%Y%m%d')
|
||||
backup_name = f'backup-{today}.zip'
|
||||
backup_path = backup_folder / backup_name
|
||||
today = datetime.date.today().strftime("%Y%m%d")
|
||||
backup_path = backup_folder / f"backup-{today}.zip"
|
||||
|
||||
assert backup_path.exists()
|
||||
with zipfile.ZipFile(backup_path, 'r') as z:
|
||||
with zipfile.ZipFile(backup_path, "r") as z:
|
||||
names = z.namelist()
|
||||
assert any('file1.txt' in n for n in names)
|
||||
assert any('file2.txt' in n for n in names)
|
||||
assert any('file3.txt' in n for n in names)
|
||||
|
||||
# Cleanup
|
||||
backup_path.unlink()
|
||||
assert any("file1.txt" in n for n in names)
|
||||
assert any("file2.txt" in n for n in names)
|
||||
assert any("file3.txt" in n for n in names)
|
||||
|
||||
|
||||
def test_backup_existing_file(tmp_path, monkeypatch, capsys):
|
||||
# Setup fake web folder
|
||||
web_folder = tmp_path / 'plots'
|
||||
def test_backup_existing_file_is_not_overwritten(tmp_path):
|
||||
web_folder = tmp_path / "plots"
|
||||
web_folder.mkdir()
|
||||
(web_folder / 'file1.txt').write_text('abc')
|
||||
|
||||
backup_folder = tmp_path / 'backups'
|
||||
(web_folder / "file1.txt").write_text("abc")
|
||||
|
||||
backup_folder = tmp_path / "backups"
|
||||
backup_folder.mkdir()
|
||||
|
||||
# Create existing backup file
|
||||
today = datetime.date.today().strftime('%Y%m%d')
|
||||
backup_name = f'backup-{today}.zip'
|
||||
backup_path = backup_folder / backup_name
|
||||
backup_path.write_text('existing backup')
|
||||
today = datetime.date.today().strftime("%Y%m%d")
|
||||
backup_path = backup_folder / f"backup-{today}.zip"
|
||||
backup_path.write_text("existing backup")
|
||||
|
||||
# Patch the module variables
|
||||
monkeypatch.setattr(backup, 'WEB_FOLDER', web_folder)
|
||||
monkeypatch.setattr(backup, 'BACKUP_FOLDER', backup_folder)
|
||||
|
||||
# Call the backup function
|
||||
backup.create_backup()
|
||||
|
||||
# Check that message about existing backup was printed
|
||||
captured = capsys.readouterr()
|
||||
assert f"Backup already exists: {backup_path}" in captured.out
|
||||
|
||||
# Cleanup
|
||||
backup_path.unlink()
|
||||
assert create_backup(web_folder, backup_folder) is True
|
||||
assert backup_path.read_text() == "existing backup"
|
||||
|
||||
|
||||
def test_backup_empty_folder(tmp_path, monkeypatch):
|
||||
# Setup empty web folder
|
||||
web_folder = tmp_path / 'plots'
|
||||
def test_backup_empty_folder(tmp_path):
|
||||
web_folder = tmp_path / "plots"
|
||||
web_folder.mkdir()
|
||||
|
||||
backup_folder = tmp_path / 'backups'
|
||||
|
||||
backup_folder = tmp_path / "backups"
|
||||
backup_folder.mkdir()
|
||||
|
||||
# Patch the module variables
|
||||
monkeypatch.setattr(backup, 'WEB_FOLDER', web_folder)
|
||||
monkeypatch.setattr(backup, 'BACKUP_FOLDER', backup_folder)
|
||||
assert create_backup(web_folder, backup_folder) is True
|
||||
|
||||
# Call the backup function
|
||||
backup.create_backup()
|
||||
|
||||
# Check that backup was created (empty)
|
||||
today = datetime.date.today().strftime('%Y%m%d')
|
||||
backup_name = f'backup-{today}.zip'
|
||||
backup_path = backup_folder / backup_name
|
||||
today = datetime.date.today().strftime("%Y%m%d")
|
||||
backup_path = backup_folder / f"backup-{today}.zip"
|
||||
|
||||
assert backup_path.exists()
|
||||
with zipfile.ZipFile(backup_path, 'r') as z:
|
||||
with zipfile.ZipFile(backup_path, "r") as z:
|
||||
assert len(z.namelist()) == 0
|
||||
|
||||
# Cleanup
|
||||
backup_path.unlink()
|
||||
|
||||
|
||||
def test_backup_nonexistent_web_folder(tmp_path, monkeypatch):
|
||||
# Setup nonexistent web folder
|
||||
web_folder = tmp_path / 'nonexistent_plots'
|
||||
backup_folder = tmp_path / 'backups'
|
||||
def test_backup_nonexistent_web_folder(tmp_path):
|
||||
web_folder = tmp_path / "nonexistent_plots"
|
||||
backup_folder = tmp_path / "backups"
|
||||
backup_folder.mkdir()
|
||||
|
||||
# Patch the module variables
|
||||
monkeypatch.setattr(backup, 'WEB_FOLDER', web_folder)
|
||||
monkeypatch.setattr(backup, 'BACKUP_FOLDER', backup_folder)
|
||||
assert create_backup(web_folder, backup_folder) is True
|
||||
|
||||
# Call the backup function
|
||||
backup.create_backup()
|
||||
|
||||
# Check that backup was created (empty since source doesn't exist)
|
||||
today = datetime.date.today().strftime('%Y%m%d')
|
||||
backup_name = f'backup-{today}.zip'
|
||||
backup_path = backup_folder / backup_name
|
||||
today = datetime.date.today().strftime("%Y%m%d")
|
||||
backup_path = backup_folder / f"backup-{today}.zip"
|
||||
|
||||
assert backup_path.exists()
|
||||
with zipfile.ZipFile(backup_path, 'r') as z:
|
||||
with zipfile.ZipFile(backup_path, "r") as z:
|
||||
assert len(z.namelist()) == 0
|
||||
|
||||
# Cleanup
|
||||
backup_path.unlink()
|
||||
|
||||
|
||||
@patch('datetime.date')
|
||||
def test_backup_with_custom_date(mock_date, tmp_path, monkeypatch):
|
||||
# Mock date to return a specific date
|
||||
@patch("datetime.date")
|
||||
def test_backup_with_custom_date(mock_date, tmp_path):
|
||||
mock_date.today.return_value.strftime.return_value = "20230908"
|
||||
|
||||
# Setup fake web folder
|
||||
web_folder = tmp_path / 'plots'
|
||||
|
||||
web_folder = tmp_path / "plots"
|
||||
web_folder.mkdir()
|
||||
(web_folder / 'file1.txt').write_text('test')
|
||||
|
||||
backup_folder = tmp_path / 'backups'
|
||||
(web_folder / "file1.txt").write_text("test")
|
||||
|
||||
backup_folder = tmp_path / "backups"
|
||||
backup_folder.mkdir()
|
||||
|
||||
# Patch the module variables
|
||||
monkeypatch.setattr(backup, 'WEB_FOLDER', web_folder)
|
||||
monkeypatch.setattr(backup, 'BACKUP_FOLDER', backup_folder)
|
||||
assert create_backup(web_folder, backup_folder) is True
|
||||
|
||||
# Call the backup function
|
||||
backup.create_backup()
|
||||
|
||||
# Check that backup was created with custom date
|
||||
backup_path = backup_folder / "backup-20230908.zip"
|
||||
assert backup_path.exists()
|
||||
|
||||
# Cleanup
|
||||
backup_path.unlink()
|
||||
|
||||
|
||||
def test_backup_folder_creation(tmp_path, monkeypatch):
|
||||
# Setup fake web folder
|
||||
web_folder = tmp_path / 'plots'
|
||||
def test_backup_folder_creation(tmp_path):
|
||||
web_folder = tmp_path / "plots"
|
||||
web_folder.mkdir()
|
||||
(web_folder / 'file1.txt').write_text('test')
|
||||
|
||||
# Don't create backup folder - let function create it
|
||||
backup_folder = tmp_path / 'new_backups'
|
||||
(web_folder / "file1.txt").write_text("test")
|
||||
|
||||
# Patch the module variables
|
||||
monkeypatch.setattr(backup, 'WEB_FOLDER', web_folder)
|
||||
monkeypatch.setattr(backup, 'BACKUP_FOLDER', backup_folder)
|
||||
# Don't create backup folder - let create_backup() create it
|
||||
backup_folder = tmp_path / "new_backups"
|
||||
|
||||
assert create_backup(web_folder, backup_folder) is True
|
||||
|
||||
# Call the backup function
|
||||
backup.create_backup()
|
||||
|
||||
# Check that backup folder was created
|
||||
assert backup_folder.exists()
|
||||
assert backup_folder.is_dir()
|
||||
|
||||
# Check that backup file was created
|
||||
today = datetime.date.today().strftime('%Y%m%d')
|
||||
backup_name = f'backup-{today}.zip'
|
||||
backup_path = backup_folder / backup_name
|
||||
assert backup_path.exists()
|
||||
|
||||
today = datetime.date.today().strftime("%Y%m%d")
|
||||
backup_path = backup_folder / f"backup-{today}.zip"
|
||||
assert backup_path.exists()
|
||||
|
||||
Reference in New Issue
Block a user