this problem might be quite specific.
This is my project structure. It's a Django project.
├── docs
│ ├── build
│ │ ├── doctrees
│ │ └── html
│ ├── Makefile
│ └── source
│ ├── code
│ ├── conf.py
│ ├── contributing.md
│ ├── index.rst
│ ├── infrastructure.md
│ └── _static
├── my-project-name
│ ├── api.py
│ ├── asgi.py
│ ├── celeryconfig.py
│ ├── celery.py
│ ├── __init__.py
│ ├── __pycache__
│ ├── routers.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
| ... some more apps
It is hosted on a private GitLab instance and I have multiple runners installed. One is a docker executor that is responsible for building the documentation via Sphinx.
The basic .gitlab-ci.yml
looks like this:
image: python:3.10-slim
stages:
- deploy
pages:
tags:
- docs
stage: deploy
script:
- python3 -m pip install django sphinx furo myst-parser
- sphinx-build -b html docs/source public/
This has been working just fine as long as I haven't tried to include Django code via the sphinx-autodoc
extension. Everything shows up on the GitLab pages. I know that Sphinx needs to load every module that it scans upfront. So this is why you have to initialize Django in the conf.py
.
The beginning of my Sphinx conf.py
looks like this:
# Sphinx needs Django loaded to correctly use the "autodoc" extension
import django
import os
import sys
from pathlib import Path
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "my-project-name.settings")
sys.path.append(Path(__file__).parent.parent.parent)
django.setup()
The last line before calling django.setup()
makes sure to include the project-level path.
Autodocumenting Django works fine with these modifications when I make html
on my local system. The modules I specify are documented nicely and no errors occur.
I push the code to my GitLab repository and let the jobs run via a docker executor.
$ python3 -m pip install django sphinx furo myst-parser
Collecting django
Downloading Django-4.1.7-py3-none-any.whl (8.1 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 8.1/8.1 MB 124.3 MB/s eta 0:00:00
Collecting sphinx
Downloading sphinx-6.1.3-py3-none-any.whl (3.0 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.0/3.0 MB 111.0 MB/s eta 0:00:00
...
# the loading continues here
After all the modules are loaded it tries to execute Sphinx. Now, this error occurs:
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
[notice] A new release of pip available: 22.3.1 -> 23.0.1
[notice] To update, run: pip install --upgrade pip
$ sphinx-build -b html docs/source public/
Running Sphinx v6.1.3
######
/builds/my-dir/my-project-name
######
Configuration error:
There is a programmable error in your configuration file:
Traceback (most recent call last):
File "/usr/local/lib/python3.10/site-packages/sphinx/config.py", line 351, in eval_config_file
exec(code, namespace) # NoQA: S102
File "/builds/my-dir/my-project-name/docs/source/conf.py", line 22, in <module>
django.setup()
File "/usr/local/lib/python3.10/site-packages/django/__init__.py", line 19, in setup
configure_logging(settings.LOGGING_CONFIG, settings.LOGGING)
File "/usr/local/lib/python3.10/site-packages/django/conf/__init__.py", line 92, in __getattr__
self._setup(name)
File "/usr/local/lib/python3.10/site-packages/django/conf/__init__.py", line 79, in _setup
self._wrapped = Settings(settings_module)
File "/usr/local/lib/python3.10/site-packages/django/conf/__init__.py", line 190, in __init__
mod = importlib.import_module(self.SETTINGS_MODULE)
File "/usr/local/lib/python3.10/importlib/__init__.py", line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
File "<frozen importlib._bootstrap>", line 992, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
File "<frozen importlib._bootstrap>", line 1004, in _find_and_load_unlocked
ModuleNotFoundError: No module named 'my-project-name'
Cleaning up project directory and file based variables
00:01
ERROR: Job failed: exit code 1
As far as I know, this usually occurs when you don't set your path variables correctly. But I set it at the project level and print it out as validation (the ### lines
in the error message). My project path is definitely /builds/my-dir/my-project-name
.
Do you have any ideas on what I could try to make it work?
sys.path.append(Path(__file__).parent.parent.parent.as_posix())
saved the day.