When trying to build PX4, a drone autopilot software, I ran into a failure that only occurs in the GitLab CI. This failure occurred in a script, which checks whether a specific tag of a git submodule is available. It turns out that GitLab only does a shallow clone of the repository, and submodules need special care.

Why did I need GitLab to clone the submodules?

We customized the gazebo simulation package to include our drone setup. These changes were pushed to a private repository, which cannot be accessed without an access token. The easiest solution is to let GitLab clone the submodules, as it will take care of the permissions. This resulted in a CI script like the following:

build_job:
  stage: build_px4
  variables:
    ROS_DISTRO_ARG: ROS_DISTRO=noetic
    # Required to clone customized px4-sitl_gazebo-classic from our private GitLab
    GIT_SUBMODULE_STRATEGY: recursive
  script:
    - /kaniko/executor
      --build-arg "CI_REGISTRY_IMAGE=$CI_REGISTRY_IMAGE"
      --build-arg $ROS_DISTRO_ARG
      --build-arg "CI_COMMIT_REF_NAME=$CI_COMMIT_REF_NAME"
      --cache
      --context $CI_PROJECT_DIR
      --dockerfile $CI_PROJECT_DIR/docker/px4/Dockerfile
      --destination $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:noetic-px4

The error

In the Dockerfile, we build PX4 using their make instructions. However, this is the error message that occurred in GitLab but not on my machine:

FAILED: src/lib/version/build_git_version.h 
cd /home/vscode/px4 && /usr/bin/python3 /home/vscode/px4/src/lib/version/px_update_git_header.py /home/vscode/px4/build/px4_sitl_default/src/lib/version/build_git_version.h --validate --git_tag 'v1.14.0-beta2-4964-gb674d6ce706'
Traceback (most recent call last):
  File "/home/vscode/px4/src/lib/version/px_update_git_header.py", line 132, in <module>
    nuttx_git_tag = re.findall(r'nuttx-[0-9]+\.[0-9]+\.[0-9]+', nuttx_git_tags)[-1].replace("nuttx-", "v")

The px_update_git_header.py script checks whether a specific git tag is available. It turns out that GitLab creates shallow clones by default, which does not include the required tag.

The solution

Typical suggestions are setting GIT_DEPTH and GIT_SUBMODULE_DEPTH to 0 to disable shallow clones. In my case, I additionally had to change the GIT_STRATEGY to clone as suggested in this issue. The resulting CI script looks like this:

build_job:
  stage: build_px4
  variables:
    ROS_DISTRO_ARG: ROS_DISTRO=noetic
    # Required to clone customized px4-sitl_gazebo-classic from our private GitLab
    GIT_STRATEGY: clone
    GIT_SUBMODULE_STRATEGY: recursive
    # Fetch the entire git history so the px_update_git_header.py script can fetch the tag
    GIT_DEPTH: "0"
    GIT_SUBMODULE_DEPTH: "0"
  script:
    - /kaniko/executor
      --build-arg "CI_REGISTRY_IMAGE=$CI_REGISTRY_IMAGE"
      --build-arg $ROS_DISTRO_ARG
      --build-arg "CI_COMMIT_REF_NAME=$CI_COMMIT_REF_NAME"
      --cache
      --context $CI_PROJECT_DIR
      --dockerfile $CI_PROJECT_DIR/docker/px4/Dockerfile
      --destination $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:noetic-px4

One drawback of these settings is that cloning takes longer. In this case, the time required for cloning is negligible compared to the other build steps.

P.S.: Yes, this is a project that will end with the ROS1 end of life.