bitwarden_workflow_linter 0.8.1__py3-none-any.whl → 0.9.0__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.
@@ -1,3 +1,3 @@
1
1
  """Metadata for Workflow Linter."""
2
2
 
3
- __version__ = "0.8.1"
3
+ __version__ = "0.9.0"
@@ -1,21 +1,24 @@
1
1
  enabled_rules:
2
- - id: bitwarden_workflow_linter.rules.name_exists.RuleNameExists
3
- level: error
4
- - id: bitwarden_workflow_linter.rules.name_capitalized.RuleNameCapitalized
5
- level: error
6
- - id: bitwarden_workflow_linter.rules.pinned_job_runner.RuleJobRunnerVersionPinned
7
- level: error
8
- - id: bitwarden_workflow_linter.rules.job_environment_prefix.RuleJobEnvironmentPrefix
9
- level: error
10
- # - id: bitwarden_workflow_linter.rules.step_approved.RuleStepUsesApproved
11
- # level: error
12
- - id: bitwarden_workflow_linter.rules.step_pinned.RuleStepUsesPinned
13
- level: error
14
- - id: bitwarden_workflow_linter.rules.underscore_outputs.RuleUnderscoreOutputs
15
- level: warning
16
- - id: bitwarden_workflow_linter.rules.run_actionlint.RunActionlint
17
- level: warning
18
- - id: bitwarden_workflow_linter.rules.check_pr_target.RuleCheckPrTarget
19
- level: warning
2
+ - id: bitwarden_workflow_linter.rules.name_exists.RuleNameExists
3
+ level: error
4
+ - id: bitwarden_workflow_linter.rules.name_capitalized.RuleNameCapitalized
5
+ level: error
6
+ - id: bitwarden_workflow_linter.rules.pinned_job_runner.RuleJobRunnerVersionPinned
7
+ level: error
8
+ - id: bitwarden_workflow_linter.rules.job_environment_prefix.RuleJobEnvironmentPrefix
9
+ level: error
10
+ # - id: bitwarden_workflow_linter.rules.step_approved.RuleStepUsesApproved
11
+ # level: error
12
+ - id: bitwarden_workflow_linter.rules.step_pinned.RuleStepUsesPinned
13
+ level: error
14
+ - id: bitwarden_workflow_linter.rules.underscore_outputs.RuleUnderscoreOutputs
15
+ level: warning
16
+ - id: bitwarden_workflow_linter.rules.run_actionlint.RunActionlint
17
+ level: warning
18
+ - id: bitwarden_workflow_linter.rules.check_pr_target.RuleCheckPrTarget
19
+ level: warning
20
+ # Cannot add this in until the rule functionality is merged through to main
21
+ # - id: bitwarden_workflow_linter.rules.permissions_exist.RulePermissionsExist
22
+ # level: warning
20
23
 
21
24
  approved_actions_path: default_actions.json
@@ -4,7 +4,6 @@ Workflows."""
4
4
  import argparse
5
5
  import os
6
6
 
7
- from functools import reduce
8
7
  from typing import Optional
9
8
 
10
9
  from .load import WorkflowBuilder, Rules
@@ -115,6 +114,7 @@ class LinterCmd:
115
114
  if len(findings) > 0:
116
115
  for finding in findings:
117
116
  print(f" - {finding}")
117
+ print(f"Issues found by {len(findings)} rules in {filename}")
118
118
  print()
119
119
 
120
120
  max_error_level = self.get_max_error_level(findings)
@@ -162,9 +162,28 @@ class LinterCmd:
162
162
  files = self.generate_files(input_files)
163
163
 
164
164
  if len(input_files) > 0:
165
- return_code = reduce(
166
- lambda a, b: a if a > b else b, map(self.lint_file, files)
167
- )
165
+ files_with_issues = []
166
+ return_code = 0
167
+ for file in files:
168
+ return_value = self.lint_file(file)
169
+ if return_value > 0:
170
+ files_with_issues.append(file)
171
+ return_code = max(return_code, return_value)
172
+
173
+ if len(files_with_issues) > 0:
174
+ newline = "\n" # For compatibility with Python 3.11
175
+ print(
176
+ f"""Found {len(files_with_issues)} file(s) with issues:
177
+ {f"{newline} ".join(files_with_issues)}
178
+
179
+ For help, refer to
180
+ - Workflow Syntax: \
181
+ https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions
182
+ - Bitwarden Examples: \
183
+ https://github.com/bitwarden/workflow-linter/tree/main/.github/workflows/examples")"""
184
+ )
185
+ else:
186
+ print("No issues found")
168
187
 
169
188
  if return_code == 1 and not strict:
170
189
  return_code = 0
@@ -27,6 +27,7 @@ class Workflow:
27
27
  name: Optional[str] = None
28
28
  on: Optional[CommentedMap] = None
29
29
  jobs: Optional[Dict[str, Job]] = None
