gitlab-ci-verify 0.0.10__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.
@@ -0,0 +1,3 @@
1
+ .venv
2
+ *.egg-info
3
+ build/
@@ -0,0 +1,222 @@
1
+ Metadata-Version: 2.1
2
+ Name: gitlab-ci-verify
3
+ Version: 0.0.10
4
+ Summary: Validate and lint your gitlab ci files using ShellCheck, the Gitlab API and curated checks
5
+ Author-email: Timo Reymann <mail@timo-reymann.de>
6
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
7
+ Classifier: Development Status :: 2 - Pre-Alpha
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.9
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Intended Audience :: Developers
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: gitlab-ci-verify-bin==0.*
16
+ Provides-Extra: dev
17
+ Requires-Dist: setuptools==70.*; extra == "dev"
18
+ Requires-Dist: setuptools-scm==8.*; extra == "dev"
19
+ Requires-Dist: twine==5.1.*; extra == "dev"
20
+ Requires-Dist: wheel==0.43.*; extra == "dev"
21
+ Requires-Dist: pydoctor==24.3.*; extra == "dev"
22
+ Requires-Dist: build==1.*; extra == "dev"
23
+
24
+ [IN IMPLEMENTATION] gitlab-ci-verify
25
+ ===
26
+ [![GitHub Release](https://img.shields.io/github/v/release/timo-reymann/gitlab-ci-verify?label=version)](https://github.com/timo-reymann/gitlab-ci-verify/releases/latest)
27
+ [![CircleCI](https://dl.circleci.com/status-badge/img/gh/timo-reymann/gitlab-ci-verify/tree/main.svg?style=shield)](https://dl.circleci.com/status-badge/redirect/gh/timo-reymann/gitlab-ci-verify/tree/main)
28
+ [![codecov](https://codecov.io/gh/timo-reymann/gitlab-ci-verify/graph/badge.svg?token=4tYXDueu5D)](https://codecov.io/gh/timo-reymann/gitlab-ci-verify)
29
+ [![Renovate](https://img.shields.io/badge/renovate-enabled-green?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNjkgMzY5Ij48Y2lyY2xlIGN4PSIxODkuOSIgY3k9IjE5MC4yIiByPSIxODQuNSIgZmlsbD0iI2ZmZTQyZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTUgLTYpIi8+PHBhdGggZmlsbD0iIzhiYjViNSIgZD0iTTI1MSAyNTZsLTM4LTM4YTE3IDE3IDAgMDEwLTI0bDU2LTU2YzItMiAyLTYgMC03bC0yMC0yMWE1IDUgMCAwMC03IDBsLTEzIDEyLTktOCAxMy0xM2ExNyAxNyAwIDAxMjQgMGwyMSAyMWM3IDcgNyAxNyAwIDI0bC01NiA1N2E1IDUgMCAwMDAgN2wzOCAzOHoiLz48cGF0aCBmaWxsPSIjZDk1NjEyIiBkPSJNMzAwIDI4OGwtOCA4Yy00IDQtMTEgNC0xNiAwbC00Ni00NmMtNS01LTUtMTIgMC0xNmw4LThjNC00IDExLTQgMTUgMGw0NyA0N2M0IDQgNCAxMSAwIDE1eiIvPjxwYXRoIGZpbGw9IiMyNGJmYmUiIGQ9Ik04MSAxODVsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzI1YzRjMyIgZD0iTTIyMCAxMDBsMjMgMjNjNCA0IDQgMTEgMCAxNkwxNDIgMjQwYy00IDQtMTEgNC0xNSAwbC0yNC0yNGMtNC00LTQtMTEgMC0xNWwxMDEtMTAxYzUtNSAxMi01IDE2IDB6Ii8+PHBhdGggZmlsbD0iIzFkZGVkZCIgZD0iTTk5IDE2N2wxOC0xOCAxOCAxOC0xOCAxOHoiLz48cGF0aCBmaWxsPSIjMDBhZmIzIiBkPSJNMjMwIDExMGwxMyAxM2M0IDQgNCAxMSAwIDE2TDE0MiAyNDBjLTQgNC0xMSA0LTE1IDBsLTEzLTEzYzQgNCAxMSA0IDE1IDBsMTAxLTEwMWM1LTUgNS0xMSAwLTE2eiIvPjxwYXRoIGZpbGw9IiMyNGJmYmUiIGQ9Ik0xMTYgMTQ5bDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMxZGRlZGQiIGQ9Ik0xMzQgMTMxbDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMxYmNmY2UiIGQ9Ik0xNTIgMTEzbDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMyNGJmYmUiIGQ9Ik0xNzAgOTVsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzFiY2ZjZSIgZD0iTTYzIDE2N2wxOC0xOCAxOCAxOC0xOCAxOHpNOTggMTMxbDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMzNGVkZWIiIGQ9Ik0xMzQgOTVsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzFiY2ZjZSIgZD0iTTE1MyA3OGwxOC0xOCAxOCAxOC0xOCAxOHoiLz48cGF0aCBmaWxsPSIjMzRlZGViIiBkPSJNODAgMTEzbDE4LTE3IDE4IDE3LTE4IDE4ek0xMzUgNjBsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzk4ZWRlYiIgZD0iTTI3IDEzMWwxOC0xOCAxOCAxOC0xOCAxOHoiLz48cGF0aCBmaWxsPSIjYjUzZTAyIiBkPSJNMjg1IDI1OGw3IDdjNCA0IDQgMTEgMCAxNWwtOCA4Yy00IDQtMTEgNC0xNiAwbC02LTdjNCA1IDExIDUgMTUgMGw4LTdjNC01IDQtMTIgMC0xNnoiLz48cGF0aCBmaWxsPSIjOThlZGViIiBkPSJNODEgNzhsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzAwYTNhMiIgZD0iTTIzNSAxMTVsOCA4YzQgNCA0IDExIDAgMTZMMTQyIDI0MGMtNCA0LTExIDQtMTUgMGwtOS05YzUgNSAxMiA1IDE2IDBsMTAxLTEwMWM0LTQgNC0xMSAwLTE1eiIvPjxwYXRoIGZpbGw9IiMzOWQ5ZDgiIGQ9Ik0yMjggMTA4bC04LThjLTQtNS0xMS01LTE2IDBMMTAzIDIwMWMtNCA0LTQgMTEgMCAxNWw4IDhjLTQtNC00LTExIDAtMTVsMTAxLTEwMWM1LTQgMTItNCAxNiAweiIvPjxwYXRoIGZpbGw9IiNhMzM5MDQiIGQ9Ik0yOTEgMjY0bDggOGM0IDQgNCAxMSAwIDE2bC04IDdjLTQgNS0xMSA1LTE1IDBsLTktOGM1IDUgMTIgNSAxNiAwbDgtOGM0LTQgNC0xMSAwLTE1eiIvPjxwYXRoIGZpbGw9IiNlYjZlMmQiIGQ9Ik0yNjAgMjMzbC00LTRjLTYtNi0xNy02LTIzIDAtNyA3LTcgMTcgMCAyNGw0IDRjLTQtNS00LTExIDAtMTZsOC04YzQtNCAxMS00IDE1IDB6Ii8+PHBhdGggZmlsbD0iIzEzYWNiZCIgZD0iTTEzNCAyNDhjLTQgMC04LTItMTEtNWwtMjMtMjNhMTYgMTYgMCAwMTAtMjNMMjAxIDk2YTE2IDE2IDAgMDEyMiAwbDI0IDI0YzYgNiA2IDE2IDAgMjJMMTQ2IDI0M2MtMyAzLTcgNS0xMiA1em03OC0xNDdsLTQgMi0xMDEgMTAxYTYgNiAwIDAwMCA5bDIzIDIzYTYgNiAwIDAwOSAwbDEwMS0xMDFhNiA2IDAgMDAwLTlsLTI0LTIzLTQtMnoiLz48cGF0aCBmaWxsPSIjYmY0NDA0IiBkPSJNMjg0IDMwNGMtNCAwLTgtMS0xMS00bC00Ny00N2MtNi02LTYtMTYgMC0yMmw4LThjNi02IDE2LTYgMjIgMGw0NyA0NmM2IDcgNiAxNyAwIDIzbC04IDhjLTMgMy03IDQtMTEgNHptLTM5LTc2Yy0xIDAtMyAwLTQgMmwtOCA3Yy0yIDMtMiA3IDAgOWw0NyA0N2E2IDYgMCAwMDkgMGw3LThjMy0yIDMtNiAwLTlsLTQ2LTQ2Yy0yLTItMy0yLTUtMnoiLz48L3N2Zz4=)](https://renovatebot.com)
30
+ [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=timo-reymann_gitlab-ci-verify&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=timo-reymann_gitlab-ci-verify)
31
+ [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=timo-reymann_gitlab-ci-verify&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=timo-reymann_gitlab-ci-verify)
32
+ [![Go Report Card](https://goreportcard.com/badge/github.com/timo-reymann/gitlab-ci-verify)](https://goreportcard.com/report/github.com/timo-reymann/gitlab-ci-verify)
33
+ [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=timo-reymann_gitlab-ci-verify&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=timo-reymann_gitlab-ci-verify)
34
+
35
+ <p align="center">
36
+ <img width="300" src="https://raw.githubusercontent.com/timo-reymann/gitlab-ci-verify/main/.github/images/logo.png">
37
+ <br />
38
+ Validate and lint your gitlab ci files using ShellCheck, the Gitlab API and curated checks
39
+ </p>
40
+
41
+ ## Features
42
+
43
+ - ShellCheck for scripts
44
+ - Validation against Pipeline Editor API for project
45
+ - Automatic detection of the current gitlab project
46
+ - Available as pre-commit hook
47
+
48
+ ## Installation
49
+
50
+ ### Manual
51
+
52
+ #### Linux (64-bit)
53
+
54
+ ```bash
55
+ curl -LO https://github.com/timo-reymann/gitlab-ci-verify/releases/download/$(curl -Lso /dev/null -w %{url_effective} https://github.com/timo-reymann/gitlab-ci-verify/releases/latest | grep -o '[^/]*$')/gitlab-ci-verify_linux-amd64 && \
56
+ chmod +x gitlab-ci-verify_linux-amd64 && \
57
+ sudo mv gitlab-ci-verify_linux-amd64 /usr/local/bin/gitlab-ci-verify
58
+ ```
59
+
60
+ #### Darwin (Intel)
61
+
62
+ ##### brew
63
+
64
+ ```bash
65
+ brew tap timo-reymann/gitlab-ci-verify
66
+ brew install gitlab-ci-verify
67
+ ```
68
+
69
+ ##### manual
70
+
71
+ ```bash
72
+ curl -LO https://github.com/timo-reymann/gitlab-ci-verify/releases/download/$(curl -Lso /dev/null -w %{url_effective} https://github.com/timo-reymann/gitlab-ci-verify/releases/latest | grep -o '[^/]*$')/gitlab-ci-verify_darwin-amd64 && \
73
+ chmod +x gitlab-ci-verify_darwin-amd64 && \
74
+ sudo mv gitlab-ci-verify_darwin-amd64 /usr/local/bin/gitlab-ci-verify
75
+ ```
76
+
77
+ ### Install with go
78
+
79
+ ```bash
80
+ go install github.com/timo-reymann/gitlab-ci-verify@latest
81
+ ```
82
+
83
+ ### Install with pip(x)
84
+
85
+ Using pipx you can just use the following command use gitlab-ci-verify as it is:
86
+
87
+ ```sh
88
+ pipx install gitlab-ci-verify
89
+ ```
90
+
91
+ If you want to use it directly using the `subprocess` module you can install it with pip:
92
+
93
+ ````sh
94
+ pip install gitlab-ci-verify
95
+ ````
96
+
97
+ And use the package like this:
98
+
99
+ ````python
100
+ from gitlab_ci_verify import verify_file
101
+
102
+ # Verify .gitlab-ci.yml in /path/to/repo is valid
103
+ valid, findings = verify_file("/path/to/repo")
104
+
105
+ # verify include.yml in /path/to/repo is valid
106
+ valid, findings = verify_file("/path/to/repo", "include.yml")
107
+
108
+ # or if you want to verify file content for a given repository
109
+ # valid, findings = verify_content("/path/to/repo","ci-yaml content")
110
+
111
+ print(f"Valid: {valid}")
112
+ print(f"Findings: {findings}")
113
+ ````
114
+
115
+ Also see the [python wrapper documentation](https://timo-reymann.github.io/gitlab-ci-verify/python-wrapper/)
116
+
117
+ ### Supported platforms
118
+
119
+ The following platforms are supported (and have prebuilt binaries /
120
+ ready to use integration):
121
+
122
+ - Linux
123
+ - 64-bit
124
+ - ARM 64-bit
125
+ - Darwin
126
+ - 64-bit
127
+ - ARM (M1/M2)
128
+ - Windows
129
+ - 64-bit
130
+ - pre-commit (x86 & ARM)
131
+ - Docker (x86 & ARM)
132
+
133
+ ### Where to find the latest release for your platform
134
+
135
+ #### Binaries
136
+
137
+ Binaries for all of these can be found on
138
+ the [latest release page](https://github.com/timo-reymann/gitlab-ci-verify/releases/latest).
139
+
140
+ #### Docker
141
+
142
+ For the docker image check the [docker hub](https://hub.docker.com/r/timoreymann/gitlab-ci-verify).
143
+
144
+ ## Usage
145
+
146
+ ### Command Line
147
+
148
+ ```sh
149
+ gitlab-ci-verify --help
150
+ ```
151
+
152
+ ### Containerized
153
+
154
+ ```sh
155
+ docker run --rm -it -v $PWD:/workspace -e GITLAB_TOKEN="your token" timoreymann/gitlab-ci-verify
156
+ ```
157
+
158
+ ### pre-commit
159
+
160
+ ```yaml
161
+ - repo: https://github.com/timo-reymann/gitlab-ci-verify
162
+ rev: main
163
+ hooks:
164
+ - id: gitlab-ci-verify
165
+ ```
166
+
167
+ ## Motivation
168
+
169
+ Unfortunately, GitLab didn't provide a tool to validate CI configuration for quite a while.
170
+ Now that changed with the `glab` CLI providing `glab ci lint` but it is quite limited and under the hood just calls the
171
+ new CI Lint API.
172
+
173
+ Throughout the years quite some tools evolved, but most of them are either outdated, painful to use or install, and
174
+ basically also provide the lint functionality from the API.
175
+
176
+ As most of the logic in pipelines is written in shell scripts via the `*script` attributes these are lacking completely
177
+ from all tools out there as well as the official lint API.
178
+
179
+ The goal of gitlab-ci-verify is to provide the stock CI Lint functionality plus shellcheck.
180
+ Completed in the future some
181
+ rules to lint that common patterns are working as intended by GitLab
182
+ and void them from being pushed and leading to unexpected behavior.
183
+
184
+ ## Contributing
185
+
186
+ I love your input! I want to make contributing to this project as easy and transparent as possible, whether it's:
187
+
188
+ - Reporting a bug
189
+ - Discussing the current state of the configuration
190
+ - Submitting a fix
191
+ - Proposing new features
192
+ - Becoming a maintainer
193
+
194
+ To get started please read the [Contribution Guidelines](./CONTRIBUTING.md).
195
+
196
+ ## Development
197
+
198
+ ### Requirements
199
+
200
+ - [Go](https://go.dev/doc/install)
201
+ - [GNU make](https://www.gnu.org/software/make/)
202
+
203
+ ### Test
204
+
205
+ ```sh
206
+ make test-coverage-report
207
+ ```
208
+
209
+ ### Build
210
+
211
+ ```sh
212
+ make build
213
+ ```
214
+
215
+ ## Credits
216
+
217
+ This whole project wouldn't be possible with the great work of the
218
+ following libraries/tools:
219
+
220
+ - [Shellcheck by koalaman](https://github.com/koalaman/shellcheck)
221
+ - [go stdlib](https://github.com/golang/go)
222
+ - [pflag by spf13](https://github.com/spf13/pflag)
@@ -0,0 +1,199 @@
1
+ [IN IMPLEMENTATION] gitlab-ci-verify
2
+ ===
3
+ [![GitHub Release](https://img.shields.io/github/v/release/timo-reymann/gitlab-ci-verify?label=version)](https://github.com/timo-reymann/gitlab-ci-verify/releases/latest)
4
+ [![CircleCI](https://dl.circleci.com/status-badge/img/gh/timo-reymann/gitlab-ci-verify/tree/main.svg?style=shield)](https://dl.circleci.com/status-badge/redirect/gh/timo-reymann/gitlab-ci-verify/tree/main)
5
+ [![codecov](https://codecov.io/gh/timo-reymann/gitlab-ci-verify/graph/badge.svg?token=4tYXDueu5D)](https://codecov.io/gh/timo-reymann/gitlab-ci-verify)
6
+ [![Renovate](https://img.shields.io/badge/renovate-enabled-green?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNjkgMzY5Ij48Y2lyY2xlIGN4PSIxODkuOSIgY3k9IjE5MC4yIiByPSIxODQuNSIgZmlsbD0iI2ZmZTQyZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTUgLTYpIi8+PHBhdGggZmlsbD0iIzhiYjViNSIgZD0iTTI1MSAyNTZsLTM4LTM4YTE3IDE3IDAgMDEwLTI0bDU2LTU2YzItMiAyLTYgMC03bC0yMC0yMWE1IDUgMCAwMC03IDBsLTEzIDEyLTktOCAxMy0xM2ExNyAxNyAwIDAxMjQgMGwyMSAyMWM3IDcgNyAxNyAwIDI0bC01NiA1N2E1IDUgMCAwMDAgN2wzOCAzOHoiLz48cGF0aCBmaWxsPSIjZDk1NjEyIiBkPSJNMzAwIDI4OGwtOCA4Yy00IDQtMTEgNC0xNiAwbC00Ni00NmMtNS01LTUtMTIgMC0xNmw4LThjNC00IDExLTQgMTUgMGw0NyA0N2M0IDQgNCAxMSAwIDE1eiIvPjxwYXRoIGZpbGw9IiMyNGJmYmUiIGQ9Ik04MSAxODVsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzI1YzRjMyIgZD0iTTIyMCAxMDBsMjMgMjNjNCA0IDQgMTEgMCAxNkwxNDIgMjQwYy00IDQtMTEgNC0xNSAwbC0yNC0yNGMtNC00LTQtMTEgMC0xNWwxMDEtMTAxYzUtNSAxMi01IDE2IDB6Ii8+PHBhdGggZmlsbD0iIzFkZGVkZCIgZD0iTTk5IDE2N2wxOC0xOCAxOCAxOC0xOCAxOHoiLz48cGF0aCBmaWxsPSIjMDBhZmIzIiBkPSJNMjMwIDExMGwxMyAxM2M0IDQgNCAxMSAwIDE2TDE0MiAyNDBjLTQgNC0xMSA0LTE1IDBsLTEzLTEzYzQgNCAxMSA0IDE1IDBsMTAxLTEwMWM1LTUgNS0xMSAwLTE2eiIvPjxwYXRoIGZpbGw9IiMyNGJmYmUiIGQ9Ik0xMTYgMTQ5bDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMxZGRlZGQiIGQ9Ik0xMzQgMTMxbDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMxYmNmY2UiIGQ9Ik0xNTIgMTEzbDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMyNGJmYmUiIGQ9Ik0xNzAgOTVsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzFiY2ZjZSIgZD0iTTYzIDE2N2wxOC0xOCAxOCAxOC0xOCAxOHpNOTggMTMxbDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMzNGVkZWIiIGQ9Ik0xMzQgOTVsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzFiY2ZjZSIgZD0iTTE1MyA3OGwxOC0xOCAxOCAxOC0xOCAxOHoiLz48cGF0aCBmaWxsPSIjMzRlZGViIiBkPSJNODAgMTEzbDE4LTE3IDE4IDE3LTE4IDE4ek0xMzUgNjBsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzk4ZWRlYiIgZD0iTTI3IDEzMWwxOC0xOCAxOCAxOC0xOCAxOHoiLz48cGF0aCBmaWxsPSIjYjUzZTAyIiBkPSJNMjg1IDI1OGw3IDdjNCA0IDQgMTEgMCAxNWwtOCA4Yy00IDQtMTEgNC0xNiAwbC02LTdjNCA1IDExIDUgMTUgMGw4LTdjNC01IDQtMTIgMC0xNnoiLz48cGF0aCBmaWxsPSIjOThlZGViIiBkPSJNODEgNzhsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzAwYTNhMiIgZD0iTTIzNSAxMTVsOCA4YzQgNCA0IDExIDAgMTZMMTQyIDI0MGMtNCA0LTExIDQtMTUgMGwtOS05YzUgNSAxMiA1IDE2IDBsMTAxLTEwMWM0LTQgNC0xMSAwLTE1eiIvPjxwYXRoIGZpbGw9IiMzOWQ5ZDgiIGQ9Ik0yMjggMTA4bC04LThjLTQtNS0xMS01LTE2IDBMMTAzIDIwMWMtNCA0LTQgMTEgMCAxNWw4IDhjLTQtNC00LTExIDAtMTVsMTAxLTEwMWM1LTQgMTItNCAxNiAweiIvPjxwYXRoIGZpbGw9IiNhMzM5MDQiIGQ9Ik0yOTEgMjY0bDggOGM0IDQgNCAxMSAwIDE2bC04IDdjLTQgNS0xMSA1LTE1IDBsLTktOGM1IDUgMTIgNSAxNiAwbDgtOGM0LTQgNC0xMSAwLTE1eiIvPjxwYXRoIGZpbGw9IiNlYjZlMmQiIGQ9Ik0yNjAgMjMzbC00LTRjLTYtNi0xNy02LTIzIDAtNyA3LTcgMTcgMCAyNGw0IDRjLTQtNS00LTExIDAtMTZsOC04YzQtNCAxMS00IDE1IDB6Ii8+PHBhdGggZmlsbD0iIzEzYWNiZCIgZD0iTTEzNCAyNDhjLTQgMC04LTItMTEtNWwtMjMtMjNhMTYgMTYgMCAwMTAtMjNMMjAxIDk2YTE2IDE2IDAgMDEyMiAwbDI0IDI0YzYgNiA2IDE2IDAgMjJMMTQ2IDI0M2MtMyAzLTcgNS0xMiA1em03OC0xNDdsLTQgMi0xMDEgMTAxYTYgNiAwIDAwMCA5bDIzIDIzYTYgNiAwIDAwOSAwbDEwMS0xMDFhNiA2IDAgMDAwLTlsLTI0LTIzLTQtMnoiLz48cGF0aCBmaWxsPSIjYmY0NDA0IiBkPSJNMjg0IDMwNGMtNCAwLTgtMS0xMS00bC00Ny00N2MtNi02LTYtMTYgMC0yMmw4LThjNi02IDE2LTYgMjIgMGw0NyA0NmM2IDcgNiAxNyAwIDIzbC04IDhjLTMgMy03IDQtMTEgNHptLTM5LTc2Yy0xIDAtMyAwLTQgMmwtOCA3Yy0yIDMtMiA3IDAgOWw0NyA0N2E2IDYgMCAwMDkgMGw3LThjMy0yIDMtNiAwLTlsLTQ2LTQ2Yy0yLTItMy0yLTUtMnoiLz48L3N2Zz4=)](https://renovatebot.com)
7
+ [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=timo-reymann_gitlab-ci-verify&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=timo-reymann_gitlab-ci-verify)
8
+ [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=timo-reymann_gitlab-ci-verify&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=timo-reymann_gitlab-ci-verify)
9
+ [![Go Report Card](https://goreportcard.com/badge/github.com/timo-reymann/gitlab-ci-verify)](https://goreportcard.com/report/github.com/timo-reymann/gitlab-ci-verify)
10
+ [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=timo-reymann_gitlab-ci-verify&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=timo-reymann_gitlab-ci-verify)
11
+
12
+ <p align="center">
13
+ <img width="300" src="https://raw.githubusercontent.com/timo-reymann/gitlab-ci-verify/main/.github/images/logo.png">
14
+ <br />
15
+ Validate and lint your gitlab ci files using ShellCheck, the Gitlab API and curated checks
16
+ </p>
17
+
18
+ ## Features
19
+
20
+ - ShellCheck for scripts
21
+ - Validation against Pipeline Editor API for project
22
+ - Automatic detection of the current gitlab project
23
+ - Available as pre-commit hook
24
+
25
+ ## Installation
26
+
27
+ ### Manual
28
+
29
+ #### Linux (64-bit)
30
+
31
+ ```bash
32
+ curl -LO https://github.com/timo-reymann/gitlab-ci-verify/releases/download/$(curl -Lso /dev/null -w %{url_effective} https://github.com/timo-reymann/gitlab-ci-verify/releases/latest | grep -o '[^/]*$')/gitlab-ci-verify_linux-amd64 && \
33
+ chmod +x gitlab-ci-verify_linux-amd64 && \
34
+ sudo mv gitlab-ci-verify_linux-amd64 /usr/local/bin/gitlab-ci-verify
35
+ ```
36
+
37
+ #### Darwin (Intel)
38
+
39
+ ##### brew
40
+
41
+ ```bash
42
+ brew tap timo-reymann/gitlab-ci-verify
43
+ brew install gitlab-ci-verify
44
+ ```
45
+
46
+ ##### manual
47
+
48
+ ```bash
49
+ curl -LO https://github.com/timo-reymann/gitlab-ci-verify/releases/download/$(curl -Lso /dev/null -w %{url_effective} https://github.com/timo-reymann/gitlab-ci-verify/releases/latest | grep -o '[^/]*$')/gitlab-ci-verify_darwin-amd64 && \
50
+ chmod +x gitlab-ci-verify_darwin-amd64 && \
51
+ sudo mv gitlab-ci-verify_darwin-amd64 /usr/local/bin/gitlab-ci-verify
52
+ ```
53
+
54
+ ### Install with go
55
+
56
+ ```bash
57
+ go install github.com/timo-reymann/gitlab-ci-verify@latest
58
+ ```
59
+
60
+ ### Install with pip(x)
61
+
62
+ Using pipx you can just use the following command use gitlab-ci-verify as it is:
63
+
64
+ ```sh
65
+ pipx install gitlab-ci-verify
66
+ ```
67
+
68
+ If you want to use it directly using the `subprocess` module you can install it with pip:
69
+
70
+ ````sh
71
+ pip install gitlab-ci-verify
72
+ ````
73
+
74
+ And use the package like this:
75
+
76
+ ````python
77
+ from gitlab_ci_verify import verify_file
78
+
79
+ # Verify .gitlab-ci.yml in /path/to/repo is valid
80
+ valid, findings = verify_file("/path/to/repo")
81
+
82
+ # verify include.yml in /path/to/repo is valid
83
+ valid, findings = verify_file("/path/to/repo", "include.yml")
84
+
85
+ # or if you want to verify file content for a given repository
86
+ # valid, findings = verify_content("/path/to/repo","ci-yaml content")
87
+
88
+ print(f"Valid: {valid}")
89
+ print(f"Findings: {findings}")
90
+ ````
91
+
92
+ Also see the [python wrapper documentation](https://timo-reymann.github.io/gitlab-ci-verify/python-wrapper/)
93
+
94
+ ### Supported platforms
95
+
96
+ The following platforms are supported (and have prebuilt binaries /
97
+ ready to use integration):
98
+
99
+ - Linux
100
+ - 64-bit
101
+ - ARM 64-bit
102
+ - Darwin
103
+ - 64-bit
104
+ - ARM (M1/M2)
105
+ - Windows
106
+ - 64-bit
107
+ - pre-commit (x86 & ARM)
108
+ - Docker (x86 & ARM)
109
+
110
+ ### Where to find the latest release for your platform
111
+
112
+ #### Binaries
113
+
114
+ Binaries for all of these can be found on
115
+ the [latest release page](https://github.com/timo-reymann/gitlab-ci-verify/releases/latest).
116
+
117
+ #### Docker
118
+
119
+ For the docker image check the [docker hub](https://hub.docker.com/r/timoreymann/gitlab-ci-verify).
120
+
121
+ ## Usage
122
+
123
+ ### Command Line
124
+
125
+ ```sh
126
+ gitlab-ci-verify --help
127
+ ```
128
+
129
+ ### Containerized
130
+
131
+ ```sh
132
+ docker run --rm -it -v $PWD:/workspace -e GITLAB_TOKEN="your token" timoreymann/gitlab-ci-verify
133
+ ```
134
+
135
+ ### pre-commit
136
+
137
+ ```yaml
138
+ - repo: https://github.com/timo-reymann/gitlab-ci-verify
139
+ rev: main
140
+ hooks:
141
+ - id: gitlab-ci-verify
142
+ ```
143
+
144
+ ## Motivation
145
+
146
+ Unfortunately, GitLab didn't provide a tool to validate CI configuration for quite a while.
147
+ Now that changed with the `glab` CLI providing `glab ci lint` but it is quite limited and under the hood just calls the
148
+ new CI Lint API.
149
+
150
+ Throughout the years quite some tools evolved, but most of them are either outdated, painful to use or install, and
151
+ basically also provide the lint functionality from the API.
152
+
153
+ As most of the logic in pipelines is written in shell scripts via the `*script` attributes these are lacking completely
154
+ from all tools out there as well as the official lint API.
155
+
156
+ The goal of gitlab-ci-verify is to provide the stock CI Lint functionality plus shellcheck.
157
+ Completed in the future some
158
+ rules to lint that common patterns are working as intended by GitLab
159
+ and void them from being pushed and leading to unexpected behavior.
160
+
161
+ ## Contributing
162
+
163
+ I love your input! I want to make contributing to this project as easy and transparent as possible, whether it's:
164
+
165
+ - Reporting a bug
166
+ - Discussing the current state of the configuration
167
+ - Submitting a fix
168
+ - Proposing new features
169
+ - Becoming a maintainer
170
+
171
+ To get started please read the [Contribution Guidelines](./CONTRIBUTING.md).
172
+
173
+ ## Development
174
+
175
+ ### Requirements
176
+
177
+ - [Go](https://go.dev/doc/install)
178
+ - [GNU make](https://www.gnu.org/software/make/)
179
+
180
+ ### Test
181
+
182
+ ```sh
183
+ make test-coverage-report
184
+ ```
185
+
186
+ ### Build
187
+
188
+ ```sh
189
+ make build
190
+ ```
191
+
192
+ ## Credits
193
+
194
+ This whole project wouldn't be possible with the great work of the
195
+ following libraries/tools:
196
+
197
+ - [Shellcheck by koalaman](https://github.com/koalaman/shellcheck)
198
+ - [go stdlib](https://github.com/golang/go)
199
+ - [pflag by spf13](https://github.com/spf13/pflag)
@@ -0,0 +1,44 @@
1
+ from os import PathLike
2
+
3
+ from gitlab_ci_verify.config import GitlabCiVerifyConfig
4
+ from gitlab_ci_verify.model import Finding
5
+ from gitlab_ci_verify.parse import _parse_output
6
+ from gitlab_ci_verify.process import _execute
7
+
8
+
9
+ def verify_file(
10
+ root: PathLike | str,
11
+ file: str | None = None,
12
+ **configuration: GitlabCiVerifyConfig,
13
+ ):
14
+ """
15
+ Verify gitlab ci file using gitlab-ci-verify
16
+
17
+ :param root: Root folder of repository
18
+ :param file: Override gitlab ci file to validate
19
+ :param configuration: Configuration to use for verification
20
+ """
21
+ proc = _execute(root, file=file, **configuration)
22
+ return _parse_output(proc)
23
+
24
+
25
+ def verify_content(
26
+ root: PathLike | str,
27
+ content: str,
28
+ **configuration: GitlabCiVerifyConfig,
29
+ ):
30
+ """
31
+ Verify gitlab ci file contents using gitlab-ci-verify
32
+
33
+ :param root: Root folder of repository
34
+ :param content: CI YAML contents
35
+ :param configuration: Configuration to use for verification
36
+ """
37
+ proc = _execute(root, file="-", stdin=content, **configuration)
38
+ return _parse_output(proc)
39
+
40
+
41
+ if __name__ == "__main__":
42
+ # valid, findings = verify_file("/Users/phpe/workspace/backend-csharp")
43
+ valid, findings = verify_content("/Users/phpe/workspace/backend-csharp", "{}")
44
+ print(valid, findings)
@@ -0,0 +1,12 @@
1
+ import typing
2
+
3
+
4
+ class GitlabCiVerifyConfig(typing.TypedDict):
5
+ gitlab_base_url: typing.Optional[str]
6
+ """Override gitlab base url"""
7
+ gitlab_token: typing.Optional[str]
8
+ """Specify explicit gitlab token"""
9
+ excluded_checks: typing.Optional[list[str]]
10
+ """Exclude set of checks"""
11
+ fail_severity: typing.Optional[str]
12
+ """On which severity findings should be considered an error"""
@@ -0,0 +1,15 @@
1
+ from dataclasses import dataclass
2
+
3
+
4
+ @dataclass(frozen=True, kw_only=True)
5
+ class Finding:
6
+ severity: str
7
+ code: str
8
+ line: int
9
+ message: str
10
+ link: str
11
+ file: str
12
+
13
+ @classmethod
14
+ def from_dict(cls, dict_val: dict[str, any]):
15
+ return Finding(**dict_val)
@@ -0,0 +1,20 @@
1
+ import json
2
+ from json import JSONDecodeError
3
+
4
+ from gitlab_ci_verify import Finding
5
+
6
+ class FindingsParseException(Exception):
7
+ pass
8
+
9
+ def _parse_output(proc):
10
+ valid = proc.returncode == 0
11
+ stdout_content = proc.stdout.read()
12
+ try:
13
+ raw_findings = json.loads(stdout_content)
14
+ except JSONDecodeError:
15
+ raise FindingsParseException(proc.stderr.read())
16
+ parsed_findings = []
17
+ for raw_finding in raw_findings:
18
+ parsed_findings.append(Finding.from_dict(raw_finding))
19
+
20
+ return valid, parsed_findings
@@ -0,0 +1,66 @@
1
+ import subprocess
2
+ from os import PathLike
3
+
4
+ from gitlab_ci_verify_bin.exec import create_subprocess
5
+
6
+ from gitlab_ci_verify import GitlabCiVerifyConfig
7
+
8
+
9
+ def _add_arg_if_set(args: list[str], config: GitlabCiVerifyConfig, key: str, flag: str):
10
+ val = config.get(key, None)
11
+ if val is not None:
12
+ args.extend(
13
+ [
14
+ flag,
15
+ val,
16
+ ]
17
+ )
18
+
19
+
20
+ def _execute(
21
+ root: PathLike | str,
22
+ file: str | None = None,
23
+ stdin=None,
24
+ **config: GitlabCiVerifyConfig
25
+ ):
26
+ args = [
27
+ "--format",
28
+ "json"
29
+ ]
30
+
31
+ _add_arg_if_set(args, config, "gitlab_base_url", "--gitlab-base-url")
32
+ _add_arg_if_set(args, config, "gitlab_token", "--gitlab-token")
33
+ _add_arg_if_set(args, config, "fail_severity", "--severity")
34
+
35
+ if file is not None:
36
+ args.extend(
37
+ [
38
+ "--gitlab-ci-file",
39
+ file,
40
+ ]
41
+ )
42
+
43
+ excluded_checks = config.get("excluded_checks", None)
44
+ if excluded_checks is not None:
45
+ for check in excluded_checks:
46
+ args.extend(
47
+ [
48
+ "--exclude",
49
+ check,
50
+ ]
51
+ )
52
+
53
+ proc = create_subprocess(
54
+ args,
55
+ stdout=subprocess.PIPE,
56
+ stderr=subprocess.PIPE,
57
+ stdin=subprocess.PIPE if stdin is not None else None,
58
+ cwd=root,
59
+ )
60
+
61
+ if stdin is not None:
62
+ proc.stdin.write(stdin)
63
+ proc.stdin.close()
64
+
65
+ proc.wait()
66
+ return proc
@@ -0,0 +1,222 @@
1
+ Metadata-Version: 2.1
2
+ Name: gitlab-ci-verify
3
+ Version: 0.0.10
4
+ Summary: Validate and lint your gitlab ci files using ShellCheck, the Gitlab API and curated checks
5
+ Author-email: Timo Reymann <mail@timo-reymann.de>
6
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
7
+ Classifier: Development Status :: 2 - Pre-Alpha
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.9
10
+ Classifier: Programming Language :: Python :: 3.10
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Intended Audience :: Developers
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: gitlab-ci-verify-bin==0.*
16
+ Provides-Extra: dev
17
+ Requires-Dist: setuptools==70.*; extra == "dev"
18
+ Requires-Dist: setuptools-scm==8.*; extra == "dev"
19
+ Requires-Dist: twine==5.1.*; extra == "dev"
20
+ Requires-Dist: wheel==0.43.*; extra == "dev"
21
+ Requires-Dist: pydoctor==24.3.*; extra == "dev"
22
+ Requires-Dist: build==1.*; extra == "dev"
23
+
24
+ [IN IMPLEMENTATION] gitlab-ci-verify
25
+ ===
26
+ [![GitHub Release](https://img.shields.io/github/v/release/timo-reymann/gitlab-ci-verify?label=version)](https://github.com/timo-reymann/gitlab-ci-verify/releases/latest)
27
+ [![CircleCI](https://dl.circleci.com/status-badge/img/gh/timo-reymann/gitlab-ci-verify/tree/main.svg?style=shield)](https://dl.circleci.com/status-badge/redirect/gh/timo-reymann/gitlab-ci-verify/tree/main)
28
+ [![codecov](https://codecov.io/gh/timo-reymann/gitlab-ci-verify/graph/badge.svg?token=4tYXDueu5D)](https://codecov.io/gh/timo-reymann/gitlab-ci-verify)
29
+ [![Renovate](https://img.shields.io/badge/renovate-enabled-green?logo=data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzNjkgMzY5Ij48Y2lyY2xlIGN4PSIxODkuOSIgY3k9IjE5MC4yIiByPSIxODQuNSIgZmlsbD0iI2ZmZTQyZSIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTUgLTYpIi8+PHBhdGggZmlsbD0iIzhiYjViNSIgZD0iTTI1MSAyNTZsLTM4LTM4YTE3IDE3IDAgMDEwLTI0bDU2LTU2YzItMiAyLTYgMC03bC0yMC0yMWE1IDUgMCAwMC03IDBsLTEzIDEyLTktOCAxMy0xM2ExNyAxNyAwIDAxMjQgMGwyMSAyMWM3IDcgNyAxNyAwIDI0bC01NiA1N2E1IDUgMCAwMDAgN2wzOCAzOHoiLz48cGF0aCBmaWxsPSIjZDk1NjEyIiBkPSJNMzAwIDI4OGwtOCA4Yy00IDQtMTEgNC0xNiAwbC00Ni00NmMtNS01LTUtMTIgMC0xNmw4LThjNC00IDExLTQgMTUgMGw0NyA0N2M0IDQgNCAxMSAwIDE1eiIvPjxwYXRoIGZpbGw9IiMyNGJmYmUiIGQ9Ik04MSAxODVsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzI1YzRjMyIgZD0iTTIyMCAxMDBsMjMgMjNjNCA0IDQgMTEgMCAxNkwxNDIgMjQwYy00IDQtMTEgNC0xNSAwbC0yNC0yNGMtNC00LTQtMTEgMC0xNWwxMDEtMTAxYzUtNSAxMi01IDE2IDB6Ii8+PHBhdGggZmlsbD0iIzFkZGVkZCIgZD0iTTk5IDE2N2wxOC0xOCAxOCAxOC0xOCAxOHoiLz48cGF0aCBmaWxsPSIjMDBhZmIzIiBkPSJNMjMwIDExMGwxMyAxM2M0IDQgNCAxMSAwIDE2TDE0MiAyNDBjLTQgNC0xMSA0LTE1IDBsLTEzLTEzYzQgNCAxMSA0IDE1IDBsMTAxLTEwMWM1LTUgNS0xMSAwLTE2eiIvPjxwYXRoIGZpbGw9IiMyNGJmYmUiIGQ9Ik0xMTYgMTQ5bDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMxZGRlZGQiIGQ9Ik0xMzQgMTMxbDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMxYmNmY2UiIGQ9Ik0xNTIgMTEzbDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMyNGJmYmUiIGQ9Ik0xNzAgOTVsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzFiY2ZjZSIgZD0iTTYzIDE2N2wxOC0xOCAxOCAxOC0xOCAxOHpNOTggMTMxbDE4LTE4IDE4IDE4LTE4IDE4eiIvPjxwYXRoIGZpbGw9IiMzNGVkZWIiIGQ9Ik0xMzQgOTVsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzFiY2ZjZSIgZD0iTTE1MyA3OGwxOC0xOCAxOCAxOC0xOCAxOHoiLz48cGF0aCBmaWxsPSIjMzRlZGViIiBkPSJNODAgMTEzbDE4LTE3IDE4IDE3LTE4IDE4ek0xMzUgNjBsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzk4ZWRlYiIgZD0iTTI3IDEzMWwxOC0xOCAxOCAxOC0xOCAxOHoiLz48cGF0aCBmaWxsPSIjYjUzZTAyIiBkPSJNMjg1IDI1OGw3IDdjNCA0IDQgMTEgMCAxNWwtOCA4Yy00IDQtMTEgNC0xNiAwbC02LTdjNCA1IDExIDUgMTUgMGw4LTdjNC01IDQtMTIgMC0xNnoiLz48cGF0aCBmaWxsPSIjOThlZGViIiBkPSJNODEgNzhsMTgtMTggMTggMTgtMTggMTh6Ii8+PHBhdGggZmlsbD0iIzAwYTNhMiIgZD0iTTIzNSAxMTVsOCA4YzQgNCA0IDExIDAgMTZMMTQyIDI0MGMtNCA0LTExIDQtMTUgMGwtOS05YzUgNSAxMiA1IDE2IDBsMTAxLTEwMWM0LTQgNC0xMSAwLTE1eiIvPjxwYXRoIGZpbGw9IiMzOWQ5ZDgiIGQ9Ik0yMjggMTA4bC04LThjLTQtNS0xMS01LTE2IDBMMTAzIDIwMWMtNCA0LTQgMTEgMCAxNWw4IDhjLTQtNC00LTExIDAtMTVsMTAxLTEwMWM1LTQgMTItNCAxNiAweiIvPjxwYXRoIGZpbGw9IiNhMzM5MDQiIGQ9Ik0yOTEgMjY0bDggOGM0IDQgNCAxMSAwIDE2bC04IDdjLTQgNS0xMSA1LTE1IDBsLTktOGM1IDUgMTIgNSAxNiAwbDgtOGM0LTQgNC0xMSAwLTE1eiIvPjxwYXRoIGZpbGw9IiNlYjZlMmQiIGQ9Ik0yNjAgMjMzbC00LTRjLTYtNi0xNy02LTIzIDAtNyA3LTcgMTcgMCAyNGw0IDRjLTQtNS00LTExIDAtMTZsOC04YzQtNCAxMS00IDE1IDB6Ii8+PHBhdGggZmlsbD0iIzEzYWNiZCIgZD0iTTEzNCAyNDhjLTQgMC04LTItMTEtNWwtMjMtMjNhMTYgMTYgMCAwMTAtMjNMMjAxIDk2YTE2IDE2IDAgMDEyMiAwbDI0IDI0YzYgNiA2IDE2IDAgMjJMMTQ2IDI0M2MtMyAzLTcgNS0xMiA1em03OC0xNDdsLTQgMi0xMDEgMTAxYTYgNiAwIDAwMCA5bDIzIDIzYTYgNiAwIDAwOSAwbDEwMS0xMDFhNiA2IDAgMDAwLTlsLTI0LTIzLTQtMnoiLz48cGF0aCBmaWxsPSIjYmY0NDA0IiBkPSJNMjg0IDMwNGMtNCAwLTgtMS0xMS00bC00Ny00N2MtNi02LTYtMTYgMC0yMmw4LThjNi02IDE2LTYgMjIgMGw0NyA0NmM2IDcgNiAxNyAwIDIzbC04IDhjLTMgMy03IDQtMTEgNHptLTM5LTc2Yy0xIDAtMyAwLTQgMmwtOCA3Yy0yIDMtMiA3IDAgOWw0NyA0N2E2IDYgMCAwMDkgMGw3LThjMy0yIDMtNiAwLTlsLTQ2LTQ2Yy0yLTItMy0yLTUtMnoiLz48L3N2Zz4=)](https://renovatebot.com)
30
+ [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=timo-reymann_gitlab-ci-verify&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=timo-reymann_gitlab-ci-verify)
31
+ [![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=timo-reymann_gitlab-ci-verify&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=timo-reymann_gitlab-ci-verify)
32
+ [![Go Report Card](https://goreportcard.com/badge/github.com/timo-reymann/gitlab-ci-verify)](https://goreportcard.com/report/github.com/timo-reymann/gitlab-ci-verify)
33
+ [![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=timo-reymann_gitlab-ci-verify&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=timo-reymann_gitlab-ci-verify)
34
+
35
+ <p align="center">
36
+ <img width="300" src="https://raw.githubusercontent.com/timo-reymann/gitlab-ci-verify/main/.github/images/logo.png">
37
+ <br />
38
+ Validate and lint your gitlab ci files using ShellCheck, the Gitlab API and curated checks
39
+ </p>
40
+
41
+ ## Features
42
+
43
+ - ShellCheck for scripts
44
+ - Validation against Pipeline Editor API for project
45
+ - Automatic detection of the current gitlab project
46
+ - Available as pre-commit hook
47
+
48
+ ## Installation
49
+
50
+ ### Manual
51
+
52
+ #### Linux (64-bit)
53
+
54
+ ```bash
55
+ curl -LO https://github.com/timo-reymann/gitlab-ci-verify/releases/download/$(curl -Lso /dev/null -w %{url_effective} https://github.com/timo-reymann/gitlab-ci-verify/releases/latest | grep -o '[^/]*$')/gitlab-ci-verify_linux-amd64 && \
56
+ chmod +x gitlab-ci-verify_linux-amd64 && \
57
+ sudo mv gitlab-ci-verify_linux-amd64 /usr/local/bin/gitlab-ci-verify
58
+ ```
59
+
60
+ #### Darwin (Intel)
61
+
62
+ ##### brew
63
+
64
+ ```bash
65
+ brew tap timo-reymann/gitlab-ci-verify
66
+ brew install gitlab-ci-verify
67
+ ```
68
+
69
+ ##### manual
70
+
71
+ ```bash
72
+ curl -LO https://github.com/timo-reymann/gitlab-ci-verify/releases/download/$(curl -Lso /dev/null -w %{url_effective} https://github.com/timo-reymann/gitlab-ci-verify/releases/latest | grep -o '[^/]*$')/gitlab-ci-verify_darwin-amd64 && \
73
+ chmod +x gitlab-ci-verify_darwin-amd64 && \
74
+ sudo mv gitlab-ci-verify_darwin-amd64 /usr/local/bin/gitlab-ci-verify
75
+ ```
76
+
77
+ ### Install with go
78
+
79
+ ```bash
80
+ go install github.com/timo-reymann/gitlab-ci-verify@latest
81
+ ```
82
+
83
+ ### Install with pip(x)
84
+
85
+ Using pipx you can just use the following command use gitlab-ci-verify as it is:
86
+
87
+ ```sh
88
+ pipx install gitlab-ci-verify
89
+ ```
90
+
91
+ If you want to use it directly using the `subprocess` module you can install it with pip:
92
+
93
+ ````sh
94
+ pip install gitlab-ci-verify
95
+ ````
96
+
97
+ And use the package like this:
98
+
99
+ ````python
100
+ from gitlab_ci_verify import verify_file
101
+
102
+ # Verify .gitlab-ci.yml in /path/to/repo is valid
103
+ valid, findings = verify_file("/path/to/repo")
104
+
105
+ # verify include.yml in /path/to/repo is valid
106
+ valid, findings = verify_file("/path/to/repo", "include.yml")
107
+
108
+ # or if you want to verify file content for a given repository
109
+ # valid, findings = verify_content("/path/to/repo","ci-yaml content")
110
+
111
+ print(f"Valid: {valid}")
112
+ print(f"Findings: {findings}")
113
+ ````
114
+
115
+ Also see the [python wrapper documentation](https://timo-reymann.github.io/gitlab-ci-verify/python-wrapper/)
116
+
117
+ ### Supported platforms
118
+
119
+ The following platforms are supported (and have prebuilt binaries /
120
+ ready to use integration):
121
+
122
+ - Linux
123
+ - 64-bit
124
+ - ARM 64-bit
125
+ - Darwin
126
+ - 64-bit
127
+ - ARM (M1/M2)
128
+ - Windows
129
+ - 64-bit
130
+ - pre-commit (x86 & ARM)
131
+ - Docker (x86 & ARM)
132
+
133
+ ### Where to find the latest release for your platform
134
+
135
+ #### Binaries
136
+
137
+ Binaries for all of these can be found on
138
+ the [latest release page](https://github.com/timo-reymann/gitlab-ci-verify/releases/latest).
139
+
140
+ #### Docker
141
+
142
+ For the docker image check the [docker hub](https://hub.docker.com/r/timoreymann/gitlab-ci-verify).
143
+
144
+ ## Usage
145
+
146
+ ### Command Line
147
+
148
+ ```sh
149
+ gitlab-ci-verify --help
150
+ ```
151
+
152
+ ### Containerized
153
+
154
+ ```sh
155
+ docker run --rm -it -v $PWD:/workspace -e GITLAB_TOKEN="your token" timoreymann/gitlab-ci-verify
156
+ ```
157
+
158
+ ### pre-commit
159
+
160
+ ```yaml
161
+ - repo: https://github.com/timo-reymann/gitlab-ci-verify
162
+ rev: main
163
+ hooks:
164
+ - id: gitlab-ci-verify
165
+ ```
166
+
167
+ ## Motivation
168
+
169
+ Unfortunately, GitLab didn't provide a tool to validate CI configuration for quite a while.
170
+ Now that changed with the `glab` CLI providing `glab ci lint` but it is quite limited and under the hood just calls the
171
+ new CI Lint API.
172
+
173
+ Throughout the years quite some tools evolved, but most of them are either outdated, painful to use or install, and
174
+ basically also provide the lint functionality from the API.
175
+
176
+ As most of the logic in pipelines is written in shell scripts via the `*script` attributes these are lacking completely
177
+ from all tools out there as well as the official lint API.
178
+
179
+ The goal of gitlab-ci-verify is to provide the stock CI Lint functionality plus shellcheck.
180
+ Completed in the future some
181
+ rules to lint that common patterns are working as intended by GitLab
182
+ and void them from being pushed and leading to unexpected behavior.
183
+
184
+ ## Contributing
185
+
186
+ I love your input! I want to make contributing to this project as easy and transparent as possible, whether it's:
187
+
188
+ - Reporting a bug
189
+ - Discussing the current state of the configuration
190
+ - Submitting a fix
191
+ - Proposing new features
192
+ - Becoming a maintainer
193
+
194
+ To get started please read the [Contribution Guidelines](./CONTRIBUTING.md).
195
+
196
+ ## Development
197
+
198
+ ### Requirements
199
+
200
+ - [Go](https://go.dev/doc/install)
201
+ - [GNU make](https://www.gnu.org/software/make/)
202
+
203
+ ### Test
204
+
205
+ ```sh
206
+ make test-coverage-report
207
+ ```
208
+
209
+ ### Build
210
+
211
+ ```sh
212
+ make build
213
+ ```
214
+
215
+ ## Credits
216
+
217
+ This whole project wouldn't be possible with the great work of the
218
+ following libraries/tools:
219
+
220
+ - [Shellcheck by koalaman](https://github.com/koalaman/shellcheck)
221
+ - [go stdlib](https://github.com/golang/go)
222
+ - [pflag by spf13](https://github.com/spf13/pflag)
@@ -0,0 +1,13 @@
1
+ .gitignore
2
+ README.md
3
+ pyproject.toml
4
+ gitlab_ci_verify/__init__.py
5
+ gitlab_ci_verify/config.py
6
+ gitlab_ci_verify/model.py
7
+ gitlab_ci_verify/parse.py
8
+ gitlab_ci_verify/process.py
9
+ gitlab_ci_verify.egg-info/PKG-INFO
10
+ gitlab_ci_verify.egg-info/SOURCES.txt
11
+ gitlab_ci_verify.egg-info/dependency_links.txt
12
+ gitlab_ci_verify.egg-info/requires.txt
13
+ gitlab_ci_verify.egg-info/top_level.txt
@@ -0,0 +1,9 @@
1
+ gitlab-ci-verify-bin==0.*
2
+
3
+ [dev]
4
+ setuptools==70.*
5
+ setuptools-scm==8.*
6
+ twine==5.1.*
7
+ wheel==0.43.*
8
+ pydoctor==24.3.*
9
+ build==1.*
@@ -0,0 +1 @@
1
+ gitlab_ci_verify
@@ -0,0 +1,60 @@
1
+ [project]
2
+ name = "gitlab-ci-verify"
3
+ description = "Validate and lint your gitlab ci files using ShellCheck, the Gitlab API and curated checks"
4
+ authors = [
5
+ { name = "Timo Reymann", email = "mail@timo-reymann.de" }
6
+ ]
7
+ readme = "README.md"
8
+ dynamic = ["version"]
9
+ classifiers = [
10
+ "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
11
+ "Development Status :: 2 - Pre-Alpha",
12
+ "Programming Language :: Python :: 3",
13
+ "Programming Language :: Python :: 3.9",
14
+ "Programming Language :: Python :: 3.10",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Intended Audience :: Developers",
18
+ ]
19
+
20
+ dependencies = [
21
+ "gitlab-ci-verify-bin==0.*"
22
+ ]
23
+
24
+
25
+ [project.optional-dependencies]
26
+ dev = [
27
+ "setuptools==70.*",
28
+ "setuptools-scm==8.*",
29
+ "twine==5.1.*",
30
+ "wheel==0.43.*",
31
+ "pydoctor==24.3.*",
32
+ "build==1.*"
33
+ ]
34
+
35
+
36
+ [tool.setuptools_scm]
37
+ root = ".."
38
+
39
+ [tool.pydoctor]
40
+ verbose = 0
41
+ warnings-as-errors = true
42
+
43
+ intersphinx = ["https://docs.python.org/3/objects.inv"]
44
+ docformat = "restructuredtext"
45
+ html-output = "gh-pages"
46
+
47
+ add-package = ["gitlab_ci_verify"]
48
+ project-name = "gitlab_ci_verify"
49
+ project-url = "https://github.com/timo-reymann/gitlab-ci-verify"
50
+
51
+ theme = "base"
52
+ template-dir = "pydoctor-theme"
53
+
54
+ [build-system]
55
+ requires = [
56
+ "setuptools",
57
+ "setuptools-scm",
58
+ "wheel",
59
+ ]
60
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+