7
7
from pathlib import Path
8
8
from unittest .mock import MagicMock
9
9
10
- import pytest
11
-
12
10
import macaron
13
11
from macaron .code_analyzer .call_graph import BaseNode , CallGraph
14
12
from macaron .parsers .actionparser import parse as parse_action
28
26
from macaron .slsa_analyzer .specs .ci_spec import CIInfo
29
27
30
28
31
- @pytest .fixture ()
32
- def build_as_code_check (setup_test ) -> BuildAsCodeCheck : # type: ignore # pylint: disable=unused-argument
33
- """Create a BuildAsCodeCheck instance.
34
-
35
- Parameters
36
- ----------
37
- setup_test
38
- Depends on setup_test fixture.
39
-
40
- Returns
41
- -------
42
- BuildAsCodeCheck
43
- The BuildAsCodeCheck instance.
44
- """
45
- return BuildAsCodeCheck ()
46
-
47
-
48
29
def test_build_as_code_check (
49
- build_as_code_check : BuildAsCodeCheck , # pylint: disable=redefined-outer-name
50
- check_result : CheckResult ,
51
30
maven_tool : Maven ,
52
31
gradle_tool : Gradle ,
53
32
poetry_tool : Poetry ,
@@ -59,6 +38,8 @@ def test_build_as_code_check(
59
38
gitlab_ci_service : GitLabCI ,
60
39
) -> None :
61
40
"""Test the Build As Code Check."""
41
+ check = BuildAsCodeCheck ()
42
+ check_result = CheckResult (justification = []) # type: ignore
62
43
bash_commands = BashCommands (caller_path = "source_file" , CI_path = "ci_file" , CI_type = "github_actions" , commands = [[]])
63
44
ci_info = CIInfo (
64
45
service = github_actions_service ,
@@ -72,131 +53,131 @@ def test_build_as_code_check(
72
53
# The target repo uses Maven build tool but does not deploy artifacts.
73
54
use_build_tool = AnalyzeContext ("use_build_tool" , os .path .abspath ("./" ), MagicMock ())
74
55
use_build_tool .dynamic_data ["build_spec" ]["tool" ] = maven_tool
75
- assert build_as_code_check .run_check (use_build_tool , check_result ) == CheckResultType .FAILED
56
+ assert check .run_check (use_build_tool , check_result ) == CheckResultType .FAILED
76
57
77
58
# The target repo uses Gradle build tool but does not deploy artifacts.
78
59
use_build_tool = AnalyzeContext ("use_build_tool" , os .path .abspath ("./" ), MagicMock ())
79
60
use_build_tool .dynamic_data ["build_spec" ]["tool" ] = gradle_tool
80
- assert build_as_code_check .run_check (use_build_tool , check_result ) == CheckResultType .FAILED
61
+ assert check .run_check (use_build_tool , check_result ) == CheckResultType .FAILED
81
62
82
63
# The target repo uses Poetry build tool but does not deploy artifacts.
83
64
use_build_tool = AnalyzeContext ("use_build_tool" , os .path .abspath ("./" ), MagicMock ())
84
65
use_build_tool .dynamic_data ["build_spec" ]["tool" ] = poetry_tool
85
- assert build_as_code_check .run_check (use_build_tool , check_result ) == CheckResultType .FAILED
66
+ assert check .run_check (use_build_tool , check_result ) == CheckResultType .FAILED
86
67
87
68
# The target repo uses Pip build tool but does not deploy artifacts.
88
69
use_build_tool = AnalyzeContext ("use_build_tool" , os .path .abspath ("./" ), MagicMock ())
89
70
use_build_tool .dynamic_data ["build_spec" ]["tool" ] = pip_tool
90
- assert build_as_code_check .run_check (use_build_tool , check_result ) == CheckResultType .FAILED
71
+ assert check .run_check (use_build_tool , check_result ) == CheckResultType .FAILED
91
72
92
73
# The target repo does not use a build tool.
93
74
no_build_tool = AnalyzeContext ("no_build_tool" , os .path .abspath ("./" ), MagicMock ())
94
- assert build_as_code_check .run_check (no_build_tool , check_result ) == CheckResultType .FAILED
75
+ assert check .run_check (no_build_tool , check_result ) == CheckResultType .FAILED
95
76
96
77
# Use mvn deploy to deploy the artifact.
97
78
maven_deploy = AnalyzeContext ("use_build_tool" , os .path .abspath ("./" ), MagicMock ())
98
79
maven_deploy .dynamic_data ["build_spec" ]["tool" ] = maven_tool
99
80
bash_commands ["commands" ] = [["mvn" , "deploy" ]]
100
81
maven_deploy .dynamic_data ["ci_services" ] = [ci_info ]
101
- assert build_as_code_check .run_check (maven_deploy , check_result ) == CheckResultType .PASSED
82
+ assert check .run_check (maven_deploy , check_result ) == CheckResultType .PASSED
102
83
103
84
# Use the mvn in the local directory to deploy the artifact.
104
85
bash_commands ["commands" ] = [["./mvn" , "deploy" ]]
105
86
maven_deploy .dynamic_data ["ci_services" ] = [ci_info ]
106
- assert build_as_code_check .run_check (maven_deploy , check_result ) == CheckResultType .PASSED
87
+ assert check .run_check (maven_deploy , check_result ) == CheckResultType .PASSED
107
88
108
89
# Use an invalid build command that has mvn.
109
90
bash_commands ["commands" ] = [["mvnblah" , "deploy" ]]
110
91
maven_deploy .dynamic_data ["ci_services" ] = [ci_info ]
111
- assert build_as_code_check .run_check (maven_deploy , check_result ) == CheckResultType .FAILED
92
+ assert check .run_check (maven_deploy , check_result ) == CheckResultType .FAILED
112
93
113
94
# Use mvn but do not deploy artifacts.
114
95
no_maven_deploy = AnalyzeContext ("use_build_tool" , os .path .abspath ("./" ), MagicMock ())
115
96
no_maven_deploy .dynamic_data ["build_spec" ]["tool" ] = maven_tool
116
97
bash_commands ["commands" ] = [["mvn" , "verify" ]]
117
98
no_maven_deploy .dynamic_data ["ci_services" ] = [ci_info ]
118
- assert build_as_code_check .run_check (no_maven_deploy , check_result ) == CheckResultType .FAILED
99
+ assert check .run_check (no_maven_deploy , check_result ) == CheckResultType .FAILED
119
100
120
101
# Use an invalid goal that has deploy keyword.
121
102
bash_commands ["commands" ] = [["mvnb" , "deployblah" ]]
122
103
no_maven_deploy .dynamic_data ["ci_services" ] = [ci_info ]
123
- assert build_as_code_check .run_check (no_maven_deploy , check_result ) == CheckResultType .FAILED
104
+ assert check .run_check (no_maven_deploy , check_result ) == CheckResultType .FAILED
124
105
125
106
# Use gradle to deploy the artifact.
126
107
gradle_deploy = AnalyzeContext ("use_build_tool" , os .path .abspath ("./" ), MagicMock ())
127
108
gradle_deploy .dynamic_data ["build_spec" ]["tool" ] = gradle_tool
128
109
bash_commands ["commands" ] = [["./gradlew" , "publishToSonatype" ]]
129
110
gradle_deploy .dynamic_data ["ci_services" ] = [ci_info ]
130
- assert build_as_code_check .run_check (gradle_deploy , check_result ) == CheckResultType .PASSED
111
+ assert check .run_check (gradle_deploy , check_result ) == CheckResultType .PASSED
131
112
132
113
# Use poetry publish to publish the artifact.
133
114
poetry_publish = AnalyzeContext ("use_build_tool" , os .path .abspath ("./" ), MagicMock ())
134
115
poetry_publish .dynamic_data ["build_spec" ]["tool" ] = poetry_tool
135
116
bash_commands ["commands" ] = [["poetry" , "publish" ]]
136
117
poetry_publish .dynamic_data ["ci_services" ] = [ci_info ]
137
- assert build_as_code_check .run_check (poetry_publish , check_result ) == CheckResultType .PASSED
118
+ assert check .run_check (poetry_publish , check_result ) == CheckResultType .PASSED
138
119
139
120
# Use Poetry but do not deploy artifacts.
140
121
no_poetry_deploy = AnalyzeContext ("use_build_tool" , os .path .abspath ("./" ), MagicMock ())
141
122
no_poetry_deploy .dynamic_data ["build_spec" ]["tool" ] = poetry_tool
142
123
bash_commands ["commands" ] = [["poetry" , "upload" ]]
143
124
no_poetry_deploy .dynamic_data ["ci_services" ] = [ci_info ]
144
- assert build_as_code_check .run_check (no_maven_deploy , check_result ) == CheckResultType .FAILED
125
+ assert check .run_check (no_maven_deploy , check_result ) == CheckResultType .FAILED
145
126
146
127
# Use twine upload to deploy the artifact.
147
128
twine_upload = AnalyzeContext ("use_build_tool" , os .path .abspath ("./" ), MagicMock ())
148
129
twine_upload .dynamic_data ["build_spec" ]["tool" ] = pip_tool
149
130
bash_commands ["commands" ] = [["twine" , "upload" , "dist/*" ]]
150
131
twine_upload .dynamic_data ["ci_services" ] = [ci_info ]
151
- assert build_as_code_check .run_check (twine_upload , check_result ) == CheckResultType .PASSED
132
+ assert check .run_check (twine_upload , check_result ) == CheckResultType .PASSED
152
133
153
134
# Use flit publish to deploy the artifact.
154
135
flit_publish = AnalyzeContext ("use_build_tool" , os .path .abspath ("./" ), MagicMock ())
155
136
flit_publish .dynamic_data ["build_spec" ]["tool" ] = pip_tool
156
137
bash_commands ["commands" ] = [["flit" , "publish" ]]
157
138
flit_publish .dynamic_data ["ci_services" ] = [ci_info ]
158
- assert build_as_code_check .run_check (flit_publish , check_result ) == CheckResultType .PASSED
139
+ assert check .run_check (flit_publish , check_result ) == CheckResultType .PASSED
159
140
160
141
# Test Jenkins.
161
142
maven_deploy = AnalyzeContext ("use_build_tool" , os .path .abspath ("./" ), MagicMock ())
162
143
maven_deploy .dynamic_data ["build_spec" ]["tool" ] = maven_tool
163
144
ci_info ["service" ] = jenkins_service
164
145
bash_commands ["commands" ] = []
165
146
maven_deploy .dynamic_data ["ci_services" ] = [ci_info ]
166
- assert build_as_code_check .run_check (maven_deploy , check_result ) == CheckResultType .FAILED
147
+ assert check .run_check (maven_deploy , check_result ) == CheckResultType .FAILED
167
148
168
149
# Test Travis.
169
150
maven_deploy = AnalyzeContext ("use_build_tool" , os .path .abspath ("./" ), MagicMock ())
170
151
maven_deploy .dynamic_data ["build_spec" ]["tool" ] = maven_tool
171
152
ci_info ["service" ] = travis_service
172
153
bash_commands ["commands" ] = []
173
154
maven_deploy .dynamic_data ["ci_services" ] = [ci_info ]
174
- assert build_as_code_check .run_check (maven_deploy , check_result ) == CheckResultType .FAILED
155
+ assert check .run_check (maven_deploy , check_result ) == CheckResultType .FAILED
175
156
176
157
# Test Circle CI.
177
158
maven_deploy = AnalyzeContext ("use_build_tool" , os .path .abspath ("./" ), MagicMock ())
178
159
maven_deploy .dynamic_data ["build_spec" ]["tool" ] = maven_tool
179
160
ci_info ["service" ] = circle_ci_service
180
161
bash_commands ["commands" ] = []
181
162
maven_deploy .dynamic_data ["ci_services" ] = [ci_info ]
182
- assert build_as_code_check .run_check (maven_deploy , check_result ) == CheckResultType .FAILED
163
+ assert check .run_check (maven_deploy , check_result ) == CheckResultType .FAILED
183
164
184
165
# Test GitLab CI.
185
166
maven_deploy = AnalyzeContext ("use_build_tool" , os .path .abspath ("./" ), MagicMock ())
186
167
maven_deploy .dynamic_data ["build_spec" ]["tool" ] = maven_tool
187
168
ci_info ["service" ] = gitlab_ci_service
188
169
bash_commands ["commands" ] = []
189
170
maven_deploy .dynamic_data ["ci_services" ] = [ci_info ]
190
- assert build_as_code_check .run_check (maven_deploy , check_result ) == CheckResultType .FAILED
171
+ assert check .run_check (maven_deploy , check_result ) == CheckResultType .FAILED
191
172
192
173
193
174
def test_gha_workflow_deployment (
194
- build_as_code_check : BuildAsCodeCheck , # pylint: disable=redefined-outer-name
195
- check_result : CheckResult ,
196
175
pip_tool : Pip ,
197
176
github_actions_service : GitHubActions ,
198
177
) -> None :
199
178
"""Test the use of verified GitHub Actions to deploy."""
179
+ check = BuildAsCodeCheck ()
180
+ check_result = CheckResult (justification = []) # type: ignore
200
181
ci_info = CIInfo (
201
182
service = github_actions_service ,
202
183
bash_commands = [],
@@ -227,4 +208,21 @@ def test_gha_workflow_deployment(
227
208
root .add_callee (callee )
228
209
github_actions_service .build_call_graph_from_node (callee )
229
210
ci_info ["callgraph" ] = gh_cg
230
- assert build_as_code_check .run_check (gha_deploy , check_result ) == CheckResultType .PASSED
211
+ assert check .run_check (gha_deploy , check_result ) == CheckResultType .PASSED
212
+
213
+ # This Github Actions workflow is not using a trusted action to publish the artifact.
214
+ root = GitHubNode (name = "root" , node_type = GHWorkflowType .NONE , source_path = "" , parsed_obj = {}, caller_path = "" )
215
+ gh_cg = CallGraph (root , "" )
216
+ workflow_path = os .path .join (workflows_dir , "pypi_publish_blah.yaml" )
217
+ parsed_obj = parse_action (workflow_path , macaron_path = str (Path (macaron .MACARON_PATH )))
218
+ callee = GitHubNode (
219
+ name = os .path .basename (workflow_path ),
220
+ node_type = GHWorkflowType .INTERNAL ,
221
+ source_path = workflow_path ,
222
+ parsed_obj = parsed_obj ,
223
+ caller_path = "" ,
224
+ )
225
+ root .add_callee (callee )
226
+ github_actions_service .build_call_graph_from_node (callee )
227
+ ci_info ["callgraph" ] = gh_cg
228
+ assert check .run_check (gha_deploy , check_result ) == CheckResultType .FAILED
0 commit comments