Advaced GitLab Pipelines

Written by Dominik Pantůček on 2025-10-23

CIracketscribblejavascript

Sometimes you need to build multiple interdependent artifacts in your CI/CD pipelines. And sometimes you can setup your workflow in a non-blocking way for many of these. Read on to see what we are using in our GitLab instance.


In one of our latest projects we have found ourselves in the need of building multiple components. The project uses React.JS frontend and Racket-driven backend. For both of these platforms there are documentation and testing tools we wanted to integrate into our CI/CD pipeline to ensure smooth development in the long run.

We also wanted to ensure that the pipeline running times do not stretch too much as that could slow down our development pace. Luckily enough, there are some jobs which depend on other jobs results and there are some jobs which do not depend on any.

As we integrate the frontend into the backend, the frontend has to be built first. Only after the frontend has been built, it is possible to build the backend binary. How do we do it? With GitLab CI/CD pipelines it is rather straightforward:

frontend-build:
  stage: frontend
  needs: []
  script:
    - cd frontend
    - npm install
    - CI=false npm run build
  artifacts:
    paths:
      - frontend/dist
      - frontend/node_modules

backend-build:
  stage: backend
  needs:
    - job: frontend-build
  script:
    - raco make app.rkt
    - raco exe --orig-exe app.rkt
  artifacts:
    paths:
      - airise-app
      - '**/compiled/*'

In our case, job artifacts are not only the ultimate result - actually most of the time they are not at all - but they serve as intermediate data to be processed in the following steps down the pipeline. In the above specification, the frontend creates some files and directories we store and then reuse in the backend build job. Then - and this is interesting - the backend build job not only stores the resulting binary but stores all files under compiled/ directories for later use as well.

The very useful part comes from the raco make command which precompiles all the Racket sources into *.zo files which can be used for other instrumentation later on. That means that when we build documentation or need to check test coverage, most of the compilation has already been performed earlier in the backend build step.

And yes, the very next step is building the backend documentation using our good old friend Scribble. The job specification is simple:

backend-doc:
  stage: documentation
  needs:
    - job: backend-build
    - job: frontend-build
  script:
    - racket tools/render-docs.rkt doc
  artifacts:
    paths:
      - doc/

As it can be expected, the backend documentation job takes the precompiled files and other dependencies from the frontend and invokes a custom online documentation renderer. The result is just the usual doc/ directory Scribble produces which contains a nice, browseable documentation structure.

In the meantime, the frontend uses JSDoc for documentation and therefore building frontend documentation can run in parallel to everything already described.

frontend-doc:
  stage: documentation
  needs:
    - job: frontend-build
  script:
    - cd frontend
    - node node_modules/jsdoc/jsdoc.js -c jsdoc.conf.json
  artifacts:
    paths:
      - doc/

For various reasons we chose to build the frontend first and only then build the documentation in parallel to building the backend.

With everything ready, we can build our PDF documentation using wkhtmltopdf and native scrible PDF support:

pdf-doc:
  stage: documentation
  needs:
    - job: backend-doc
    - job: frontend-doc
    - job: backend-build
    - job: frontend-build
    - job: user-doc
  script:
    - mkdir -p pdfdoc
    - wkhtmltopdf doc/frontend/global.html pdfdoc/frontend.pdf
    - scribble --pdf --dest pdfdoc --dest-name backend.pdf tools/render-docs.scrbl
    - mv user-doc-cz.pdf pdfdoc/
  artifacts:
    paths:
      - pdfdoc/

Everyone should get the idea by now. However the whole pipeline we use is slightly more complex in the end:

Advanced Pipeline

Hope you liked our venture into the realm of advanced CI/CD pipelines in GitLab and see ya next time!