saltext.gandi 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 (151) hide show
  1. saltext_gandi-0.1.0/.codecov.yml +25 -0
  2. saltext_gandi-0.1.0/.copier-answers.yml +33 -0
  3. saltext_gandi-0.1.0/.coveragerc +44 -0
  4. saltext_gandi-0.1.0/.envrc.example +7 -0
  5. saltext_gandi-0.1.0/.gitignore +136 -0
  6. saltext_gandi-0.1.0/.gitlab/issue_templates/Bug.md +16 -0
  7. saltext_gandi-0.1.0/.gitlab/issue_templates/Feature.md +4 -0
  8. saltext_gandi-0.1.0/.gitlab/merge_request_templates/Default.md +7 -0
  9. saltext_gandi-0.1.0/.gitlab-ci.yml +199 -0
  10. saltext_gandi-0.1.0/.pre-commit-config.yaml +150 -0
  11. saltext_gandi-0.1.0/.pre-commit-hooks/check-cli-examples.py +64 -0
  12. saltext_gandi-0.1.0/.pre-commit-hooks/check-gitlab-ci.py +50 -0
  13. saltext_gandi-0.1.0/.pre-commit-hooks/make-autodocs.py +123 -0
  14. saltext_gandi-0.1.0/.pylintrc +679 -0
  15. saltext_gandi-0.1.0/CHANGELOG.md +22 -0
  16. saltext_gandi-0.1.0/CODE-OF-CONDUCT.md +127 -0
  17. saltext_gandi-0.1.0/CONTRIBUTING.md +14 -0
  18. saltext_gandi-0.1.0/LICENSE +373 -0
  19. saltext_gandi-0.1.0/Makefile +58 -0
  20. saltext_gandi-0.1.0/PKG-INFO +182 -0
  21. saltext_gandi-0.1.0/README.md +125 -0
  22. saltext_gandi-0.1.0/changelog/.template.jinja +15 -0
  23. saltext_gandi-0.1.0/docs/Makefile +20 -0
  24. saltext_gandi-0.1.0/docs/_ext/saltdomain.py +18 -0
  25. saltext_gandi-0.1.0/docs/_static/.gitkeep +0 -0
  26. saltext_gandi-0.1.0/docs/changelog.md +12 -0
  27. saltext_gandi-0.1.0/docs/conf.py +199 -0
  28. saltext_gandi-0.1.0/docs/index.rst +47 -0
  29. saltext_gandi-0.1.0/docs/make.bat +35 -0
  30. saltext_gandi-0.1.0/docs/ref/.gitkeep +0 -0
  31. saltext_gandi-0.1.0/docs/ref/modules/index.rst +16 -0
  32. saltext_gandi-0.1.0/docs/ref/modules/saltext.gandi.modules.gandi_billing.rst +5 -0
  33. saltext_gandi-0.1.0/docs/ref/modules/saltext.gandi.modules.gandi_domain.rst +5 -0
  34. saltext_gandi-0.1.0/docs/ref/modules/saltext.gandi.modules.gandi_linkedzone.rst +5 -0
  35. saltext_gandi-0.1.0/docs/ref/modules/saltext.gandi.modules.gandi_livedns.rst +5 -0
  36. saltext_gandi-0.1.0/docs/ref/modules/saltext.gandi.modules.gandi_mod.rst +5 -0
  37. saltext_gandi-0.1.0/docs/ref/runners/index.rst +16 -0
  38. saltext_gandi-0.1.0/docs/ref/runners/saltext.gandi.runners.gandi_billing.rst +5 -0
  39. saltext_gandi-0.1.0/docs/ref/runners/saltext.gandi.runners.gandi_domain.rst +5 -0
  40. saltext_gandi-0.1.0/docs/ref/runners/saltext.gandi.runners.gandi_linkedzone.rst +5 -0
  41. saltext_gandi-0.1.0/docs/ref/runners/saltext.gandi.runners.gandi_livedns.rst +5 -0
  42. saltext_gandi-0.1.0/docs/ref/runners/saltext.gandi.runners.gandi_mod.rst +5 -0
  43. saltext_gandi-0.1.0/docs/ref/states/index.rst +14 -0
  44. saltext_gandi-0.1.0/docs/ref/states/saltext.gandi.states.gandi_domain.rst +5 -0
  45. saltext_gandi-0.1.0/docs/ref/states/saltext.gandi.states.gandi_linkedzone.rst +5 -0
  46. saltext_gandi-0.1.0/docs/ref/states/saltext.gandi.states.gandi_livedns.rst +5 -0
  47. saltext_gandi-0.1.0/docs/ref/utils/index.rst +18 -0
  48. saltext_gandi-0.1.0/docs/ref/utils/saltext.gandi.utils.billing.rst +5 -0
  49. saltext_gandi-0.1.0/docs/ref/utils/saltext.gandi.utils.client.rst +5 -0
  50. saltext_gandi-0.1.0/docs/ref/utils/saltext.gandi.utils.domain.rst +5 -0
  51. saltext_gandi-0.1.0/docs/ref/utils/saltext.gandi.utils.linkedzone.rst +5 -0
  52. saltext_gandi-0.1.0/docs/ref/utils/saltext.gandi.utils.livedns.rst +5 -0
  53. saltext_gandi-0.1.0/docs/ref/utils/saltext.gandi.utils.profile.rst +5 -0
  54. saltext_gandi-0.1.0/docs/ref/utils/saltext.gandi.utils.resources.rst +5 -0
  55. saltext_gandi-0.1.0/docs/sitevars.rst +0 -0
  56. saltext_gandi-0.1.0/docs/topics/configuration.md +224 -0
  57. saltext_gandi-0.1.0/docs/topics/dns-models.md +141 -0
  58. saltext_gandi-0.1.0/docs/topics/installation.md +28 -0
  59. saltext_gandi-0.1.0/docs/topics/testing.md +171 -0
  60. saltext_gandi-0.1.0/docs/topics/troubleshooting.md +148 -0
  61. saltext_gandi-0.1.0/docs/topics/usage.md +256 -0
  62. saltext_gandi-0.1.0/endpoints-report.txt +125 -0
  63. saltext_gandi-0.1.0/noxfile.py +545 -0
  64. saltext_gandi-0.1.0/pyproject.toml +198 -0
  65. saltext_gandi-0.1.0/setup.cfg +4 -0
  66. saltext_gandi-0.1.0/setup.py +5 -0
  67. saltext_gandi-0.1.0/src/saltext/gandi/__init__.py +28 -0
  68. saltext_gandi-0.1.0/src/saltext/gandi/modules/__init__.py +0 -0
  69. saltext_gandi-0.1.0/src/saltext/gandi/modules/gandi_billing.py +92 -0
  70. saltext_gandi-0.1.0/src/saltext/gandi/modules/gandi_domain.py +1526 -0
  71. saltext_gandi-0.1.0/src/saltext/gandi/modules/gandi_linkedzone.py +436 -0
  72. saltext_gandi-0.1.0/src/saltext/gandi/modules/gandi_livedns.py +962 -0
  73. saltext_gandi-0.1.0/src/saltext/gandi/modules/gandi_mod.py +225 -0
  74. saltext_gandi-0.1.0/src/saltext/gandi/runners/__init__.py +0 -0
  75. saltext_gandi-0.1.0/src/saltext/gandi/runners/gandi_billing.py +98 -0
  76. saltext_gandi-0.1.0/src/saltext/gandi/runners/gandi_domain.py +1535 -0
  77. saltext_gandi-0.1.0/src/saltext/gandi/runners/gandi_linkedzone.py +443 -0
  78. saltext_gandi-0.1.0/src/saltext/gandi/runners/gandi_livedns.py +971 -0
  79. saltext_gandi-0.1.0/src/saltext/gandi/runners/gandi_mod.py +176 -0
  80. saltext_gandi-0.1.0/src/saltext/gandi/states/__init__.py +0 -0
  81. saltext_gandi-0.1.0/src/saltext/gandi/states/gandi_domain.py +755 -0
  82. saltext_gandi-0.1.0/src/saltext/gandi/states/gandi_linkedzone.py +385 -0
  83. saltext_gandi-0.1.0/src/saltext/gandi/states/gandi_livedns.py +675 -0
  84. saltext_gandi-0.1.0/src/saltext/gandi/utils/__init__.py +0 -0
  85. saltext_gandi-0.1.0/src/saltext/gandi/utils/billing.py +97 -0
  86. saltext_gandi-0.1.0/src/saltext/gandi/utils/client.py +682 -0
  87. saltext_gandi-0.1.0/src/saltext/gandi/utils/domain.py +903 -0
  88. saltext_gandi-0.1.0/src/saltext/gandi/utils/linkedzone.py +371 -0
  89. saltext_gandi-0.1.0/src/saltext/gandi/utils/livedns.py +627 -0
  90. saltext_gandi-0.1.0/src/saltext/gandi/utils/profile.py +88 -0
  91. saltext_gandi-0.1.0/src/saltext/gandi/utils/resources.py +229 -0
  92. saltext_gandi-0.1.0/src/saltext/gandi/version.py +1 -0
  93. saltext_gandi-0.1.0/src/saltext.gandi.egg-info/PKG-INFO +182 -0
  94. saltext_gandi-0.1.0/src/saltext.gandi.egg-info/SOURCES.txt +149 -0
  95. saltext_gandi-0.1.0/src/saltext.gandi.egg-info/dependency_links.txt +1 -0
  96. saltext_gandi-0.1.0/src/saltext.gandi.egg-info/entry_points.txt +2 -0
  97. saltext_gandi-0.1.0/src/saltext.gandi.egg-info/not-zip-safe +1 -0
  98. saltext_gandi-0.1.0/src/saltext.gandi.egg-info/requires.txt +35 -0
  99. saltext_gandi-0.1.0/src/saltext.gandi.egg-info/scm_file_list.json +143 -0
  100. saltext_gandi-0.1.0/src/saltext.gandi.egg-info/scm_version.json +8 -0
  101. saltext_gandi-0.1.0/src/saltext.gandi.egg-info/top_level.txt +1 -0
  102. saltext_gandi-0.1.0/tests/__init__.py +0 -0
  103. saltext_gandi-0.1.0/tests/conftest.py +55 -0
  104. saltext_gandi-0.1.0/tests/functional/__init__.py +0 -0
  105. saltext_gandi-0.1.0/tests/functional/conftest.py +150 -0
  106. saltext_gandi-0.1.0/tests/functional/modules/__init__.py +0 -0
  107. saltext_gandi-0.1.0/tests/functional/modules/test_gandi.py +50 -0
  108. saltext_gandi-0.1.0/tests/functional/modules/test_gandi_billing.py +30 -0
  109. saltext_gandi-0.1.0/tests/functional/runners/__init__.py +0 -0
  110. saltext_gandi-0.1.0/tests/functional/states/__init__.py +0 -0
  111. saltext_gandi-0.1.0/tests/functional/states/test_gandi_domain.py +93 -0
  112. saltext_gandi-0.1.0/tests/functional/states/test_gandi_linkedzone.py +58 -0
  113. saltext_gandi-0.1.0/tests/functional/states/test_gandi_livedns.py +58 -0
  114. saltext_gandi-0.1.0/tests/integration/__init__.py +0 -0
  115. saltext_gandi-0.1.0/tests/integration/conftest.py +133 -0
  116. saltext_gandi-0.1.0/tests/integration/modules/__init__.py +0 -0
  117. saltext_gandi-0.1.0/tests/integration/modules/test_gandi.py +54 -0
  118. saltext_gandi-0.1.0/tests/integration/modules/test_gandi_billing.py +66 -0
  119. saltext_gandi-0.1.0/tests/integration/modules/test_gandi_domain.py +131 -0
  120. saltext_gandi-0.1.0/tests/integration/modules/test_gandi_linkedzone.py +111 -0
  121. saltext_gandi-0.1.0/tests/integration/modules/test_gandi_livedns.py +158 -0
  122. saltext_gandi-0.1.0/tests/integration/runners/__init__.py +0 -0
  123. saltext_gandi-0.1.0/tests/integration/states/__init__.py +0 -0
  124. saltext_gandi-0.1.0/tests/integration/states/test_gandi_livedns.py +188 -0
  125. saltext_gandi-0.1.0/tests/unit/__init__.py +0 -0
  126. saltext_gandi-0.1.0/tests/unit/conftest.py +86 -0
  127. saltext_gandi-0.1.0/tests/unit/modules/__init__.py +0 -0
  128. saltext_gandi-0.1.0/tests/unit/modules/test_gandi.py +103 -0
  129. saltext_gandi-0.1.0/tests/unit/runners/__init__.py +0 -0
  130. saltext_gandi-0.1.0/tests/unit/runners/test_gandi.py +61 -0
  131. saltext_gandi-0.1.0/tests/unit/states/__init__.py +0 -0
  132. saltext_gandi-0.1.0/tests/unit/states/test_gandi_domain.py +443 -0
  133. saltext_gandi-0.1.0/tests/unit/states/test_gandi_linkedzone.py +297 -0
  134. saltext_gandi-0.1.0/tests/unit/states/test_gandi_livedns.py +441 -0
  135. saltext_gandi-0.1.0/tests/unit/utils/__init__.py +0 -0
  136. saltext_gandi-0.1.0/tests/unit/utils/test_client.py +537 -0
  137. saltext_gandi-0.1.0/tests/unit/utils/test_domain.py +309 -0
  138. saltext_gandi-0.1.0/tests/unit/utils/test_linkedzone.py +255 -0
  139. saltext_gandi-0.1.0/tests/unit/utils/test_livedns.py +335 -0
  140. saltext_gandi-0.1.0/tests/unit/utils/test_profile.py +73 -0
  141. saltext_gandi-0.1.0/tools/gandi_docs.py +110 -0
  142. saltext_gandi-0.1.0/tools/helpers/__init__.py +0 -0
  143. saltext_gandi-0.1.0/tools/helpers/cmd.py +297 -0
  144. saltext_gandi-0.1.0/tools/helpers/copier.py +114 -0
  145. saltext_gandi-0.1.0/tools/helpers/git.py +30 -0
  146. saltext_gandi-0.1.0/tools/helpers/pre_commit.py +115 -0
  147. saltext_gandi-0.1.0/tools/helpers/prompt.py +54 -0
  148. saltext_gandi-0.1.0/tools/helpers/venv.py +128 -0
  149. saltext_gandi-0.1.0/tools/initialize.py +26 -0
  150. saltext_gandi-0.1.0/tools/verify_endpoints.py +109 -0
  151. saltext_gandi-0.1.0/tools/version.py +92 -0
