qcdrivers 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. qcdrivers-0.1.0/.gitattributes +34 -0
  2. qcdrivers-0.1.0/.gitignore +67 -0
  3. qcdrivers-0.1.0/.gitlab-ci.yml +178 -0
  4. qcdrivers-0.1.0/.pre-commit-config.yaml +29 -0
  5. qcdrivers-0.1.0/.python-version +1 -0
  6. qcdrivers-0.1.0/CHANGELOG.md +7 -0
  7. qcdrivers-0.1.0/CONTRIBUTING.md +90 -0
  8. qcdrivers-0.1.0/LICENSE +661 -0
  9. qcdrivers-0.1.0/PKG-INFO +134 -0
  10. qcdrivers-0.1.0/README.md +99 -0
  11. qcdrivers-0.1.0/gl-sast-report.json +3415 -0
  12. qcdrivers-0.1.0/gl-secret-detection-report.json +50 -0
  13. qcdrivers-0.1.0/pyproject.toml +119 -0
  14. qcdrivers-0.1.0/release.env +2 -0
  15. qcdrivers-0.1.0/src/qcdrivers/__init__.py +9 -0
  16. qcdrivers-0.1.0/src/qcdrivers/basel/__init__.py +12 -0
  17. qcdrivers-0.1.0/src/qcdrivers/basel/amplifiers/__init__.py +10 -0
  18. qcdrivers-0.1.0/src/qcdrivers/basel/amplifiers/amplifiers.py +107 -0
  19. qcdrivers-0.1.0/src/qcdrivers/basel/amplifiers/dummy.py +136 -0
  20. qcdrivers-0.1.0/src/qcdrivers/basel/dacs/__init__.py +9 -0
  21. qcdrivers-0.1.0/src/qcdrivers/basel/dacs/dacs.py +1497 -0
  22. qcdrivers-0.1.0/src/qcdrivers/basel/dacs/dacs_controller.py +2132 -0
  23. qcdrivers-0.1.0/src/qcdrivers/bluefors/__init__.py +7 -0
  24. qcdrivers-0.1.0/src/qcdrivers/bluefors/fridges/README.md +42 -0
  25. qcdrivers-0.1.0/src/qcdrivers/bluefors/fridges/__init__.py +7 -0
  26. qcdrivers-0.1.0/src/qcdrivers/bluefors/fridges/fridges.py +384 -0
  27. qcdrivers-0.1.0/src/qcdrivers/buffered/__init__.py +26 -0
  28. qcdrivers-0.1.0/src/qcdrivers/buffered/_typing.py +30 -0
  29. qcdrivers-0.1.0/src/qcdrivers/buffered/base.py +90 -0
  30. qcdrivers-0.1.0/src/qcdrivers/buffered/basel/__init__.py +5 -0
  31. qcdrivers-0.1.0/src/qcdrivers/buffered/basel/nodes.py +217 -0
  32. qcdrivers-0.1.0/src/qcdrivers/buffered/keysight/__init__.py +5 -0
  33. qcdrivers-0.1.0/src/qcdrivers/buffered/keysight/nodes.py +234 -0
  34. qcdrivers-0.1.0/src/qcdrivers/buffered/qdevil/__init__.py +5 -0
  35. qcdrivers-0.1.0/src/qcdrivers/buffered/qdevil/nodes.py +269 -0
  36. qcdrivers-0.1.0/src/qcdrivers/buffered/squad/__init__.py +5 -0
  37. qcdrivers-0.1.0/src/qcdrivers/buffered/squad/nodes.py +91 -0
  38. qcdrivers-0.1.0/src/qcdrivers/buffered/zurich/__init__.py +5 -0
  39. qcdrivers-0.1.0/src/qcdrivers/buffered/zurich/nodes.py +736 -0
  40. qcdrivers-0.1.0/src/qcdrivers/entropy/README.md +164 -0
  41. qcdrivers-0.1.0/src/qcdrivers/entropy/__init__.py +9 -0
  42. qcdrivers-0.1.0/src/qcdrivers/entropy/adr/__init__.py +7 -0
  43. qcdrivers-0.1.0/src/qcdrivers/entropy/adr/adr.py +229 -0
  44. qcdrivers-0.1.0/src/qcdrivers/entropy/heater/__init__.py +7 -0
  45. qcdrivers-0.1.0/src/qcdrivers/entropy/heater/heater.py +181 -0
  46. qcdrivers-0.1.0/src/qcdrivers/harvard/__init__.py +10 -0
  47. qcdrivers-0.1.0/src/qcdrivers/harvard/dacs/__init__.py +10 -0
  48. qcdrivers-0.1.0/src/qcdrivers/harvard/dacs/dacs.py +781 -0
  49. qcdrivers-0.1.0/src/qcdrivers/keysight/__init__.py +12 -0
  50. qcdrivers-0.1.0/src/qcdrivers/keysight/dmms/Keysight_34410A.py +20 -0
  51. qcdrivers-0.1.0/src/qcdrivers/keysight/dmms/Keysight_34461A.py +20 -0
  52. qcdrivers-0.1.0/src/qcdrivers/keysight/dmms/Keysight_344xxA_submodules.py +1121 -0
  53. qcdrivers-0.1.0/src/qcdrivers/keysight/dmms/__init__.py +4 -0
  54. qcdrivers-0.1.0/src/qcdrivers/keysight/vna/N52xx.py +501 -0
  55. qcdrivers-0.1.0/src/qcdrivers/keysight/vna/__init__.py +9 -0
  56. qcdrivers-0.1.0/src/qcdrivers/qdevil/__init__.py +7 -0
  57. qcdrivers-0.1.0/src/qcdrivers/qdevil/qdac2/__init__.py +7 -0
  58. qcdrivers-0.1.0/src/qcdrivers/qdevil/qdac2/qdac2.py +2912 -0
  59. qcdrivers-0.1.0/src/qcdrivers/rwth/__init__.py +7 -0
  60. qcdrivers-0.1.0/src/qcdrivers/rwth/mux/README.md +56 -0
  61. qcdrivers-0.1.0/src/qcdrivers/rwth/mux/__init__.py +7 -0
  62. qcdrivers-0.1.0/src/qcdrivers/rwth/mux/helpers/firmware/control.ino +77 -0
  63. qcdrivers-0.1.0/src/qcdrivers/rwth/mux/helpers/firmware/firmware.ino +295 -0
  64. qcdrivers-0.1.0/src/qcdrivers/rwth/mux/helpers/firmware/identify.ino +192 -0
  65. qcdrivers-0.1.0/src/qcdrivers/rwth/mux/helpers/firmware/voltage.ino +25 -0
  66. qcdrivers-0.1.0/src/qcdrivers/rwth/mux/mux.py +398 -0
  67. qcdrivers-0.1.0/src/qcdrivers/squad/__init__.py +9 -0
  68. qcdrivers-0.1.0/src/qcdrivers/squad/curry/README.md +151 -0
  69. qcdrivers-0.1.0/src/qcdrivers/squad/curry/__init__.py +23 -0
  70. qcdrivers-0.1.0/src/qcdrivers/squad/curry/curry.py +349 -0
  71. qcdrivers-0.1.0/src/qcdrivers/squad/helpers/__init__.py +9 -0
  72. qcdrivers-0.1.0/src/qcdrivers/squad/helpers/helpers.py +366 -0
  73. qcdrivers-0.1.0/src/qcdrivers/squad/mux/README.md +40 -0
  74. qcdrivers-0.1.0/src/qcdrivers/squad/mux/__init__.py +7 -0
  75. qcdrivers-0.1.0/src/qcdrivers/squad/mux/helpers/24x24.ino +36 -0
  76. qcdrivers-0.1.0/src/qcdrivers/squad/mux/helpers/AD75019.cpp +144 -0
  77. qcdrivers-0.1.0/src/qcdrivers/squad/mux/helpers/AD75019.h +132 -0
  78. qcdrivers-0.1.0/src/qcdrivers/squad/mux/helpers/AD75019_24.cpp +197 -0
  79. qcdrivers-0.1.0/src/qcdrivers/squad/mux/helpers/AD75019_24.h +123 -0
  80. qcdrivers-0.1.0/src/qcdrivers/squad/mux/helpers/firmware.ino +120 -0
  81. qcdrivers-0.1.0/src/qcdrivers/squad/mux/mux.py +256 -0
  82. qcdrivers-0.1.0/src/qcdrivers/stanford/__init__.py +7 -0
  83. qcdrivers-0.1.0/src/qcdrivers/stanford/vccs.py +169 -0
  84. qcdrivers-0.1.0/tests/conftest.py +67 -0
  85. qcdrivers-0.1.0/tests/hardware/README.md +12 -0
  86. qcdrivers-0.1.0/tests/hardware/basel_dac_testing.py +165 -0
  87. qcdrivers-0.1.0/tests/hardware/keysight_vna_testing.py +29 -0
  88. qcdrivers-0.1.0/tests/hardware/notebooks/rwth_mux_test.ipynb +925 -0
  89. qcdrivers-0.1.0/tests/hardware/notebooks/squad_AD75019_test.ipynb +179 -0
  90. qcdrivers-0.1.0/tests/stubs.py +38 -0
  91. qcdrivers-0.1.0/tests/test_basel_dac_utilities.py +163 -0
  92. qcdrivers-0.1.0/tests/test_buffered_basel.py +181 -0
  93. qcdrivers-0.1.0/tests/test_buffered_nodes.py +677 -0
  94. qcdrivers-0.1.0/tests/test_buffered_zurich.py +524 -0
  95. qcdrivers-0.1.0/tests/test_curry.py +173 -0
  96. qcdrivers-0.1.0/tests/test_harvard_dac_utilities.py +47 -0
  97. qcdrivers-0.1.0/tests/test_public_api.py +59 -0
  98. qcdrivers-0.1.0/uv.lock +1790 -0
