Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: LaTeX processing in external Docker container #446

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
ef94623
refactor: move latex processing into its own container
b0ink Aug 8, 2024
9486bed
refactor: task pdf generation
b0ink Aug 10, 2024
afb98ea
refactor: cleanup latex docker command and compile script
b0ink Aug 10, 2024
a63cee8
fix: set correct exit status
b0ink Aug 10, 2024
a6632c5
refactor: create a new working directory for each unique latex render
b0ink Aug 12, 2024
7f2e3e9
chore: fix .ipynb latex math tests
b0ink Aug 12, 2024
9bb71a8
chore: simplify check
b0ink Aug 12, 2024
6d388c1
refactor: move pdf generation into latex helper module
b0ink Aug 12, 2024
4227d9e
refactor: create additional work subfolder
b0ink Aug 16, 2024
01acc43
chore: remove work directory on completion
b0ink Aug 16, 2024
0180384
refactor: raise error on failed pdf generation
b0ink Aug 16, 2024
38b109a
chore: comment
b0ink Aug 16, 2024
b779475
chore: use latex env variables
b0ink Aug 16, 2024
0cd611f
refactor: reorganise latex script
b0ink Aug 17, 2024
dd6f0de
chore: remove texlive shell folder
b0ink Aug 17, 2024
cba910d
chore: rename latex build script
b0ink Aug 17, 2024
a8dead9
chore: use english library to replace global vars
b0ink Aug 20, 2024
1cacc20
ci: add texlive dockerfile
b0ink Aug 20, 2024
ce988b2
refactor: implement texlive docker workflow back into rails-latex
b0ink Aug 21, 2024
0f993a9
fix: set dockerfile context
b0ink Aug 23, 2024
2e0c0a5
Merge remote-tracking branch 'doubtfirelms/new/scorm' into refactor/l…
b0ink Sep 17, 2024
807f567
fix: allow docker exec to work in gh actions
b0ink Sep 21, 2024
9a76044
ci: add new texlive container to gh actions
b0ink Sep 21, 2024
0370df4
fix: ensure log is still copied if pdf gen fails
b0ink Sep 21, 2024
8f682e6
chore: remove texlive install scripts
b0ink Sep 21, 2024
b1153df
ci: manually stop texlive service after unit tests complete
b0ink Sep 22, 2024
c104a30
ci: add unique image scopes to fix cache conflicts
b0ink Sep 22, 2024
722dbeb
refactor: keep containers alive with sleep infinity
b0ink Sep 24, 2024
7bd1649
chore: remove unused packages
b0ink Sep 24, 2024
cb75e65
chore: replace double quotes with single quotes
b0ink Sep 24, 2024
3400a54
refactor: keep containers alive with sleep infinity
b0ink Sep 25, 2024
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
57 changes: 0 additions & 57 deletions .ci-setup/texlive-install.sh

This file was deleted.

11 changes: 0 additions & 11 deletions .ci-setup/texlive.profile

This file was deleted.

46 changes: 44 additions & 2 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ env:
DF_ENCRYPTION_DETERMINISTIC_KEY: "anlmuJ6cB3bN3biXRbYvmPsC5ALPFqGG"
DF_ENCRYPTION_KEY_DERIVATION_SALT: "hzPR8D4qpOnAg7VeAhkhWw6JmmzKJB10"
DF_REDIS_SIDEKIQ_URL: "redis://redis:6379/0"
LATEX_CONTAINER_NAME: doubtfire-texlive
LATEX_BUILD_PATH: /texlive/shell/latex_build.sh