30
+ permissions: Optional[object] = None # This can be a CommentedMap or a string
30
31
 
31
32
  @classmethod
32
33
  def init(cls: Self, key: str, filename: str, data: CommentedMap) -> Self:
@@ -35,6 +36,7 @@ class Workflow:
35
36
  "filename": filename,
36
37
  "name": data["name"] if "name" in data else None,
37
38
  "on": data["on"] if "on" in data else None,
39
+ "permissions": data["permissions"] if "permissions" in data else None,
38
40
  }
39
41
 
40
42
  new_workflow = cls.from_dict(init_data)
@@ -0,0 +1,43 @@
1
+ """A Rule to enforce that the required permissions are specified on every workflow"""
2
+
3
+ from typing import Optional, Tuple
4
+
5
+ from ..models.workflow import Workflow
6
+ from ..rule import Rule
7
+ from ..utils import LintLevels, Settings
8
+
9
+
10
+ class RulePermissionsExist(Rule):
11
+ """
12
+ Rule to enforce that the required permissions are specified on every workflow.
13
+
14
+ To allow for keeping repository default GITHUB_TOKEN permissions to a minimum,
15
+ each workflow must specify the permissions block (including read).
16
+
17
+ This has 2 benefits:
18
+ 1) When changing the default repository setting to a more restrictive one,
19
+ the workflows will not be affected.
20
+ 2) It is clear to the user what permissions are required for the workflow to run.
21
+ """
22
+
23
+ def __init__(
24
+ self,
25
+ settings: Optional[Settings] = None,
26
+ lint_level: Optional[LintLevels] = LintLevels.NONE,
27
+ ) -> None:
28
+ self.message = (
29
+ "A top-level permissions section must be configured in the workflow."
30
+ )
31
+ self.on_fail = lint_level
32
+ self.compatibility = [Workflow]
33
+ self.settings = settings
34
+
35
+ def permissions_exist(self, obj: Workflow) -> bool:
36
+ if obj.permissions is None:
37
+ return False
38
+ return True
39
+
40
+ def fn(self, obj: Workflow) -> Tuple[bool, str]:
41
+ if not self.permissions_exist(obj):
42
+ return False, f"{self.message}"
43
+ return True, ""
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bitwarden_workflow_linter
3
- Version: 0.8.1
3
+ Version: 0.9.0
4
4
  Summary: Custom GitHub Action Workflow Linter
5
5
  Project-URL: Homepage, https://github.com/bitwarden/workflow-linter
6
6
  Project-URL: Issues, https://github.com/bitwarden/workflow-linter/issues
@@ -60,20 +60,20 @@ the below and create a `settings.yaml` in the directory that `bwwl` will be runn
60
60
 
61
61
  ```yaml
62
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
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
77
 
78
78
  approved_actions_path: default_actions.json
79
79
  ```
@@ -187,7 +187,10 @@ By default, a new Rule needs five things:
187
187
  not support Rules that check against multiple objects at a time OR file level formatting (one empty between each step or
188
188
  two empty lines between each job)
189
189
 
190
- To activate a rule after implementing it, add it to `settings.yaml` in the project's base folder
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
191
194
  and `src/bitwarden_workflow_linter/default_settings.yaml` to make the rule default
192
195
 
193
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.
@@ -1,29 +1,30 @@
1
- bitwarden_workflow_linter/__about__.py,sha256=LeOJJbXhsTU5QogIsNNh2VPPW_vI_w1MZ06yMA9VcsQ,59
1
+ bitwarden_workflow_linter/__about__.py,sha256=ub5QYCamqV0NyTuwhUXuzDYRfqugcJMsH8foRBKHQlc,59
2
2
  bitwarden_workflow_linter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  bitwarden_workflow_linter/actions.py,sha256=LAn3yQeMMmCOvJWeTn3dE1U2nyEJqIBMwESq3TtY9hE,9069
4
4
  bitwarden_workflow_linter/cli.py,sha256=wgkK1MlVbo6Zx3f2CZZ_tkSWq_hdsGciHJA1knX6Yuw,1699
5
5
  bitwarden_workflow_linter/default_actions.json,sha256=ssK4tTcaNJdJczfRK5jvEsUUGdk59xogKRntlHP2JTQ,12762
6
- bitwarden_workflow_linter/default_settings.yaml,sha256=1UqxfpeEgdp9qTaM03EheDXFy6opCb2SelA6fnie-04,910
7
- bitwarden_workflow_linter/lint.py,sha256=RDHv5jGeGCf5XIHE8jyqQET3-cFykl7223SQVS4Q3pg,5525
6
+ bitwarden_workflow_linter/default_settings.yaml,sha256=nlI0V3GBqocx9x7Wy7Bpq-7zeIm07JnEB_HplcjvtLs,1136
7
+ bitwarden_workflow_linter/lint.py,sha256=R0dXkwir0KzXFHWfWlqpH_CyBwa7O8wHSBTy560u94g,6322
8
8
  bitwarden_workflow_linter/load.py,sha256=FWxotIlB0vyKzrVw87sOx3qdRiJG_0hVHRbbLXZY4Sc,5553
