Skip to content
Open
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
32 changes: 29 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
# SPDX-License-Identifier: AGPL-3.0-or-later

ARG VERSION=latest
FROM rero/rero-mef-base:${VERSION}

LABEL maintainer="software@rero.ch"
LABEL description="MEF (Multilingual Entity File) server with records for persons, works, etc. for reuse in integrated library systems (ILS)."
# ---------------------------------------------------------------------------
# Builder: installs dependencies and builds the web assets using the
# toolchain (gcc, Node.js, git, uv) provided by the base image.
# ---------------------------------------------------------------------------
FROM rero/rero-mef-base:${VERSION} AS builder

USER 0

Expand All @@ -19,3 +21,27 @@ USER 1000

ENV INVENIO_COLLECT_STORAGE='flask_collect.storage.file'
RUN uv run --no-sync ./scripts/bootstrap --deploy

# ---------------------------------------------------------------------------
# Runtime: only the built virtualenv, static assets and app code - no
# compilers, Node.js, git or editors.
# ---------------------------------------------------------------------------
FROM python:3.14-slim-bookworm AS runtime

LABEL maintainer="software@rero.ch"
LABEL description="MEF (Multilingual Entity File) server with records for persons, works, etc. for reuse in integrated library systems (ILS)."

ENV WORKING_DIR=/invenio
ENV INVENIO_INSTANCE_PATH=${WORKING_DIR}/var/instance

RUN mkdir -p ${INVENIO_INSTANCE_PATH} && \
useradd invenio --uid 1000 --home ${WORKING_DIR} && \
chown -R invenio:invenio ${WORKING_DIR} && \
chmod -R go+w ${WORKING_DIR}

COPY --from=builder /usr/local/bin/uv /usr/local/bin/uvx /usr/local/bin/
COPY --from=builder --chown=invenio:invenio ${WORKING_DIR}/src ${WORKING_DIR}/src
COPY --from=builder --chown=invenio:invenio ${INVENIO_INSTANCE_PATH} ${INVENIO_INSTANCE_PATH}

WORKDIR ${WORKING_DIR}/src
USER 1000
14 changes: 7 additions & 7 deletions Dockerfile.base
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ LABEL description="MEF (Multilingual Entity File) server with records for person

# require debian packages
RUN apt-get update -y && apt-get upgrade -y
RUN apt-get install --no-install-recommends -y git vim-tiny curl gcc gnupg libc6-dev procps && rm -rf /var/lib/apt/lists/*
RUN pip install --upgrade setuptools wheel pip uv
RUN apt-get install --no-install-recommends -y git vim-tiny curl gcc gnupg libc6-dev procps ca-certificates && \
pip install --upgrade setuptools wheel pip uv

# # uwsgi uwsgitop uwsgi-tools

# Install Node
RUN apt-get update && apt-get install -y ca-certificates curl gnupg
RUN mkdir -p /etc/apt/keyrings
RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
RUN apt-get update && apt-get install nodejs -y
RUN mkdir -p /etc/apt/keyrings && \
curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \
echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \
Comment thread
rerowep marked this conversation as resolved.
apt-get update && apt-get install --no-install-recommends -y nodejs && \
rm -rf /var/lib/apt/lists/*

# Install Invenio
ENV WORKING_DIR=/invenio
Expand Down
7 changes: 7 additions & 0 deletions rero_mef/extensions/deleted.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@

"""Deleted state propagation extension for MEF records."""

import logging
from copy import deepcopy

from invenio_records.extensions import RecordExtension

logger = logging.getLogger(__name__)


class DeletedStateExtension(RecordExtension):
"""Invenio record extension that propagates ``deleted`` state on MEF records.
Expand Down Expand Up @@ -36,6 +39,10 @@ def _propagate_deleted(self, record):
try:
deleted = source_data.get(entity_name, {}).get("deleted")
except AttributeError:
logger.warning(
f"Dangling $ref for {entity_name} on "
f"{type(record).__name__} {record.get('pid')}"
)
deleted = None
if deleted:
record["deleted"] = deleted
Expand Down
19 changes: 19 additions & 0 deletions tests/unit/test_extensions_deleted.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

"""Test DeletedStateExtension."""

import logging

from rero_mef.extensions.deleted import DeletedStateExtension


Expand All @@ -24,6 +26,23 @@ def test_propagate_deleted_skips_dangling_ref():
assert record["deleted"] == "2025-02-03T10:36:42+00:00"


def test_propagate_deleted_logs_dangling_ref_warning(caplog):
"""A dangling $ref logs a warning naming the entity, record type, and PID.

Regression test for the warning emitted by _propagate_deleted's except
branch: it must identify enough to find the offending record, while the
existing fallback behavior (a later valid ref still wins) keeps working.
"""
record = FakeMefRecord(pid="1", viaf={"$ref": "..."}, idref={"$ref": "..."})

with caplog.at_level(logging.WARNING):
result = DeletedStateExtension()._propagate_deleted(record)

assert result is True
assert record["deleted"] == "2025-02-03T10:36:42+00:00"
assert "Dangling $ref for viaf on FakeMefRecord 1" in caplog.text


def test_propagate_deleted_all_refs_dangling():
"""When every linked ref is dangling, a stale deleted flag is cleared."""

Expand Down