jobs:
unit-tests:
Expand All @@ -49,21 +51,53 @@ jobs:
uses: actions/checkout@v4
- name: Set up docker buildx
uses: docker/setup-buildx-action@v3
- name: Build TexLive image
uses: docker/build-push-action@v5
with:
context: .
file: texlive.Dockerfile
push: false
load: true
tags: doubtfire-texlive-development:local
cache-from: type=gha,scope=texlive
cache-to: type=gha,mode=max,scope=texlive
- name: Build base doubtfire-api development image
uses: docker/build-push-action@v5
with:
context: .
push: false
load: true
tags: doubtfire-api-development:local
cache-from: type=gha
cache-to: type=gha,mode=max
cache-from: type=gha,scope=doubtfire-api
cache-to: type=gha,mode=max,scope=doubtfire-api
- name: Start TexLive service
uses: addnab/docker-run-action@v3
with:
image: doubtfire-texlive-development:local
options: >
--name ${{ env.LATEX_CONTAINER_NAME }}
-v ${{ github.workspace }}/student-work:/student-work
-v ${{ github.workspace }}/public/assets/images:/doubtfire/public/assets/images
-v ${{ github.workspace }}/test_files:/doubtfire/test_files
-v ${{ github.workspace }}/tmp/rails-latex:/workdir/texlive-latex
--detach
run: sleep infinity
- name: Test TexLive container
uses: addnab/docker-run-action@v3
with:
image: doubtfire-api-development:local
options: >
-v ${{ github.workspace }}:/doubtfire
-v /var/run/docker.sock:/var/run/docker.sock
run: docker exec -t ${{ env.LATEX_CONTAINER_NAME }} lualatex -v
- name: Populate database
uses: addnab/docker-run-action@v3
with:
image: doubtfire-api-development:local
options: >
-v ${{ github.workspace }}:/doubtfire
-v ${{ github.workspace }}/student-work:/student-work
-v /var/run/docker.sock:/var/run/docker.sock
-e RAILS_ENV
-e DF_STUDENT_WORK_DIR
-e DF_INSTITUTION_HOST
Expand All @@ -81,13 +115,17 @@ jobs:
-e DF_ENCRYPTION_DETERMINISTIC_KEY
-e DF_ENCRYPTION_KEY_DERIVATION_SALT
-e DF_REDIS_SIDEKIQ_URL
-e LATEX_CONTAINER_NAME
-e LATEX_BUILD_PATH
run: bundle exec rake db:populate
- name: Run unit tests
uses: addnab/docker-run-action@v3
with:
image: doubtfire-api-development:local
options: >
-v ${{ github.workspace }}:/doubtfire
-v ${{ github.workspace }}/student-work:/student-work
-v /var/run/docker.sock:/var/run/docker.sock
-e RAILS_ENV
-e DF_STUDENT_WORK_DIR
-e DF_INSTITUTION_HOST
Expand All @@ -105,4 +143,8 @@ jobs:
-e DF_ENCRYPTION_DETERMINISTIC_KEY
-e DF_ENCRYPTION_KEY_DERIVATION_SALT
-e DF_REDIS_SIDEKIQ_URL
-e LATEX_CONTAINER_NAME
-e LATEX_BUILD_PATH
run: TERM=xterm bundle exec rails test
- name: Stop TexLive service
run: docker rm -f ${{ env.LATEX_CONTAINER_NAME }}
3 changes: 0 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ RUN apt-get update \
wget \
redis \
libc6-dev \
librsvg2-bin \
docker-ce \
docker-ce-cli \
containerd.io \
Expand All @@ -34,8 +33,6 @@ RUN apt-get update \
WORKDIR /doubtfire

COPY ./.ci-setup/ /doubtfire/.ci-setup/
RUN ./.ci-setup/texlive-install.sh
ENV PATH /tmp/texlive/bin/x86_64-linux:/tmp/texlive/bin/aarch64-linux:$PATH

RUN gem install bundler -v '2.4.5'

Expand Down
7 changes: 7 additions & 0 deletions app/helpers/latex_helper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module LatexHelper
def generate_pdf(template:)
raise 'LATEX_CONTAINER_NAME is not set' if ENV['LATEX_CONTAINER_NAME'].nil?
raise 'LATEX_BUILD_PATH is not set' if ENV['LATEX_BUILD_PATH'].nil?
render_to_string(template: template, layout: true)
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ def compress_portfolio

# This class scaffolds the creation of the portfolio - mapping the required data into the erb template
class ProjectAppController < ApplicationController
include LatexHelper

attr_accessor :student,
:project,
:base_path,
Expand Down Expand Up @@ -66,7 +68,8 @@ def init(project, is_retry)
end

def make_pdf
render_to_string(template: '/portfolio/portfolio_pdf', layout: true)
logger.debug 'Running make_pdf: (portfolio)'
generate_pdf(template: '/portfolio/portfolio_pdf')
end
end

Expand Down
6 changes: 4 additions & 2 deletions app/models/task.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1062,6 +1062,8 @@ def in_process_files_for_task(is_retry)
end

class TaskAppController < ApplicationController
include LatexHelper

attr_accessor :task
attr_accessor :files
attr_accessor :base_path
Expand All @@ -1086,8 +1088,8 @@ def make_pdf
FileHelper.qpdf(f[:path])
end
end
logger.debug "Preprocessing complete, rendering file."
render_to_string(template: '/task/task_pdf', layout: true)
logger.debug 'Preprocessing complete, rendering file.'
generate_pdf(template: '/task/task_pdf')
end
end

Expand Down
15 changes: 14 additions & 1 deletion app/views/layouts/application.pdf.erbtex
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
<% @latex_config={ :recipe => [ {:command => "lualatex",:runs => 2} ], :supporting => Rails.root.join('app', 'views', 'layouts', 'jupynotex.py') } %>
<%
@latex_config = {
:supporting => [
Rails.root.join('app', 'views', 'layouts', 'jupynotex.py'),
Rails.root.join('lib', 'shell', 'latex_run.sh')
],
:recipe => [
{ :command => './latex_run.sh', :runs => 1 }
],
:preservework => false,
:workdir => -> { "#{Process.pid}-#{Thread.current.object_id}-#{Time.now.to_i}" }
}
%>

\DocumentMetadata{uncompress}
\documentclass[11pt,a4paper]{article}
\usepackage[T1]{fontenc}
Expand Down
9 changes: 0 additions & 9 deletions deployAppSvr.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,14 @@ RUN apt-get update \
cron \
msmtp-mta bsd-mailx \
redis \
librsvg2-bin \
docker-ce \
docker-ce-cli \
containerd.io \
librsvg2-bin \
&& apt-get clean

