-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Generate PDF reports from HTML using
grover
gem
Before, the [`wicked_pdf` gem][wicked] was used to generate PDF files for the means and merits reports from HTML templates. This gem relies on [`wkhtmltopdf`][wk] to generate PDFs from HTML. As part of the [work to upgrade to Ruby version to 3.1.3][ruby], we discovered that `wkhtmltopdf` was no longer available as part the Alpine image. As outlined in the repo, the project is no longer actively maintained —so we took a decision to migrate away from that tool and consider alternatives. The [`grover` gem][grover] makes use of [`puppeteer`][puppeteer] to render HTML in a headless browser and save a PDF file. Other approaches were identified (e.g writing PDFs [using `prawn`][prawn]), but ultimately `grover` was chosen as a drop-in replacement. This replaces `wicked_pdf` with `grover` for means and merits report creation (which are subsequently sent to CCMS), and updates the respective controllers so that PDF files can be rendered in the browser for testing purposes. Ensuring Puppeteer and Chromium are available in each scenario (locally, unit tests in CI, and in alpine environments) requires a slightly different approach in each instance. This is not ideal, but it is necessary. Puppeteer is not run in a sandbox environment (running as a non-root user in Alpine is convoluted), but since the only PDFs we generate are from HTML we write and control, this should not pose a security risk. [wicked]: https://github.com/mileszs/wicked_pdf [wk]: https://github.com/wkhtmltopdf/wkhtmltopdf [ruby]: #4663 (comment) [grover]: https://github.com/Studiosity/grover [puppeteer]: https://github.com/puppeteer/puppeteer [prawn]: https://github.com/prawnpdf/prawn
- Loading branch information
1 parent
92ccd60
commit fa6f06f
Showing
21 changed files
with
425 additions
and
326 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,9 +14,9 @@ executors: | |
docker: | ||
- image: cimg/ruby:3.1.2-browsers | ||
environment: | ||
- RAILS_ENV=test | ||
- TZ: "Europe/London" | ||
- CI: true | ||
RAILS_ENV: test | ||
TZ: "Europe/London" | ||
CACHE_VERSION: v1 | ||
cloud-platform-executor: | ||
docker: | ||
- image: ministryofjustice/cloud-platform-tools:2.1 | ||
|
@@ -33,7 +33,7 @@ executors: | |
- image: ministryofjustice/apply-ci:latest-3.1.2 | ||
environment: | ||
GITHUB_TEAM_NAME_SLUG: laa-apply-for-legal-aid | ||
CI: true | ||
CACHE_VERSION: v1 | ||
- image: cimg/postgres:10.18 | ||
- image: cimg/redis:5.0 | ||
- image: ghcr.io/ministryofjustice/hmpps-clamav:latest | ||
|
@@ -99,24 +99,22 @@ references: | |
restore_gems_cache: &restore_gems_cache | ||
restore_cache: | ||
keys: | ||
- v2.7-gems-cache-{{ checksum "Gemfile.lock" }} | ||
- v2.7-gems-cache- | ||
- v2.7-gems-cache-{{ .Environment.CACHE_VERSION }}-{{ checksum "Gemfile.lock" }} | ||
|
||
restore_js_packages_cache: &restore_js_packages_cache | ||
restore_cache: | ||
keys: | ||
- v2.7-yarn-packages-cache-{{ checksum "yarn.lock" }} | ||
- v2.7-yarn-packages-cache- | ||
- v2.7-yarn-packages-cache-{{ .Environment.CACHE_VERSION }}-{{ checksum "yarn.lock" }} | ||
|
||
save_gems_cache: &save_gems_cache | ||
save_cache: | ||
key: v2.7-gems-cache-{{ checksum "Gemfile.lock" }} | ||
key: v2.7-gems-cache-{{ .Environment.CACHE_VERSION }}-{{ checksum "Gemfile.lock" }} | ||
paths: | ||
- vendor/bundle | ||
|
||
save_js_packages_cache: &save_js_packages_cache | ||
save_cache: | ||
key: v2.7-yarn-packages-cache-{{ checksum "yarn.lock" }} | ||
key: v2.7-yarn-packages-cache-{{ .Environment.CACHE_VERSION }}-{{ checksum "yarn.lock" }} | ||
paths: | ||
- node_modules | ||
|
||
|
@@ -190,6 +188,19 @@ jobs: | |
- *restore_js_packages_cache | ||
- *install_js_packages | ||
- *save_js_packages_cache | ||
- run: | ||
name: Install Headless Chrome dependencies | ||
command: | | ||
sudo apt-get install -yq \ | ||
gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 \ | ||
libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 \ | ||
libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 \ | ||
libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates \ | ||
fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget | ||
- run: | ||
name: Install Puppeteer with Chromium | ||
command: | | ||
yarn add [email protected] | ||
- run: | ||
name: Setup Code Climate test-reporter | ||
command: | | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,12 @@ | ||
module Providers | ||
class MeritsReportsController < ProviderBaseController | ||
authorize_with_policy_method :show_submitted_application? | ||
|
||
def show | ||
render pdf: "Merit report", | ||
layout: "pdf", | ||
show_as_html: params.key?(:debug) | ||
html = render_to_string "show", layout: "pdf" | ||
pdf = Grover.new(html).to_pdf | ||
|
||
send_data pdf, filename: "merits_report.pdf", type: "application/pdf", disposition: "inline" | ||
end | ||
end | ||
end |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
Grover.configure do |config| | ||
protocol = if Rails.env.development? | ||
"http://" | ||
else | ||
"https://" | ||
end | ||
|
||
config.options = { | ||
format: "A4", | ||
emulate_media: "print", | ||
prefer_css_page_size: true, | ||
bypass_csp: true, | ||
cache: false, | ||
wait_until: "networkidle2", | ||
display_url: protocol + ENV.fetch("HOST", "localhost:3002"), | ||
margin: { | ||
top: "10mm", | ||
bottom: "10mm", | ||
left: "10mm", | ||
right: "20mm", | ||
}, | ||
launch_args: ["--no-sandbox"], | ||
} | ||
end |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,25 @@ RUN apk --no-cache add --virtual build-dependencies \ | |
py3-pip | ||
RUN pip3 install awscli | ||
|
||
# Install Chromium and Puppeteer for PDF generation | ||
# Installs latest Chromium package available on Alpine (Chromium 108) | ||
RUN apk add --no-cache \ | ||
chromium \ | ||
nss \ | ||
freetype \ | ||
harfbuzz \ | ||
ca-certificates \ | ||
ttf-freefont \ | ||
nodejs \ | ||
yarn | ||
|
||
# Tell Puppeteer to skip installing Chrome. We'll be using the installed package. | ||
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true | ||
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser | ||
|
||
# Install latest version of Puppeteer that works with Chromium 108 | ||
RUN yarn add [email protected] | ||
|
||
# Install kubectl | ||
RUN curl -Lo /usr/local/bin/kubectl \ | ||
--retry 3 \ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
const { join } = require('path') | ||
|
||
/** | ||
* @type {import("puppeteer").Configuration} | ||
*/ | ||
module.exports = { | ||
cacheDirectory: join(__dirname, '.cache', 'puppeteer') | ||
} |
Oops, something went wrong.