# Build and publish on GitLab

If your documentation sources are hosted on [GitLab](https://gitlab.com/), you can use [GitLab CI/CD](https://docs.gitlab.com/ee/ci/) to build your documentation website and deploy it to [GitLab Pages](https://docs.gitlab.com/ee/user/project/pages/).

Procedure:

1. Enable GitLab Pages for the project. Open your project on GitLab, select `Settings | General`, expand the Visibility, project features, permissions section, and enable Pages.

2. In the  `[writerside.cfg](writerside-cfg.html)`  file, set the `web-path` parameter for `images` to `img`.

```XML

<ihp version="2.0">
    <topics dir="topics"/>
    <images dir="images" web-path="img"/>
    <instance src="hi.tree"/>
</ihp>

```

3. In the project root, create a file named `.gitlab-ci.yml`, where you will define your CI/CD pipeline.

The following sample pipeline will trigger on every push to the `main` branch in the repository. the pipeline builds, tests, and publishes documentation from the [starter project](projects.html), where the default module name is `Writerside` and the default instance ID is `hi`:

```YAML
variables:
  INSTANCE: 'Writerside/hi'
  DOCKER_VERSION: 'XXX.YYYYY'
  # IS_GROUP: 'true'  # Uncomment to build a group

stages:
  - build
  - test
  - deploy

build:
  stage: build
  image: registry.jetbrains.team/p/writerside/builder/writerside-builder:$DOCKER_VERSION
  script:
    - set -e
    - export DISPLAY=:99
    - Xvfb :99 &
    - PROJECT_ID=$(echo $INSTANCE | cut -d'/' -f2 | tr '[:lower:]' '[:upper:]')
    - ARTIFACT="webHelp${PROJECT_ID}2-all.zip"
    - /opt/builder/bin/idea.sh helpbuilderinspect -source-dir . -product $INSTANCE --runner gitlab -output-dir public
    - echo "Testing existence of $ARTIFACT..."
    - ls -la public
    - test -e public/$ARTIFACT
  artifacts:
    paths:
      - public/$ARTIFACT
      - public/report.json
      - public/$ALGOLIA_ARTIFACT
    expire_in: 1 week

test:
  stage: test
  image: eclipse-temurin:21-jdk-alpine
  before_script:
    - apk add curl
  script:
    - cd public
    - curl -o wrs-checker.jar -L https://packages.jetbrains.team/maven/p/writerside/maven/com/jetbrains/writerside/writerside-ci-checker/1.0/writerside-ci-checker-1.0.jar
    - java -jar wrs-checker.jar report.json $INSTANCE
  dependencies:
    - build

pages:
  stage: deploy
  image: ubuntu:latest
  before_script:
    - apt-get update -y && apt-get install unzip -y

  script:
    - PROJECT_ID=$(echo $INSTANCE | cut -d'/' -f2 | tr '[:lower:]' '[:upper:]')
    - ARTIFACT="webHelp${PROJECT_ID}2-all.zip"
    - echo "Using artifact $ARTIFACT"
    - cd public
    - unzip -O UTF-8 $ARTIFACT
  dependencies:
    - build
  artifacts:
    paths:
      - public
    expire_in: 1 week
```

4. If necessary, set the correct values for environment variables:

INSTANCE
: The name of the [module](projects.html#help_module) and [instance](instances.html) ID separated by a slash. The module name is the directory with  `[writerside.cfg](writerside-cfg.html)` . It is designated by the icon ![module icon](https://resources.jetbrains.com/help/img/writerside/module.svg) in the Project tool window.
:
:
:
: For example, the default module name in a starter project is `Writerside` and the instance ID is `hi`. So in this case, set the variable to `Writerside/hi`.
:
:
:
: > **Note:**
: > If you want to [build multiple instances](build-groups.html), set `IS_GROUP: 'true'` and make sure the `INSTANCE` variable points to the necessary build group.
: >
: >
: >
: > Also, in this case, save the artifacts to `path: artifacts/*`.

DOCKER_VERSION
: The version of the Writerside Docker builder to use for generating the documentation artifacts. The current latest version is 2026.08.0328.
:
:
:
: When you update to a newer version of Writerside, set the new Docker builder version to ensure results similar to what you see in the local preview and local builds.

5. Commit the `.gitlab-ci.yml` and push it to GitLab.

## Upload search indexes

If you also [configure Algolia search](algolia-search.html#gitlab), you can modify the CI/CD pipeline further and add the `publish-indexes` stage that will automatically update the search indexes after a successful deployment.

You will also need to add Algolia indexes to the `public` artifacts' folder that the `build` stage produces, and specify the following additional environment variables:

ALGOLIA_APP_NAME
: Algolia application ID

ALGOLIA_INDEX_NAME
: Name of Algolia index

CONFIG_JSON_PRODUCT
: Help instance ID from the  [tree file](help-modules.html#tree-file)  or the value of the `web-path` attribute specified in  `[writerside.cfg](writerside-cfg.html)`  if it is different from the ID

CONFIG_JSON_VERSION
: Help instance version (usually the same as the branch name) specified in  `[writerside.cfg](writerside-cfg.html)`

> **Note:**
> You can find the application ID and API keys in your Algolia account settings under [API Keys](https://dashboard.algolia.com/account/api-keys).
>
>
>
> Specify your private API key as a secret. The workflow will reference it via `$ALGOLIA_KEY`.

Here is how it all looks in a single workflow file:

```YAML
variables:
  INSTANCE: 'Writerside/hi'
  DOCKER_VERSION: 'XXX.YYYYY'
  # IS_GROUP: 'true'  # Uncomment to build a group
  ALGOLIA_APP_NAME: 'V6MS25BRYB'
  ALGOLIA_INDEX_NAME: 'MY_INDEX'
  CONFIG_JSON_PRODUCT: 'HI'
  CONFIG_JSON_VERSION: '1.0'

stages:
  - build
  - test
  - deploy
  - search

build:
  stage: build
  image: registry.jetbrains.team/p/writerside/builder/writerside-builder:$DOCKER_VERSION
  script:
    - set -e
    - export DISPLAY=:99
    - Xvfb :99 &
    - PROJECT_ID=$(echo $INSTANCE | cut -d'/' -f2 | tr '[:lower:]' '[:upper:]')
    - ARTIFACT="webHelp${PROJECT_ID}2-all.zip"
    - /opt/builder/bin/idea.sh helpbuilderinspect -source-dir . -product $INSTANCE --runner gitlab -output-dir public
    - echo "Testing existence of $ARTIFACT..."
    - ls -la public
    - test -e public/$ARTIFACT
  artifacts:
    paths:
      - public/$ARTIFACT
      - public/report.json
      - public/$ALGOLIA_ARTIFACT
    expire_in: 1 week

test:
  stage: test
  image: eclipse-temurin:21-jdk-alpine
  before_script:
    - apk add curl
  script:
    - cd public
    - curl -o wrs-checker.jar -L https://packages.jetbrains.team/maven/p/writerside/maven/com/jetbrains/writerside/writerside-ci-checker/1.0/writerside-ci-checker-1.0.jar
    - java -jar wrs-checker.jar report.json $INSTANCE
  dependencies:
    - build

pages:
  stage: deploy
  image: ubuntu:latest
  before_script:
    - apt-get update -y && apt-get install unzip -y

  script:
    - PROJECT_ID=$(echo $INSTANCE | cut -d'/' -f2 | tr '[:lower:]' '[:upper:]')
    - ARTIFACT="webHelp${PROJECT_ID}2-all.zip"
    - echo "Using artifact $ARTIFACT"
    - cd public
    - unzip -O UTF-8 $ARTIFACT
  dependencies:
    - build
  artifacts:
    paths:
      - public
    expire_in: 1 week

search:
  stage: search
  image: registry.jetbrains.team/p/writerside/builder/algolia-publisher:latest
  dependencies:
    - build
    - test
    - pages
  script:
    - echo "Checking contents of the public directory..."
    - ls -la public
    - if [ -z "$ALGOLIA_KEY" ]; then
      echo "ALGOLIA_KEY is not set in Gitlab secrets";
      exit 1;
      fi
    - echo "ALGOLIA_KEY is set"
    - PROJECT_ID=$(echo $INSTANCE | cut -d'/' -f2 | tr '[:lower:]' '[:upper:]')
    - ALGOLIA_ARTIFACT="algolia-indexes-${PROJECT_ID}.zip"
    - echo "ALGOLIA_ARTIFACT is $ALGOLIA_ARTIFACT"
    - if [ ! -f "public/$ALGOLIA_ARTIFACT" ]; then
      echo "Artifacts file public/$ALGOLIA_ARTIFACT not found!";
      exit 1;
      fi
    - unzip -O UTF-8 public/$ALGOLIA_ARTIFACT -d algolia-indexes
    - env "algolia-key=$ALGOLIA_KEY" java -jar /opt/builder/help-publication-agent.jar update-index --application-name $ALGOLIA_APP_NAME --index-name $ALGOLIA_INDEX_NAME --product $CONFIG_JSON_PRODUCT --version $CONFIG_JSON_VERSION --index-directory algolia-indexes/ 2>&1 | tee algolia-update-index-log.txt
  artifacts:
    paths:
      - algolia-update-index-log.txt
    expire_in: 1 week
```

## Build to PDF

You can configure a separate pipeline or stage in an existing pipeline to produce a PDF artifact. Here is an example of a separate pipeline with a `build_pdf` stage that produces a PDF:

```YAML
variables:
  INSTANCE: 'Writerside/hi'
  DOCKER_VERSION: '2026.08.0328'
  PDF: 'PDF.xml'

stages:
  - build_pdf

build_pdf:
  stage: build_pdf
  image: registry.jetbrains.team/p/writerside/builder/writerside-builder:$DOCKER_VERSION
  script:
    - set -e
    - export DISPLAY=:99
    - Xvfb :99 &
    - PROJECT_ID=$(echo $INSTANCE | cut -d'/' -f2 | tr '[:lower:]' '[:upper:]')
    - PDF_FILE="pdfSource${PROJECT_ID}.pdf"
    - HTML_FILE="pdfSource${PROJECT_ID}.html"
    - /opt/builder/bin/idea.sh helpbuilderinspect -source-dir . -product $INSTANCE --runner gitlab -output-dir public -pdf $PDF
    - echo "Testing existence of $PDF_FILE and $HTML_FILE"
    - test -e public/$PDF_FILE
    - test -e public/$HTML_FILE
  artifacts:
    paths:
      - public/$PDF_FILE
      - public/$HTML_FILE
    expire_in: 1 week

```

> **Note:**
> You should have the `PDF.xml` file in the  [cfg directory](help-modules.html#build-config-dir) . For more information, see [Export to PDF](export-to-pdf.html).

