bitwarden_workflow_linter 0.12.1__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.
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/workflows/bwwl_operations.yml +2 -2
- bitwarden_workflow_linter-0.12.3/.python-version +1 -0
- bitwarden_workflow_linter-0.12.3/PKG-INFO +274 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/Pipfile +1 -1
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/Pipfile.lock +1 -1
- bitwarden_workflow_linter-0.12.3/README.md +248 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/__about__.py +1 -1
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/default_actions.json +10 -0
- bitwarden_workflow_linter-0.12.1/.python-version +0 -1
- bitwarden_workflow_linter-0.12.1/PKG-INFO +0 -200
- bitwarden_workflow_linter-0.12.1/README.md +0 -174
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.editorconfig +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.gitattributes +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/CODEOWNERS +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/renovate.json +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/workflows/_version_type.yml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/workflows/cd.yml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/workflows/ci.yml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/workflows/enforce-labels.yml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/workflows/examples/ci.yaml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/workflows/examples/example-references/_build.yml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/workflows/examples/example-references/_docker.yml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/workflows/examples/example-references/_test.yml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/workflows/examples/example-references/_version.yml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/workflows/examples/example.yaml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/workflows/examples/scan.yaml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.github/workflows/scan.yml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.gitignore +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/.husky/pre-commit +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/CONTRIBUTING.md +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/LICENSE.txt +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/RULE_ROLLOUT.md +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/SECURITY.md +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/Taskfile.yml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/package-lock.json +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/package.json +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/pylintrc +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/pyproject.toml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/pyproject.toml.tpl +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/settings.yaml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/__init__.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/actions.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/cli.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/default_settings.yaml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/lint.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/load.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/models/__init__.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/models/job.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/models/step.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/models/workflow.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rule.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/__init__.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/check_pr_target.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/job_environment_prefix.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/name_capitalized.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/name_exists.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/permissions_exist.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/pinned_job_runner.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/run_actionlint.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/step_approved.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/step_pinned.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/rules/underscore_outputs.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/src/bitwarden_workflow_linter/utils.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/__init__.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/conftest.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test-alt.yml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test-min-incorrect.yaml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test-min.yaml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test-outputs-incorrect.yml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test.yml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test_a.yaml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test_workflow.yaml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/fixtures/test_workflow_incorrect.yaml +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/rules/__init__.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_check_pr_target.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_job_environment_prefix.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_name_capitalized.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_name_exists.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_permissions_exist.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_pinned_job_runner.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_run_actionlint.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_step_approved.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_step_pinned.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/rules/test_underscore_output.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/test_job.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/test_lint.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/test_load.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/test_rule.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/test_step.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → bitwarden_workflow_linter-0.12.3}/tests/test_utils.py +0 -0
- {bitwarden_workflow_linter-0.12.1 → 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.
|
57
|
+
- name: Set up Python 3.12
|
58
58
|
uses: actions/setup-python@42375524e23c412d93fb67b49958b491fce71c38 # v5.4.0
|
59
59
|
with:
|
60
|
-
python-version: "3.
|
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.
|
@@ -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.
|
@@ -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",
|
@@ -294,6 +299,11 @@
|
|
294
299
|
"sha": "c6b79182b9b666aa4f630f4a6be9158ead62536e",
|
295
300
|
"version": "v1.2.0"
|
296
301
|
},
|
302
|
+
"grafana/setup-k6-action": {
|
303
|
+
"name": "grafana/setup-k6-action",
|
304
|
+
"sha": "ffe7d7290dfa715e48c2ccc924d068444c94bde2",
|
305
|
+
"version": "v1.1.0"
|
306
|
+
},
|
297
307
|
"hashicorp/setup-packer": {
|
298
308
|
"name": "hashicorp/setup-packer",
|
299
309
|
"sha": "1aa358be5cf73883762b302a3a03abd66e75b232",
|
@@ -1 +0,0 @@
|
|
1
|
-
3.11
|