bitwarden_workflow_linter 0.0.3__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.
- bitwarden_workflow_linter/__about__.py +3 -0
- bitwarden_workflow_linter/__init__.py +0 -0
- bitwarden_workflow_linter/actions.py +218 -0
- bitwarden_workflow_linter/cli.py +55 -0
- bitwarden_workflow_linter/default_actions.json +262 -0
- bitwarden_workflow_linter/default_settings.yaml +8 -0
- bitwarden_workflow_linter/lint.py +173 -0
- bitwarden_workflow_linter/load.py +146 -0
- bitwarden_workflow_linter/models/__init__.py +0 -0
- bitwarden_workflow_linter/models/job.py +56 -0
- bitwarden_workflow_linter/models/step.py +48 -0
- bitwarden_workflow_linter/models/workflow.py +45 -0
- bitwarden_workflow_linter/rule.py +101 -0
- bitwarden_workflow_linter/rules/__init__.py +0 -0
- bitwarden_workflow_linter/rules/job_environment_prefix.py +72 -0
- bitwarden_workflow_linter/rules/name_capitalized.py +56 -0
- bitwarden_workflow_linter/rules/name_exists.py +59 -0
- bitwarden_workflow_linter/rules/pinned_job_runner.py +52 -0
- bitwarden_workflow_linter/rules/step_approved.py +101 -0
- bitwarden_workflow_linter/rules/step_pinned.py +98 -0
- bitwarden_workflow_linter/utils.py +179 -0
- bitwarden_workflow_linter-0.0.3.dist-info/METADATA +182 -0
- bitwarden_workflow_linter-0.0.3.dist-info/RECORD +26 -0
- bitwarden_workflow_linter-0.0.3.dist-info/WHEEL +4 -0
- bitwarden_workflow_linter-0.0.3.dist-info/entry_points.txt +2 -0
- bitwarden_workflow_linter-0.0.3.dist-info/licenses/LICENSE.txt +674 -0
@@ -0,0 +1,182 @@
|
|
1
|
+
Metadata-Version: 2.3
|
2
|
+
Name: bitwarden_workflow_linter
|
3
|
+
Version: 0.0.3
|
4
|
+
Summary: Custom GitHub Action Workflow Linter
|
5
|
+
Project-URL: Homepage, https://github.com/bitwarden/workflow-linter
|
6
|
+
Project-URL: Issues, https://github.com/bitwarden/workflow-linter/issues
|
7
|
+
License-File: LICENSE.txt
|
8
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
9
|
+
Classifier: Operating System :: OS Independent
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
11
|
+
Requires-Python: >=3.11
|
12
|
+
Requires-Dist: annotated-types==0.7.0
|
13
|
+
Requires-Dist: dataclasses-json==0.6.6
|
14
|
+
Requires-Dist: marshmallow==3.21.2
|
15
|
+
Requires-Dist: mypy-extensions==1.0.0
|
16
|
+
Requires-Dist: packaging==24.0
|
17
|
+
Requires-Dist: pydantic-core==2.18.3
|
18
|
+
Requires-Dist: pydantic==2.7.2
|
19
|
+
Requires-Dist: pyyaml==6.0.1
|
20
|
+
Requires-Dist: ruamel-yaml-clib==0.2.8
|
21
|
+
Requires-Dist: ruamel-yaml==0.18.6
|
22
|
+
Requires-Dist: typing-extensions==4.12.0
|
23
|
+
Requires-Dist: typing-inspect==0.9.0
|
24
|
+
Requires-Dist: urllib3==2.2.1
|
25
|
+
Description-Content-Type: text/markdown
|
26
|
+
|
27
|
+
# Bitwarden Workflow Linter
|
28
|
+
|
29
|
+
Bitwarden's Workflow Linter is an extensible linter to apply opinionated organization-specific
|
30
|
+
GitHub Action standards. It was designed to be used alongside tools like
|
31
|
+
[action-lint](https://github.com/rhysd/actionlint) and
|
32
|
+
[yamllint](https://github.com/adrienverge/yamllint) to check for correct Action syntax and enforce
|
33
|
+
specific YAML standards.
|
34
|
+
|
35
|
+
To see an example of Workflow Linter in practice in GitHub Action, see the
|
36
|
+
[composite Action](https://github.com/bitwarden/gh-actions/tree/main/lint-workflow).
|
37
|
+
|
38
|
+
## Installation
|
39
|
+
|
40
|
+
## From GitHub Release
|
41
|
+
|
42
|
+
```
|
43
|
+
Not yet implemented
|
44
|
+
```
|
45
|
+
|
46
|
+
### Locally
|
47
|
+
|
48
|
+
```
|
49
|
+
git clone git@github.com:bitwarden/workflow-linter.git
|
50
|
+
cd workflow-linter
|
51
|
+
|
52
|
+
pip install -e .
|
53
|
+
```
|
54
|
+
|
55
|
+
## Usage
|
56
|
+
|
57
|
+
### Setup settings.yaml
|
58
|
+
|
59
|
+
If a non-default configuration is desired (different than `src/bitwarden_workflow_linter/default_settings.yaml`), copy
|
60
|
+
the below and create a `settings.yaml` in the directory that `bwwl` will be running from.
|
61
|
+
|
62
|
+
```yaml
|
63
|
+
enabled_rules:
|
64
|
+
- bitwarden_workflow_linter.rules.name_exists.RuleNameExists
|
65
|
+
- bitwarden_workflow_linter.rules.name_capitalized.RuleNameCapitalized
|
66
|
+
- bitwarden_workflow_linter.rules.pinned_job_runner.RuleJobRunnerVersionPinned
|
67
|
+
- bitwarden_workflow_linter.rules.job_environment_prefix.RuleJobEnvironmentPrefix
|
68
|
+
- bitwarden_workflow_linter.rules.step_pinned.RuleStepUsesPinned
|
69
|
+
|
70
|
+
approved_actions_path: default_actions.json
|
71
|
+
```
|
72
|
+
|
73
|
+
```
|
74
|
+
usage: bwwl [-h] [-v] {lint,actions} ...
|
75
|
+
|
76
|
+
positional arguments:
|
77
|
+
{lint,actions}
|
78
|
+
lint Verify that a GitHub Action Workflow follows all of the Rules.
|
79
|
+
actions Add or Update Actions in the pre-approved list.
|
80
|
+
|
81
|
+
options:
|
82
|
+
-h, --help show this help message and exit
|
83
|
+
-v, --verbose
|
84
|
+
```
|
85
|
+
|
86
|
+
## Development
|
87
|
+
|
88
|
+
### Requirements
|
89
|
+
|
90
|
+
- Python 3.11
|
91
|
+
- pipenv
|
92
|
+
|
93
|
+
### Setup
|
94
|
+
|
95
|
+
```
|
96
|
+
pipenv install --dev
|
97
|
+
pipenv shell
|
98
|
+
```
|
99
|
+
|
100
|
+
### Testing
|
101
|
+
|
102
|
+
All built-in `src/bitwarden_workflow_linter/rules` should have 100% code coverage and we should shoot for an overall coverage of 80%+.
|
103
|
+
We are lax on the
|
104
|
+
[imperative shell](https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell)
|
105
|
+
(code interacting with other systems; ie. disk, network, etc), but we strive to maintain a high coverage over the
|
106
|
+
functional core (objects and models).
|
107
|
+
|
108
|
+
```
|
109
|
+
pipenv shell
|
110
|
+
pytest tests --cov=src
|
111
|
+
```
|
112
|
+
|
113
|
+
### Code Reformatting
|
114
|
+
|
115
|
+
We adhere to PEP8 and use `black` to maintain this adherence. `black` should be run on any change being merged
|
116
|
+
to `main`.
|
117
|
+
|
118
|
+
```
|
119
|
+
pipenv shell
|
120
|
+
black .
|
121
|
+
```
|
122
|
+
|
123
|
+
### Linting
|
124
|
+
|
125
|
+
We loosely use [Google's Python style guide](https://google.github.io/styleguide/pyguide.html), but yield to
|
126
|
+
`black` when there is a conflict
|
127
|
+
|
128
|
+
```
|
129
|
+
pipenv shell
|
130
|
+
pylint --rcfile pylintrc src/ tests/
|
131
|
+
```
|
132
|
+
|
133
|
+
### Add a new Rule
|
134
|
+
|
135
|
+
A new Rule is created by extending the Rule base class and overriding the `fn(obj: Union[Workflow, Job, Step])` method.
|
136
|
+
Available attributes of `Workflows`, `Jobs` and `Steps` can be found in their definitons under `src/models`.
|
137
|
+
|
138
|
+
For a simple example, we'll take a look at enforcing the existence of the `name` key in a Job. This is already done by
|
139
|
+
default with the src.rules.name_exists.RuleNameExists, but provides a simple enough example to walk through.
|
140
|
+
|
141
|
+
```python
|
142
|
+
from typing import Union, Tuple
|
143
|
+
|
144
|
+
from ..rule import Rule
|
145
|
+
from ..models.job import Job
|
146
|
+
from ..models.workflow import Workflow
|
147
|
+
from ..models.step import Step
|
148
|
+
from ..utils import LintLevels, Settings
|
149
|
+
|
150
|
+
|
151
|
+
class RuleJobNameExists(Rule):
|
152
|
+
def __init__(self, settings: Settings = None) -> None:
|
153
|
+
self.message = "name must exist"
|
154
|
+
self.on_fail: LintLevels = LintLevels.ERROR
|
155
|
+
self.compatibility: List[Union[Workflow, Job, Step]] = [Job]
|
156
|
+
self.settings: Settings = settings
|
157
|
+
|
158
|
+
def fn(self, obj: Job) -> Tuple[bool, str]:
|
159
|
+
"""<doc block goes here> """
|
160
|
+
if obj.name is not None:
|
161
|
+
return True, ""
|
162
|
+
return False, self.message
|
163
|
+
```
|
164
|
+
|
165
|
+
By default, a new Rule needs five things:
|
166
|
+
|
167
|
+
- `self.message`: The message to return to the user on a lint failure
|
168
|
+
- `self.on_fail`: The level of failure on a lint failure (NONE, WARNING, ERROR).
|
169
|
+
NONE and WARNING will exit with a code of 0 (unless using `strict` mode for WARNING).
|
170
|
+
ERROR will exit with a non-zero exit code
|
171
|
+
- `self.compatibility`: The list of objects this rule is compatible with. This is used to create separate instances of
|
172
|
+
the Rule for each object in the Rules collection.
|
173
|
+
- `self.settings`: In general, this should default to what is shown here, but allows for overrides
|
174
|
+
- `self.fn`: The function doing the actual work to check the object and enforce the standard.
|
175
|
+
|
176
|
+
`fn` can be as simple or as complex as it needs to be to run a check on a _single_ object. This linter currently does
|
177
|
+
not support Rules that check against multiple objects at a time OR file level formatting (one empty between each step or
|
178
|
+
two empty lines between each job)
|
179
|
+
|
180
|
+
### ToDo
|
181
|
+
|
182
|
+
- [ ] Add Rule to assert correct format for single line run
|
@@ -0,0 +1,26 @@
|
|
1
|
+
bitwarden_workflow_linter/__about__.py,sha256=KbbxYy_rLR2HkiKmhQYMcL4RRAhh7MG3ylAz_mbGpQo,59
|
2
|
+
bitwarden_workflow_linter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
+
bitwarden_workflow_linter/actions.py,sha256=daob3be2Y22gfsAmGhTgBRCgGk18mlGduqc5Zn1Onz4,7897
|
4
|
+
bitwarden_workflow_linter/cli.py,sha256=oM3Cjo2y5NrzN1BfqGRiOhOC6IzPDEnEh14v3bsiqak,1700
|
5
|
+
bitwarden_workflow_linter/default_actions.json,sha256=BeFllnAu9v6cX6eeGeNoQf3rXs7ZOjAtjTNBQuAZ8-k,8087
|
6
|
+
bitwarden_workflow_linter/default_settings.yaml,sha256=yRvAt06Hupv7mSrSGGdWKJruecvEO55CazIbxP34plg,428
|
7
|
+
bitwarden_workflow_linter/lint.py,sha256=z83h7XOnULngPqTwlo5LKCK2ciUu4oalwixKVcFLWac,5461
|
8
|
+
bitwarden_workflow_linter/load.py,sha256=FYbSKgjVCleqiYKR_dB92C3EcP89knNMkxVr2yZZO9o,4473
|
9
|
+
bitwarden_workflow_linter/rule.py,sha256=Qb60JiUDAWN3ayrMGoSbbDCSFmw-ql8djzAkxISaob4,3250
|
10
|
+
bitwarden_workflow_linter/utils.py,sha256=IN_jSZQXRwutgFQ6n7xtD1OrTpx9YS_cHLZKDOEUhfc,4696
|
11
|
+
bitwarden_workflow_linter/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
12
|
+
bitwarden_workflow_linter/models/job.py,sha256=YXzs5CIIM1WEtzAk918QfIioqLcdr4vCOr3fs0uVEu0,1929
|
13
|
+
bitwarden_workflow_linter/models/step.py,sha256=1bKAtKZmHcO8O1e_HuoXxR1bwHDEXUssYo7EHOjY7QI,1711
|
14
|
+
bitwarden_workflow_linter/models/workflow.py,sha256=MkqvIY4JX2eWFODNTodS_l4I8uUq08WCHy3C4kYcL0s,1395
|
15
|
+
bitwarden_workflow_linter/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
16
|
+
bitwarden_workflow_linter/rules/job_environment_prefix.py,sha256=QCYNj-sX5VB5v49OkBdmFGDkm1E2ebcfiAvlkDVNx7g,2415
|
17
|
+
bitwarden_workflow_linter/rules/name_capitalized.py,sha256=3IXvE_vCZ097P7gtHbhQZlwi83Rt239iJfVjmgG26to,1752
|
18
|
+
bitwarden_workflow_linter/rules/name_exists.py,sha256=MxcaNQz64JXeHRPiOip9BxJNgPdpKQa7Z51mDoNw2hU,1681
|
19
|
+
bitwarden_workflow_linter/rules/pinned_job_runner.py,sha256=Dm6_sdPX0yFMji_y2LMFj4gWFaToEgauyBVpNRP2qiI,1606
|
20
|
+
bitwarden_workflow_linter/rules/step_approved.py,sha256=UIi9_z9j75SpQUmo29MLDhjLklqd4h0D-UYqkdcaju0,3307
|
21
|
+
bitwarden_workflow_linter/rules/step_pinned.py,sha256=JSdKW-2Z8_ozQ3aAU7oYYt2ym3GLEilMfXBVqj1QU_E,3286
|
22
|
+
bitwarden_workflow_linter-0.0.3.dist-info/METADATA,sha256=5Wg-TjUZxbvnihnAX8HkbsEVEh_30-hJxnslx-pujTE,5912
|
23
|
+
bitwarden_workflow_linter-0.0.3.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
|
24
|
+
bitwarden_workflow_linter-0.0.3.dist-info/entry_points.txt,sha256=SA_yF9CwL4VMUvdcmCd7k9rjsQNzfeOUBuDnMnaO8QQ,60
|
25
|
+
bitwarden_workflow_linter-0.0.3.dist-info/licenses/LICENSE.txt,sha256=uY-7N9tbI7xc_c0WeTIGpacSCnsB91N05eCIg3bkaRw,35140
|
26
|
+
bitwarden_workflow_linter-0.0.3.dist-info/RECORD,,
|