diff --git a/jobs/maven-indexer-exporter.yml b/jobs/maven-indexer-exporter.yml
new file mode 100644
--- /dev/null
+++ b/jobs/maven-indexer-exporter.yml
@@ -0,0 +1,40 @@
+- job-template: &build_and_push
+    name: "{name}/build-and-push"
+    description: Build the docker image and publish it to a registry
+    node: built-in
+    project-type: pipeline
+    auth-token: "ph4br1cat0r"
+    dsl: !include-jinja2: templates/swh-build-docker-image.groovy.j2
+
+    parameters:
+      - string:
+          name: TAG
+          description: Tag to build the image and then use as name
+
+- job-template:
+    name: "{name}/gitlab-build-and-push"
+    description: Build the docker image and publish it to a registry (GitLab)
+    auth-token:
+    parameters:
+    gitlab_project: true
+    gitlab_project_name: swh/devel/fixtures/maven-index-exporter
+    properties:
+      - gitlab:
+          connection: "{gitlab_connection_name}"
+    triggers:
+      - gitlab:
+          trigger-push: true
+          trigger-merge-request: false
+          add-ci-message: true
+          # secret jenkins token is generated when executing tox
+          secret-token: !include-raw: jobs/templates/jenkins-token
+    <<: *build_and_push
+
+- project:
+    name: DLSMAVEXP
+    display-name: maven-index-exporter
+    repo_name: maven-index-exporter
+    jobs:
+      - "{name}"
+      - "{name}/build-and-push"
+      - "{name}/gitlab-build-and-push"
diff --git a/jobs/swh-build-docker-image.yml b/jobs/swh-build-docker-image.yml
deleted file mode 100644
--- a/jobs/swh-build-docker-image.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-- job-template:
-    name: "{name}/build-and-push"
-    description: Build the docker image and publish it to a registry
-    node: built-in
-    project-type: pipeline
-    auth-token: 'ph4br1cat0r'
-    dsl:
-      !include-jinja2: templates/swh-build-docker-image.groovy.j2
-
-    parameters:
-      - string:
-          name: TAG
-          description: Tag to build the image and then use as name
-
-- project:
-    name: DLSMAVEXP
-    display-name: maven-index-exporter
-    repo_name: maven-index-exporter
-    jobs:
-      - "{name}"
-      - "{name}/build-and-push"
diff --git a/jobs/templates/swh-build-docker-image.groovy.j2 b/jobs/templates/swh-build-docker-image.groovy.j2
--- a/jobs/templates/swh-build-docker-image.groovy.j2
+++ b/jobs/templates/swh-build-docker-image.groovy.j2
@@ -2,7 +2,13 @@
 
 // Normalize to "latest" if we build from head commit (main or master)
 // Otherwise, keep the transmitted tag
+{%- if gitlab_project %}
+// remove refs/tags/ prefix from source branch
+def tag = env.gitlabSourceBranch.substring(10)
+{%- else %}
 def tag = params.TAG
+{%- endif %}
+
 def tag_name = ( tag == "origin/main" || tag == "origin/master" ) ? "latest" : tag
 
 // The following is configured in jenkins manually:
@@ -27,35 +33,67 @@
 // - push: publish to the registry
 // TAG, REGISTRY_URL must be provided
 
-node('built-in') {
-  stage ('Pre-cleanup') {
-    cleanWs()
-  }
-  stage('Checkout Repository') {
-    checkout([
-      $class: 'GitSCM',
-      branches: [[name: tag]],
-      userRemoteConfigs: [[
-        url: "https://forge.softwareheritage.org/source/${repo_name}/",
-      ]],
-    ])
-  }
-  def dockerImage
-  stage ('Build image') {
-    sh "make build TAG=${tag} IMAGE_LABEL=${image_label}"
-  }
-  stage ('Push image') {
-    // first make sure the image is ok
-    sh "make test TAG=${tag}"
-    // then publish it
-    docker.withRegistry("https://${registry_url}", dockerCredentialsKeyID) {
-      sh "make push TAG=${tag} REGISTRY_URL=${registry_url}"
+pipeline {
+  agent any
+  stages {
+    stage ('Pre-cleanup') {
+      steps {
+        cleanWs()
+      }
     }
+    stage('Checkout Repository') {
+      steps {
+        {%- if gitlab_project %}
+        updateGitlabCommitStatus name: 'jenkins', state: 'running'
+        {%- endif %}
+        checkout([
+          $class: 'GitSCM',
+          branches: [[name: tag]],
+          userRemoteConfigs: [[
+            {%- if not gitlab_project %}
+            url: "https://forge.softwareheritage.org/source/${repo_name}/",
+            {%- else %}
+            url: "{{gitlab_url}}/{{gitlab_project_name}}"
+            {%- endif %}
+          ]],
+        ])
+      }
+    }
+    stage ('Build image') {
+      steps {
+        sh "make build TAG=${tag} IMAGE_LABEL=${image_label}"
+      }
+    }
+    stage ('Push image') {
+      steps {
+        script {
+          // first make sure the image is ok
+          sh "make test TAG=${tag}"
+          // then publish it
+          docker.withRegistry("https://${registry_url}", dockerCredentialsKeyID) {
+            sh "make push TAG=${tag} REGISTRY_URL=${registry_url}"
+          }
+        }
+      }
+    }
+  }
+  post {
     always {
-      // finally clean workspace
-      cleanWs()
       // and locally built image (resulting from the current jenkins build)
       sh "make clean IMAGE_LABEL=${image_label}"
+      // finally clean workspace
+      cleanWs()
+    }
+    {%- if gitlab_project %}
+    failure {
+      updateGitlabCommitStatus name: 'jenkins', state: 'failed'
+    }
+    success {
+      updateGitlabCommitStatus name: 'jenkins', state: 'success'
+    }
+    aborted {
+      updateGitlabCommitStatus name: 'jenkins', state: 'canceled'
     }
+    {%- endif %}
   }
 }
diff --git a/jobs/tools/setup-gitlab-webhooks.groovy.j2 b/jobs/tools/setup-gitlab-webhooks.groovy.j2
--- a/jobs/tools/setup-gitlab-webhooks.groovy.j2
+++ b/jobs/tools/setup-gitlab-webhooks.groovy.j2
@@ -32,6 +32,8 @@
                              true, true, false)
           setupGitlabWebhook("swh/infra/swh-mirror", "DFP/gitlab-run-tests",
                              true, true, false)
+          setupGitlabWebhook("swh/devel/fixtures/maven-index-exporter", "DLSMAVEXP/gitlab-build-and-push",
+                             false, false, true)
 
           projects = readYaml(file: 'jobs/swh-packages.yaml')
           for (project in projects) {