diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..a8b7e89 --- /dev/null +++ b/.dockerignore @@ -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__ diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 2e0e5f7..fe99449 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -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 }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a5cd341 --- /dev/null +++ b/Dockerfile @@ -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"] diff --git a/src/archivist/server.py b/src/archivist/server.py index d0d0f9e..f4a09df 100644 --- a/src/archivist/server.py +++ b/src/archivist/server.py @@ -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") diff --git a/tests/test_server.py b/tests/test_server.py index 4703f30..0525720 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -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()