bitwarden_workflow_linter 0.12.8__tar.gz → 0.13.1__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.12.8 → bitwarden_workflow_linter-0.13.1}/.github/CODEOWNERS +1 -1
  2. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/renovate.json +1 -1
  3. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/workflows/ci.yml +2 -0
  4. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/PKG-INFO +1 -1
  5. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/__about__.py +1 -1
  6. bitwarden_workflow_linter-0.13.1/src/bitwarden_workflow_linter/actionlint_version.yaml +1 -0
  7. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/rules/run_actionlint.py +37 -32
  8. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/utils.py +20 -1
  9. bitwarden_workflow_linter-0.13.1/tests/rules/test_run_actionlint.py +377 -0
  10. bitwarden_workflow_linter-0.12.8/tests/rules/test_run_actionlint.py +0 -181
  11. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.editorconfig +0 -0
  12. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.gitattributes +0 -0
  13. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  14. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  15. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/workflows/_version_type.yml +0 -0
  16. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/workflows/actionlint_windows.yml +0 -0
  17. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/workflows/bwwl_operations.yml +0 -0
  18. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/workflows/cd.yml +0 -0
  19. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/workflows/enforce-labels.yml +0 -0
  20. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/workflows/examples/ci.yaml +0 -0
  21. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/workflows/examples/example-references/_build.yml +0 -0
  22. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/workflows/examples/example-references/_docker.yml +0 -0
  23. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/workflows/examples/example-references/_test.yml +0 -0
  24. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/workflows/examples/example-references/_version.yml +0 -0
  25. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/workflows/examples/example.yaml +0 -0
  26. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/workflows/examples/scan.yaml +0 -0
  27. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.github/workflows/scan.yml +0 -0
  28. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.gitignore +0 -0
  29. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.husky/pre-commit +0 -0
  30. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/.python-version +0 -0
  31. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/CONTRIBUTING.md +0 -0
  32. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/LICENSE.txt +0 -0
  33. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/Pipfile +0 -0
  34. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/Pipfile.lock +0 -0
  35. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/README.md +0 -0
  36. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/RULE_ROLLOUT.md +0 -0
  37. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/SECURITY.md +0 -0
  38. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/Taskfile.yml +0 -0
  39. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/actionlint_version.json +0 -0
  40. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/package-lock.json +0 -0
  41. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/package.json +0 -0
  42. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/pylintrc +0 -0
  43. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/pyproject.toml +0 -0
  44. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/pyproject.toml.tpl +0 -0
  45. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/settings.yaml +0 -0
  46. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/__init__.py +0 -0
  47. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/actions.py +0 -0
  48. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/cli.py +0 -0
  49. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/default_actions.json +0 -0
  50. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/default_settings.yaml +0 -0
  51. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/lint.py +0 -0
  52. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/load.py +0 -0
  53. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/models/__init__.py +0 -0
  54. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/models/job.py +0 -0
  55. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/models/step.py +0 -0
  56. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/models/workflow.py +0 -0
  57. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/rule.py +0 -0
  58. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/rules/__init__.py +0 -0
  59. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/rules/check_pr_target.py +0 -0
  60. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/rules/job_environment_prefix.py +0 -0
  61. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/rules/name_capitalized.py +0 -0
  62. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/rules/name_exists.py +0 -0
  63. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/rules/permissions_exist.py +0 -0
  64. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/rules/pinned_job_runner.py +0 -0
  65. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/rules/step_approved.py +0 -0
  66. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/rules/step_pinned.py +0 -0
  67. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/src/bitwarden_workflow_linter/rules/underscore_outputs.py +0 -0
  68. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/__init__.py +0 -0
  69. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/conftest.py +0 -0
  70. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/fixtures/test-alt.yml +0 -0
  71. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/fixtures/test-min-incorrect.yaml +0 -0
  72. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/fixtures/test-min.yaml +0 -0
  73. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/fixtures/test-outputs-incorrect.yml +0 -0
  74. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/fixtures/test.yml +0 -0
  75. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/fixtures/test_a.yaml +0 -0
  76. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/fixtures/test_workflow.yaml +0 -0
  77. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/fixtures/test_workflow_incorrect.yaml +0 -0
  78. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/rules/__init__.py +0 -0
  79. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/rules/test_check_pr_target.py +0 -0
  80. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/rules/test_job_environment_prefix.py +0 -0
  81. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/rules/test_name_capitalized.py +0 -0
  82. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/rules/test_name_exists.py +0 -0
  83. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/rules/test_permissions_exist.py +0 -0
  84. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/rules/test_pinned_job_runner.py +0 -0
  85. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/rules/test_step_approved.py +0 -0
  86. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/rules/test_step_pinned.py +0 -0
  87. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/rules/test_underscore_output.py +0 -0
  88. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/test_job.py +0 -0
  89. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/test_lint.py +0 -0
  90. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/test_load.py +0 -0
  91. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/test_rule.py +0 -0
  92. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/test_step.py +0 -0
  93. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/test_utils.py +0 -0
  94. {bitwarden_workflow_linter-0.12.8 → bitwarden_workflow_linter-0.13.1}/tests/test_workflow.py +0 -0
