Working with MfGames Writing, CI, and Docker

One of the main points of having MfGames Writing is to automate the publication process.


I appear to be writing a short series of post about the tools I use for publication and writing.

  1. Semantic Versions and Releases: Why semantic versioning helps with the writing process.
  2. Evolution of MfGames Writing: A brief history and reasoning behind the tools.
  3. First Steps Using MfGames Writing: Starting a new project with MfGames Writing.
  4. Adding Content to MfGames Writing: Adding front and back matter to novels.
  5. Working with MfGames Writing, CI, and Docker: Adding automatic building with commits.
  6. Additional Formats for MfGames Writing: How to create PDF, MOBI, DOCX, and HTML versions.
  7. Theming for MfGames Writing: A light introduction on how to customize the output.
  8. Integrating Semantic Versioning into MfGames Writing: Tying semantic releases into the process.

Adding Scripts

We've installed the commands in a previous step, but hooking them up in the package.json makes life a lot easier.

  "name": "test-project",
  "private": true,
  "version": "0.0.0"
  "scripts": {
    "build:epub": "mfgames-writing-format build epub",
    "build:pdf": "mfgames-writing-format build pdf",
    "build:html": "mfgames-writing-format build html",
    "build:docx": "sed 's@&#173;@@g' < $npm_package_name-$npm_package_version.html | pandoc -f html -t docx -o $npm_package_name-$npm_package_version.docx",
    "build:mobi": "kindlegen $npm_package_name-$npm_package_version.epub",
    "build": "npm run build:epub && npm run build:mobi && npm run build:pdf && npm run build:html && npm run build:docx"

Basically this sets up my basic suite of scripts that let me generate everything or one specific file.

$ npm run build:epub
$ npm run build

You can see we use a couple other programs like pandoc to make DOCX files from HTML or MOBI files using the EPUB file and kindlegen.

I use $npm_package_name to pull in the package name (as I said, I use them for consistency) which lets me produce files with a consistent pattern including the version number.

The other formats (HTML, PDF, etc) will be talked about in tomorrow's post.

CI Configuration

I use GitLab as my primary development platform. I like the company, the fact they open-source much of their code, and their features. Most important is that they provide private repos, which means I can have one repo for every novel I work on.

GitLab has a continual integration (CI) service which will automatically run whenever I push up code. This is controlled by the .gitlab-ci.yml file.

# This Docker image contains all the libraries and tools to generate files.
image: dmoonfire/mfgames-writing-js:1.1.1

    - publish

    stage: publish
        - docker

    # Generate the various publication files.
        - npm ci
        - npm run build

    # Keeping artifacts means we can download them after the fact.
        expire_in: 1 week
            - "*.pdf"
            - "*.epub"
            - "*.mobi"
            - "*.docx"
            - "*.html"

If CI is turned on in GitLab and this file is present, then it will automatically run the commands in the script section. It then takes the resulting PDF, EPUB, MOBI, DOCX, and HTML files and zips them up to be found on the website. Basically this runs the same command that you can run manually which makes it easier to test.

Download Button


In the .gitlab-ci.yml file, you may notice we use a Docker image dmoonfire/mfgames-writing-js:1.1.1. This is up on DockerHub and includes the various programs and utilities needed to generate the files. Some of the formats, in specific WeasyPrint, have specific installations and I found that having a Docker image makes life a lot easier.

The image contains:

  • NPM and required packages
  • WeasyPrint
  • KindleGen
  • Pandoc
  • PdfTk (pdfcat)