Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Allowlist: exclude everything, then add back only what the build needs.
# Keeps the context to the source tree plus git metadata, rather than the
# 172MB the repo weighs with .venv and local state in it.
*

# The package itself. README.md and LICENSE are not optional -- pyproject.toml
# declares them via `readme` and `license-files`, so the build fails without them.
!src
!pyproject.toml
!README.md
!LICENSE

# Migrations. Small, and the only way to upgrade an existing database.
!alembic
!alembic.ini

# setuptools-scm reads the version from here. Dropping it breaks the build.
!.git

# Re-exclude caches that live inside the directories added back above.
**/__pycache__
28 changes: 13 additions & 15 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,18 @@ on:
types: [published]

jobs:
deploy:
release-job:
runs-on: ubuntu-latest
environment: release
permissions:
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Build package
run: uv build --python 3.11

- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
- uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v6
with:
file: ./Dockerfile
push: true
tags: simonsobs/archivist:${{ github.event.release.tag_name }}
8 changes: 8 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM python:3.13

COPY . archivist
RUN pip install --no-cache-dir --upgrade ./archivist

ENV ARCHIVIST_CONFIG_PATH=/etc/archivist/config.json
ENTRYPOINT ["archivist", "-c", "/etc/archivist/config.json"]
CMD ["start-server"]
4 changes: 0 additions & 4 deletions src/archivist/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,8 @@ async def startup_shutdown_server(app: FastAPI):
"""
from loguru import logger

from .database import create_all

logger.info("Archivist server starting up")

create_all()

reconcile_orphaned_archives()

thread_pool = ThreadPoolExecutor(max_workers=4, thread_name_prefix="worker")
Expand Down
4 changes: 0 additions & 4 deletions tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,9 @@ async def _run():
mock.patch.object(server_module, "_status_worker_loop", lambda: started.append("status")),
mock.patch.object(server_module, "_callback_worker_loop", lambda: started.append("callback")),
mock.patch.object(server_module, "reconcile_orphaned_archives") as mock_reconcile,
mock.patch("archivist.database.create_all") as mock_create_all,
):
asyncio.run(_run())

# Crash recovery has to run once, after the schema exists but before any
# worker can dequeue -- otherwise it races the rows it is meant to reclaim.
mock_create_all.assert_called_once()
mock_reconcile.assert_called_once()
assert sorted(started) == ["archive", "callback", "status"]
assert server_module._archive_stop_event.is_set()
Loading