# Setup the folder where we will deploy the code
WORKDIR /doubtfire

# Install LaTex
COPY ./.ci-setup /doubtfire/.ci-setup
RUN /doubtfire/.ci-setup/texlive-install.sh

# Install bundler
RUN gem install bundler -v '2.4.5'
RUN bundle config set --global without development test staging
Expand All @@ -49,9 +43,6 @@ RUN bundle config set --global without development test staging
COPY ./Gemfile ./Gemfile.lock /doubtfire/
RUN bundle install

# Setup path
ENV PATH /tmp/texlive/bin/x86_64-linux:/tmp/texlive/bin/aarch64-linux:$PATH

# Copy doubtfire-api source
COPY . /doubtfire/

Expand Down
19 changes: 19 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ services:
- ./:/doubtfire
- ../data/tmp:/doubtfire/tmp
- ../data/student-work:/student-work
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
- dev-db
environment:
Expand Down Expand Up @@ -61,6 +62,10 @@ services:
# RABBITMQ_USERNAME: secure_credentials
# RABBITMQ_PASSWORD: secure_credentials

# Latex details
LATEX_CONTAINER_NAME: doubtfire-texlive
LATEX_BUILD_PATH: /texlive/shell/latex_build.sh

dev-db:
container_name: doubtfire-dev-db
image: mariadb
Expand All @@ -71,3 +76,17 @@ services:
MYSQL_PASSWORD: pwd
volumes:
- ../data/database:/var/lib/mysql

texlive:
container_name: doubtfire-texlive
build:
context: .
dockerfile: texlive.Dockerfile
volumes:
- ../data/student-work:/student-work
- ./public/assets/images:/doubtfire/public/assets/images
- ./test_files:/doubtfire/test_files
- ./tmp/rails-latex:/workdir/texlive-latex
depends_on:
- df-api
command: sleep infinity
23 changes: 23 additions & 0 deletions lib/shell/latex_build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/sh

# This script is copied into the TeX Live container and remotely executed by latex_run.sh

OUTPUT_DIR=$1

cd /workdir/texlive-latex/${OUTPUT_DIR}

# Initialise work subfolder
mkdir -p work
cp *.tex *.py work/
cd work

# Compile PDF
lualatex -shell-escape -interaction=batchmode -halt-on-error input.tex
echo "Running lualatex a second time to remove temporary last page..."
lualatex -shell-escape -interaction=batchmode -halt-on-error input.tex

# Copy PDF to parent directory and cleanup
cp *.log ../
cp *.pdf ../
cd ..
rm -rf work
5 changes: 5 additions & 0 deletions lib/shell/latex_run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/sh
# This script is copied into tmp/rails-latex/$WORK_DIR/ and executed by rails-latex

WORK_DIR=$(basename "$PWD")
docker exec -t $LATEX_CONTAINER_NAME $LATEX_BUILD_PATH $WORK_DIR
Copy link
Member

Choose a reason for hiding this comment

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

We should check that these environment variables exist - either here or in the application.rb file. Then report an error so that the config can be checked.
$LATEX_CONTAINER_NAME
$LATEX_BUILD_PATH

Copy link
Member

Choose a reason for hiding this comment

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

Should we default LATEX_BUILD_PATH to /texlive/shell/latex_build.sh if it is not set?

5 changes: 5 additions & 0 deletions test/models/task_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,12 @@ def test_ipynb_to_pdf

# Test if latex math was rendered properly
reader = PDF::Reader.new(task.final_pdf_path)

# PDF-reader incorrectly parses "weight (kg) / height (m)^2" as "weight (2g) / height (m)", misplacing the ^2
# Detecting "height" and "weight" confirms correct LaTeX rendering
assert reader.pages.last.text.include?("BMI: bmi ="), reader.pages.last.text
assert reader.pages.last.text.include?("weight")
assert reader.pages.last.text.include?("height (m)")

# ensure the notice is not included when the notebook doesn't have long lines source code cells
# and no errors
Expand Down
4 changes: 2 additions & 2 deletions test_files/submissions/vectorial_graph.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
Expand Down Expand Up @@ -951,7 +951,7 @@
"source": [
"Formula for calculating\n",
"\n",
"BMI: $\\text{bmi}=\\frac{\\text{weight}}{\\text{height}^2}$"
"BMI: $\\text{bmi}=\\frac{\\text{weig}\\text{ht (kg)}}{\\text{hei} \\text{ght (m)}^2}$"
]
}
],
Expand Down
14 changes: 14 additions & 0 deletions texlive.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM texlive/texlive:latest

RUN apt-get update \
&& apt-get install -y \
imagemagick \
inkscape \
librsvg2-bin \
b0ink marked this conversation as resolved.
Show resolved Hide resolved
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

COPY ./lib/shell/latex_build.sh /texlive/shell/latex_build.sh
RUN chmod +x /texlive/shell/latex_build.sh

CMD ["sh", "-c", "sleep infinity"]