@@ -0,0 +1,25 @@
1
+ ---
2
+ coverage:
3
+ status:
4
+ project:
5
+ default: false
6
+ app:
7
+ informational: true
8
+ paths:
9
+ - src/
10
+ tests:
11
+ informational: true
12
+ paths:
13
+ - tests/
14
+ patch:
15
+ default: false
16
+ app:
17
+ informational: true
18
+ paths:
19
+ - src/
20
+ tests:
21
+ informational: true
22
+ paths:
23
+ - tests/
24
+ github_checks:
25
+ annotations: false
@@ -0,0 +1,33 @@
1
+ # Autogenerated. Do not edit this by hand, use `copier update`.
2
+ ---
3
+ _commit: 0.10.0
4
+ _src_path: https://github.com/salt-extensions/salt-extension-copier
5
+ author: Gary T. Giesen
6
+ author_email: ggiesen@giesen.me
7
+ coc_contact: ggiesen@giesen.me
8
+ copyright_begin: 2026
9
+ docs_url: https://ggiesen.gitlab.io/saltext-gandi/
10
+ integration_name: Gandi
11
+ license: other
12
+ license_classifier: 'License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)'
13
+ loaders:
14
+ - module
15
+ - runner
16
+ - state
17
+ max_salt_version: '3008'
18
+ no_saltext_namespace: false
19
+ os_support:
20
+ - Linux
21
+ - macOS
22
+ - Windows
23
+ package_name: gandi
24
+ project_name: gandi
25
+ python_requires: '3.10'
26
+ relax_pylint: false
27
+ salt_version: '3006'
28
+ source_url: https://gitlab.com/ggiesen/saltext-gandi
29
+ ssh_fixtures: false
30
+ summary: Salt Extension for interacting with the Gandi.net API
31
+ test_containers: false
32
+ tracker_url: https://gitlab.com/ggiesen/saltext-gandi/-/issues
33
+ url: https://gitlab.com/ggiesen/saltext-gandi
@@ -0,0 +1,44 @@
1
+ [run]
2
+ branch = True
3
+ cover_pylib = False
4
+ relative_files = True
5
+ parallel = True
6
+ concurrency = multiprocessing
7
+
8
+ omit =
9
+ .nox/*
10
+ setup.py
11
+
12
+ [report]
13
+ # Regexes for lines to exclude from consideration
14
+ exclude_also =
15
+ # Don't complain about missing debug-only code:
16
+ def __repr__
17
+
18
+ # Don't complain if tests don't hit defensive assertion code:
19
+ raise AssertionError
20
+ raise NotImplementedError
21
+
22
+ # Don't complain if non-runnable code isn't run:
23
+ if 0:
24
+ if False:
25
+ if __name__ == .__main__.:
26
+ if TYPE_CHECKING:
27
+ @(abc\.)?abstractmethod
28
+
29
+ # Add markers which exclude statements in between.
30
+ # Requires coverage>=7.6.0.
31
+ no cover: start(?s:.)*?no cover: stop
32
+
33
+ omit =
34
+ .nox/*
35
+ setup.py
36
+
37
+ ignore_errors = True
38
+
39
+ [paths]
40
+ source =
41
+ saltext/gandi
42
+ src/saltext/gandi
43
+ testsuite =
44
+ tests/
@@ -0,0 +1,7 @@
1
+ layout_saltext() {
2
+ VIRTUAL_ENV="$(python3 tools/initialize.py --print-venv)"
3
+ PATH_add "$VIRTUAL_ENV/bin"
4
+ export VIRTUAL_ENV
5
+ }
6
+
7
+ layout_saltext
@@ -0,0 +1,136 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ pip-wheel-metadata/
24
+ share/python-wheels/
25
+ *.egg-info/
26
+ .installed.cfg
27
+ *.egg
28
+ MANIFEST
29
+
30
+ # PyInstaller
31
+ # Usually these files are written by a python script from a template
32
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
33
+ *.manifest
34
+ *.spec
35
+
36
+ # Installer logs
37
+ pip-log.txt
38
+ pip-delete-this-directory.txt
39
+
40
+ # Unit test / coverage reports
41
+ htmlcov/
42
+ .tox/
43
+ .nox/
44
+ .coverage
45
+ .coverage.*
46
+ .cache
47
+ nosetests.xml
48
+ coverage.xml
49
+ *.cover
50
+ *.py,cover
51
+ .hypothesis/
52
+ .pytest_cache/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ target/
76
+
77
+ # Jupyter Notebook
78
+ .ipynb_checkpoints
79
+
80
+ # IPython
81
+ profile_default/
82
+ ipython_config.py
83
+
84
+ # pyenv
85
+ .python-version
86
+
87
+ # pipenv
88
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
90
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
91
+ # install all needed dependencies.
92
+ #Pipfile.lock
93
+
94
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95
+ __pypackages__/
96
+
97
+ # Celery stuff
98
+ celerybeat-schedule
99
+ celerybeat.pid
100
+
101
+ # SageMath parsed files
102
+ *.sage.py
103
+
104
+ # Environments
105
+ !.envrc.example
106
+ .env
107
+ .venv
108
+ env/
109
+ venv/
110
+ ENV/
111
+ env.bak/
112
+ venv.bak/
113
+
114
+ # Spyder project settings
115
+ .spyderproject
116
+ .spyproject
117
+
118
+ # Rope project settings
119
+ .ropeproject
120
+
121
+ # mkdocs documentation
122
+ /site
123
+
124
+ # mypy
125
+ .mypy_cache/
126
+ .dmypy.json
127
+ dmypy.json
128
+
129
+ # Pyre type checker
130
+ .pyre/
131
+
132
+ # Ignore the setuptools_scm auto-generated version module
133
+ src/saltext/gandi/version.py
134
+
135
+ # Ignore CI generated artifacts
136
+ artifacts/
@@ -0,0 +1,16 @@
1
+ ## Description
2
+
3
+
4
+ ## Setup
5
+ (Salt version, extension version, master vs minion, which Gandi API, production
6
+ or sandbox)
7
+
8
+ ## Steps to reproduce
9
+
10
+
11
+ ## Expected vs actual
12
+
13
+
14
+ ## Trace-ID
15
+ (If the failure came back from the Gandi API, the error message includes a
16
+ `Trace-ID`. Paste it here -- Gandi support can look the request up by it.)
@@ -0,0 +1,4 @@
1
+ ## What
2
+
3
+
4
+ ## Why
@@ -0,0 +1,7 @@
1
+ ## What does this MR do?
2
+
3
+
4
+ ## Related issues
5
+
6
+
7
+ ## Tests
@@ -0,0 +1,199 @@
1
+ # GitLab CI for saltext-gandi.
2
+ #
3
+ # The salt-extension-copier template ships CI as GitHub Actions, which do not
4
+ # run on GitLab. This pipeline reproduces that matrix natively on GitLab:
5
+ # pre-commit lint, a nox test matrix across Salt/Python, a docs build, and
6
+ # GitLab Pages. Salt version is selected through the noxfile's SALT_REQUIREMENT
7
+ # environment variable (see noxfile.py).
8
+ #
9
+ # The matrix covers the two Salt majors upstream currently marks as supported
10
+ # LTS releases (3006 and 3008). 3007 is deliberately omitted: the copier
11
+ # template's own support data marks it `supported: false`. Python bounds per
12
+ # Salt major come from that same data -- 3006 tops out at 3.11, 3008 goes
13
+ # further, so the matrix is not a full cross product.
14
+
15
+ stages:
16
+ - lint
17
+ - test
18
+ - docs
19
+ - publish
20
+
21
+ variables:
22
+ PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
23
+
24
+ # No `cache:` here on purpose. The self-hosted runner has no [runners.cache]
25
+ # backend configured, so declaring one only produces
26
+ # "ERROR: Could not create cache adapter" on every job. Artifacts are unaffected;
27
+ # they go through GitLab.
28
+
29
+ .py-base:
30
+ before_script:
31
+ - python -m pip install --upgrade pip nox
32
+
33
+ pre-commit:
34
+ stage: lint
35
+ image: python:3.10
36
+ before_script:
37
+ - python -m pip install --upgrade pip pre-commit
38
+ script:
39
+ - pre-commit run --all-files --show-diff-on-failure --color always
40
+
41
+ .tests:
42
+ stage: test
43
+ extends: .py-base
44
+ # Unit and functional only. The integration tests talk to Gandi's sandbox and
45
+ # need credentials, so they get their own job that runs on a schedule.
46
+ script:
47
+ - nox --force-color -e tests-3 -- tests/unit tests/functional -vv --showlocals
48
+ coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/'
49
+ artifacts:
50
+ when: always
51
+ reports:
52
+ junit: artifacts/junit-report.xml
53
+ paths:
54
+ - artifacts/
55
+ expire_in: 2 weeks
56
+
57
+ tests-salt3006-py3.10:
58
+ extends: .tests
59
+ image: python:3.10
60
+ variables:
61
+ SALT_REQUIREMENT: "salt>=3006,<3007"
62
+ tests-salt3006-py3.11:
63
+ extends: .tests
64
+ image: python:3.11
65
+ variables:
66
+ SALT_REQUIREMENT: "salt>=3006,<3007"
67
+ tests-salt3008-py3.10:
68
+ extends: .tests
69
+ image: python:3.10
70
+ variables:
71
+ SALT_REQUIREMENT: "salt>=3008"
72
+ tests-salt3008-py3.12:
73
+ extends: .tests
74
+ image: python:3.12
75
+ variables:
76
+ SALT_REQUIREMENT: "salt>=3008"
77
+
78
+ # Check the endpoint table in src/saltext/gandi/utils/resources.py against
79
+ # Gandi's live documentation.
80
+ #
81
+ # Gandi publishes no OpenAPI or RAML document, so there is nothing to diff
82
+ # schemas against. What the docs do carry is a complete, machine-readable
83
+ # endpoint index: every operation gets an HTML anchor id of the form
84
+ # `#get-v5-livedns-domains-fqdn-records`. tools/verify_endpoints.py scrapes
85
+ # those and diffs them against the resource table, which catches endpoints
86
+ # added or withdrawn upstream.
87
+ #
88
+ # It cannot catch field-level drift -- that only surfaces at runtime, or in the
89
+ # sandbox integration job below.
90
+ #
91
+ # Scheduled rather than per-push: it depends on api.gandi.net being up, and a
92
+ # docs outage should not fail an unrelated merge request.
93
+ verify-endpoints:
94
+ stage: test
95
+ extends: .py-base
96
+ image: python:3.10
97
+ script:
98
+ - nox --force-color -e verify-endpoints
99
+ artifacts:
100
+ when: always
101
+ paths:
102
+ - endpoints-report.txt
103
+ expire_in: 2 weeks
104
+ rules:
105
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
106
+ - when: manual
107
+ allow_failure: true
108
+
109
+ # Integration tests against Gandi's sandbox (api.sandbox.gandi.net).
110
+ #
111
+ # Sandbox accounts are separate from production ones and are created at
112
+ # admin.sandbox.gandi.net; the token below is a sandbox personal access token,
113
+ # stored as a masked, protected CI variable. Nothing here can touch production:
114
+ # the profile hardcodes the sandbox base URL, and the job fails fast if
115
+ # GANDI_SANDBOX_TOKEN is unset rather than silently falling back.
116
+ #
117
+ # Scheduled only. These tests create and destroy real objects in the sandbox,
118
+ # and running them on every merge request would both slow the pipeline down and
119
+ # make the sandbox account's state depend on pipeline concurrency.
120
+ integration-sandbox:
121
+ stage: test
122
+ extends: .py-base
123
+ image: python:3.10
124
+ script:
125
+ - test -n "$GANDI_SANDBOX_TOKEN" || { echo "GANDI_SANDBOX_TOKEN is not set"; exit 1; }
126
+ - nox --force-color -e tests-3 -- tests/integration --run-destructive -vv
127
+ artifacts:
128
+ when: always
129
+ reports:
130
+ junit: artifacts/junit-report.xml
131
+ paths:
132
+ - artifacts/
133
+ expire_in: 2 weeks
134
+ rules:
135
+ - if: '$CI_PIPELINE_SOURCE == "schedule"'
136
+ - when: manual
137
+ allow_failure: true
138
+
139
+ .docs-base:
140
+ image: python:3.10
141
+ # sphinxcontrib-spelling wraps the enchant C library, which is not in the
142
+ # python images. Without it Sphinx aborts loading the extension.
143
+ before_script:
144
+ - apt-get update -qq
145
+ - apt-get install -y -qq libenchant-2-2 hunspell-en-us
146
+ - python -m pip install --upgrade pip nox
147
+
148
+ docs:
149
+ stage: docs
150
+ extends: .docs-base
151
+ script:
152
+ - nox --force-color -e docs
153
+ artifacts:
154
+ paths:
155
+ - docs/_build/html
156
+ expire_in: 2 weeks
157
+
158
+ pages:
159
+ stage: docs
160
+ extends: .docs-base
161
+ script:
162
+ - nox --force-color -e docs
163
+ - mv docs/_build/html public
164
+ artifacts:
165
+ paths:
166
+ - public
167
+ rules:
168
+ - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
169
+
170
+ # Publish to PyPI via Trusted Publishing (OIDC, no stored token).
171
+ #
172
+ # This is deliberately a MANUAL, tag-only job: nothing is published without an
173
+ # operator clicking "run", so tagging a release does not auto-fire an upload.
174
+ # It relies on a PyPI trusted publisher configured for this project with:
175
+ # namespace ggiesen / repo saltext-gandi / pipeline .gitlab-ci.yml /
176
+ # environment "release"
177
+ # The ``environment: release`` below MUST match that PyPI configuration, and the
178
+ # ``aud: pypi`` id_token is what twine exchanges for a short-lived PyPI token.
179
+ publish:
180
+ stage: publish
181
+ image: python:3.12
182
+ variables:
183
+ # setuptools_scm needs the full history and the tag object to derive a clean
184
+ # release version; the default shallow clone can yield a "+local" version.
185
+ GIT_DEPTH: "0"
186
+ id_tokens:
187
+ PYPI_ID_TOKEN:
188
+ aud: pypi
189
+ environment: release
190
+ before_script:
191
+ - python -m pip install --upgrade build twine
192
+ script:
193
+ - python -m build
194
+ - twine check dist/*
195
+ # No credentials passed: twine uses the PYPI_ID_TOKEN trusted-publishing flow.
196
+ - twine upload dist/*
197
+ rules:
198
+ - if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+/'
199
+ when: manual
@@ -0,0 +1,150 @@
1
+ ---
2
+ minimum_pre_commit_version: 2.4.0
3
+ repos:
4
+ - repo: https://github.com/pre-commit/pre-commit-hooks
5
+ rev: 3e8a8703264a2f4a69428a0aa4dcb512790b2c8c # v6.0.0
6
+ hooks:
7
+ - id: check-merge-conflict # Check for files that contain merge conflict strings.
8
+ args: [--assume-in-merge]
9
+ - id: trailing-whitespace # Trim trailing whitespace.
10
+ args: [--markdown-linebreak-ext=md]
11
+ - id: mixed-line-ending # Ensure files use UNIX-style newlines only.
12
+ args: [--fix=lf]
13
+ - id: end-of-file-fixer # Ensure files end with a newline.
14
+ - id: check-ast # Check whether files parse as valid Python.
15
+
16
+ # ----- Formatting ---------------------------------------------------------------------------->
17
+ - repo: https://github.com/saltstack/pre-commit-remove-import-headers
18
+ rev: e79f595c0df31b8cb152c53993ce7c3c64f07cd4 # 1.1.0
19
+ hooks:
20
+ - id: remove-import-headers
21
+
22
+ - repo: local
23
+ hooks:
24
+ - id: check-cli-examples
25
+ name: Check CLI examples on execution modules
26
+ entry: python .pre-commit-hooks/check-cli-examples.py
27
+ language: python
28
+ files: ^src/saltext/gandi/modules/.*\.py$
29
+
30
+ - repo: local
31
+ hooks:
32
+ - id: check-gitlab-ci
33
+ name: Check .gitlab-ci.yml references resolve
34
+ entry: python .pre-commit-hooks/check-gitlab-ci.py
35
+ language: python
36
+ # `language: system` would rely on a `python` on PATH, which is not
37
+ # guaranteed -- pre-commit invoked from the venv does not put one there.
38
+ additional_dependencies:
39
+ - PyYAML
40
+ files: ^\.gitlab-ci\.yml$
41
+ pass_filenames: false
42
+
43
+ - id: check-docs
44
+ name: Check rST doc files exist for modules/states
45
+ entry: python .pre-commit-hooks/make-autodocs.py
46
+ language: python
47
+ pass_filenames: false
48
+
49
+ - repo: https://github.com/saltstack/salt-rewrite
50
+ # Automatically rewrite code with known rules
51
+ rev: 2401c0faef69b6b846c719d611bcfe358234d5d1 # 2.5.2
52
+ hooks:
53
+ - id: salt-rewrite
54
+ alias: rewrite-docstrings
55
+ name: Salt extensions docstrings auto-fixes
56
+ files: ^src/saltext/gandi/.*\.py$
57
+ args: [--silent]
58
+
59
+ - repo: https://github.com/saltstack/salt-rewrite
60
+ # Automatically rewrite code with known rules
61
+ rev: 2401c0faef69b6b846c719d611bcfe358234d5d1 # 2.5.2
62
+ hooks:
63
+ - id: salt-rewrite
64
+ alias: rewrite-tests
65
+ name: Rewrite the test suite
66
+ files: ^tests/.*\.py$
67
+ args: [--silent, -E, fix_docstrings]
68
+
69
+ - repo: https://github.com/asottile/pyupgrade
70
+ rev: 75992aaa40730136014f34227e0135f63fc951b4 # v3.21.2
71
+ hooks:
72
+ - id: pyupgrade
73
+ name: Rewrite Code to be Py3.10+
74
+ args: [
75
+ --py310-plus,
76
+ ]
77
+ exclude: src/saltext/gandi/version.py
78
+
79
+ - repo: https://github.com/PyCQA/isort
80
+ rev: a333737ed43df02b18e6c95477ea1b285b3de15a # 8.0.1
81
+ hooks:
82
+ - id: isort
83
+ args: [
84
+ --py 310,
85
+ ]
86
+ exclude: src/saltext/gandi/(__init__|version).py
87
+
88
+ - repo: https://github.com/psf/black
89
+ rev: 87928e6d6761a4a6d22250e1fee5601b3998086e # 26.5.1
90
+ hooks:
91
+ - id: black
92
+ args: [-l 100]
93
+ exclude: src/saltext/gandi/version.py
94
+
95
+ - repo: https://github.com/adamchainz/blacken-docs
96
+ rev: fda77690955e9b63c6687d8806bafd56a526e45f # 1.20.0
97
+ hooks:
98
+ - id: blacken-docs
99
+ args: [--skip-errors]
100
+ files: ^(docs/.*\.rst|src/saltext/gandi/.*\.py)$
101
+ additional_dependencies:
102
+ - black==26.5.1
103
+ # <---- Formatting -----------------------------------------------------------------------------
104
+
105
+ # ----- Security ------------------------------------------------------------------------------>
106
+ - repo: https://github.com/PyCQA/bandit
107
+ rev: 92ae8b82fb422a639f0ed8d99e96cea769594e08 # 1.9.4
108
+ hooks:
109
+ - id: bandit
110
+ alias: bandit-salt
111
+ name: Run bandit against the code base
112
+ args: [--silent, -lll, --skip, B701]
113
+ exclude: src/saltext/gandi/version.py
114
+
115
+ - repo: https://github.com/PyCQA/bandit
116
+ rev: 92ae8b82fb422a639f0ed8d99e96cea769594e08 # 1.9.4
117
+ hooks:
118
+ - id: bandit
119
+ alias: bandit-tests
120
+ name: Run bandit against the test suite
121
+ args: [--silent, -lll, --skip, B701]
122
+ files: ^tests/.*
123
+ # <---- Security -------------------------------------------------------------------------------
124
+
125
+ # ----- Code Analysis ------------------------------------------------------------------------->
126
+
127
+ - repo: local
128
+ hooks:
129
+ - id: nox
130
+ alias: lint-src
131
+ name: Lint Source Code
132
+ language: python
133
+ entry: nox -e lint-code-pre-commit --
134
+ files: ^((setup|noxfile)|src/.*)\.py$
135
+ require_serial: true
136
+ additional_dependencies:
137
+ - nox==2026.4.10
138
+ - uv==0.11.26 # Makes this hook much faster
139
+
140
+ - id: nox
141
+ alias: lint-tests
142
+ name: Lint Tests
143
+ language: python
144
+ entry: nox -e lint-tests-pre-commit --
145
+ files: ^tests/.*\.py$
146
+ require_serial: true
147
+ additional_dependencies:
148
+ - nox==2026.4.10
149
+ - uv==0.11.26 # Makes this hook much faster
150
+ # <---- Code Analysis --------------------------------------------------------------------------
@@ -0,0 +1,64 @@
1
+ import ast
2
+ import pathlib
3
+ import re
4
+ import sys
5
+
6
+ CODE_ROOT = pathlib.Path(__file__).resolve().parent.parent
7
+ EXECUTION_MODULES_PATH = CODE_ROOT / "src" / "saltext" / "gandi" / "modules"
8
+
9
+
10
+ def check_cli_examples(files):
11
+ """
12
+ Check that every function on every execution module provides a CLI example
13
+ """
14
+ errors = 0
15
+ for file in files:
16
+ path = pathlib.Path(file).resolve()
17
+ try:
18
+ relpath = path.relative_to(EXECUTION_MODULES_PATH)
19
+ if str(relpath.parent) != ".":
20
+ # We don't want to check nested packages
21
+ continue
22
+ except ValueError:
23
+ # We're only interested in execution modules
24
+ continue
25
+ module = ast.parse(path.read_text(), filename=str(path))
26
+ for funcdef in [node for node in module.body if isinstance(node, ast.FunctionDef)]:
27
+ if funcdef.name.startswith("_"):
28
+ # We're not interested in internal functions
29
+ continue
30
+
31
+ docstring = ast.get_docstring(funcdef, clean=False)
32
+ if not docstring:
33
+ errors += 1
34
+ print(
35
+ "The function {!r} on '{}' does not have a docstring".format(
36
+ funcdef.name,
37
+ path.relative_to(CODE_ROOT),
38
+ ),
39
+ file=sys.stderr,
40
+ )
41
+ continue
42
+
43
+ if _check_cli_example_present(docstring) is False:
44
+ errors += 1
45
+ print(
46
+ "The function {!r} on '{}' does not have a 'CLI Example:' in it's docstring".format(
47
+ funcdef.name,
48
+ path.relative_to(CODE_ROOT),
49
+ ),
50
+ file=sys.stderr,
51
+ )
52
+ continue
53
+ sys.exit(errors)
54
+
55
+
56
+ CLI_EXAMPLE_PRESENT_RE = re.compile(r"CLI Example(?:s)?:")
57
+
58
+
59
+ def _check_cli_example_present(docstring):
60
+ return CLI_EXAMPLE_PRESENT_RE.search(docstring) is not None
61
+
62
+
63
+ if __name__ == "__main__":
64
+ check_cli_examples(sys.argv[1:])