1
1
using Semmle . Extraction . CSharp ;
2
2
using Semmle . Util . Logging ;
3
3
using Semmle . Autobuild . Shared ;
4
- using Semmle . Util ;
5
- using System . Linq ;
6
4
7
5
namespace Semmle . Autobuild . CSharp
8
6
{
@@ -31,16 +29,25 @@ public CSharpAutobuildOptions(IBuildActions actions) : base(actions)
31
29
32
30
public class CSharpAutobuilder : Autobuilder < CSharpAutobuildOptions >
33
31
{
34
- private const string buildCommandDocsUrl =
35
- "https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-the-codeql-workflow-for-compiled-languages" ;
36
-
37
- private readonly AutoBuildRule autoBuildRule ;
38
-
39
- public CSharpAutobuilder ( IBuildActions actions , CSharpAutobuildOptions options ) : base ( actions , options , new CSharpDiagnosticClassifier ( ) ) =>
40
- this . autoBuildRule = new AutoBuildRule ( this ) ;
32
+ public CSharpAutobuilder ( IBuildActions actions , CSharpAutobuildOptions options ) : base ( actions , options ) { }
41
33
42
34
public override BuildScript GetBuildScript ( )
43
35
{
36
+ /// <summary>
37
+ /// A script that checks that the C# extractor has been executed.
38
+ /// </summary>
39
+ BuildScript CheckExtractorRun ( bool warnOnFailure ) =>
40
+ BuildScript . Create ( actions =>
41
+ {
42
+ if ( actions . FileExists ( Extractor . GetCSharpLogPath ( ) ) )
43
+ return 0 ;
44
+
45
+ if ( warnOnFailure )
46
+ Log ( Severity . Error , "No C# code detected during build." ) ;
47
+
48
+ return 1 ;
49
+ } ) ;
50
+
44
51
var attempt = BuildScript . Failure ;
45
52
switch ( GetCSharpBuildStrategy ( ) )
46
53
{
@@ -58,9 +65,47 @@ public override BuildScript GetBuildScript()
58
65
attempt = new DotNetRule ( ) . Analyse ( this , false ) & CheckExtractorRun ( true ) ;
59
66
break ;
60
67
case CSharpBuildStrategy . Auto :
68
+ var cleanTrapFolder =
69
+ BuildScript . DeleteDirectory ( TrapDir ) ;
70
+ var cleanSourceArchive =
71
+ BuildScript . DeleteDirectory ( SourceArchiveDir ) ;
72
+ var tryCleanExtractorArgsLogs =
73
+ BuildScript . Create ( actions =>
74
+ {
75
+ foreach ( var file in Extractor . GetCSharpArgsLogs ( ) )
76
+ {
77
+ try
78
+ {
79
+ actions . FileDelete ( file ) ;
80
+ }
81
+ catch // lgtm[cs/catch-of-all-exceptions] lgtm[cs/empty-catch-block]
82
+ { }
83
+ }
84
+
85
+ return 0 ;
86
+ } ) ;
87
+ var attemptExtractorCleanup =
88
+ BuildScript . Try ( cleanTrapFolder ) &
89
+ BuildScript . Try ( cleanSourceArchive ) &
90
+ tryCleanExtractorArgsLogs &
91
+ BuildScript . DeleteFile ( Extractor . GetCSharpLogPath ( ) ) ;
92
+
93
+ /// <summary>
94
+ /// Execute script `s` and check that the C# extractor has been executed.
95
+ /// If either fails, attempt to cleanup any artifacts produced by the extractor,
96
+ /// and exit with code 1, in order to proceed to the next attempt.
97
+ /// </summary>
98
+ BuildScript IntermediateAttempt ( BuildScript s ) =>
99
+ ( s & CheckExtractorRun ( false ) ) |
100
+ ( attemptExtractorCleanup & BuildScript . Failure ) ;
101
+
61
102
attempt =
62
- // Attempt a few different build strategies to see if one works
63
- this . autoBuildRule . Analyse ( this , true ) |
103
+ // First try .NET Core
104
+ IntermediateAttempt ( new DotNetRule ( ) . Analyse ( this , true ) ) |
105
+ // Then MSBuild
106
+ ( ( ) => IntermediateAttempt ( new MsBuildRule ( ) . Analyse ( this , true ) ) ) |
107
+ // And finally look for a script that might be a build script
108
+ ( ( ) => new BuildCommandAutoRule ( DotNetRule . WithDotNet ) . Analyse ( this , true ) & CheckExtractorRun ( true ) ) |
64
109
// All attempts failed: print message
65
110
AutobuildFailure ( ) ;
66
111
break ;
@@ -69,127 +114,6 @@ public override BuildScript GetBuildScript()
69
114
return attempt ;
70
115
}
71
116
72
- /// <summary>
73
- /// A script that checks that the C# extractor has been executed.
74
- /// </summary>
75
- public BuildScript CheckExtractorRun ( bool warnOnFailure ) =>
76
- BuildScript . Create ( actions =>
77
- {
78
- if ( actions . FileExists ( Extractor . GetCSharpLogPath ( ) ) )
79
- return 0 ;
80
-
81
- if ( warnOnFailure )
82
- Log ( Severity . Error , "No C# code detected during build." ) ;
83
-
84
- return 1 ;
85
- } ) ;
86
-
87
- protected override void AutobuildFailureDiagnostic ( )
88
- {
89
- // if `ScriptPath` is not null here, the `BuildCommandAuto` rule was
90
- // run and found at least one script to execute
91
- if ( this . autoBuildRule . BuildCommandAutoRule . ScriptPath is not null )
92
- {
93
- var relScriptPath = this . MakeRelative ( autoBuildRule . BuildCommandAutoRule . ScriptPath ) ;
94
-
95
- // if we found multiple build scripts in the project directory, then we can say
96
- // as much to indicate that we may have picked the wrong one;
97
- // otherwise, we just report that the one script we found didn't work
98
- DiagnosticMessage message =
99
- this . autoBuildRule . BuildCommandAutoRule . CandidatePaths . Count ( ) > 1 ?
100
- new (
101
- this . Options . Language ,
102
- "multiple-build-scripts" ,
103
- "There are multiple potential build scripts" ,
104
- markdownMessage :
105
- "CodeQL found multiple potential build scripts for your project and " +
106
- $ "attempted to run `{ relScriptPath } `, which failed. " +
107
- "This may not be the right build script for your project. " +
108
- $ "Set up a [manual build command]({ buildCommandDocsUrl } )."
109
- ) :
110
- new (
111
- this . Options . Language ,
112
- "script-failure" ,
113
- "Unable to build project using build script" ,
114
- markdownMessage :
115
- "CodeQL attempted to build your project using a script located at " +
116
- $ "`{ relScriptPath } `, which failed. " +
117
- $ "Set up a [manual build command]({ buildCommandDocsUrl } )."
118
- ) ;
119
-
120
- AddDiagnostic ( message ) ;
121
- }
122
-
123
- // project files which don't exist get marked as not .NET core projects, but we don't want
124
- // to show an error for this if the files don't exist
125
- var foundNotDotNetProjects = autoBuildRule . DotNetRule . NotDotNetProjects . Where (
126
- proj => this . Actions . FileExists ( proj . FullPath )
127
- ) ;
128
-
129
- // both dotnet and msbuild builds require project or solution files; if we haven't found any
130
- // then neither of those rules would've worked
131
- if ( this . ProjectsOrSolutionsToBuild . Count == 0 )
132
- {
133
- this . AddDiagnostic ( new (
134
- this . Options . Language ,
135
- "no-projects-or-solutions" ,
136
- "No project or solutions files found" ,
137
- markdownMessage :
138
- "CodeQL could not find any project or solution files in your repository. " +
139
- $ "Set up a [manual build command]({ buildCommandDocsUrl } )."
140
- ) ) ;
141
- }
142
- // show a warning if there are projects which are not compatible with .NET Core, in case that is unintentional
143
- else if ( foundNotDotNetProjects . Any ( ) )
144
- {
145
- this . AddDiagnostic ( new (
146
- this . Options . Language ,
147
- "dotnet-incompatible-projects" ,
148
- "Some projects are incompatible with .NET Core" ,
149
- severity : DiagnosticMessage . TspSeverity . Warning ,
150
- markdownMessage : $ """
151
- CodeQL found some projects which cannot be built with .NET Core:
152
-
153
- { autoBuildRule . DotNetRule . NotDotNetProjects . Select ( p => this . MakeRelative ( p . FullPath ) ) . ToMarkdownList ( MarkdownUtil . CodeFormatter , 5 ) }
154
- """
155
- ) ) ;
156
- }
157
-
158
- // report any projects that failed to build with .NET Core
159
- if ( autoBuildRule . DotNetRule . FailedProjectsOrSolutions . Any ( ) )
160
- {
161
- this . AddDiagnostic ( new (
162
- this . Options . Language ,
163
- "dotnet-build-failure" ,
164
- "Some projects or solutions failed to build using .NET Core" ,
165
- markdownMessage : $ """
166
- CodeQL was unable to build the following projects using .NET Core:
167
-
168
- { autoBuildRule . DotNetRule . FailedProjectsOrSolutions . Select ( p => this . MakeRelative ( p . FullPath ) ) . ToMarkdownList ( MarkdownUtil . CodeFormatter , 10 ) }
169
-
170
- Set up a [manual build command]({ buildCommandDocsUrl } ).
171
- """
172
- ) ) ;
173
- }
174
-
175
- // report any projects that failed to build with MSBuild
176
- if ( autoBuildRule . MsBuildRule . FailedProjectsOrSolutions . Any ( ) )
177
- {
178
- this . AddDiagnostic ( new (
179
- this . Options . Language ,
180
- "msbuild-build-failure" ,
181
- "Some projects or solutions failed to build using MSBuild" ,
182
- markdownMessage : $ """
183
- CodeQL was unable to build the following projects using MSBuild:
184
-
185
- { autoBuildRule . MsBuildRule . FailedProjectsOrSolutions . Select ( p => this . MakeRelative ( p . FullPath ) ) . ToMarkdownList ( MarkdownUtil . CodeFormatter , 10 ) }
186
-
187
- Set up a [manual build command]({ buildCommandDocsUrl } ).
188
- """
189
- ) ) ;
190
- }
191
- }
192
-
193
117
/// <summary>
194
118
/// Gets the build strategy that the autobuilder should apply, based on the
195
119
/// options in the `lgtm.yml` file.
0 commit comments