bitwarden_workflow_linter 0.14.3__tar.gz → 0.14.4__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 (94) hide show
  1. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/workflows/examples/ci.yaml +2 -0
  2. bitwarden_workflow_linter-0.14.4/.github/workflows/examples/pull_request_target.yml +33 -0
  3. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/PKG-INFO +1 -1
  4. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/settings.yaml +1 -0
  5. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/__about__.py +1 -1
  6. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/default_settings.yaml +1 -0
  7. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/rules/check_pr_target.py +6 -10
  8. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/utils.py +8 -1
  9. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/rules/test_check_pr_target.py +56 -2
  10. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.editorconfig +0 -0
  11. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.gitattributes +0 -0
  12. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/CODEOWNERS +0 -0
  13. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  14. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  15. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/renovate.json +0 -0
  16. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/workflows/_version_type.yml +0 -0
  17. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/workflows/actionlint_windows.yml +0 -0
  18. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/workflows/bwwl_operations.yml +0 -0
  19. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/workflows/cd.yml +0 -0
  20. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/workflows/ci.yml +0 -0
  21. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/workflows/enforce-labels.yml +0 -0
  22. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/workflows/examples/example-references/_build.yml +0 -0
  23. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/workflows/examples/example-references/_docker.yml +0 -0
  24. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/workflows/examples/example-references/_test.yml +0 -0
  25. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/workflows/examples/example-references/_version.yml +0 -0
  26. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/workflows/examples/example.yaml +0 -0
  27. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/workflows/examples/scan.yaml +0 -0
  28. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.github/workflows/scan.yml +0 -0
  29. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.gitignore +0 -0
  30. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.husky/pre-commit +0 -0
  31. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/.python-version +0 -0
  32. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/CONTRIBUTING.md +0 -0
  33. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/LICENSE.txt +0 -0
  34. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/Pipfile +0 -0
  35. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/Pipfile.lock +0 -0
  36. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/README.md +0 -0
  37. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/RULE_ROLLOUT.md +0 -0
  38. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/SECURITY.md +0 -0
  39. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/Taskfile.yml +0 -0
  40. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/actionlint_version.json +0 -0
  41. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/package-lock.json +0 -0
  42. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/package.json +0 -0
  43. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/pylintrc +0 -0
  44. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/pyproject.toml +0 -0
  45. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/pyproject.toml.tpl +0 -0
  46. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/__init__.py +0 -0
  47. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/actionlint_version.yaml +0 -0
  48. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/actions.py +0 -0
  49. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/cli.py +0 -0
  50. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/default_actions.json +0 -0
  51. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/lint.py +0 -0
  52. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/load.py +0 -0
  53. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/models/__init__.py +0 -0
  54. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/models/job.py +0 -0
  55. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/models/step.py +0 -0
  56. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/models/workflow.py +0 -0
  57. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/rule.py +0 -0
  58. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/rules/__init__.py +0 -0
  59. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/rules/job_environment_prefix.py +0 -0
  60. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/rules/name_capitalized.py +0 -0
  61. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/rules/name_exists.py +0 -0
  62. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/rules/permissions_exist.py +0 -0
  63. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/rules/pinned_job_runner.py +0 -0
  64. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/rules/run_actionlint.py +0 -0
  65. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/rules/step_approved.py +0 -0
  66. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/rules/step_pinned.py +0 -0
  67. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/src/bitwarden_workflow_linter/rules/underscore_outputs.py +0 -0
  68. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/__init__.py +0 -0
  69. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/conftest.py +0 -0
  70. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/fixtures/test-alt.yml +0 -0
  71. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/fixtures/test-min-incorrect.yaml +0 -0
  72. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/fixtures/test-min.yaml +0 -0
  73. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/fixtures/test-outputs-incorrect.yml +0 -0
  74. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/fixtures/test.yml +0 -0
  75. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/fixtures/test_a.yaml +0 -0
  76. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/fixtures/test_workflow.yaml +0 -0
  77. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/fixtures/test_workflow_incorrect.yaml +0 -0
  78. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/rules/__init__.py +0 -0
  79. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/rules/test_job_environment_prefix.py +0 -0
  80. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/rules/test_name_capitalized.py +0 -0
  81. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/rules/test_name_exists.py +0 -0
  82. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/rules/test_permissions_exist.py +0 -0
  83. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/rules/test_pinned_job_runner.py +0 -0
  84. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/rules/test_run_actionlint.py +0 -0
  85. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/rules/test_step_approved.py +0 -0
  86. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/rules/test_step_pinned.py +0 -0
  87. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/rules/test_underscore_output.py +0 -0
  88. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/test_job.py +0 -0
  89. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/test_lint.py +0 -0
  90. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/test_load.py +0 -0
  91. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/test_rule.py +0 -0
  92. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/test_step.py +0 -0
  93. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/test_utils.py +0 -0
  94. {bitwarden_workflow_linter-0.14.3 → bitwarden_workflow_linter-0.14.4}/tests/test_workflow.py +0 -0
