bitwarden_workflow_linter 0.4.6__tar.gz → 0.4.7__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.4.6 → bitwarden_workflow_linter-0.4.7}/.gitignore +4 -1
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/PKG-INFO +5 -4
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/README.md +4 -3
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/settings.yaml +1 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/__about__.py +1 -1
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/default_settings.yaml +1 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/load.py +19 -5
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/models/workflow.py +3 -1
- bitwarden_workflow_linter-0.4.7/src/bitwarden_workflow_linter/rules/run_actionlint.py +108 -0
- bitwarden_workflow_linter-0.4.7/tests/fixtures/test_workflow.yaml +32 -0
- bitwarden_workflow_linter-0.4.7/tests/fixtures/test_workflow_incorrect.yaml +36 -0
- bitwarden_workflow_linter-0.4.7/tests/rules/test_run_actionlint.py +181 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/test_workflow.py +3 -3
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.editorconfig +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.gitattributes +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.github/CODEOWNERS +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.github/renovate.json +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.github/workflows/_version_type.yml +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.github/workflows/cd.yml +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.github/workflows/ci.yml +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.github/workflows/enforce-labels.yml +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.github/workflows/scan.yml +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.github/workflows/update_actions.yml +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.husky/pre-commit +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.python-version +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/CONTRIBUTING.md +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/LICENSE.txt +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/Pipfile +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/Pipfile.lock +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/SECURITY.md +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/Taskfile.yml +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/package-lock.json +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/package.json +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/pylintrc +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/pyproject.toml +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/pyproject.toml.tpl +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/__init__.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/actions.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/cli.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/default_actions.json +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/lint.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/models/__init__.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/models/job.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/models/step.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/rule.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/rules/__init__.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/rules/job_environment_prefix.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/rules/name_capitalized.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/rules/name_exists.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/rules/pinned_job_runner.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/rules/step_approved.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/rules/step_pinned.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/rules/underscore_outputs.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/src/bitwarden_workflow_linter/utils.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/__init__.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/conftest.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/fixtures/test-alt.yml +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/fixtures/test-min-incorrect.yaml +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/fixtures/test-min.yaml +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/fixtures/test-outputs-incorrect.yml +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/fixtures/test.yml +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/fixtures/test_a.yaml +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/rules/__init__.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/rules/test_job_environment_prefix.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/rules/test_name_capitalized.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/rules/test_name_exists.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/rules/test_pinned_job_runner.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/rules/test_step_approved.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/rules/test_step_pinned.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/rules/test_underscore_output.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/test_job.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/test_lint.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/test_load.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/test_rule.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/test_step.py +0 -0
- {bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/test_utils.py +0 -0
@@ -12,7 +12,7 @@ Thumbs.db
|
|
12
12
|
*.sublime-workspace
|
13
13
|
|
14
14
|
# Visual Studio Code
|
15
|
-
.vscode
|
15
|
+
.vscode
|
16
16
|
!.vscode/settings.json
|
17
17
|
!.vscode/tasks.json
|
18
18
|
!.vscode/launch.json
|
@@ -35,3 +35,6 @@ flake.*
|
|
35
35
|
# Python
|
36
36
|
**/__pycache__/**
|
37
37
|
*.pyc
|
38
|
+
.venv/
|
39
|
+
.pytest_cache
|
40
|
+
.pytype
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: bitwarden_workflow_linter
|
3
|
-
Version: 0.4.
|
3
|
+
Version: 0.4.7
|
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
|
@@ -27,9 +27,8 @@ Description-Content-Type: text/markdown
|
|
27
27
|
# Bitwarden Workflow Linter
|
28
28
|
|
29
29
|
Bitwarden's Workflow Linter is an extensible linter to apply opinionated organization-specific
|
30
|
-
GitHub Action standards. It was designed to be used alongside
|
31
|
-
[
|
32
|
-
[yamllint](https://github.com/adrienverge/yamllint) to check for correct Action syntax and enforce
|
30
|
+
GitHub Action standards. It was designed to be used alongside
|
31
|
+
[yamllint](https://github.com/adrienverge/yamllint) to enforce
|
33
32
|
specific YAML standards.
|
34
33
|
|
35
34
|
To see an example of Workflow Linter in practice in GitHub Action, see the
|
@@ -90,6 +89,8 @@ options:
|
|
90
89
|
|
91
90
|
- Python 3.11
|
92
91
|
- pipenv
|
92
|
+
- Windows systems: Chocolatey package manager
|
93
|
+
- Mac OS systems: Homebrew package manager
|
93
94
|
|
94
95
|
### Setup
|
95
96
|
|
@@ -1,9 +1,8 @@
|
|
1
1
|
# Bitwarden Workflow Linter
|
2
2
|
|
3
3
|
Bitwarden's Workflow Linter is an extensible linter to apply opinionated organization-specific
|
4
|
-
GitHub Action standards. It was designed to be used alongside
|
5
|
-
[
|
6
|
-
[yamllint](https://github.com/adrienverge/yamllint) to check for correct Action syntax and enforce
|
4
|
+
GitHub Action standards. It was designed to be used alongside
|
5
|
+
[yamllint](https://github.com/adrienverge/yamllint) to enforce
|
7
6
|
specific YAML standards.
|
8
7
|
|
9
8
|
To see an example of Workflow Linter in practice in GitHub Action, see the
|
@@ -64,6 +63,8 @@ options:
|
|
64
63
|
|
65
64
|
- Python 3.11
|
66
65
|
- pipenv
|
66
|
+
- Windows systems: Chocolatey package manager
|
67
|
+
- Mac OS systems: Homebrew package manager
|
67
68
|
|
68
69
|
### Setup
|
69
70
|
|
@@ -6,5 +6,6 @@ enabled_rules:
|
|
6
6
|
- bitwarden_workflow_linter.rules.step_approved.RuleStepUsesApproved
|
7
7
|
- bitwarden_workflow_linter.rules.step_pinned.RuleStepUsesPinned
|
8
8
|
- bitwarden_workflow_linter.rules.underscore_outputs.RuleUnderscoreOutputs
|
9
|
+
- bitwarden_workflow_linter.rules.run_actionlint.RunActionlint
|
9
10
|
|
10
11
|
approved_actions_path: default_actions.json
|
@@ -6,5 +6,6 @@ enabled_rules:
|
|
6
6
|
- bitwarden_workflow_linter.rules.step_approved.RuleStepUsesApproved
|
7
7
|
- bitwarden_workflow_linter.rules.step_pinned.RuleStepUsesPinned
|
8
8
|
- bitwarden_workflow_linter.rules.underscore_outputs.RuleUnderscoreOutputs
|
9
|
+
- bitwarden_workflow_linter.rules.run_actionlint.RunActionlint
|
9
10
|
|
10
11
|
approved_actions_path: default_actions.json
|
@@ -39,20 +39,32 @@ class WorkflowBuilder:
|
|
39
39
|
objects (depending on their location in the file).
|
40
40
|
"""
|
41
41
|
with open(filename, encoding="utf8") as file:
|
42
|
-
|
42
|
+
if not file:
|
43
|
+
raise WorkflowBuilderError(f"Could not load {filename}")
|
44
|
+
try:
|
45
|
+
return yaml.load(file)
|
46
|
+
except Exception as e:
|
47
|
+
raise WorkflowBuilderError(f"Error loading YAML file {filename}: {e}")
|
43
48
|
|
44
49
|
@classmethod
|
45
|
-
def __build_workflow(cls, loaded_yaml: CommentedMap) -> Workflow:
|
50
|
+
def __build_workflow(cls, filename: str, loaded_yaml: CommentedMap) -> Workflow:
|
46
51
|
"""Parse the YAML and build out the workflow to run Rules against.
|
47
52
|
|
48
53
|
Args:
|
54
|
+
filename:
|
55
|
+
The name of the file that the YAML was loaded from
|
49
56
|
loaded_yaml:
|
50
57
|
YAML that was loaded from either code or a file
|
51
58
|
|
52
59
|
Returns
|
53
60
|
A Workflow to run linting Rules against
|
54
61
|
"""
|
55
|
-
|
62
|
+
try:
|
63
|
+
if not loaded_yaml:
|
64
|
+
raise WorkflowBuilderError("No YAML loaded")
|
65
|
+
return Workflow.init("", filename, loaded_yaml)
|
66
|
+
except Exception as e:
|
67
|
+
raise WorkflowBuilderError(f"Error building workflow: {e}")
|
56
68
|
|
57
69
|
@classmethod
|
58
70
|
def build(
|
@@ -76,9 +88,11 @@ class WorkflowBuilder:
|
|
76
88
|
be loaded from disk
|
77
89
|
"""
|
78
90
|
if from_file and filename is not None:
|
79
|
-
return cls.__build_workflow(
|
91
|
+
return cls.__build_workflow(
|
92
|
+
filename, cls.__load_workflow_from_file(filename)
|
93
|
+
)
|
80
94
|
elif not from_file and workflow is not None:
|
81
|
-
return cls.__build_workflow(workflow)
|
95
|
+
return cls.__build_workflow("", workflow)
|
82
96
|
|
83
97
|
raise WorkflowBuilderError(
|
84
98
|
"The workflow must either be built from a file or from a CommentedMap"
|
@@ -23,14 +23,16 @@ class Workflow:
|
|
23
23
|
"""
|
24
24
|
|
25
25
|
key: str = ""
|
26
|
+
filename: Optional[str] = None
|
26
27
|
name: Optional[str] = None
|
27
28
|
on: Optional[CommentedMap] = None
|
28
29
|
jobs: Optional[Dict[str, Job]] = None
|
29
30
|
|
30
31
|
@classmethod
|
31
|
-
def init(cls: Self, key: str, data: CommentedMap) -> Self:
|
32
|
+
def init(cls: Self, key: str, filename: str, data: CommentedMap) -> Self:
|
32
33
|
init_data = {
|
33
34
|
"key": key,
|
35
|
+
"filename": filename,
|
34
36
|
"name": data["name"] if "name" in data else None,
|
35
37
|
"on": data["on"] if "on" in data else None,
|
36
38
|
}
|
@@ -0,0 +1,108 @@
|
|
1
|
+
"""A Rule to run actionlint on workflows."""
|
2
|
+
|
3
|
+
from typing import Optional, Tuple
|
4
|
+
import subprocess
|
5
|
+
import platform
|
6
|
+
import urllib.request
|
7
|
+
import os
|
8
|
+
|
9
|
+
from ..rule import Rule
|
10
|
+
from ..models.workflow import Workflow
|
11
|
+
from ..utils import LintLevels, Settings
|
12
|
+
|
13
|
+
|
14
|
+
def install_actionlint(platform_system: str) -> Tuple[bool, str]:
|
15
|
+
"""If actionlint is not installed, detects OS platform
|
16
|
+
and installs actionlint"""
|
17
|
+
|
18
|
+
error = f"An error occurred when installing Actionlint on {platform_system}"
|
19
|
+
|
20
|
+
if platform_system.startswith("Linux"):
|
21
|
+
return install_actionlint_source(error)
|
22
|
+
elif platform_system == "Darwin":
|
23
|
+
try:
|
24
|
+
subprocess.run(["brew", "install", "actionlint"], check=True)
|
25
|
+
return True, ""
|
26
|
+
except (FileNotFoundError, subprocess.CalledProcessError):
|
27
|
+
return False, f"{error} : check Brew installation"
|
28
|
+
elif platform_system.startswith("Win"):
|
29
|
+
try:
|
30
|
+
subprocess.run(["choco", "install", "actionlint", "-y"], check=True)
|
31
|
+
return True, ""
|
32
|
+
except (FileNotFoundError, subprocess.CalledProcessError):
|
33
|
+
return False, f"{error} : check Choco installation"
|
34
|
+
return False, error
|
35
|
+
|
36
|
+
|
37
|
+
def install_actionlint_source(error) -> Tuple[bool, str]:
|
38
|
+
"""Install Actionlint Binary from provided script"""
|
39
|
+
url = "https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash"
|
40
|
+
version = "1.6.17"
|
41
|
+
request = urllib.request.urlopen(url)
|
42
|
+
with open("download-actionlint.bash", "wb+") as fp:
|
43
|
+
fp.write(request.read())
|
44
|
+
try:
|
45
|
+
subprocess.run(["bash", "download-actionlint.bash", version], check=True)
|
46
|
+
return True, os.getcwd()
|
47
|
+
except (FileNotFoundError, subprocess.CalledProcessError):
|
48
|
+
return False, error
|
49
|
+
|
50
|
+
|
51
|
+
def check_actionlint(platform_system: str) -> Tuple[bool, str]:
|
52
|
+
"""Check if the actionlint is in the system's PATH."""
|
53
|
+
try:
|
54
|
+
subprocess.run(
|
55
|
+
["actionlint", "--version"],
|
56
|
+
stdout=subprocess.PIPE,
|
57
|
+
stderr=subprocess.PIPE,
|
58
|
+
check=True,
|
59
|
+
)
|
60
|
+
return True, ""
|
61
|
+
except subprocess.CalledProcessError:
|
62
|
+
return (
|
63
|
+
False,
|
64
|
+
"Failed to install Actionlint, \
|
65
|
+
please check your package installer or manually install it",
|
66
|
+
)
|
67
|
+
except FileNotFoundError:
|
68
|
+
return install_actionlint(platform_system)
|
69
|
+
|
70
|
+
|
71
|
+
class RunActionlint(Rule):
|
72
|
+
"""Rule to run actionlint as part of workflow linter V2."""
|
73
|
+
|
74
|
+
def __init__(self, settings: Optional[Settings] = None) -> None:
|
75
|
+
self.message = "Actionlint must pass without errors"
|
76
|
+
self.on_fail = LintLevels.WARNING
|
77
|
+
self.compatibility = [Workflow]
|
78
|
+
self.settings = settings
|
79
|
+
|
80
|
+
def fn(self, obj: Workflow) -> Tuple[bool, str]:
|
81
|
+
if not obj or not obj.filename:
|
82
|
+
raise AttributeError(
|
83
|
+
"Running actionlint without a filename is not currently supported"
|
84
|
+
)
|
85
|
+
|
86
|
+
installed, location = check_actionlint(platform.system())
|
87
|
+
if installed:
|
88
|
+
if location:
|
89
|
+
result = subprocess.run(
|
90
|
+
[location + "/actionlint", obj.filename],
|
91
|
+
capture_output=True,
|
92
|
+
text=True,
|
93
|
+
check=False,
|
94
|
+
)
|
95
|
+
else:
|
96
|
+
result = subprocess.run(
|
97
|
+
["actionlint", obj.filename],
|
98
|
+
capture_output=True,
|
99
|
+
text=True,
|
100
|
+
check=False,
|
101
|
+
)
|
102
|
+
if result.returncode == 1:
|
103
|
+
return False, result.stdout
|
104
|
+
if result.returncode > 1:
|
105
|
+
return False, result.stdout
|
106
|
+
return True, ""
|
107
|
+
else:
|
108
|
+
return False, self.message
|
@@ -0,0 +1,32 @@
|
|
1
|
+
name: test
|
2
|
+
on:
|
3
|
+
workflow_dispatch:
|
4
|
+
pull_request:
|
5
|
+
|
6
|
+
jobs:
|
7
|
+
job-key:
|
8
|
+
name: Test
|
9
|
+
runs-on: ubuntu-latest
|
10
|
+
steps:
|
11
|
+
- name: Test
|
12
|
+
run: echo test
|
13
|
+
|
14
|
+
call-workflow:
|
15
|
+
uses: bitwarden/server/.github/workflows/workflow-linter.yml@master
|
16
|
+
|
17
|
+
test-normal-action:
|
18
|
+
name: Download Latest
|
19
|
+
runs-on: ubuntu-20.04
|
20
|
+
steps:
|
21
|
+
- name: Checkout
|
22
|
+
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
|
23
|
+
|
24
|
+
- run: |
|
25
|
+
echo test
|
26
|
+
|
27
|
+
test-local-action:
|
28
|
+
name: Testing a local action call
|
29
|
+
runs-on: ubuntu-20.04
|
30
|
+
steps:
|
31
|
+
- name: local-action
|
32
|
+
uses: ./version-bump
|
@@ -0,0 +1,36 @@
|
|
1
|
+
name: test
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches:
|
5
|
+
-
|
6
|
+
path:
|
7
|
+
- "src/**"
|
8
|
+
workflow_dispatch:
|
9
|
+
|
10
|
+
jobs:
|
11
|
+
job-key:
|
12
|
+
name: Test
|
13
|
+
runs-on: ubuntu-latest
|
14
|
+
steps:
|
15
|
+
- name: Test
|
16
|
+
run: echo test
|
17
|
+
|
18
|
+
call-workflow:
|
19
|
+
uses: bitwarden/server/.github/workflows/workflow-linter.yml@master
|
20
|
+
|
21
|
+
test-normal-action:
|
22
|
+
name: Download Latest
|
23
|
+
runs-on: ubuntu-20.04
|
24
|
+
steps:
|
25
|
+
- name: Checkout
|
26
|
+
uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b
|
27
|
+
|
28
|
+
- run: |
|
29
|
+
echo test
|
30
|
+
|
31
|
+
test-local-action:
|
32
|
+
name: Testing a local action call
|
33
|
+
runs-on: ubuntu-20.04
|
34
|
+
steps:
|
35
|
+
- name: local-action
|
36
|
+
uses: ./version-bump
|
@@ -0,0 +1,181 @@
|
|
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
|
@@ -72,7 +72,7 @@ jobs:
|
|
72
72
|
|
73
73
|
|
74
74
|
def test_simple_workflow(simple_workflow_yaml):
|
75
|
-
workflow = Workflow.init("", simple_workflow_yaml)
|
75
|
+
workflow = Workflow.init("", None, simple_workflow_yaml)
|
76
76
|
|
77
77
|
assert workflow.name == "test"
|
78
78
|
assert len(workflow.on.keys()) == 1
|
@@ -80,7 +80,7 @@ def test_simple_workflow(simple_workflow_yaml):
|
|
80
80
|
|
81
81
|
|
82
82
|
def test_complex_workflow(complex_workflow_yaml):
|
83
|
-
workflow = Workflow.init("", complex_workflow_yaml)
|
83
|
+
workflow = Workflow.init("", None, complex_workflow_yaml)
|
84
84
|
|
85
85
|
assert workflow.name == "test"
|
86
86
|
assert len(workflow.on.keys()) == 2
|
@@ -91,7 +91,7 @@ def test_workflow_extra_kwargs(simple_workflow_yaml):
|
|
91
91
|
extra_data_workflow = simple_workflow_yaml
|
92
92
|
extra_data_workflow["extra"] = "This should not exist"
|
93
93
|
|
94
|
-
workflow = Workflow.init("", extra_data_workflow)
|
94
|
+
workflow = Workflow.init("", None, extra_data_workflow)
|
95
95
|
|
96
96
|
with pytest.raises(Exception):
|
97
97
|
assert workflow.extra == "test"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.github/PULL_REQUEST_TEMPLATE.md
RENAMED
File without changes
|
File without changes
|
File without changes
|
{bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.github/workflows/cd.yml
RENAMED
File without changes
|
{bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.github/workflows/ci.yml
RENAMED
File without changes
|
File without changes
|
{bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/.github/workflows/scan.yml
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/fixtures/test-alt.yml
RENAMED
File without changes
|
File without changes
|
{bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/fixtures/test-min.yaml
RENAMED
File without changes
|
File without changes
|
File without changes
|
{bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/fixtures/test_a.yaml
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/rules/test_name_exists.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{bitwarden_workflow_linter-0.4.6 → bitwarden_workflow_linter-0.4.7}/tests/rules/test_step_pinned.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|