@@ -0,0 +1,34 @@
1
+ # Line-ending normalisation.
2
+ #
3
+ # Text files are stored LF in the repository and checked out LF everywhere,
4
+ # including Windows. Without this the working tree depends on each clone's
5
+ # core.autocrlf setting, so the same file differs between machines and a
6
+ # formatter that enforces LF fights the checkout on every commit.
7
+ #
8
+ # Applying this renormalises files whose stored form is currently CRLF. Run
9
+ # `git add --renormalize .` once, in its own commit.
10
+ * text=auto eol=lf
11
+
12
+ # cmd.exe requires CRLF in batch files.
13
+ *.bat text eol=crlf
14
+ *.cmd text eol=crlf
15
+
16
+ # Shell scripts must stay LF or they fail on Linux and macOS with ^M errors.
17
+ *.sh text eol=lf
18
+
19
+ # Binary assets: never convert, never diff as text.
20
+ *.png binary
21
+ *.jpg binary
22
+ *.jpeg binary
23
+ *.gif binary
24
+ *.ico binary
25
+ *.webp binary
26
+ *.pdf binary
27
+ *.zip binary
28
+ *.woff binary
29
+ *.woff2 binary
30
+ *.ttf binary
31
+ *.otf binary
32
+
33
+ # Collapse the lockfile in GitLab merge request diffs; it is generated output.
34
+ uv.lock -diff linguist-generated=true gitlab-generated=true
@@ -0,0 +1,67 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+
4
+ # Distribution / packaging
5
+ .Python
6
+ build/
7
+ develop-eggs/
8
+ dist/
9
+ *.egg-info/
10
+ .installed.cfg
11
+ *.egg
12
+ MANIFEST
13
+ .DS_Store
14
+ # Installer logs
15
+ pip-log.txt
16
+ pip-delete-this-directory.txt
17
+
18
+ # Unit test / coverage reports
19
+ .tox/
20
+ .nox/
21
+ .uv-cache/
22
+ .coverage
23
+ .coverage.*
24
+ .cache
25
+ nosetests.xml
26
+ coverage.xml
27
+ report.xml
28
+ *.cover
29
+ *.py,cover
30
+ .pytest_cache/
31
+
32
+ # Sphinx documentation
33
+ docs/_build/
34
+
35
+ # PyBuilder
36
+ .pybuilder/
37
+ target/
38
+
39
+ # Jupyter Notebook
40
+ .ipynb_checkpoints
41
+
42
+ # IPython
43
+ profile_default/
44
+ ipython_config.py
45
+
46
+ # Environments
47
+ .env
48
+ .venv
49
+ env/
50
+ venv/
51
+ ENV/
52
+ env.bak/
53
+ venv.bak/
54
+ *_env/
55
+
56
+ # Spyder project settings
57
+ .spyderproject
58
+ .spyproject
59
+
60
+ # mkdocs documentation
61
+ /site
62
+
63
+ # mypy
64
+ .mypy_cache/
65
+ .dmypy.json
66
+ dmypy.json
67
+ .DS_Store
@@ -0,0 +1,178 @@
1
+ image: "python:3.13"
2
+
3
+ # Branch model: feature branches -> preview -> main. Everything is linted and
4
+ # tested on every branch, preview additionally proves the package builds, and
5
+ # only main creates a release.
6
+
7
+ stages:
8
+ - format
9
+ - test
10
+ - release
11
+
12
+ include:
13
+ - template: Security/SAST.gitlab-ci.yml
14
+ - template: Security/Secret-Detection.gitlab-ci.yml
15
+
16
+ variables:
17
+ SECRET_DETECTION_ENABLED: "true"
18
+ UV_CACHE_DIR: "$CI_PROJECT_DIR/.uv-cache"
19
+
20
+ sast:
21
+ stage: test
22
+
23
+ secret_detection:
24
+ stage: test
25
+
26
+ lint:
27
+ stage: format
28
+ before_script:
29
+ - curl -LsSf https://astral.sh/uv/install.sh | sh
30
+ - source $HOME/.local/bin/env
31
+ # Keep this exact version aligned with pyproject.toml and pre-commit.
32
+ - uv tool install ruff@0.16.6
33
+ script:
34
+ - ruff check .
35
+ - ruff format --check .
36
+
37
+ pytest:
38
+ stage: test
39
+ # Python 3.13 is the supported runtime for this release.
40
+ parallel:
41
+ matrix:
42
+ - PYTHON_VERSION: ["3.13"]
43
+ image: "python:${PYTHON_VERSION}"
44
+ before_script:
45
+ - curl -LsSf https://astral.sh/uv/install.sh | sh
46
+ - source $HOME/.local/bin/env
47
+ script:
48
+ - uv sync --python "$PYTHON_VERSION" --extra test
49
+ - uv run --python "$PYTHON_VERSION" pytest --cov --cov-report=term --cov-report=xml --junitxml=report.xml
50
+ coverage: '/^TOTAL.*\s+(\d+%)$/'
51
+ artifacts:
52
+ when: always
53
+ reports:
54
+ junit: report.xml
55
+ coverage_report:
56
+ coverage_format: cobertura
57
+ path: coverage.xml
58
+ cache:
59
+ key: uv-$CI_JOB_NAME-$PYTHON_VERSION
60
+ paths:
61
+ - .uv-cache
62
+
63
+ # Windows gets a full run because Zarr stores and file locking behave
64
+ # differently there. Coverage is reported by the Linux jobs only.
65
+ pytest-windows:
66
+ stage: test
67
+ tags:
68
+ - windows
69
+ variables:
70
+ PYTHON_VERSION: "3.13"
71
+ before_script:
72
+ - powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
73
+ - $env:Path = "$env:USERPROFILE\.local\bin;$env:Path"
74
+ script:
75
+ - uv sync --python $env:PYTHON_VERSION --extra test
76
+ - uv run --python $env:PYTHON_VERSION pytest --junitxml=report.xml
77
+ artifacts:
78
+ when: always
79
+ reports:
80
+ junit: report.xml
81
+ cache:
82
+ key: uv-$CI_JOB_NAME-$PYTHON_VERSION
83
+ paths:
84
+ - .uv-cache
85
+
86
+ semantic_release:
87
+ stage: release
88
+ rules:
89
+ - if: $CI_COMMIT_BRANCH == "main"
90
+ variables:
91
+ # semantic-release needs all commits and tags to calculate the next version.
92
+ GIT_DEPTH: 0
93
+ GIT_STRATEGY: clone
94
+ before_script:
95
+ - curl -LsSf https://astral.sh/uv/install.sh | sh
96
+ - source $HOME/.local/bin/env
97
+ - git config --global user.name "Janitor"
98
+ - git config --global user.email "squad@fz-juelich.de"
99
+ - git remote set-url origin https://squad_janitor:$CI_FORMAT@$CI_SERVER_HOST/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME
100
+ # GitLab checks out a detached HEAD, while semantic-release needs a branch.
101
+ - git fetch origin $CI_COMMIT_BRANCH
102
+ - git checkout $CI_COMMIT_BRANCH
103
+ - git reset --hard origin/$CI_COMMIT_BRANCH
104
+ - uv tool install python-semantic-release
105
+ script:
106
+ - |
107
+ RELEASE_TAG="$(semantic-release version --print-tag)"
108
+ LAST_TAG="$(semantic-release version --print-last-released-tag)"
109
+ if [ "$RELEASE_TAG" = "$LAST_TAG" ]; then
110
+ echo "No release-worthy commits; no version will be published."
111
+ echo "RELEASE_CREATED=false" > release.env
112
+ exit 0
113
+ fi
114
+ echo "RELEASE_CREATED=true" > release.env
115
+ echo "RELEASE_TAG=$RELEASE_TAG" >> release.env
116
+ semantic-release version --push --changelog --no-vcs-release
117
+ artifacts:
118
+ paths:
119
+ - dist/
120
+ - CHANGELOG.md
121
+ - release.env
122
+ expire_in: never
123
+ reports:
124
+ dotenv: release.env
125
+
126
+ gitlab_release:
127
+ stage: release
128
+ image: registry.gitlab.com/gitlab-org/cli:latest
129
+ needs:
130
+ - job: semantic_release
131
+ artifacts: true
132
+ rules:
133
+ - if: $CI_COMMIT_BRANCH == "main"
134
+ variables:
135
+ GLAB_ENABLE_CI_AUTOLOGIN: "true"
136
+ script:
137
+ - |
138
+ if [ "$RELEASE_CREATED" != "true" ]; then
139
+ echo "semantic-release did not cut a version; no GitLab Release needed."
140
+ exit 0
141
+ fi
142
+ unset GITLAB_TOKEN GITLAB_ACCESS_TOKEN OAUTH_TOKEN
143
+ glab release create "$RELEASE_TAG" \
144
+ --name "Release $RELEASE_TAG" \
145
+ --notes-file CHANGELOG.md \
146
+ --ref "$RELEASE_TAG"
147
+
148
+ pypi:
149
+ stage: release
150
+ needs:
151
+ - job: semantic_release
152
+ artifacts: true
153
+ rules:
154
+ - if: $CI_COMMIT_BRANCH == "main" && $PYPI_SPANDAN
155
+ before_script:
156
+ - curl -LsSf https://astral.sh/uv/install.sh | sh
157
+ - source $HOME/.local/bin/env
158
+ script:
159
+ - |
160
+ if ! ls dist/*.whl >/dev/null 2>&1; then
161
+ echo "semantic-release produced no distribution -- nothing to publish."
162
+ exit 0
163
+ fi
164
+ - uv publish --token "$PYPI_SPANDAN"
165
+
166
+ build_package:
167
+ stage: release
168
+ rules:
169
+ - if: $CI_COMMIT_BRANCH == "preview"
170
+ before_script:
171
+ - curl -LsSf https://astral.sh/uv/install.sh | sh
172
+ - source $HOME/.local/bin/env
173
+ script:
174
+ - uv build
175
+ artifacts:
176
+ paths:
177
+ - dist/*.tar.gz
178
+ - dist/*.whl
@@ -0,0 +1,29 @@
1
+ # Run `uv sync --extra dev` then `uv run pre-commit install` once per clone.
2
+ #
3
+ # Rules live in pyproject.toml ([tool.ruff]), so these hooks apply exactly the
4
+ # same configuration as the CI `lint` job.
5
+ repos:
6
+ - repo: https://github.com/astral-sh/ruff-pre-commit
7
+ # Keep this exact version aligned with pyproject.toml and .gitlab-ci.yml.
8
+ rev: v0.16.6
9
+ hooks:
10
+ # NOTE: Import sorting is part of `ruff check` via the "I" rules; the `ruff format`
11
+ # does not do it.
12
+ - id: ruff-check
13
+ args: [--fix]
14
+ - id: ruff-format
15
+
16
+ - repo: https://github.com/pre-commit/pre-commit-hooks
17
+ rev: v6.0.0
18
+ hooks:
19
+ - id: check-added-large-files
20
+ # A check to ensure large files, e.g., test measurement data, does not end up in the repository.
21
+ args: [--maxkb=512]
22
+ - id: check-merge-conflict
23
+ - id: check-toml
24
+ - id: check-yaml
25
+ - id: end-of-file-fixer
26
+ - id: trailing-whitespace
27
+ # Two trailing spaces are a hard line break in Markdown; stripping them
28
+ # silently reflows the README and the docs pages.
29
+ args: [--markdown-linebreak-ext=md]
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,7 @@
1
+ ## QCDrivers Changelog
2
+
3
+ <!-- version list -->
4
+
5
+ ## v0.1.0 (2026-09-06)
6
+
7
+ - Initial Release
@@ -0,0 +1,90 @@
1
+ # Contributing to QCDrivers
2
+
3
+ Thank you for contributing to QCDrivers. Contributions may include new drivers,
4
+ improvements to existing drivers, bug fixes, tests, and documentation.
5
+
6
+ ## Before you begin
7
+
8
+ For a larger change, please open an
9
+ [issue](https://gitlab.com/squad-lab/qcdrivers/-/issues) first so that the
10
+ implementation can be discussed before work begins. Bug reports should include
11
+ the instrument model, relevant firmware version, connection method, and enough
12
+ information to reproduce the problem.
13
+
14
+ ## Development setup
15
+
16
+ QCDrivers requires Python 3.13. Clone the repository and install the development
17
+ dependencies with `uv`:
18
+
19
+ ```console
20
+ git clone https://gitlab.com/squad-lab/qcdrivers
21
+ cd qcdrivers
22
+ uv sync --extra dev
23
+ uv run pre-commit install
24
+ ```
25
+
26
+ Create a separate branch for each contribution. This keeps changes focused and
27
+ makes them easier to review.
28
+
29
+ ## Adding or updating a driver
30
+
31
+ Drivers belong in `src/qcdrivers/` and are grouped first by manufacturer and then
32
+ by instrument category. Please use the existing packages as a reference and keep
33
+ instrument-specific implementation details in their own modules.
34
+
35
+ Every package should expose its public classes from `__init__.py` and list them in
36
+ `__all__`. Users should be able to import a driver from its category package
37
+ without knowing the name of its implementation module. For example:
38
+
39
+ ```python
40
+ from qcdrivers.basel.dacs import BaselDac2
41
+ ```
42
+
43
+ New drivers should follow the QCoDeS conventions, include clear documentation,
44
+ and avoid introducing dependencies that are not required by the driver. Please
45
+ update the README or any relevant driver documentation when public behavior or
46
+ usage changes.
47
+
48
+ ## Tests
49
+
50
+ Add automated tests under `tests/` whenever the behavior can be tested without
51
+ physical hardware. Hardware communication should be mocked or replaced with a
52
+ small stub where practical.
53
+
54
+ Interactive hardware bring-up scripts belong in `tests/hardware/`. Their names
55
+ must not match pytest's `test_*.py` or `*_test.py` patterns, because these scripts
56
+ may use hard-coded addresses and must never run in CI.
57
+
58
+ Run the test suite before submitting a change:
59
+
60
+ ```console
61
+ uv run pytest
62
+ ```
63
+
64
+ ## Code quality
65
+
66
+ Run the same linting and formatting checks used by CI:
67
+
68
+ ```console
69
+ uv run ruff check .
70
+ uv run ruff format --check .
71
+ uv run pre-commit run --all-files
72
+ ```
73
+
74
+ To apply Ruff's automatic fixes and formatting locally, run:
75
+
76
+ ```console
77
+ uv run ruff check --fix .
78
+ uv run ruff format .
79
+ ```
80
+
81
+ ## Merge requests
82
+
83
+ Open a merge request with a clear description of the change, the reason for it,
84
+ and how it was tested. Keep unrelated changes in separate merge requests and
85
+ call out anything that could not be tested without hardware.
86
+
87
+ Feature branches normally merge into `preview`, where the package is built and
88
+ tested before release. The `main` branch is used for releases. All merge requests
89
+ must pass the lint, test, security, and secret-detection jobs configured in the
90
+ GitLab pipeline.