Sharing an asset (in this case CSS) between 2 different apps via Docker

Remembering to do the same thing in 2 places and keep 2 distinct files in sync isn’t the easiest thing to do

The The National Archive (TNA) Case Law project consists of 2 separate web applications, the public-facing UI and the editorial ‘backoffice’ application which TNA’s legal editors use to check and publish documents to the public UI.

The public UI contains a CSS file used to format the judgments (and decisions) to look as much like their MS Word original formats as possible. The editor UI also contains the same CSS, editors can see how the judgments will look once published.

What this meant for edits

We were running into an issue in the team, where edits to the judgment CSS in the public UI were not being replicated to the editor UI. Remembering to do the same thing in 2 places and keep 2 totally distinct files in sync isn’t the easiest thing to do, especially in a busy and fast-moving project like TNA.

We therefore decided that the 2 separate repositories and applications should share this one CSS file (of many). The applications are otherwise completely distinct from each other, but they need to share this one asset.

Initially, we tried achieving this with Git submodules – adding the public UI as an app in Django using a submodule, and taking the shared CSS from the included app. Although this worked locally, we had issues with deployment in staging. And adding an entire app to another app in order to share one asset felt like overkill.

A helpful suggestion

bob, our Head of Technical Operations, suggested we use Docker instead. To achieve this we had to break the process down into a few steps:

For starters, we needed to agree on the version of the judgment CSS to be shared. We decided that the public UI should be the “source of truth”, as it’s the “main” application, and the one our end-users see.

The public UI is released via tags, so the version of the judgment css on the `main` branch isn’t always the one users are seeing. We therefore needed to be able to include only the released version of the CSS to ensure the editors are seeing the same judgment layout as the public.

Luckily, both repositories are public, so we didn’t need to worry about using authentication to get either the latest release tag, or the CSS.

The steps we took

Using Github’s API, you can get the latest release tag for a repo with:

curl -H "Accept: application/vnd.github+json" | jq -r .tag_name

This gets a JSON response from Github, and uses jq to parse out the tag_name, which at the time of publication resolves to v1.3.14

We can then use this tag to build a URL to the raw judgment CSS:

Using some nesting, we can combine the 2 and use curl to get the raw judgment CSS for the latest tag:

curl$(curl -H "Accept: application/vnd.github+json" | jq -r .tag_name)/ds_judgements_public_ui/sass/includes/_judgment_text.scss -o ds_caselaw_editor_ui/sass/includes/_judgment_text.scss

Now we know how to get the CSS, let’s use Docker to add it to the editor UI application.

In the editor UI application’s Dockerfile, after building Django, we copy the app to the working directory:

# copy application code to WORKDIR

Once the application is copied, we can use the above to retrieve the CSS from the public UI repository on Github. First we need to install curl and jq:

RUN apt-get update && apt-get install -y jq curl

Then we use the command above to get the CSS, and copy it into the right place in the application:

RUN curl$(curl -H "Accept: application/vnd.github+json" | jq -r .tag_name)/ds_judgements_public_ui/sass/includes/_judgment_text.scss -o ds_caselaw_editor_ui/sass/includes/_judgment_text.scss

And that’s it. The editor UI now contains the latest released version of the judgment CSS, we know both applications are in sync with each other. And the CSS cannot be edited in the editor UI application, because it only exists in the Dockerised version and not on the developer’s filesystem.