bitwarden_workflow_linter 0.12.2__tar.gz → 0.12.3__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 (93) hide show
  1. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/workflows/bwwl_operations.yml +2 -2
  2. bitwarden_workflow_linter-0.12.3/.python-version +1 -0
  3. bitwarden_workflow_linter-0.12.3/PKG-INFO +274 -0
  4. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/Pipfile +1 -1
  5. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/Pipfile.lock +1 -1
  6. bitwarden_workflow_linter-0.12.3/README.md +248 -0
  7. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/__about__.py +1 -1
  8. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/default_actions.json +5 -0
  9. bitwarden_workflow_linter-0.12.2/.python-version +0 -1
  10. bitwarden_workflow_linter-0.12.2/PKG-INFO +0 -200
  11. bitwarden_workflow_linter-0.12.2/README.md +0 -174
  12. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.editorconfig +0 -0
  13. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.gitattributes +0 -0
  14. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/CODEOWNERS +0 -0
  15. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  16. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  17. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/renovate.json +0 -0
  18. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/workflows/_version_type.yml +0 -0
  19. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/workflows/cd.yml +0 -0
  20. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/workflows/ci.yml +0 -0
  21. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/workflows/enforce-labels.yml +0 -0
  22. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/workflows/examples/ci.yaml +0 -0
  23. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/workflows/examples/example-references/_build.yml +0 -0
  24. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/workflows/examples/example-references/_docker.yml +0 -0
  25. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/workflows/examples/example-references/_test.yml +0 -0
  26. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/workflows/examples/example-references/_version.yml +0 -0
  27. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/workflows/examples/example.yaml +0 -0
  28. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/workflows/examples/scan.yaml +0 -0
  29. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.github/workflows/scan.yml +0 -0
  30. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.gitignore +0 -0
  31. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/.husky/pre-commit +0 -0
  32. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/CONTRIBUTING.md +0 -0
  33. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/LICENSE.txt +0 -0
  34. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/RULE_ROLLOUT.md +0 -0
  35. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/SECURITY.md +0 -0
  36. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/Taskfile.yml +0 -0
  37. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/package-lock.json +0 -0
  38. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/package.json +0 -0
  39. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/pylintrc +0 -0
  40. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/pyproject.toml +0 -0
  41. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/pyproject.toml.tpl +0 -0
  42. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/settings.yaml +0 -0
  43. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/__init__.py +0 -0
  44. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/actions.py +0 -0
  45. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/cli.py +0 -0
  46. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/default_settings.yaml +0 -0
  47. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/lint.py +0 -0
  48. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/load.py +0 -0
  49. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/models/__init__.py +0 -0
  50. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/models/job.py +0 -0
  51. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/models/step.py +0 -0
  52. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/models/workflow.py +0 -0
  53. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rule.py +0 -0
  54. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/__init__.py +0 -0
  55. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/check_pr_target.py +0 -0
  56. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/job_environment_prefix.py +0 -0
  57. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/name_capitalized.py +0 -0
  58. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/name_exists.py +0 -0
  59. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/permissions_exist.py +0 -0
  60. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/pinned_job_runner.py +0 -0
  61. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/run_actionlint.py +0 -0
  62. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/step_approved.py +0 -0
  63. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/step_pinned.py +0 -0
  64. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/underscore_outputs.py +0 -0
  65. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/utils.py +0 -0
  66. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/__init__.py +0 -0
  67. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/conftest.py +0 -0
  68. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test-alt.yml +0 -0
  69. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test-min-incorrect.yaml +0 -0
  70. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test-min.yaml +0 -0
  71. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test-outputs-incorrect.yml +0 -0
  72. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test.yml +0 -0
  73. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test_a.yaml +0 -0
  74. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test_workflow.yaml +0 -0
  75. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test_workflow_incorrect.yaml +0 -0
  76. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/rules/__init__.py +0 -0
  77. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_check_pr_target.py +0 -0
  78. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_job_environment_prefix.py +0 -0
  79. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_name_capitalized.py +0 -0
  80. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_name_exists.py +0 -0
  81. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_permissions_exist.py +0 -0
  82. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_pinned_job_runner.py +0 -0
  83. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_run_actionlint.py +0 -0
  84. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_step_approved.py +0 -0
  85. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_step_pinned.py +0 -0
  86. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_underscore_output.py +0 -0
  87. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/test_job.py +0 -0
  88. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/test_lint.py +0 -0
  89. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/test_load.py +0 -0
  90. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/test_rule.py +0 -0
  91. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/test_step.py +0 -0
  92. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/test_utils.py +0 -0
  93. {bitwarden_workflow_linter-0.12.2 → bitwarden_workflow_linter-0.12.3}/tests/test_workflow.py +0 -0
@@ -54,10 +54,10 @@ jobs:
54
54
  git config --local user.email "106330231+bitwarden-devops-bot@users.noreply.github.com"
55
55
  git config --local user.name "bitwarden-devops-bot"
56
56
 
57
- - name: Set up Python 3.11
57
+ - name: Set up Python 3.12
58
58
  uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
59
59
  with:
60
- python-version: "3.11"
60
+ python-version: "3.12"
61
61
 
