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.
@@ -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,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.25.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ bwwl = bitwarden_workflow_linter.cli:main