@@ -9,5 +9,5 @@
9
9
 
10
10
  # AppSec owns default_actions and actionlint_version files
11
11
  src/bitwarden_workflow_linter/default_actions.json @bitwarden/team-appsec
12
- actionlint_version.json @bitwarden/team-appsec
12
+ src/bitwarden_workflow_linter/actionlint_version.yaml @bitwarden/team-appsec
13
13
 
@@ -23,7 +23,7 @@
23
23
  "customManagers": [
24
24
  {
25
25
  "customType": "regex",
26
- "fileMatch": ["^actionlint_version\\.json$"],
26
+ "fileMatch": ["^actionlint_version\\.yaml$"],
27
27
  "matchStrings": [
28
28
  "\"actionlint_version\":\\s*\"(?<currentValue>[^\"]+)\""
29
29
  ],
@@ -29,6 +29,8 @@ jobs:
29
29
  pipenv install --dev
30
30
 
31
31
  - name: Run pytest
32
+ env:
33
+ PYTHONPATH: "${{ github.workspace }}/src"
32
34
  run: pipenv run pytest tests --cov=src
33
35
 
34
36
  - name: Check type hinting
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bitwarden_workflow_linter
3
- Version: 0.12.8
3
+ Version: 0.13.1
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
@@ -1,3 +1,3 @@
1
1
  """Metadata for Workflow Linter."""
2
2
 
3
- __version__ = "0.12.8"
3
+ __version__ = "0.13.1"
@@ -5,49 +5,31 @@ import subprocess
5
5
  import platform
6
6
  import urllib.request
7
7
  import os
8
- import json
9
8
 
10
9
  from ..rule import Rule
11
10
  from ..models.workflow import Workflow
12
11
  from ..utils import LintLevels, Settings
13
12
 
14
13
 
15
- def install_actionlint(platform_system: str) -> Tuple[bool, str]:
14
+ def install_actionlint(platform_system: str, version: str) -> Tuple[bool, str]:
16
15
  """If actionlint is not installed, detects OS platform
17
16
  and installs actionlint"""
18
17
 
19
18
  error = f"An error occurred when installing Actionlint on {platform_system}"
20
19
 
21
- if platform_system.startswith("Linux"):
22
- return install_actionlint_source(error)
23
- elif platform_system == "Darwin":
24
- try:
25
- subprocess.run(["brew", "install", "actionlint"], check=True)
26
- return True, ""
27
- except (FileNotFoundError, subprocess.CalledProcessError):
28
- return False, f"{error} : check Brew installation"
20
+ if platform_system.startswith(("Linux", "Darwin")):
21
+ """Homebrew does not maintain non-latest versions of actionlint so Mac will install from source"""
22
+ return install_actionlint_source(error,version)
29
23
  elif platform_system.startswith("Win"):
30
24
  try:
31
- subprocess.run(["choco", "install", "actionlint", "-y"], check=True)
25
+ subprocess.run(["choco", "install", "actionlint", "-y", f"--version='{version}'"], check=True)
32
26
  return True, ""
33
27
  except (FileNotFoundError, subprocess.CalledProcessError):
34
28
  return False, f"{error} : check Choco installation"
35
29
  return False, error
36
30
 
37
- # temporarily commenting out this logic to allow time to troubleshoot it running in CI
38
- # def load_config() -> dict:
39
- # """Load configuration from a JSON file."""
40
- # config_path = os.path.join(os.path.dirname(__file__), "../../../actionlint_version.json")
41
- # if not os.path.exists(config_path):
42
- # raise FileNotFoundError(f"Configuration file not found: {config_path}")
43
- # with open(config_path, "r") as config_file:
44
- # return json.load(config_file)
45
-
46
- def install_actionlint_source(error) -> Tuple[bool, str]:
47
- #config = load_config()
48
- #if "actionlint_version" not in config:
49
- # raise KeyError("The 'actionlint_version' is missing in the configuration file.")
50
- version = "1.7.7"
31
+ def install_actionlint_source(error, version) -> Tuple[bool, str]:
32
+ version = version
51
33
  """Install Actionlint Binary from provided script"""
52
34
  url = "https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash"
53
35
  request = urllib.request.urlopen(url)
@@ -55,21 +37,24 @@ def install_actionlint_source(error) -> Tuple[bool, str]:
55
37
  fp.write(request.read())
56
38
  try:
57
39
  subprocess.run(["bash", "download-actionlint.bash", version], check=True)
58
- return True, os.getcwd()
40
+ return True, "./actionlint"
59
41
  except (FileNotFoundError, subprocess.CalledProcessError):
60
42
  return False, error
61
43
 
62
44
 
63
- def check_actionlint(platform_system: str) -> Tuple[bool, str]:
45
+ def check_actionlint_path(platform_system: str, version: str) -> Tuple[bool, str]:
64
46
  """Check if the actionlint is in the system's PATH."""
65
47
  try:
66
- subprocess.run(
48
+ installed = subprocess.run(
67
49
  ["actionlint", "--version"],
68
50
  stdout=subprocess.PIPE,
69
51
  stderr=subprocess.PIPE,
70
52
  check=True,
71
53
  )
72
- return True, ""
54
+ if version in f"{installed}":
55
+ return True, ""
56
+ else:
57
+ return install_actionlint(platform_system, version)
73
58
  except subprocess.CalledProcessError:
74
59
  return (
75
60
  False,
@@ -77,7 +62,23 @@ def check_actionlint(platform_system: str) -> Tuple[bool, str]:
77
62
  please check your package installer or manually install it",
78
63
  )
79
64
  except FileNotFoundError:
80
- return install_actionlint(platform_system)
65
+ return check_actionlint_local(platform_system, version)
66
+
67
+ def check_actionlint_local(platform_system: str, version: str) -> Tuple[bool, str]:
68
+
69
+ try:
70
+ installed = subprocess.run(
71
+ ["./actionlint", "--version"],
72
+ stdout=subprocess.PIPE,
73
+ stderr=subprocess.PIPE,
74
+ check=True,
75
+ )
76
+ if version in f"{installed}":
77
+ return True, "./actionlint"
78
+ else:
79
+ return install_actionlint(platform_system, version)
80
+ except FileNotFoundError:
81
+ return install_actionlint(platform_system, version)
81
82
 
82
83
 
83
84
  class RunActionlint(Rule):
@@ -95,11 +96,15 @@ class RunActionlint(Rule):
95
96
  "Running actionlint without a filename is not currently supported"
96
97
  )
97
98
 
98
- installed, location = check_actionlint(platform.system())
99
+ if not self.settings.actionlint_version:
100
+ raise KeyError("The 'actionlint_version' is missing in the configuration file.")
101
+
102
+ """Check if Actionlint is alerady installed and if it is installed somewhere not on the PATH (location)"""
103
+ installed, location = check_actionlint_path(platform.system(), self.settings.actionlint_version)
99
104
  if installed:
100
105
  if location:
101
106
  result = subprocess.run(
102
- [location + "/actionlint", obj.filename],
107
+ [location, obj.filename],
103
108
  capture_output=True,
104
109
  text=True,
105
110
  check=False,
@@ -107,17 +107,18 @@ class SettingsError(Exception):
107
107
 
108
108
  SettingsFromFactory = TypeVar("SettingsFromFactory", bound="Settings")
109
109
 
110
-
111
110
  class Settings:
112
111
  """Class that contains configuration-as-code for any portion of the app."""
113
112
 
114
113
  enabled_rules: list[dict[str, str]]
115
114
  approved_actions: dict[str, Action]
115
+ actionlint_version: str
116
116
 
117
117
  def __init__(
118
118
  self,
119
119
  enabled_rules: Optional[list[dict[str, str]]] = None,
120
120
  approved_actions: Optional[dict[str, dict[str, str]]] = None,
121
+ actionlint_version: Optional[str] = None,
121
122
  ) -> None:
122
123
  """Settings object that can be overridden in settings.py.
123
124
 
@@ -134,7 +135,11 @@ class Settings:
134
135
 
135
136
  if approved_actions is None:
136
137
  approved_actions = {}
138
+
139
+ if actionlint_version is None:
140
+ actionlint_version = ""
137
141
 
142
+ self.actionlint_version = actionlint_version
138
143
  self.enabled_rules = enabled_rules
139
144
  self.approved_actions = {
140
145
  name: Action(**action) for name, action in approved_actions.items()
@@ -142,6 +147,7 @@ class Settings:
142
147
 
143
148
  @staticmethod
144
149
  def factory() -> SettingsFromFactory:
150
+ # load default settings
145
151
  with (
146
152
  importlib.resources.files("bitwarden_workflow_linter")
147
153
  .joinpath("default_settings.yaml")
@@ -149,6 +155,16 @@ class Settings:
149
155
  ):
150
156
  settings = yaml.load(file)
151
157
 
158
+ # load actionlint version
159
+ with (
160
+ importlib.resources.files("bitwarden_workflow_linter")
161
+ .joinpath("actionlint_version.yaml")
162
+ .open("r", encoding="utf-8") as version_file
163
+ ):
164
+ version_data = yaml.load(version_file)
165
+ actionlint_version = version_data["actionlint_version"]
166
+
167
+ # load override settings
152
168
  settings_filename = "settings.yaml"
153
169
  local_settings = None
154
170
 
@@ -159,6 +175,7 @@ class Settings:
159
175
  if local_settings:
160
176
  settings.update(local_settings)
161
177
 
178
+ # load approved actions
162
179
  if settings["approved_actions_path"] == "default_actions.json":
163
180
  with (
164
181
  importlib.resources.files("bitwarden_workflow_linter")
@@ -172,7 +189,9 @@ class Settings:
172
189
  ) as action_file:
173
190
  settings["approved_actions"] = json.load(action_file)
174
191
 
192
+
175
193
  return Settings(
176
194
  enabled_rules=settings["enabled_rules"],
177
195
  approved_actions=settings["approved_actions"],
196
+ actionlint_version=actionlint_version,
178
197
  )
@@ -0,0 +1,377 @@
1
+ """Test src/bitwarden_workflow_linter/rules/run_actionlint."""
2
+
3
+ import pytest
4
+ import subprocess
5
+ import os
6
+
7
+ from ruamel.yaml import YAML
8
+
9
+ from src.bitwarden_workflow_linter.utils import Settings
10
+ from src.bitwarden_workflow_linter.load import WorkflowBuilder
11
+ from src.bitwarden_workflow_linter.rules.run_actionlint import (
12
+ RunActionlint,
13
+ install_actionlint_source,
14
+ check_actionlint_path,
15
+ install_actionlint,
16
+ check_actionlint_local,
17
+ )
18
+
19
+ yaml = YAML()
20
+ settings = Settings.factory()
21
+
22
+ @pytest.fixture(name="rule")
23
+ def fixture_rule():
24
+ return RunActionlint(settings)
25
+
26
+
27
+ def test_rule_on_correct_workflow(rule):
28
+ rule.settings = settings
29
+ correct_workflow = WorkflowBuilder.build("tests/fixtures/test_workflow.yaml")
30
+ result, _ = rule.fn(correct_workflow)
31
+ assert result is True
32
+
33
+
34
+ def test_rule_on_incorrect_workflow(rule):
35
+ rule.settings = settings
36
+ incorrect_workflow = WorkflowBuilder.build(
37
+ "tests/fixtures/test_workflow_incorrect.yaml"
38
+ )
39
+ result, _ = rule.fn(incorrect_workflow)
40
+ assert result is False
41
+
42
+
43
+ def test_pass_install_actionlint_linux():
44
+ result, _ = install_actionlint("Linux", settings.actionlint_version)
45
+ assert result is True
46
+
47
+
48
+ def test_install_actionlint_darwin(monkeypatch):
49
+ def mock_run(*args, **kwargs):
50
+ return subprocess.CompletedProcess(args, 0)
51
+
52
+ monkeypatch.setattr(subprocess, "run", mock_run)
53
+ result, _ = install_actionlint("Darwin", settings.actionlint_version)
54
+ assert result is True
55
+
56
+
57
+ def test_failed_install_actionlint_darwin(monkeypatch):
58
+ def mock_run(*args, **kwargs):
59
+ raise subprocess.CalledProcessError(1, "cmd")
60
+
61
+ monkeypatch.setattr(subprocess, "run", mock_run)
62
+ result, error = install_actionlint("Darwin", settings.actionlint_version)
63
+ assert result is False
64
+ assert "An error occurred" in error
65
+
66
+
67
+ def test_install_actionlint_windows(monkeypatch):
68
+ def mock_run(*args, **kwargs):
69
+ return subprocess.CompletedProcess(args, 0)
70
+
71
+ monkeypatch.setattr(subprocess, "run", mock_run)
72
+ result, _ = install_actionlint("Windows", settings.actionlint_version)
73
+ assert result is True
74
+
75
+
76
+ def test_failed_install_actionlint_windows(monkeypatch):
77
+ def mock_run(*args, **kwargs):
78
+ raise subprocess.CalledProcessError(1, "cmd")
79
+
80
+ monkeypatch.setattr(subprocess, "run", mock_run)
81
+ result, error = install_actionlint("Windows", settings.actionlint_version)
82
+ assert result is False
83
+ assert "An error occurred" in error
84
+
85
+
86
+ def test_install_actionlint_source(monkeypatch):
87
+ def mock_run(*args, **kwargs):
88
+ return subprocess.CompletedProcess(args, 0)
89
+
90
+ monkeypatch.setattr(subprocess, "run", mock_run)
91
+
92
+ result, _ = install_actionlint_source("An error occurred", settings.actionlint_version)
93
+ assert result is True
94
+
95
+
96
+ def test_failed_install_actionlint_source(monkeypatch):
97
+ def mock_run(*args, **kwargs):
98
+ raise subprocess.CalledProcessError(1, "cmd")
99
+
100
+ monkeypatch.setattr(subprocess, "run", mock_run)
101
+
102
+ result, error = install_actionlint_source("An error occurred", settings.actionlint_version)
103
+ assert result is False
104
+ assert "An error occurred" in error
105
+
106
+ # test_check_actionlint in path
107
+ def test_check_actionlint_in_path(monkeypatch):
108
+ def mock_installed(*args, **kwargs):
109
+ return settings.actionlint_version
110
+
111
+ monkeypatch.setattr(subprocess, "run", mock_installed)
112
+
113
+ result, message = check_actionlint_path("Linux", settings.actionlint_version)
114
+ assert result is True
115
+ assert message == ""
116
+
117
+ def test_check_actionlint_not_in_path(monkeypatch):
118
+ def mock_run(*args, **kwargs):
119
+ raise subprocess.CalledProcessError(1, args[0])
120
+
121
+ monkeypatch.setattr(subprocess, "run", mock_run)
122
+
123
+ result, message = check_actionlint_path("Linux", settings.actionlint_version)
124
+ assert result is False
125
+ assert message == "Failed to install Actionlint, please check your package installer or manually install it"
126
+
127
+ def test_run_actionlint_not_installed(monkeypatch, rule):
128
+ def mock_check_actionlint_path(*args, **kwargs):
129
+ return False, ""
130
+
131
+ monkeypatch.setattr(
132
+ "src.bitwarden_workflow_linter.rules.run_actionlint.check_actionlint_path",
133
+ mock_check_actionlint_path,
134
+ )
135
+
136
+ workflow = WorkflowBuilder.build("tests/fixtures/test_workflow.yaml")
137
+ result, error = rule.fn(workflow)
138
+ assert result is False
139
+ assert "Actionlint must pass" in error
140
+
141
+ def test_run_actionlint_installed_error(monkeypatch, rule):
142
+ def mock_check_actionlint_path(*args, **kwargs):
143
+ return True, "/mock/location"
144
+
145
+ def mock_run(*args, **kwargs):
146
+ return subprocess.CompletedProcess(args, 110, stdout="An error occurred")
147
+
148
+ monkeypatch.setattr(subprocess, "run", mock_run)
149
+ monkeypatch.setattr(
150
+ "src.bitwarden_workflow_linter.rules.run_actionlint.check_actionlint_path",
151
+ mock_check_actionlint_path,
152
+ )
153
+
154
+ workflow = WorkflowBuilder.build("tests/fixtures/test_workflow.yaml")
155
+ result, error = rule.fn(workflow)
156
+ assert result is False
157
+ assert "An error occurred" in error
158
+
159
+ # test_check_actionlint_installed
160
+ def test_check_actionlint_installed_linux(monkeypatch):
161
+ def mock_run(*args, **kwargs):
162
+ return subprocess.CompletedProcess(args, 0)
163
+
164
+ monkeypatch.setattr(subprocess, "run", mock_run)
165
+
166
+ result, _ = check_actionlint_path("Linux", settings.actionlint_version)
167
+ assert result is True
168
+
169
+ def test_check_actionlint_installed_darwin(monkeypatch):
170
+ def mock_run(*args, **kwargs):
171
+ return subprocess.CompletedProcess(args, 0)
172
+
173
+ monkeypatch.setattr(subprocess, "run", mock_run)
174
+
175
+ result, _ = check_actionlint_path("Darwin", settings.actionlint_version)
176
+ assert result is True
177
+
178
+ def test_check_actionlint_installed_windows(monkeypatch):
179
+ def mock_run(*args, **kwargs):
180
+ return subprocess.CompletedProcess(args, 0)
181
+
182
+ monkeypatch.setattr(subprocess, "run", mock_run)
183
+
184
+ result, _ = check_actionlint_path("Windows", settings.actionlint_version)
185
+ assert result is True
186
+
187
+
188
+ #test_failed_check_actionlint_installed
189
+ def test_failed_check_actionlint_installed_linux(monkeypatch):
190
+ def mock_run(*args, **kwargs):
191
+ raise subprocess.CalledProcessError(1, "cmd")
192
+
193
+ monkeypatch.setattr(subprocess, "run", mock_run)
194
+
195
+ result, _ = check_actionlint_path("Linux", settings.actionlint_version)
196
+ assert result is False
197
+
198
+ def test_failed_check_actionlint_installed_darwin(monkeypatch):
199
+ def mock_run(*args, **kwargs):
200
+ raise subprocess.CalledProcessError(1, "cmd")
201
+
202
+ monkeypatch.setattr(subprocess, "run", mock_run)
203
+
204
+ result, _ = check_actionlint_path("Darwin", settings.actionlint_version)
205
+ assert result is False
206
+
207
+ def test_failed_check_actionlint_installed_windows(monkeypatch):
208
+ def mock_run(*args, **kwargs):
209
+ raise subprocess.CalledProcessError(1, "cmd")
210
+
211
+ monkeypatch.setattr(subprocess, "run", mock_run)
212
+
213
+ result, _ = check_actionlint_path("Windows", settings.actionlint_version)
214
+ assert result is False
215
+
216
+ # test_check_actionlint_installed_locally
217
+ def test_check_actionlint_installed_locally_linux(monkeypatch):
218
+ monkeypatch.setattr(os.path, "exists", True)
219
+
220
+ result, message = check_actionlint_local("Linux", settings.actionlint_version)
221
+
222
+ assert result is True
223
+ assert message == "./actionlint"
224
+
225
+ def test_check_actionlint_installed_locally_darwin(monkeypatch):
226
+ monkeypatch.setattr(os.path, "exists", True)
227
+
228
+ result, message = check_actionlint_local("Darwin", settings.actionlint_version)
229
+
230
+ assert result is True
231
+ assert message == "./actionlint"
232
+
233
+ def test_check_actionlint_installed_locally_windows(monkeypatch):
234
+ def mock_exists(*args, **kwargs):
235
+ return True
236
+
237
+ def mock_run(*args, **kwargs):
238
+ return subprocess.CompletedProcess(args, 0)
239
+
240
+ monkeypatch.setattr(os.path, "exists", mock_exists)
241
+ monkeypatch.setattr(subprocess, "run", mock_run)
242
+
243
+ result, _ = check_actionlint_local("Windows", settings.actionlint_version)
244
+
245
+ assert result is True
246
+
247
+ # test_install_actionlint
248
+ def test_install_actionlint_linux():
249
+ result, _ = install_actionlint("Linux", settings.actionlint_version)
250
+ assert result is True
251
+
252
+ def test_install_actionlint_darwin(monkeypatch):
253
+ def mock_run(*args, **kwargs):
254
+ return subprocess.CompletedProcess(args, 0)
255
+
256
+ monkeypatch.setattr(subprocess, "run", mock_run)
257
+ result, _ = install_actionlint("Darwin", settings.actionlint_version)
258
+ assert result is True
259
+
260
+ def test_install_actionlint_windows(monkeypatch):
261
+ def mock_run(*args, **kwargs):
262
+ return subprocess.CompletedProcess(args, 0)
263
+
264
+ monkeypatch.setattr(subprocess, "run", mock_run)
265
+ result, _ = install_actionlint("Windows", settings.actionlint_version)
266
+ assert result is True
267
+
268
+ def test_install_actionlint_source(monkeypatch):
269
+ def mock_run(*args, **kwargs):
270
+ return subprocess.CompletedProcess(args, 0)
271
+
272
+ monkeypatch.setattr(subprocess, "run", mock_run)
273
+
274
+ result, _ = install_actionlint_source("An error occurred", settings.actionlint_version)
275
+ assert result is True
276
+
277
+ # test non available OS
278
+ def test_install_actionlint_non_available_os():
279
+ result, error = install_actionlint("MockOS", settings.actionlint_version)
280
+ assert result is False
281
+ assert "An error occurred when installing Actionlint on MockOS" in error
282
+
283
+ # test_failed_install_actionlint
284
+ def test_failed_install_actionlint_darwin(monkeypatch):
285
+ def mock_run(*args, **kwargs):
286
+ raise subprocess.CalledProcessError(1, "cmd")
287
+
288
+ monkeypatch.setattr(subprocess, "run", mock_run)
289
+ result, error = install_actionlint("Darwin", settings.actionlint_version)
290
+ assert result is False
291
+ assert "An error occurred" in error
292
+
293
+ def test_failed_install_actionlint_windows(monkeypatch):
294
+ def mock_run(*args, **kwargs):
295
+ raise subprocess.CalledProcessError(1, "cmd")
296
+
297
+ monkeypatch.setattr(subprocess, "run", mock_run)
298
+ result, error = install_actionlint("Windows", settings.actionlint_version)
299
+ assert result is False
300
+ assert "An error occurred" in error
301
+
302
+ def test_failed_install_actionlint_linux(monkeypatch):
303
+ def mock_run(*args, **kwargs):
304
+ raise subprocess.CalledProcessError(1, "cmd")
305
+
306
+ monkeypatch.setattr(subprocess, "run", mock_run)
307
+
308
+ result, error = install_actionlint_source("An error occurred", settings.actionlint_version)
309
+ assert result is False
310
+ assert "An error occurred" in error
311
+
312
+ def test_check_actionlint_not_installed(monkeypatch):
313
+ def mock_run(*args, **kwargs):
314
+ raise FileNotFoundError
315
+
316
+ monkeypatch.setattr(subprocess, "run", mock_run)
317
+
318
+ result, _ = check_actionlint_path("Linux", settings.actionlint_version)
319
+ assert result is False
320
+
321
+
322
+ def test_run_actionlint_installed(monkeypatch, rule):
323
+ rule.settings = settings
324
+
325
+ def mock_check_actionlint(*args, **kwargs):
326
+ return True, "/mock/location"
327
+
328
+ def mock_run(*args, **kwargs):
329
+ return subprocess.CompletedProcess(args, 0, stdout="")
330
+
331
+ monkeypatch.setattr(subprocess, "run", mock_run)
332
+ monkeypatch.setattr(
333
+ "src.bitwarden_workflow_linter.rules.run_actionlint.check_actionlint_path",
334
+ mock_check_actionlint,
335
+ )
336
+
337
+ workflow = WorkflowBuilder.build("tests/fixtures/test_workflow.yaml")
338
+ result, _ = rule.fn(workflow)
339
+ assert result is True
340
+
341
+
342
+ def test_run_actionlint_not_installed(monkeypatch, rule):
343
+ rule.settings = settings
344
+
345
+ def mock_check_actionlint(*args, **kwargs):
346
+ return False, ""
347
+
348
+ monkeypatch.setattr(
349
+ "src.bitwarden_workflow_linter.rules.run_actionlint.check_actionlint_path",
350
+ mock_check_actionlint,
351
+ )
352
+
353
+ workflow = WorkflowBuilder.build("tests/fixtures/test_workflow.yaml")
354
+ result, error = rule.fn(workflow)
355
+ assert result is False
356
+ assert "Actionlint must pass" in error
357
+
358
+
359
+ def test_run_actionlint_installed_error(monkeypatch, rule):
360
+ rule.settings = settings
361
+
362
+ def mock_check_actionlint(*args, **kwargs):
363
+ return True, "/mock/location"
364
+
365
+ def mock_run(*args, **kwargs):
366
+ return subprocess.CompletedProcess(args, 110, stdout="An error occurred")
367
+
368
+ monkeypatch.setattr(subprocess, "run", mock_run)
369
+ monkeypatch.setattr(
370
+ "src.bitwarden_workflow_linter.rules.run_actionlint.check_actionlint_path",
371
+ mock_check_actionlint,
372
+ )
373
+
374
+ workflow = WorkflowBuilder.build("tests/fixtures/test_workflow.yaml")
375
+ result, error = rule.fn(workflow)
376
+ assert result is False
377
+ assert "An error occurred" in error
@@ -1,181 +0,0 @@
1
- """Test src/bitwarden_workflow_linter/rules/run_actionlint."""
2
-
3
- import pytest
4
- import subprocess
5
-
6
- from ruamel.yaml import YAML
7
-
8
- from src.bitwarden_workflow_linter.load import WorkflowBuilder
9
- from src.bitwarden_workflow_linter.rules.run_actionlint import (
10
- RunActionlint,
11
- install_actionlint_source,
12
- check_actionlint,
13
- install_actionlint,
14
- )
15
-
16
- yaml = YAML()
17
-
18
-
19
- @pytest.fixture(name="rule")
20
- def fixture_rule():
21
- return RunActionlint()
22
-
23
-
24
- def test_rule_on_correct_workflow(rule):
25
- correct_workflow = WorkflowBuilder.build("tests/fixtures/test_workflow.yaml")
26
- result, _ = rule.fn(correct_workflow)
27
- assert result is True
28
-
29
-
30
- def test_rule_on_incorrect_workflow(rule):
31
- incorrect_workflow = WorkflowBuilder.build(
32
- "tests/fixtures/test_workflow_incorrect.yaml"
33
- )
34
- result, _ = rule.fn(incorrect_workflow)
35
- assert result is False
36
-
37
-
38
- def test_pass_install_actionlint_linux():
39
- result, _ = install_actionlint("Linux")
40
- assert result is True
41
-
42
-
43
- def test_install_actionlint_darwin(monkeypatch):
44
- def mock_run(*args, **kwargs):
45
- return subprocess.CompletedProcess(args, 0)
46
-
47
- monkeypatch.setattr(subprocess, "run", mock_run)
48
- result, _ = install_actionlint("Darwin")
49
- assert result is True
50
-
51
-
52
- def test_failed_install_actionlint_darwin(monkeypatch):
53
- def mock_run(*args, **kwargs):
54
- raise subprocess.CalledProcessError(1, "cmd")
55
-
56
- monkeypatch.setattr(subprocess, "run", mock_run)
57
- result, error = install_actionlint("Darwin")
58
- assert result is False
59
- assert "An error occurred" in error
60
-
61
-
62
- def test_install_actionlint_windows(monkeypatch):
63
- def mock_run(*args, **kwargs):
64
- return subprocess.CompletedProcess(args, 0)
65
-
66
- monkeypatch.setattr(subprocess, "run", mock_run)
67
- result, _ = install_actionlint("Windows")
68
- assert result is True
69
-
70
-
71
- def test_failed_install_actionlint_windows(monkeypatch):
72
- def mock_run(*args, **kwargs):
73
- raise subprocess.CalledProcessError(1, "cmd")
74
-
75
- monkeypatch.setattr(subprocess, "run", mock_run)
76
- result, error = install_actionlint("Windows")
77
- assert result is False
78
- assert "An error occurred" in error
79
-
80
-
81
- def test_install_actionlint_source(monkeypatch):
82
- def mock_run(*args, **kwargs):
83
- return subprocess.CompletedProcess(args, 0)
84
-
85
- monkeypatch.setattr(subprocess, "run", mock_run)
86
-
87
- result, _ = install_actionlint_source("An error occurred")
88
- assert result is True
89
-
90
-
91
- def test_failed_install_actionlint_source(monkeypatch):
92
- def mock_run(*args, **kwargs):
93
- raise subprocess.CalledProcessError(1, "cmd")
94
-
95
- monkeypatch.setattr(subprocess, "run", mock_run)
96
-
97
- result, error = install_actionlint_source("An error occurred")
98
- assert result is False
99
- assert "An error occurred" in error
100
-
101
-
102
- def test_check_actionlint_installed(monkeypatch):
103
- def mock_run(*args, **kwargs):
104
- return subprocess.CompletedProcess(args, 0)
105
-
106
- monkeypatch.setattr(subprocess, "run", mock_run)
107
-
108
- result, _ = check_actionlint("Linux")
109
- assert result is True
110
-
111
-
112
- def test_failed_check_actionlint_installed(monkeypatch):
113
- def mock_run(*args, **kwargs):
114
- raise subprocess.CalledProcessError(1, "cmd")
115
-
116
- monkeypatch.setattr(subprocess, "run", mock_run)
117
-
118
- result, _ = check_actionlint("Linux")
119
- assert result is False
120
-
121
-
122
- def test_check_actionlint_not_installed(monkeypatch):
123
- def mock_run(*args, **kwargs):
124
- raise FileNotFoundError
125
-
126
- monkeypatch.setattr(subprocess, "run", mock_run)
127
-
128
- result, _ = check_actionlint("Linux")
129
- assert result is False
130
-
131
-
132
- def test_run_actionlint_installed(monkeypatch, rule):
133
- def mock_check_actionlint(*args, **kwargs):
134
- return True, "/mock/location"
135
-
136
- def mock_run(*args, **kwargs):
137
- return subprocess.CompletedProcess(args, 0, stdout="")
138
-
139
- monkeypatch.setattr(subprocess, "run", mock_run)
140
- monkeypatch.setattr(
141
- "src.bitwarden_workflow_linter.rules.run_actionlint.check_actionlint",
142
- mock_check_actionlint,
143
- )
144
-
145
- workflow = WorkflowBuilder.build("tests/fixtures/test_workflow.yaml")
146
- result, _ = rule.fn(workflow)
147
- assert result is True
148
-
149
-
150
- def test_run_actionlint_not_installed(monkeypatch, rule):
151
- def mock_check_actionlint(*args, **kwargs):
152
- return False, ""
153
-
154
- monkeypatch.setattr(
155
- "src.bitwarden_workflow_linter.rules.run_actionlint.check_actionlint",
156
- mock_check_actionlint,
157
- )
158
-
159
- workflow = WorkflowBuilder.build("tests/fixtures/test_workflow.yaml")
160
- result, error = rule.fn(workflow)
161
- assert result is False
162
- assert "Actionlint must pass" in error
163
-
164
-
165
- def test_run_actionlint_installed_error(monkeypatch, rule):
166
- def mock_check_actionlint(*args, **kwargs):
167
- return True, "/mock/location"
168
-
169
- def mock_run(*args, **kwargs):
170
- return subprocess.CompletedProcess(args, 110, stdout="An error occurred")
171
-
172
- monkeypatch.setattr(subprocess, "run", mock_run)
173
- monkeypatch.setattr(
174
- "src.bitwarden_workflow_linter.rules.run_actionlint.check_actionlint",
175
- mock_check_actionlint,
176
- )
177
-
178
- workflow = WorkflowBuilder.build("tests/fixtures/test_workflow.yaml")
179
- result, error = rule.fn(workflow)
180
- assert result is False
181
- assert "An error occurred" in error