62
62
  - name: Install bwwl binary
63
63
  run: python -m pip install --upgrade bitwarden_workflow_linter
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,274 @@
1
+ Metadata-Version: 2.4
2
+ Name: bitwarden_workflow_linter
3
+ Version: 0.12.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 GitHub Action standards. It was designed to be used alongside [yamllint](https://github.com/adrienverge/yamllint) to enforce specific YAML standards.
30
+
31
+ To see an example of Workflow Linter in practice in GitHub Action, see the [composite Action](https://github.com/bitwarden/gh-actions/tree/main/lint-workflow).
32
+
33
+ ## Prerequisites
34
+
35
+ - Python 3.12
36
+ - pipenv
37
+ - Windows systems: Chocolatey package manager
38
+ - Mac OS systems: Homebrew package manager
39
+ - pipx
40
+
41
+ ## Setup
42
+
43
+ 1. **Create the virtual environment:**
44
+ ```bash
45
+ python3.12 -m venv /Users/$USER/bitwarden_workflow_linter_venv
46
+ ```
47
+
48
+ 2. **Activate the virtual environment:**
49
+ ```bash
50
+ source /Users/$USER/bitwarden_workflow_linter_venv/bin/activate
51
+ ```
52
+
53
+ ## Installation
54
+
55
+ ### From PyPI
56
+ This is the recommended method for most users. Installing from PyPI ensures you get the latest stable release and is the easiest way to install and update the package.
57
+
58
+
59
+ 1. **Install Bitwarden Workflow Linter:**
60
+ ```bash
61
+ pip install --upgrade bitwarden_workflow_linter
62
+ ```
63
+
64
+ 2. **Deactivate the virtual environment (optional):**
65
+ ```bash
66
+ deactivate
67
+ ```
68
+ #### Using pipx
69
+
70
+ Alternatively, you can install `bwwl` globally using `pipx` to keep it isolated:
71
+
72
+ 1. **Install Bitwarden Workflow Linter:**
73
+ ```bash
74
+ pipx install bitwarden_workflow_linter --python python3.12
75
+ ```
76
+
77
+ This method is ideal for running `bwwl` as a standalone CLI tool without managing a virtual environment manually.
78
+
79
+ ### From GitHub Release
80
+ Use this method if you need a specific version of the package that is not yet available on PyPI, or if you want to access pre-release versions.
81
+
82
+ 1. **Download the release tarball or zip file from GitHub:**
83
+ ```bash
84
+ wget https://github.com/bitwarden/workflow-linter/archive/refs/tags/vX.Y.Z.tar.gz
85
+ tar -xzf vX.Y.Z.tar.gz
86
+ cd workflow-linter-X.Y.Z
87
+ ```
88
+
89
+ 2. **Install the package:**
90
+ ```bash
91
+ pip install .
92
+ ```
93
+
94
+ 3. **Deactivate the virtual environment (optional):**
95
+ ```bash
96
+ deactivate
97
+ ```
98
+
99
+ ### Locally
100
+ This method is useful for developers who want to contribute to the project or need to make local modifications to the source code. *Make sure to follow the virtual environment prerequisite setup*
101
+ 1. **Clone the repository:**
102
+ ```bash
103
+ git clone git@github.com:bitwarden/workflow-linter.git
104
+ cd workflow-linter
105
+ ```
106
+
107
+ 2. **Install the package:**
108
+ ```bash
109
+ pip install -e .
110
+ ```
111
+
112
+ 3. **Deactivate the virtual environment (optional):**
113
+ ```bash
114
+ deactivate
115
+ ```
116
+
117
+ ## Usage
118
+
119
+ ### Setup settings.yaml
120
+
121
+ If a non-default configuration is desired (different than `src/bitwarden_workflow_linter/default_settings.yaml`), copy the below and create a `settings.yaml` in the directory that `bwwl` will be running from.
122
+
123
+ ```yaml
124
+ enabled_rules:
125
+ - id: bitwarden_workflow_linter.rules.name_exists.RuleNameExists
126
+ level: error
127
+ - id: bitwarden_workflow_linter.rules.name_capitalized.RuleNameCapitalized
128
+ level: error
129
+ - id: bitwarden_workflow_linter.rules.pinned_job_runner.RuleJobRunnerVersionPinned
130
+ level: error
131
+ - id: bitwarden_workflow_linter.rules.job_environment_prefix.RuleJobEnvironmentPrefix
132
+ level: error
133
+ - id: bitwarden_workflow_linter.rules.step_pinned.RuleStepUsesPinned
134
+ level: error
135
+ - id: bitwarden_workflow_linter.rules.underscore_outputs.RuleUnderscoreOutputs
136
+ level: warning
137
+ - id: bitwarden_workflow_linter.rules.run_actionlint.RunActionlint
138
+ level: warning
139
+
140
+ approved_actions_path: default_actions.json
141
+ ```
142
+
143
+ ### Command Line Usage
144
+
145
+ ```bash
146
+ usage: bwwl [-h] [-v] {lint,actions} ...
147
+
148
+ positional arguments:
149
+ {lint,actions}
150
+ lint Verify that a GitHub Action Workflow follows all of the Rules.
151
+ actions Add or Update Actions in the pre-approved list.
152
+
153
+ options:
154
+ -h, --help show this help message and exit
155
+ -v, --verbose
156
+ ```
157
+ ## Pre-commit Hook Setup
158
+
159
+ ### Navigate to the `.git/hooks` directory in the repository you wish to lint:
160
+
161
+ ```bash
162
+ cd .git/hooks
163
+ ```
164
+
165
+ ### Create the `pre-commit` file (if it does not already exist):
166
+
167
+ ```bash
168
+ touch pre-commit
169
+ ```
170
+
171
+ ### Make the script executable:
172
+
173
+ ```bash
174
+ chmod +x pre-commit
175
+ ```
176
+
177
+ ### Edit the `pre-commit` script:
178
+
179
+ Open the `pre-commit` file with your favorite text editor and add the following content, replacing `/Users/$USER/bitwarden_workflow_linter_venv/bin/activate` with the actual path to your virtual environment:
180
+
181
+ ```bash
182
+ #!/bin/bash
183
+ set -e
184
+ # Activate the virtual environment
185
+ source "/Users/$USER/bitwarden_workflow_linter_venv/bin/activate"
186
+ # Get the repository root directory
187
+ repo_root=$(git rev-parse --show-toplevel)
188
+ # Run your Python script
189
+ bwwl lint -f "$repo_root/.github/workflows"
190
+ # Deactivate the virtual environment (optional)
191
+ deactivate
192
+ ```
193
+
194
+ ### Test the Hook:
195
+
196
+ Try committing a change to the repository. The pre-commit hook should run the workflow linter.
197
+
198
+ ## Development
199
+
200
+ ### Setup
201
+ Refer to the [Locally](#locally) instructions above to clone the repository and install the package.
202
+
203
+ ### Testing
204
+
205
+ All built-in `src/bitwarden_workflow_linter/rules` should have 100% code coverage and we should shoot for an overall coverage of 80%+. We are lax on the [imperative shell](https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell) (code interacting with other systems; ie. disk, network, etc), but we strive to maintain a high coverage over the functional core (objects and models).
206
+
207
+ ```bash
208
+ pipenv shell
209
+ pytest tests --cov=src
210
+ ```
211
+
212
+ ### Code Reformatting
213
+
214
+ We adhere to PEP8 and use `black` to maintain this adherence. `black` should be run on any change being merged to `main`.
215
+
216
+ ```bash
217
+ pipenv shell
218
+ black .
219
+ ```
220
+
221
+ ### Linting
222
+
223
+ We loosely use [Google's Python style guide](https://google.github.io/styleguide/pyguide.html), but yield to `black` when there is a conflict.
224
+
225
+ ```bash
226
+ pipenv shell
227
+ pylint --rcfile pylintrc src/ tests/
228
+ ```
229
+
230
+ ### Add a new Rule
231
+
232
+ A new Rule is created by extending the Rule base class and overriding the `fn(obj: Union[Workflow, Job, Step])` method. Available attributes of `Workflows`, `Jobs` and `Steps` can be found in their definitions under `src/models`.
233
+
234
+ 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 default with the `src.rules.name_exists.RuleNameExists`, but provides a simple enough example to walk through.
235
+
236
+ ```python
237
+ from typing import Union, Tuple
238
+
239
+ from ..rule import Rule
240
+ from ..models.job import Job
241
+ from ..models.workflow import Workflow
242
+ from ..models.step import Step
243
+ from ..utils import LintLevels, Settings
244
+
245
+
246
+ class RuleJobNameExists(Rule):
247
+ def __init__(self, settings: Settings = None, lint_level: Optional[LintLevels] = LintLevels.ERROR) -> None:
248
+ self.message = "name must exist"
249
+ self.on_fail: LintLevels = lint_level
250
+ self.compatibility: List[Union[Workflow, Job, Step]] = [Job]
251
+ self.settings: Settings = settings
252
+
253
+ def fn(self, obj: Job) -> Tuple[bool, str]:
254
+ """<doc block goes here> """
255
+ if obj.name is not None:
256
+ return True, ""
257
+ return False, self.message
258
+ ```
259
+
260
+ By default, a new Rule needs five things:
261
+
262
+ - `self.message`: The message to return to the user on a lint failure
263
+ - `self.on_fail`: The level of failure on a lint failure (NONE, WARNING, ERROR). NONE and WARNING will exit with a code of 0 (unless using `strict` mode for WARNING). ERROR will exit with a non-zero exit code
264
+ - `self.compatibility`: The list of objects this rule is compatible with. This is used to create separate instances of the Rule for each object in the Rules collection.
265
+ - `self.settings`: In general, this should default to what is shown here, but allows for overrides
266
+ - `self.fn`: The function doing the actual work to check the object and enforce the standard.
267
+
268
+ `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 not support Rules that check against multiple objects at a time OR file level formatting (one empty between each step or two empty lines between each job).
269
+
270
+ _IMPORTANT: A rule must be implemented and tested then merged into `main` before it can be activated._ This is because the released version of `bwwl` will use the current `settings.yaml` file, but it will not have the new rule functionality yet and cause an error in the workflow linting of this repository.
271
+
272
+ To activate a rule after implementing and releasing it, add it to `settings.yaml` in the project's base folder and `src/bitwarden_workflow_linter/default_settings.yaml` to make the rule default.
273
+
274
+ Before creating a new rule please read the [Workflow linter rule rollout process](./RULE_ROLLOUT.md) document in which you'll find the process for rolling out new workflow linter rules.
@@ -21,4 +21,4 @@ hatchling = "*"
21
21
  build = "*"
22
22
 
23
23
  [requires]
24
- python_version = "3.11"
24
+ python_version = "3.12"
@@ -5,7 +5,7 @@
5
5
  },
6
6
  "pipfile-spec": 6,
7
7
  "requires": {
8
- "python_version": "3.11"
8
+ "python_version": "3.12"
9
9
  },
10
10
  "sources": [
11
11
  {
@@ -0,0 +1,248 @@
1
+ # Bitwarden Workflow Linter
2
+
3
+ Bitwarden's Workflow Linter is an extensible linter to apply opinionated organization-specific GitHub Action standards. It was designed to be used alongside [yamllint](https://github.com/adrienverge/yamllint) to enforce specific YAML standards.
4
+
5
+ To see an example of Workflow Linter in practice in GitHub Action, see the [composite Action](https://github.com/bitwarden/gh-actions/tree/main/lint-workflow).
6
+
7
+ ## Prerequisites
8
+
9
+ - Python 3.12
10
+ - pipenv
11
+ - Windows systems: Chocolatey package manager
12
+ - Mac OS systems: Homebrew package manager
13
+ - pipx
14
+
15
+ ## Setup
16
+
17
+ 1. **Create the virtual environment:**
18
+ ```bash
19
+ python3.12 -m venv /Users/$USER/bitwarden_workflow_linter_venv
20
+ ```
21
+
22
+ 2. **Activate the virtual environment:**
23
+ ```bash
24
+ source /Users/$USER/bitwarden_workflow_linter_venv/bin/activate
25
+ ```
26
+
27
+ ## Installation
28
+
29
+ ### From PyPI
30
+ This is the recommended method for most users. Installing from PyPI ensures you get the latest stable release and is the easiest way to install and update the package.
31
+
32
+
33
+ 1. **Install Bitwarden Workflow Linter:**
34
+ ```bash
35
+ pip install --upgrade bitwarden_workflow_linter
36
+ ```
37
+
38
+ 2. **Deactivate the virtual environment (optional):**
39
+ ```bash
40
+ deactivate
41
+ ```
42
+ #### Using pipx
43
+
44
+ Alternatively, you can install `bwwl` globally using `pipx` to keep it isolated:
45
+
46
+ 1. **Install Bitwarden Workflow Linter:**
47
+ ```bash
48
+ pipx install bitwarden_workflow_linter --python python3.12
49
+ ```
50
+
51
+ This method is ideal for running `bwwl` as a standalone CLI tool without managing a virtual environment manually.
52
+
53
+ ### From GitHub Release
54
+ Use this method if you need a specific version of the package that is not yet available on PyPI, or if you want to access pre-release versions.
55
+
56
+ 1. **Download the release tarball or zip file from GitHub:**
57
+ ```bash
58
+ wget https://github.com/bitwarden/workflow-linter/archive/refs/tags/vX.Y.Z.tar.gz
59
+ tar -xzf vX.Y.Z.tar.gz
60
+ cd workflow-linter-X.Y.Z
61
+ ```
62
+
63
+ 2. **Install the package:**
64
+ ```bash
65
+ pip install .
66
+ ```
67
+
68
+ 3. **Deactivate the virtual environment (optional):**
69
+ ```bash
70
+ deactivate
71
+ ```
72
+
73
+ ### Locally
74
+ This method is useful for developers who want to contribute to the project or need to make local modifications to the source code. *Make sure to follow the virtual environment prerequisite setup*
75
+ 1. **Clone the repository:**
76
+ ```bash
77
+ git clone git@github.com:bitwarden/workflow-linter.git
78
+ cd workflow-linter
79
+ ```
80
+
81
+ 2. **Install the package:**
82
+ ```bash
83
+ pip install -e .
84
+ ```
85
+
86
+ 3. **Deactivate the virtual environment (optional):**
87
+ ```bash
88
+ deactivate
89
+ ```
90
+
91
+ ## Usage
92
+
93
+ ### Setup settings.yaml
94
+
95
+ If a non-default configuration is desired (different than `src/bitwarden_workflow_linter/default_settings.yaml`), copy the below and create a `settings.yaml` in the directory that `bwwl` will be running from.
96
+
97
+ ```yaml
98
+ enabled_rules:
99
+ - id: bitwarden_workflow_linter.rules.name_exists.RuleNameExists
100
+ level: error
101
+ - id: bitwarden_workflow_linter.rules.name_capitalized.RuleNameCapitalized
102
+ level: error
103
+ - id: bitwarden_workflow_linter.rules.pinned_job_runner.RuleJobRunnerVersionPinned
104
+ level: error
105
+ - id: bitwarden_workflow_linter.rules.job_environment_prefix.RuleJobEnvironmentPrefix
106
+ level: error
107
+ - id: bitwarden_workflow_linter.rules.step_pinned.RuleStepUsesPinned
108
+ level: error
109
+ - id: bitwarden_workflow_linter.rules.underscore_outputs.RuleUnderscoreOutputs
110
+ level: warning
111
+ - id: bitwarden_workflow_linter.rules.run_actionlint.RunActionlint
112
+ level: warning
113
+
114
+ approved_actions_path: default_actions.json
115
+ ```
116
+
117
+ ### Command Line Usage
118
+
119
+ ```bash
120
+ usage: bwwl [-h] [-v] {lint,actions} ...
121
+
122
+ positional arguments:
123
+ {lint,actions}
124
+ lint Verify that a GitHub Action Workflow follows all of the Rules.
125
+ actions Add or Update Actions in the pre-approved list.
126
+
127
+ options:
128
+ -h, --help show this help message and exit
129
+ -v, --verbose
130
+ ```
131
+ ## Pre-commit Hook Setup
132
+
133
+ ### Navigate to the `.git/hooks` directory in the repository you wish to lint:
134
+
135
+ ```bash
136
+ cd .git/hooks
137
+ ```
138
+
139
+ ### Create the `pre-commit` file (if it does not already exist):
140
+
141
+ ```bash
142
+ touch pre-commit
143
+ ```
144
+
145
+ ### Make the script executable:
146
+
147
+ ```bash
148
+ chmod +x pre-commit
149
+ ```
150
+
151
+ ### Edit the `pre-commit` script:
152
+
153
+ Open the `pre-commit` file with your favorite text editor and add the following content, replacing `/Users/$USER/bitwarden_workflow_linter_venv/bin/activate` with the actual path to your virtual environment:
154
+
155
+ ```bash
156
+ #!/bin/bash
157
+ set -e
158
+ # Activate the virtual environment
159
+ source "/Users/$USER/bitwarden_workflow_linter_venv/bin/activate"
160
+ # Get the repository root directory
161
+ repo_root=$(git rev-parse --show-toplevel)
162
+ # Run your Python script
163
+ bwwl lint -f "$repo_root/.github/workflows"
164
+ # Deactivate the virtual environment (optional)
165
+ deactivate
166
+ ```
167
+
168
+ ### Test the Hook:
169
+
170
+ Try committing a change to the repository. The pre-commit hook should run the workflow linter.
171
+
172
+ ## Development
173
+
174
+ ### Setup
175
+ Refer to the [Locally](#locally) instructions above to clone the repository and install the package.
176
+
177
+ ### Testing
178
+
179
+ All built-in `src/bitwarden_workflow_linter/rules` should have 100% code coverage and we should shoot for an overall coverage of 80%+. We are lax on the [imperative shell](https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell) (code interacting with other systems; ie. disk, network, etc), but we strive to maintain a high coverage over the functional core (objects and models).
180
+
181
+ ```bash
182
+ pipenv shell
183
+ pytest tests --cov=src
184
+ ```
185
+
186
+ ### Code Reformatting
187
+
188
+ We adhere to PEP8 and use `black` to maintain this adherence. `black` should be run on any change being merged to `main`.
189
+
190
+ ```bash
191
+ pipenv shell
192
+ black .
193
+ ```
194
+
195
+ ### Linting
196
+
197
+ We loosely use [Google's Python style guide](https://google.github.io/styleguide/pyguide.html), but yield to `black` when there is a conflict.
198
+
199
+ ```bash
200
+ pipenv shell
201
+ pylint --rcfile pylintrc src/ tests/
202
+ ```
203
+
204
+ ### Add a new Rule
205
+
206
+ A new Rule is created by extending the Rule base class and overriding the `fn(obj: Union[Workflow, Job, Step])` method. Available attributes of `Workflows`, `Jobs` and `Steps` can be found in their definitions under `src/models`.
207
+
208
+ 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 default with the `src.rules.name_exists.RuleNameExists`, but provides a simple enough example to walk through.
209
+
210
+ ```python
211
+ from typing import Union, Tuple
212
+
213
+ from ..rule import Rule
214
+ from ..models.job import Job
215
+ from ..models.workflow import Workflow
216
+ from ..models.step import Step
217
+ from ..utils import LintLevels, Settings
218
+
219
+
220
+ class RuleJobNameExists(Rule):
221
+ def __init__(self, settings: Settings = None, lint_level: Optional[LintLevels] = LintLevels.ERROR) -> None:
222
+ self.message = "name must exist"
223
+ self.on_fail: LintLevels = lint_level
224
+ self.compatibility: List[Union[Workflow, Job, Step]] = [Job]
225
+ self.settings: Settings = settings
226
+
227
+ def fn(self, obj: Job) -> Tuple[bool, str]:
228
+ """<doc block goes here> """
229
+ if obj.name is not None:
230
+ return True, ""
231
+ return False, self.message
232
+ ```
233
+
234
+ By default, a new Rule needs five things:
235
+
236
+ - `self.message`: The message to return to the user on a lint failure
237
+ - `self.on_fail`: The level of failure on a lint failure (NONE, WARNING, ERROR). NONE and WARNING will exit with a code of 0 (unless using `strict` mode for WARNING). ERROR will exit with a non-zero exit code
238
+ - `self.compatibility`: The list of objects this rule is compatible with. This is used to create separate instances of the Rule for each object in the Rules collection.
239
+ - `self.settings`: In general, this should default to what is shown here, but allows for overrides
240
+ - `self.fn`: The function doing the actual work to check the object and enforce the standard.
241
+
242
+ `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 not support Rules that check against multiple objects at a time OR file level formatting (one empty between each step or two empty lines between each job).
243
+
244
+ _IMPORTANT: A rule must be implemented and tested then merged into `main` before it can be activated._ This is because the released version of `bwwl` will use the current `settings.yaml` file, but it will not have the new rule functionality yet and cause an error in the workflow linting of this repository.
245
+
246
+ To activate a rule after implementing and releasing it, add it to `settings.yaml` in the project's base folder and `src/bitwarden_workflow_linter/default_settings.yaml` to make the rule default.
247
+
248
+ Before creating a new rule please read the [Workflow linter rule rollout process](./RULE_ROLLOUT.md) document in which you'll find the process for rolling out new workflow linter rules.
@@ -1,3 +1,3 @@
1
1
  """Metadata for Workflow Linter."""
2
2
 
3
- __version__ = "0.12.2"
3
+ __version__ = "0.12.3"
@@ -249,6 +249,11 @@
249
249
  "sha": "49b3bc8e6bdd4a60e6116a5414239cba5943d3cf",
250
250
  "version": "v3.2.0"
251
251
  },
252
+ "dorny/paths-filter": {
253
+ "name": "dorny/paths-filter",
254
+ "sha": "de90cc6fb38fc0963ad72b210f1f284cd68cea36",
255
+ "version": "v3.0.2"
256
+ },
252
257
  "dorny/test-reporter": {
253
258
  "name": "dorny/test-reporter",
254
259
  "sha": "31a54ee7ebcacc03a09ea97a7e5465a47b84aea5",
@@ -1 +0,0 @@
1
- 3.11
@@ -1,200 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: bitwarden_workflow_linter
3
- Version: 0.12.2
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
31
- [yamllint](https://github.com/adrienverge/yamllint) to enforce
32
- specific YAML standards.
33
-
34
- To see an example of Workflow Linter in practice in GitHub Action, see the
35
- [composite Action](https://github.com/bitwarden/gh-actions/tree/main/lint-workflow).
36
-
37
- ## Installation
38
-
39
- ## From GitHub Release
40
-
41
- ```
42
- Not yet implemented
43
- ```
44
-
45
- ### Locally
46
-
47
- ```
48
- git clone git@github.com:bitwarden/workflow-linter.git
49
- cd workflow-linter
50
-
51
- pip install -e .
52
- ```
53
-
54
- ## Usage
55
-
56
- ### Setup settings.yaml
57
-
58
- If a non-default configuration is desired (different than `src/bitwarden_workflow_linter/default_settings.yaml`), copy
59
- the below and create a `settings.yaml` in the directory that `bwwl` will be running from.
60
-
61
- ```yaml
62
- enabled_rules:
63
- - id: bitwarden_workflow_linter.rules.name_exists.RuleNameExists
64
- level: error
65
- - id: bitwarden_workflow_linter.rules.name_capitalized.RuleNameCapitalized
66
- level: error
67
- - id: bitwarden_workflow_linter.rules.pinned_job_runner.RuleJobRunnerVersionPinned
68
- level: error
69
- - id: bitwarden_workflow_linter.rules.job_environment_prefix.RuleJobEnvironmentPrefix
70
- level: error
71
- - id: bitwarden_workflow_linter.rules.step_pinned.RuleStepUsesPinned
72
- level: error
73
- - id: bitwarden_workflow_linter.rules.underscore_outputs.RuleUnderscoreOutputs
74
- level: warning
75
- - id: bitwarden_workflow_linter.rules.run_actionlint.RunActionlint
76
- level: warning
77
-
78
- approved_actions_path: default_actions.json
79
- ```
80
-
81
- ```
82
- usage: bwwl [-h] [-v] {lint,actions} ...
83
-
84
- positional arguments:
85
- {lint,actions}
86
- lint Verify that a GitHub Action Workflow follows all of the Rules.
87
- actions Add or Update Actions in the pre-approved list.
88
-
89
- options:
90
- -h, --help show this help message and exit
91
- -v, --verbose
92
- ```
93
-
94
- ## Development
95
-
96
- ### Requirements
97
-
98
- - Python 3.11
99
- - pipenv
100
- - Windows systems: Chocolatey package manager
101
- - Mac OS systems: Homebrew package manager
102
-
103
- ### Setup
104
-
105
- ```
106
- pipenv install --dev
107
- pipenv shell
108
- ```
109
-
110
- ### Testing
111
-
112
- All built-in `src/bitwarden_workflow_linter/rules` should have 100% code coverage and we should shoot for an overall coverage of 80%+.
113
- We are lax on the
114
- [imperative shell](https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell)
115
- (code interacting with other systems; ie. disk, network, etc), but we strive to maintain a high coverage over the
116
- functional core (objects and models).
117
-
118
- ```
119
- pipenv shell
120
- pytest tests --cov=src
121
- ```
122
-
123
- ### Code Reformatting
124
-
125
- We adhere to PEP8 and use `black` to maintain this adherence. `black` should be run on any change being merged
126
- to `main`.
127
-
128
- ```
129
- pipenv shell
130
- black .
131
- ```
132
-
133
- ### Linting
134
-
135
- We loosely use [Google's Python style guide](https://google.github.io/styleguide/pyguide.html), but yield to
136
- `black` when there is a conflict
137
-
138
- ```
139
- pipenv shell
140
- pylint --rcfile pylintrc src/ tests/
141
- ```
142
-
143
- ### Add a new Rule
144
-
145
- A new Rule is created by extending the Rule base class and overriding the `fn(obj: Union[Workflow, Job, Step])` method.
146
- Available attributes of `Workflows`, `Jobs` and `Steps` can be found in their definitons under `src/models`.
147
-
148
- 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
149
- default with the src.rules.name_exists.RuleNameExists, but provides a simple enough example to walk through.
150
-
151
- ```python
152
- from typing import Union, Tuple
153
-
154
- from ..rule import Rule
155
- from ..models.job import Job
156
- from ..models.workflow import Workflow
157
- from ..models.step import Step
158
- from ..utils import LintLevels, Settings
159
-
160
-
161
- class RuleJobNameExists(Rule):
162
- def __init__(self, settings: Settings = None, lint_level: Optional[LintLevels] = LintLevels.ERROR) -> None:
163
- self.message = "name must exist"
164
- self.on_fail: LintLevels = lint_level
165
- self.compatibility: List[Union[Workflow, Job, Step]] = [Job]
166
- self.settings: Settings = settings
167
-
168
- def fn(self, obj: Job) -> Tuple[bool, str]:
169
- """<doc block goes here> """
170
- if obj.name is not None:
171
- return True, ""
172
- return False, self.message
173
- ```
174
-
175
- By default, a new Rule needs five things:
176
-
177
- - `self.message`: The message to return to the user on a lint failure
178
- - `self.on_fail`: The level of failure on a lint failure (NONE, WARNING, ERROR).
179
- NONE and WARNING will exit with a code of 0 (unless using `strict` mode for WARNING).
180
- ERROR will exit with a non-zero exit code
181
- - `self.compatibility`: The list of objects this rule is compatible with. This is used to create separate instances of
182
- the Rule for each object in the Rules collection.
183
- - `self.settings`: In general, this should default to what is shown here, but allows for overrides
184
- - `self.fn`: The function doing the actual work to check the object and enforce the standard.
185
-
186
- `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
187
- not support Rules that check against multiple objects at a time OR file level formatting (one empty between each step or
188
- two empty lines between each job)
189
-
190
- _IMPORTANT: A rule must be implemented and tested then merged into `main` before it can be activated.<br>_
191
- This is because the released version of bwwl will use the current `settings.yaml` file, but it will not have the new rule functionality yet and cause an error in the workflow linting of this repository.
192
-
193
- To activate a rule after implementing and releasing it, add it to `settings.yaml` in the project's base folder
194
- and `src/bitwarden_workflow_linter/default_settings.yaml` to make the rule default
195
-
196
- Before creating a new rule please read the [Workflow linter rule rollout process](./RULE_ROLLOUT.md) document in which you'll find the process for rolling out new workflow linter rules.
197
-
198
- ### To-Do
199
-
200
- - [ ] Add Rule to assert correct format for single line run
@@ -1,174 +0,0 @@
1
- # Bitwarden Workflow Linter
2
-
3
- Bitwarden's Workflow Linter is an extensible linter to apply opinionated organization-specific
4
- GitHub Action standards. It was designed to be used alongside
5
- [yamllint](https://github.com/adrienverge/yamllint) to enforce
6
- specific YAML standards.
7
-
8
- To see an example of Workflow Linter in practice in GitHub Action, see the
9
- [composite Action](https://github.com/bitwarden/gh-actions/tree/main/lint-workflow).
10
-
11
- ## Installation
12
-
13
- ## From GitHub Release
14
-
15
- ```
16
- Not yet implemented
17
- ```
18
-
19
- ### Locally
20
-
21
- ```
22
- git clone git@github.com:bitwarden/workflow-linter.git
23
- cd workflow-linter
24
-
25
- pip install -e .
26
- ```
27
-
28
- ## Usage
29
-
30
- ### Setup settings.yaml
31
-
32
- If a non-default configuration is desired (different than `src/bitwarden_workflow_linter/default_settings.yaml`), copy
33
- the below and create a `settings.yaml` in the directory that `bwwl` will be running from.
34
-
35
- ```yaml
36
- enabled_rules:
37
- - id: bitwarden_workflow_linter.rules.name_exists.RuleNameExists
38
- level: error
39
- - id: bitwarden_workflow_linter.rules.name_capitalized.RuleNameCapitalized
40
- level: error
41
- - id: bitwarden_workflow_linter.rules.pinned_job_runner.RuleJobRunnerVersionPinned
42
- level: error
43
- - id: bitwarden_workflow_linter.rules.job_environment_prefix.RuleJobEnvironmentPrefix
44
- level: error
45
- - id: bitwarden_workflow_linter.rules.step_pinned.RuleStepUsesPinned
46
- level: error
47
- - id: bitwarden_workflow_linter.rules.underscore_outputs.RuleUnderscoreOutputs
48
- level: warning
49
- - id: bitwarden_workflow_linter.rules.run_actionlint.RunActionlint
50
- level: warning
51
-
52
- approved_actions_path: default_actions.json
53
- ```
54
-
55
- ```
56
- usage: bwwl [-h] [-v] {lint,actions} ...
57
-
58
- positional arguments:
59
- {lint,actions}
60
- lint Verify that a GitHub Action Workflow follows all of the Rules.
61
- actions Add or Update Actions in the pre-approved list.
62
-
63
- options:
64
- -h, --help show this help message and exit
65
- -v, --verbose
66
- ```
67
-
68
- ## Development
69
-
70
- ### Requirements
71
-
72
- - Python 3.11
73
- - pipenv
74
- - Windows systems: Chocolatey package manager
75
- - Mac OS systems: Homebrew package manager
76
-
77
- ### Setup
78
-
79
- ```
80
- pipenv install --dev
81
- pipenv shell
82
- ```
83
-
84
- ### Testing
85
-
86
- All built-in `src/bitwarden_workflow_linter/rules` should have 100% code coverage and we should shoot for an overall coverage of 80%+.
87
- We are lax on the
88
- [imperative shell](https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell)
89
- (code interacting with other systems; ie. disk, network, etc), but we strive to maintain a high coverage over the
90
- functional core (objects and models).
91
-
92
- ```
93
- pipenv shell
94
- pytest tests --cov=src
95
- ```
96
-
97
- ### Code Reformatting
98
-
99
- We adhere to PEP8 and use `black` to maintain this adherence. `black` should be run on any change being merged
100
- to `main`.
101
-
102
- ```
103
- pipenv shell
104
- black .
105
- ```
106
-
107
- ### Linting
108
-
109
- We loosely use [Google's Python style guide](https://google.github.io/styleguide/pyguide.html), but yield to
110
- `black` when there is a conflict
111
-
112
- ```
113
- pipenv shell
114
- pylint --rcfile pylintrc src/ tests/
115
- ```
116
-
117
- ### Add a new Rule
118
-
119
- A new Rule is created by extending the Rule base class and overriding the `fn(obj: Union[Workflow, Job, Step])` method.
120
- Available attributes of `Workflows`, `Jobs` and `Steps` can be found in their definitons under `src/models`.
121
-
122
- 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
123
- default with the src.rules.name_exists.RuleNameExists, but provides a simple enough example to walk through.
124
-
125
- ```python
126
- from typing import Union, Tuple
127
-
128
- from ..rule import Rule
129
- from ..models.job import Job
130
- from ..models.workflow import Workflow
131
- from ..models.step import Step
132
- from ..utils import LintLevels, Settings
133
-
134
-
135
- class RuleJobNameExists(Rule):
136
- def __init__(self, settings: Settings = None, lint_level: Optional[LintLevels] = LintLevels.ERROR) -> None:
137
- self.message = "name must exist"
138
- self.on_fail: LintLevels = lint_level
139
- self.compatibility: List[Union[Workflow, Job, Step]] = [Job]
140
- self.settings: Settings = settings
141
-
142
- def fn(self, obj: Job) -> Tuple[bool, str]:
143
- """<doc block goes here> """
144
- if obj.name is not None:
145
- return True, ""
146
- return False, self.message
147
- ```
148
-
149
- By default, a new Rule needs five things:
150
-
151
- - `self.message`: The message to return to the user on a lint failure
152
- - `self.on_fail`: The level of failure on a lint failure (NONE, WARNING, ERROR).
153
- NONE and WARNING will exit with a code of 0 (unless using `strict` mode for WARNING).
154
- ERROR will exit with a non-zero exit code
155
- - `self.compatibility`: The list of objects this rule is compatible with. This is used to create separate instances of
156
- the Rule for each object in the Rules collection.
157
- - `self.settings`: In general, this should default to what is shown here, but allows for overrides
158
- - `self.fn`: The function doing the actual work to check the object and enforce the standard.
159
-
160
- `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
161
- not support Rules that check against multiple objects at a time OR file level formatting (one empty between each step or
162
- two empty lines between each job)
163
-
164
- _IMPORTANT: A rule must be implemented and tested then merged into `main` before it can be activated.<br>_
165
- This is because the released version of bwwl will use the current `settings.yaml` file, but it will not have the new rule functionality yet and cause an error in the workflow linting of this repository.
166
-
167
- To activate a rule after implementing and releasing it, add it to `settings.yaml` in the project's base folder
168
- and `src/bitwarden_workflow_linter/default_settings.yaml` to make the rule default
169
-
170
- Before creating a new rule please read the [Workflow linter rule rollout process](./RULE_ROLLOUT.md) document in which you'll find the process for rolling out new workflow linter rules.
171
-
172
- ### To-Do
173
-
174
- - [ ] Add Rule to assert correct format for single line run