@@ -6,11 +6,13 @@ name: CI
6
6
 
7
7
  on:
8
8
  workflow_dispatch: # Allows you to run this workflow manually from the Actions tab
9
+ workflow_call: # Allows this workflow to be called from another workflow
9
10
  pull_request: # When a pull request event occurs
10
11
 
11
12
  permissions: # Sets permissions of the GITHUB_TOKEN
12
13
  checks: write # Permits an action to create a check run
13
14
  contents: read # For actions to fetch code and list commits
15
+ packages: read # For actions to fetch packages
14
16
  id-token: write # Required to fetch an OpenID Connect (OIDC) token
15
17
  pull-requests: write # Permits an action to add a label to a pull request
16
18
 
@@ -0,0 +1,33 @@
1
+ # This workflow is intended to be run when we need to build the client and produce artifacts that require secrets
2
+ # when the PR source branch does not have access to secrets (e.g. a fork).
3
+ # This workflow will run in the context of the target of the PR and have access to secrets.
4
+ # This should only be done after reviewing the PR to ensure that no malicious code has been introduced,
5
+ # as it could allow the code on the forked branch to have access to workflow secrets.
6
+
7
+ name: Build Thing on PR Target
8
+
9
+ permissions:
10
+ checks: read
11
+ contents: read
12
+
13
+ on:
14
+ pull_request_target:
15
+ types: [opened, synchronize, reopened]
16
+ branches:
17
+ - main
18
+
19
+ defaults:
20
+ run:
21
+ shell: bash
22
+
23
+ jobs:
24
+ check-run:
25
+ name: Check PR run
26
+ uses: bitwarden/gh-actions/.github/workflows/check-run.yml@main
27
+
28
+ run-workflow:
29
+ name: Build Thing
30
+ needs: check-run
31
+ if: ${{ github.event.pull_request.head.repo.full_name != github.repository }}
32
+ uses: ./.github/workflows/examples/ci.yaml
33
+ secrets: inherit
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bitwarden_workflow_linter
3
- Version: 0.14.3
3
+ Version: 0.14.4
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
@@ -21,3 +21,4 @@ enabled_rules:
21
21
  level: warning
22
22
 
23
23
  approved_actions_path: default_actions.json
24
+ default_branch: main
@@ -1,3 +1,3 @@
1
1
  """Metadata for Workflow Linter."""
2
2
 
3
- __version__ = "0.14.3"
3
+ __version__ = "0.14.4"
@@ -21,3 +21,4 @@ enabled_rules:
21
21
  level: warning
22
22
 
23
23
  approved_actions_path: default_actions.json
24
+ default_branch: main
@@ -27,16 +27,12 @@ class RuleCheckPrTarget(Rule):
27
27
  self.compatibility = [Workflow]
28
28
  self.settings = settings
29
29
 
30
- def targets_main_branch(self, obj:Workflow) -> bool:
31
- if obj.on["pull_request_target"].get("branches"):
32
- branches_list = obj.on["pull_request_target"].get("branches")
33
- if isinstance(branches_list, str):
34
- branches_list = [branches_list]
35
- if any(branch != 'main' for branch in branches_list):
36
- return False
37
- else:
38
- return False
39
- return True
30
+ def targets_main_branch(self, obj: Workflow) -> bool:
31
+ default_branch = self.settings.default_branch
32
+ branches = obj.on["pull_request_target"].get("branches", [])
33
+ if isinstance(branches, str):
34
+ branches = [branches]
35
+ return len(branches) == 1 and branches[0] == default_branch
40
36
 
41
37
  def has_check_run(self, obj: Workflow) -> Tuple[bool, str]:
42
38
  for name, job in obj.jobs.items():
@@ -113,12 +113,14 @@ class Settings:
113
113
  enabled_rules: list[dict[str, str]]
114
114
  approved_actions: dict[str, Action]
115
115
  actionlint_version: str
116
+ default_branch: Optional[str]
116
117
 
117
118
  def __init__(
118
119
  self,
119
120
  enabled_rules: Optional[list[dict[str, str]]] = None,
120
121
  approved_actions: Optional[dict[str, dict[str, str]]] = None,
121
122
  actionlint_version: Optional[str] = None,
123
+ default_branch: Optional[str] = None,
122
124
  ) -> None:
123
125
  """Settings object that can be overridden in settings.py.
124
126
 
@@ -144,6 +146,7 @@ class Settings:
144
146
  self.approved_actions = {
145
147
  name: Action(**action) for name, action in approved_actions.items()
146
148
  }
149
+ self.default_branch = default_branch
147
150
 
148
151
  @staticmethod
149
152
  def factory() -> SettingsFromFactory:
@@ -189,9 +192,13 @@ class Settings:
189
192
  ) as action_file:
190
193
  settings["approved_actions"] = json.load(action_file)
191
194
 
192
-
195
+ default_branch = settings.get("default_branch")
196
+ if default_branch is None or len(default_branch) == 0:
197
+ raise Exception("The default_branch is not set in the default_settings.yaml file")
198
+
193
199
  return Settings(
194
200
  enabled_rules=settings["enabled_rules"],
195
201
  approved_actions=settings["approved_actions"],
196
202
  actionlint_version=actionlint_version,
203
+ default_branch=default_branch,
197
204
  )
@@ -3,11 +3,14 @@
3
3
  import pytest
4
4
 
5
5
  from ruamel.yaml import YAML
6
+ from unittest.mock import patch
6
7
 
7
8
  from src.bitwarden_workflow_linter.load import WorkflowBuilder
8
9
  from src.bitwarden_workflow_linter.rules.check_pr_target import (
9
10
  RuleCheckPrTarget,
10
11
  )
12
+ from src.bitwarden_workflow_linter.models.workflow import Workflow
13
+ from src.bitwarden_workflow_linter.utils import Settings
11
14
 
12
15
  yaml = YAML()
13
16
  message = "A check-run job must be included as a direct job dependency when pull_request_target is used and the workflow may only apply to runs on the main branch"
@@ -232,14 +235,65 @@ jobs:
232
235
 
233
236
  @pytest.fixture(name="rule")
234
237
  def fixture_rule():
235
- return RuleCheckPrTarget()
238
+ settings= Settings(default_branch="main")
239
+ return RuleCheckPrTarget(settings=settings)
240
+
241
+ @pytest.fixture
242
+ def mock_workflow():
243
+ return Workflow(
244
+ on={
245
+ "pull_request_target": {
246
+ "branches": ["main"]
247
+ }
248
+ },
249
+ jobs={}
250
+ )
251
+ def test_targets_main_branch_with_settings_yaml(mock_workflow):
252
+ settings = Settings(default_branch="main")
253
+ rule = RuleCheckPrTarget(settings=settings)
254
+ assert rule.targets_main_branch(mock_workflow) is True
255
+
256
+ def test_targets_custom_default_branch(mock_workflow):
257
+ settings = Settings(
258
+ enabled_rules=[],
259
+ approved_actions={},
260
+ actionlint_version="",
261
+ default_branch="production"
262
+ )
263
+ rule = RuleCheckPrTarget(settings=settings)
264
+ mock_workflow.on["pull_request_target"]["branches"] = ["production"]
265
+ assert rule.targets_main_branch(mock_workflow) is True
266
+
267
+ def test_targets_main_branch_no_default_branch(mock_workflow):
268
+ # Mock the factory method to simulate loading default settings
269
+ with patch("src.bitwarden_workflow_linter.utils.Settings.factory") as mock_factory:
270
+ # Simulate the default settings returned by the factory
271
+ mock_factory.return_value = Settings(default_branch="main")
272
+
273
+ # Use the mocked factory to create the Settings instance
274
+ settings = Settings.factory()
275
+ rule = RuleCheckPrTarget(settings=settings)
276
+
277
+ # Assert that the workflow targets the main branch
278
+ assert rule.targets_main_branch(mock_workflow) is True
279
+
280
+ def test_targets_main_branch_incorrect_branch(mock_workflow):
281
+ settings = Settings({"default_branch": "main"})
282
+ rule = RuleCheckPrTarget(settings=settings)
283
+ mock_workflow.on["pull_request_target"]["branches"] = ["feature"]
284
+ assert rule.targets_main_branch(mock_workflow) is False
285
+
286
+ def test_targets_main_branch_no_branches_specified(mock_workflow):
287
+ settings = Settings({"default_branch": "main"})
288
+ rule = RuleCheckPrTarget(settings=settings)
289
+ mock_workflow.on["pull_request_target"].pop("branches")
290
+ assert rule.targets_main_branch(mock_workflow) is False
236
291
 
237
292
  def test_rule_on_correct_workflow(rule, correct_workflow):
238
293
  result, message = rule.fn(correct_workflow)
239
294
  assert result is True
240
295
  assert message == ""
241
296
 
242
-
243
297
  def test_rule_on_no_checkworkflow(rule, no_check_workflow):
244
298
  result, message = rule.fn(no_check_workflow)
245
299
  assert result is False