9
9
  bitwarden_workflow_linter/rule.py,sha256=Qb60JiUDAWN3ayrMGoSbbDCSFmw-ql8djzAkxISaob4,3250
10
10
  bitwarden_workflow_linter/utils.py,sha256=wMrq5_gAprbGYPdwbn8fL316aeVG2rGEDV1I7NMl4LE,4717
11
11
  bitwarden_workflow_linter/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  bitwarden_workflow_linter/models/job.py,sha256=d4F0QG35DqaqgfbPa2YDRRxOZZakFDktIOsuUa-BbC8,2387
13
13
  bitwarden_workflow_linter/models/step.py,sha256=j81iWYWcNI9x55n1MOR0N6ogKaQ_4-CKu9LnI_fwEOE,1814
14
- bitwarden_workflow_linter/models/workflow.py,sha256=Jr1CJSCpII9Z4RT6Sh1wjzZU6ov3fZt45BmTrfLNLLE,1479
14
+ bitwarden_workflow_linter/models/workflow.py,sha256=lIgGI2cDwC2lTOM-k3fqKgceLdSJ6vhTLCAhaeoD-fc,1645
15
15
  bitwarden_workflow_linter/rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
16
  bitwarden_workflow_linter/rules/check_pr_target.py,sha256=9BHztMzSedmIiFil_qVb3h93-6ku8X8vx06s2FozxHo,3547
17
17
  bitwarden_workflow_linter/rules/job_environment_prefix.py,sha256=bdE8l4B5DQiCFVmblXTs4ptsHPGvjhJrR5ONo2kRY2U,2757
18
18
  bitwarden_workflow_linter/rules/name_capitalized.py,sha256=lGHPi_Ix0DVSzGEdrUm2vAEQD4qQ8dxU1hddsCdqA2w,2126
19
19
  bitwarden_workflow_linter/rules/name_exists.py,sha256=kdMIURN3u8qdDvw6YKxg7VF5bkzGxVVXAO3KAqY1-54,1826
20
+ bitwarden_workflow_linter/rules/permissions_exist.py,sha256=_qOonJ0tyIH3Wp0e-0cppyVIbY9Sr7DuZPZdwxjYMaI,1432
20
21
  bitwarden_workflow_linter/rules/pinned_job_runner.py,sha256=VPQfMu3SgIFdl-B8wOXzzK6tMx2hWWSJbKL5KG3xcaI,1751
21
22
  bitwarden_workflow_linter/rules/run_actionlint.py,sha256=K-RLQRXs591Ud_kiNQHhIJf5mU59HtnR2qrhW-HamlQ,3806
22
23
  bitwarden_workflow_linter/rules/step_approved.py,sha256=4pUCrOlWomo43bwGBunORphv1RJzc3spRKgZ4VLtDS0,3304
23
24
  bitwarden_workflow_linter/rules/step_pinned.py,sha256=MagV8LNdgRKyncmSdH9V-TlIcsdjzoDHDWqovzWon9E,3559
24
25
  bitwarden_workflow_linter/rules/underscore_outputs.py,sha256=LoCsDN_EfQ8H9n5BfZ5xCe7BeHqJGPMcV0vo1c9YJcw,4275
25
- bitwarden_workflow_linter-0.8.1.dist-info/METADATA,sha256=NnlT9ESOxLxhH5jciGb1hgwPcXAGeaIZrM-wnHlLzLA,6602
26
- bitwarden_workflow_linter-0.8.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
27
- bitwarden_workflow_linter-0.8.1.dist-info/entry_points.txt,sha256=SA_yF9CwL4VMUvdcmCd7k9rjsQNzfeOUBuDnMnaO8QQ,60
28
- bitwarden_workflow_linter-0.8.1.dist-info/licenses/LICENSE.txt,sha256=uY-7N9tbI7xc_c0WeTIGpacSCnsB91N05eCIg3bkaRw,35140
29
- bitwarden_workflow_linter-0.8.1.dist-info/RECORD,,
26
+ bitwarden_workflow_linter-0.9.0.dist-info/METADATA,sha256=j237wBsOz9BzlIufH0IpQWdJBJnn4WGUKEtevK9w_aA,6955
27
+ bitwarden_workflow_linter-0.9.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
28
+ bitwarden_workflow_linter-0.9.0.dist-info/entry_points.txt,sha256=SA_yF9CwL4VMUvdcmCd7k9rjsQNzfeOUBuDnMnaO8QQ,60
29
+ bitwarden_workflow_linter-0.9.0.dist-info/licenses/LICENSE.txt,sha256=uY-7N9tbI7xc_c0WeTIGpacSCnsB91N05eCIg3bkaRw,35140
30
+ bitwarden_workflow_linter-0.9.0.dist-info/RECORD,,