gitlab-cicd-python-wrapper 0.1.0__py3-none-any.whl
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.
- gitlab_cicd_python_wrapper/__init__.py +99 -0
- gitlab_cicd_python_wrapper/_async.py +50 -0
- gitlab_cicd_python_wrapper/artifacts.py +40 -0
- gitlab_cicd_python_wrapper/cache.py +25 -0
- gitlab_cicd_python_wrapper/cli.py +69 -0
- gitlab_cicd_python_wrapper/common.py +87 -0
- gitlab_cicd_python_wrapper/component.py +148 -0
- gitlab_cicd_python_wrapper/environment.py +22 -0
- gitlab_cicd_python_wrapper/globals.py +44 -0
- gitlab_cicd_python_wrapper/image.py +22 -0
- gitlab_cicd_python_wrapper/include.py +75 -0
- gitlab_cicd_python_wrapper/job.py +96 -0
- gitlab_cicd_python_wrapper/needs.py +19 -0
- gitlab_cicd_python_wrapper/pages.py +10 -0
- gitlab_cicd_python_wrapper/pipeline.py +102 -0
- gitlab_cicd_python_wrapper/py.typed +0 -0
- gitlab_cicd_python_wrapper/release.py +14 -0
- gitlab_cicd_python_wrapper/retry.py +12 -0
- gitlab_cicd_python_wrapper/rules.py +28 -0
- gitlab_cicd_python_wrapper/secrets.py +24 -0
- gitlab_cicd_python_wrapper/serialization.py +64 -0
- gitlab_cicd_python_wrapper/spec.py +55 -0
- gitlab_cicd_python_wrapper/trigger.py +23 -0
- gitlab_cicd_python_wrapper/variables.py +12 -0
- gitlab_cicd_python_wrapper-0.1.0.dist-info/METADATA +262 -0
- gitlab_cicd_python_wrapper-0.1.0.dist-info/RECORD +28 -0
- gitlab_cicd_python_wrapper-0.1.0.dist-info/WHEEL +4 -0
- gitlab_cicd_python_wrapper-0.1.0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gitlab-cicd-python-wrapper
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Pydantic models wrapping GitLab CI/CD YAML with 1:1 mapping
|
|
5
|
+
License: MIT
|
|
6
|
+
Author: Szymon Richert
|
|
7
|
+
Author-email: szymon.rychu@gmail.com
|
|
8
|
+
Requires-Python: >=3.11,<4.0
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
15
|
+
Requires-Dist: aiofiles (>=24.0,<25.0)
|
|
16
|
+
Requires-Dist: pydantic (>=2.0,<3.0)
|
|
17
|
+
Requires-Dist: ruamel.yaml (>=0.18,<0.19)
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# Gitlab CICD Python Wrapper
|
|
21
|
+
|
|
22
|
+
Pydantic models wrapping every GitLab CI/CD YAML keyword with 1:1 mapping to
|
|
23
|
+
[GitLab CI/CD YAML reference](https://docs.gitlab.com/ci/yaml/).
|
|
24
|
+
|
|
25
|
+
## Features
|
|
26
|
+
|
|
27
|
+
- Programmatic pipeline generation using Python-native objects
|
|
28
|
+
- Validation framework for existing pipelines
|
|
29
|
+
- Comment-preserving round-trip serialization (load -> validate -> write = identical YAML)
|
|
30
|
+
- GitLab CI/CD Component parsing with input validation
|
|
31
|
+
- Both sync and async APIs
|
|
32
|
+
- CLI validator and pre-commit hook
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install gitlab-cicd-python-wrapper
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Or with Poetry:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
poetry add gitlab-cicd-python-wrapper
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Compatibility Matrix
|
|
47
|
+
|
|
48
|
+
| GitLab Version | Pipeline Coverage | Component Coverage | Notes |
|
|
49
|
+
|----------------|-------------------|-------------------|-------|
|
|
50
|
+
| 17.x | Full | Full | All keywords as of 17.9 |
|
|
51
|
+
| 16.x | Full | Partial | Components GA in 17.0 |
|
|
52
|
+
| 15.x | Partial | N/A | Deprecated keywords still accepted |
|
|
53
|
+
|
|
54
|
+
## Quick Start
|
|
55
|
+
|
|
56
|
+
### Generate a Pipeline
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from gitlab_cicd_python_wrapper import Pipeline, Job, Image, Artifacts
|
|
60
|
+
|
|
61
|
+
pipeline = Pipeline(
|
|
62
|
+
stages=["build", "test", "deploy"],
|
|
63
|
+
jobs={
|
|
64
|
+
"build": Job(
|
|
65
|
+
stage="build",
|
|
66
|
+
image=Image(name="python:3.11"),
|
|
67
|
+
script=["pip install -r requirements.txt", "python setup.py build"],
|
|
68
|
+
artifacts=Artifacts(paths=["dist/"]),
|
|
69
|
+
),
|
|
70
|
+
"test": Job(
|
|
71
|
+
stage="test",
|
|
72
|
+
script=["pytest"],
|
|
73
|
+
needs=["build"],
|
|
74
|
+
),
|
|
75
|
+
},
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
print(pipeline.to_yaml())
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Validate an Existing Pipeline
|
|
82
|
+
|
|
83
|
+
```python
|
|
84
|
+
from gitlab_cicd_python_wrapper import Pipeline
|
|
85
|
+
|
|
86
|
+
# Load and validate
|
|
87
|
+
pipeline = Pipeline.from_yaml(".gitlab-ci.yml")
|
|
88
|
+
print(f"Stages: {pipeline.stages}")
|
|
89
|
+
print(f"Jobs: {list(pipeline.jobs.keys())}")
|
|
90
|
+
|
|
91
|
+
# Validate without loading
|
|
92
|
+
errors = Pipeline.validate_file(".gitlab-ci.yml")
|
|
93
|
+
if errors:
|
|
94
|
+
for err in errors:
|
|
95
|
+
print(f"Error: {err}")
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Round-Trip Editing (Comments Preserved)
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from gitlab_cicd_python_wrapper import Pipeline
|
|
102
|
+
|
|
103
|
+
# Load -> modify -> save preserves comments and formatting
|
|
104
|
+
pipeline = Pipeline.from_yaml(".gitlab-ci.yml")
|
|
105
|
+
pipeline.to_yaml("validated-output.yml")
|
|
106
|
+
# Output is byte-identical to input for unmodified pipelines
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## CLI Validator
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Validate pipeline files
|
|
113
|
+
gitlab-cicd-validate .gitlab-ci.yml
|
|
114
|
+
|
|
115
|
+
# Validate multiple files
|
|
116
|
+
gitlab-cicd-validate .gitlab-ci.yml .gitlab/ci/*.yml
|
|
117
|
+
|
|
118
|
+
# Validate component templates
|
|
119
|
+
gitlab-cicd-validate --component templates/build.yml
|
|
120
|
+
|
|
121
|
+
# JSON output
|
|
122
|
+
gitlab-cicd-validate --format json .gitlab-ci.yml
|
|
123
|
+
|
|
124
|
+
# Strict mode (fail on warnings)
|
|
125
|
+
gitlab-cicd-validate --strict .gitlab-ci.yml
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Pre-commit Hook
|
|
129
|
+
|
|
130
|
+
Add to your `.pre-commit-config.yaml`:
|
|
131
|
+
|
|
132
|
+
```yaml
|
|
133
|
+
repos:
|
|
134
|
+
- repo: https://github.com/szymonrychu/gitlab-cicd-python-wrapper
|
|
135
|
+
rev: v0.1.0
|
|
136
|
+
hooks:
|
|
137
|
+
- id: gitlab-cicd-validate
|
|
138
|
+
args: ['--strict']
|
|
139
|
+
- id: gitlab-cicd-validate-components
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
This validates `.gitlab-ci.yml` and any YAML files under `.gitlab/ci/` automatically,
|
|
143
|
+
plus component templates under `templates/`.
|
|
144
|
+
|
|
145
|
+
## Component Parsing
|
|
146
|
+
|
|
147
|
+
Parse and validate GitLab CI/CD components with input validation:
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from gitlab_cicd_python_wrapper import Component
|
|
151
|
+
|
|
152
|
+
# Load a component template
|
|
153
|
+
component = Component.from_yaml("templates/deploy.yml")
|
|
154
|
+
|
|
155
|
+
# Inspect the spec
|
|
156
|
+
for name, input_def in component.spec.inputs.items():
|
|
157
|
+
print(f"{name}: type={input_def.type}, default={input_def.default}")
|
|
158
|
+
|
|
159
|
+
# Validate inputs (raises ValueError on failure)
|
|
160
|
+
resolved = component.validate_inputs({
|
|
161
|
+
"stage": "deploy",
|
|
162
|
+
"environment": "production",
|
|
163
|
+
"timeout": 3600,
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
# Render with inputs interpolated (returns a Pipeline)
|
|
167
|
+
pipeline = component.render({
|
|
168
|
+
"stage": "deploy",
|
|
169
|
+
"environment": "production",
|
|
170
|
+
"timeout": 3600,
|
|
171
|
+
})
|
|
172
|
+
print(pipeline.to_yaml())
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Dynamic Child Pipelines
|
|
176
|
+
|
|
177
|
+
Generate pipelines dynamically for use with `trigger:include`:
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
from gitlab_cicd_python_wrapper import Pipeline, Job
|
|
181
|
+
|
|
182
|
+
services = ["api", "web", "worker"]
|
|
183
|
+
|
|
184
|
+
jobs = {}
|
|
185
|
+
for svc in services:
|
|
186
|
+
jobs[f"build-{svc}"] = Job(
|
|
187
|
+
stage="build",
|
|
188
|
+
image="docker:latest",
|
|
189
|
+
script=[f"docker build -t {svc} services/{svc}/"],
|
|
190
|
+
tags=["docker"],
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
child = Pipeline(stages=["build"], jobs=jobs)
|
|
194
|
+
child.to_yaml("generated-pipeline.yml")
|
|
195
|
+
|
|
196
|
+
# Parent pipeline triggers it:
|
|
197
|
+
# trigger:
|
|
198
|
+
# include:
|
|
199
|
+
# - artifact: generated-pipeline.yml
|
|
200
|
+
# job: generate-pipeline
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Async API
|
|
204
|
+
|
|
205
|
+
```python
|
|
206
|
+
import asyncio
|
|
207
|
+
from gitlab_cicd_python_wrapper import AsyncPipeline, AsyncComponent
|
|
208
|
+
|
|
209
|
+
async def main():
|
|
210
|
+
# Pipeline
|
|
211
|
+
pipeline = await AsyncPipeline.from_yaml(".gitlab-ci.yml")
|
|
212
|
+
print(f"Stages: {pipeline.stages}")
|
|
213
|
+
print(f"Jobs: {list(pipeline.jobs.keys())}")
|
|
214
|
+
await AsyncPipeline.to_yaml(pipeline, "validated-output.yml")
|
|
215
|
+
|
|
216
|
+
# Component
|
|
217
|
+
component = await AsyncComponent.from_yaml("templates/build.yml")
|
|
218
|
+
resolved = component.validate_inputs({"image": "python:3.12"})
|
|
219
|
+
|
|
220
|
+
asyncio.run(main())
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Docker
|
|
224
|
+
|
|
225
|
+
Run the validator as a container:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
docker run --rm -v $(pwd):/data szymonrychu/gitlab-cicd-python-wrapper /data/.gitlab-ci.yml
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## PyPI Configuration
|
|
232
|
+
|
|
233
|
+
To publish this library to PyPI using GitHub Actions trusted publishing:
|
|
234
|
+
|
|
235
|
+
1. Create an account at [pypi.org](https://pypi.org)
|
|
236
|
+
2. Go to "Your projects" -> "Publishing" -> "Add a new pending publisher"
|
|
237
|
+
3. Set: GitHub owner=`szymonrychu`, repo=`gitlab-cicd-python-wrapper`,
|
|
238
|
+
workflow=`pypi.yaml`, environment=`pypi`
|
|
239
|
+
4. Create a GitHub environment named `pypi` in your repo settings
|
|
240
|
+
5. Push a semantic version tag (e.g., `v0.1.0`) to trigger the publish workflow
|
|
241
|
+
|
|
242
|
+
## Development
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
# Install dependencies
|
|
246
|
+
mise install
|
|
247
|
+
poetry install
|
|
248
|
+
|
|
249
|
+
# Run tests
|
|
250
|
+
poetry run pytest
|
|
251
|
+
|
|
252
|
+
# Run linters
|
|
253
|
+
pre-commit run --all-files
|
|
254
|
+
|
|
255
|
+
# Run CLI
|
|
256
|
+
poetry run gitlab-cicd-validate .gitlab-ci.yml
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## License
|
|
260
|
+
|
|
261
|
+
MIT
|
|
262
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
gitlab_cicd_python_wrapper/__init__.py,sha256=izJGQLQYfNwlhT4CfQj2PkyaMyxPer_qJxGWsAqov4o,2729
|
|
2
|
+
gitlab_cicd_python_wrapper/_async.py,sha256=4utMoYEjSw0hY0VLXggM-w8M_A2ZM7NylUDkFzNSj1Q,1640
|
|
3
|
+
gitlab_cicd_python_wrapper/artifacts.py,sha256=9iHV_3x-auI5JOyBP1rxi829xxOIVJfL0CefpeqIrCs,1413
|
|
4
|
+
gitlab_cicd_python_wrapper/cache.py,sha256=hh176DIj5_Ybt1wZyQvLWKxaDpo3we39FxpclOjgpbo,708
|
|
5
|
+
gitlab_cicd_python_wrapper/cli.py,sha256=vLppAfcDCp2MscCgkgG89A-ZDAEnBJ0GqTkiqRFY_uM,2283
|
|
6
|
+
gitlab_cicd_python_wrapper/common.py,sha256=sS2MWShEiFj0_HOKCEOy4jOY1-nedmfo74U61CcGyx4,1964
|
|
7
|
+
gitlab_cicd_python_wrapper/component.py,sha256=6QGTFpndL-cZ3I-Zkmly6mKzG-UUI5u0UqgcIQ8Rukc,5518
|
|
8
|
+
gitlab_cicd_python_wrapper/environment.py,sha256=OJlIJizqFFZCTcidGvkadxQeQd2RbWxoKjUAowDeig8,630
|
|
9
|
+
gitlab_cicd_python_wrapper/globals.py,sha256=9TSMuwNCZEH49DAYsfcP289FjyHMsql86iQCE9iipyI,1452
|
|
10
|
+
gitlab_cicd_python_wrapper/image.py,sha256=ZRN5-x59O3vdq8gjra24ySAZBqazRhZqEQnrHtuM0t4,579
|
|
11
|
+
gitlab_cicd_python_wrapper/include.py,sha256=yw9Z5elalYbDR0i6-rSvseSh4mbglssJ_h19tLoK4aA,1910
|
|
12
|
+
gitlab_cicd_python_wrapper/job.py,sha256=u7M6tZYr7NwjSA3jqyPbHn7zzbuk_-bkaKZigaCWAbE,3257
|
|
13
|
+
gitlab_cicd_python_wrapper/needs.py,sha256=srle4kFGF2qKLLWJ3yxZpwIrjk4_9tq0d2RTL5Kv-wQ,423
|
|
14
|
+
gitlab_cicd_python_wrapper/pages.py,sha256=bTnMPDhmxEgpiVP4Ugq7Y5xwWYaX8pdkkV5jMUbzp-k,239
|
|
15
|
+
gitlab_cicd_python_wrapper/pipeline.py,sha256=UN5mByMH27gxmFt1pCXgFUFfVD_OgdopuWy46Hx8RdY,3146
|
|
16
|
+
gitlab_cicd_python_wrapper/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
+
gitlab_cicd_python_wrapper/release.py,sha256=T62NekMPNtBq83_-HQF46xj23Zv9YWHG6qgGqco5b-0,346
|
|
18
|
+
gitlab_cicd_python_wrapper/retry.py,sha256=9a8C7KcBdXDmhE6_to3cVCiS64dgS71h_gjD4VLd6pI,312
|
|
19
|
+
gitlab_cicd_python_wrapper/rules.py,sha256=Oeb38l_V13UCsodGqjIfou1kyQJ26bV46ilL9BQ0lDs,853
|
|
20
|
+
gitlab_cicd_python_wrapper/secrets.py,sha256=XQfloQmdkIsJfMRjG7Ebayy4z0rWiOT1ILc0gQQqAR8,484
|
|
21
|
+
gitlab_cicd_python_wrapper/serialization.py,sha256=uarKZy2CTYpiM9zsZjw87mxvRd-9dpn1wzQ3BlECrL4,1610
|
|
22
|
+
gitlab_cicd_python_wrapper/spec.py,sha256=QFtpzSpulzHs8OD3mDcaGGXd2WBT-DinPV3Tbf9Hf_w,1960
|
|
23
|
+
gitlab_cicd_python_wrapper/trigger.py,sha256=6_aFJ-dJJxT3of8GskHkfdzRc4xbCiFxDQe7cpDBqOg,612
|
|
24
|
+
gitlab_cicd_python_wrapper/variables.py,sha256=3gGqgeNpEJXVIC_LqJe0JBYdj2lQzhTNdOF1n3G3uHY,296
|
|
25
|
+
gitlab_cicd_python_wrapper-0.1.0.dist-info/METADATA,sha256=_ui1FIF7UqQu-yEgG2_B0elFCPeElDUrJpCOEJNsCnQ,6653
|
|
26
|
+
gitlab_cicd_python_wrapper-0.1.0.dist-info/WHEEL,sha256=Vz2fHgx6HFtSwhs8KvkHLqH5Ea4w1_rner5uNVGCeIE,88
|
|
27
|
+
gitlab_cicd_python_wrapper-0.1.0.dist-info/entry_points.txt,sha256=7NbmwUr5FV_UzfkTARFO7g9BaOBbUu9_wM7InnynvM8,76
|
|
28
|
+
gitlab_cicd_python_wrapper-0.1.0.dist-info/RECORD,,
|