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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,5 @@ packages/docs-nextra/public/bundle
.next
cspell.json
*.timestamp-*
.cspell
.cspell
**/__pycache__/
71 changes: 71 additions & 0 deletions prefigure-lambda/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# 1. Use the AWS Lambda Python 3.12 base image (Amazon Linux 2023)
FROM public.ecr.aws/lambda/python:3.12

# 2. Install System Build Tools & Dependencies
# Amazon Linux 2023 uses 'dnf' (like Fedora).
# We install the exact dependencies requested for Pycairo:
# - cairo-devel
# - pkgconf-pkg-config (This provides the 'pkg-config' tool on AWS Linux)
# - python3-devel
#
# We also need:
# - gcc, make (to compile cairo/liblouis)
# - librsvg2-tools (for rsvg-convert)
# - nodejs/npm (for prefigure math)
# - git (to clone repos)

RUN dnf update -y && \
dnf install -y \
gcc \
gcc-c++ \
make \
automake \
libtool \
git \
tar \
gzip \
zip \
cairo-devel \
pkgconf-pkg-config \
python3-devel \
librsvg2-tools \
libxml2-devel \
nodejs \
npm \
&& dnf clean all

# 3. Install Liblouis (Braille support) from Source
# (Standard yum/dnf does not have liblouis, so we build it)
WORKDIR /tmp/liblouis-build
RUN git clone https://github.com/liblouis/liblouis.git . && \
./autogen.sh && \
./configure --enable-ucs4 --prefix=/usr && \
make && \
make install && \
cd python && \
pip install . && \
cd / && \
rm -rf /tmp/liblouis-build

# 4. Install Pycairo explicitly
# We do this before prefigure to ensure the C compilation succeeds.
RUN pip install pycairo

# 5. Pin Prefigure version and share it with runtime cache keying.
ARG PREFIG_VERSION=0.5.15
ENV PREFIG_CACHE_VERSION=${PREFIG_VERSION}

# 5. Install Prefigure
# We use the [pycairo] extra to tell prefig we have it.
RUN pip install "prefig[pycairo]==${PREFIG_VERSION}"

Comment on lines +37 to +61
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Docker build pulls source directly from GitHub default branches (git clone liblouis and pip install git+.../prefigure.git) without pinning to a tag/commit. That makes builds non-reproducible and increases supply-chain risk if upstream changes. Consider pinning to specific versions/SHAs (and optionally verifying checksums) so the deployed Lambda image is deterministic.

Copilot uses AI. Check for mistakes.
# 6. Initialize Prefigure
# This downloads MathJax and fonts.
RUN prefig init

# 7. Copy Handler Code
WORKDIR ${LAMBDA_TASK_ROOT}
COPY app.py .

# 8. Set the CMD to your handler
CMD [ "app.lambda_handler" ]
114 changes: 114 additions & 0 deletions prefigure-lambda/ENDPOINT_TESTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# PreFigure Endpoint Testing

This file is a quick checklist for validating the deployed endpoint at:

- `https://prefigure.doenet.org/build`
- `https://prefigure.doenet.org/version`

## Prerequisites

- `curl` installed
- Optional: `jq` for easier JSON inspection

## 0) Version check

```bash
curl -sS https://prefigure.doenet.org/version
```

Expected response:

```json
{"version": "0.5.15"}
```


## 1) Success path: empty graph, no annotations

Create a minimal input file:

```bash
cat > /tmp/prefigure-empty.xml <<'XML'
<diagram dimensions="(0,0,1,1)">
<graph></graph>
</diagram>
XML
```

Send request:

```bash
curl -sS -X POST "https://prefigure.doenet.org/build" \
-H "Content-Type: application/xml" \
--data-binary @/tmp/prefigure-empty.xml
```

Expected response:

- HTTP status: `200`
- JSON fields include:
- `svg` (non-empty string)
- `annotationsXml` is `null`
- `annotationsGenerated` is `false`
- `cached` is `true` or `false`

Optional quick assert with `jq`:

```bash
curl -sS -X POST "https://prefigure.doenet.org/build" \
-H "Content-Type: application/xml" \
--data-binary @/tmp/prefigure-empty.xml \
| jq '{hasSvg:(.svg|type=="string" and (.svg|length>0)), annotationsXmlIsNull:(.annotationsXml==null), annotationsGenerated, cached}'
```

## 2) Error path: malformed XML + debug diagnostics

Send malformed XML and keep status/body:

```bash
curl -sS -o /tmp/prefigure-bad.body -w "%{http_code}\n" \
-X POST "https://prefigure.doenet.org/build?debug=1" \
-H "Content-Type: application/xml" \
--data-binary '<diagram dimensions="(0,0,1,1)"><graph></diagram>'
cat /tmp/prefigure-bad.body
```

Expected response:

- HTTP status: `422`
- `errorCode` is `build_failed`
- Includes diagnostics:
- `prefigReturnCode`
- `command`
- `cwd`
- `stderr`
- `stdout`
- `work_dir_contents` (when `debug=1`)
- `output_dir_contents` (when `debug=1`)

Optional quick assert with `jq`:

```bash
cat /tmp/prefigure-bad.body | jq '{errorCode, hasDebugLists:(has("work_dir_contents") and has("output_dir_contents"))}'
```

## 3) Cache sanity check

Run the same success request twice and compare `cached`:

```bash
for i in 1 2; do
curl -sS -X POST "https://prefigure.doenet.org/build" \
-H "Content-Type: application/xml" \
--data-binary @/tmp/prefigure-empty.xml \
| jq '{run:'"$i"', cached, hash}'
done
```

Typically first run is `cached: false` and second run becomes `cached: true` for the same input/hash.

## Notes

- Use `?debug=1` only for troubleshooting error responses.
- Endpoint contract details are documented in:
- `PreFigure on AWS Lambda: Complete Setup.md`
Loading