pmdtester 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ci/build.sh +91 -0
- data/.ci/files/env.gpg +1 -0
- data/.github/workflows/build.yml +39 -0
- data/.gitignore +9 -0
- data/.hoerc +1 -1
- data/.rubocop.yml +6 -2
- data/.ruby-version +1 -0
- data/History.md +40 -0
- data/Manifest.txt +24 -9
- data/README.rdoc +45 -30
- data/Rakefile +5 -3
- data/config/all-java.xml +1 -1
- data/config/design.xml +1 -1
- data/config/projectlist_1_0_0.xsd +2 -1
- data/config/projectlist_1_1_0.xsd +31 -0
- data/lib/pmdtester.rb +8 -7
- data/lib/pmdtester/builders/liquid_renderer.rb +73 -0
- data/lib/pmdtester/builders/pmd_report_builder.rb +102 -78
- data/lib/pmdtester/builders/project_builder.rb +100 -0
- data/lib/pmdtester/builders/project_hasher.rb +126 -0
- data/lib/pmdtester/builders/rule_set_builder.rb +92 -47
- data/lib/pmdtester/builders/simple_progress_logger.rb +4 -4
- data/lib/pmdtester/builders/summary_report_builder.rb +62 -131
- data/lib/pmdtester/collection_by_file.rb +55 -0
- data/lib/pmdtester/parsers/options.rb +19 -0
- data/lib/pmdtester/parsers/pmd_report_document.rb +74 -29
- data/lib/pmdtester/parsers/projects_parser.rb +2 -4
- data/lib/pmdtester/pmd_branch_detail.rb +29 -19
- data/lib/pmdtester/pmd_configerror.rb +23 -24
- data/lib/pmdtester/pmd_error.rb +34 -34
- data/lib/pmdtester/pmd_report_detail.rb +9 -12
- data/lib/pmdtester/pmd_tester_utils.rb +55 -0
- data/lib/pmdtester/pmd_violation.rb +66 -28
- data/lib/pmdtester/project.rb +21 -48
- data/lib/pmdtester/report_diff.rb +179 -111
- data/lib/pmdtester/resource_locator.rb +4 -0
- data/lib/pmdtester/runner.rb +66 -64
- data/pmdtester.gemspec +27 -36
- data/resources/_includes/diff_pill_row.html +6 -0
- data/resources/css/bootstrap.min.css +7 -0
- data/resources/css/datatables.min.css +36 -0
- data/resources/css/pmd-tester.css +131 -0
- data/resources/js/bootstrap.min.js +7 -0
- data/resources/js/code-snippets.js +66 -0
- data/resources/js/datatables.min.js +726 -0
- data/resources/js/jquery-3.2.1.slim.min.js +4 -0
- data/resources/js/jquery.min.js +2 -0
- data/resources/js/popper.min.js +5 -0
- data/resources/js/project-report.js +136 -0
- data/resources/project_diff_report.html +205 -0
- data/resources/project_index.html +102 -0
- metadata +64 -20
- data/.travis.yml +0 -40
- data/lib/pmdtester/builders/diff_builder.rb +0 -31
- data/lib/pmdtester/builders/diff_report/configerrors.rb +0 -50
- data/lib/pmdtester/builders/diff_report/errors.rb +0 -71
- data/lib/pmdtester/builders/diff_report/violations.rb +0 -77
- data/lib/pmdtester/builders/diff_report_builder.rb +0 -99
- data/lib/pmdtester/builders/html_report_builder.rb +0 -56
- data/resources/css/maven-base.css +0 -155
- data/resources/css/maven-theme.css +0 -171
@@ -1,4 +1,5 @@
|
|
1
1
|
<?xml version="1.0" ?>
|
2
|
+
<!-- version 1.0.0 -->
|
2
3
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
3
4
|
<xs:element name="projectlist">
|
4
5
|
<xs:complexType>
|
@@ -25,4 +26,4 @@
|
|
25
26
|
<xs:element name="exclude-pattern" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
|
26
27
|
</xs:sequence>
|
27
28
|
</xs:complexType>
|
28
|
-
</xs:schema>
|
29
|
+
</xs:schema>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<?xml version="1.0" ?>
|
2
|
+
<!-- version 1.1.0 -->
|
3
|
+
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
4
|
+
<xs:element name="projectlist">
|
5
|
+
<xs:complexType>
|
6
|
+
<xs:sequence>
|
7
|
+
<xs:element name="description" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
8
|
+
<xs:element name="project" type="project" minOccurs="1" maxOccurs="unbounded"/>
|
9
|
+
</xs:sequence>
|
10
|
+
</xs:complexType>
|
11
|
+
</xs:element>
|
12
|
+
<xs:complexType name="project">
|
13
|
+
<xs:sequence>
|
14
|
+
<xs:element name="name" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
15
|
+
<xs:element name="type" minOccurs="1" maxOccurs="1">
|
16
|
+
<xs:simpleType>
|
17
|
+
<xs:restriction base="xs:string">
|
18
|
+
<xs:enumeration value="git"/>
|
19
|
+
<xs:enumeration value="hg"/>
|
20
|
+
</xs:restriction>
|
21
|
+
</xs:simpleType>
|
22
|
+
</xs:element>
|
23
|
+
<xs:element name="connection" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
24
|
+
<xs:element name="webview-url" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
25
|
+
<xs:element name="tag" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
26
|
+
<xs:element name="exclude-pattern" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
|
27
|
+
<xs:element name="build-command" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
28
|
+
<xs:element name="auxclasspath-command" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
29
|
+
</xs:sequence>
|
30
|
+
</xs:complexType>
|
31
|
+
</xs:schema>
|
data/lib/pmdtester.rb
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'logger'
|
4
|
+
require 'logger/colors'
|
4
5
|
|
5
6
|
require_relative 'pmdtester/cmd'
|
7
|
+
require_relative 'pmdtester/collection_by_file'
|
6
8
|
require_relative 'pmdtester/pmd_branch_detail'
|
7
9
|
require_relative 'pmdtester/pmd_configerror'
|
8
10
|
require_relative 'pmdtester/pmd_error'
|
9
11
|
require_relative 'pmdtester/pmd_report_detail'
|
12
|
+
require_relative 'pmdtester/pmd_tester_utils'
|
10
13
|
require_relative 'pmdtester/pmd_violation'
|
11
14
|
require_relative 'pmdtester/project'
|
12
15
|
require_relative 'pmdtester/report_diff'
|
@@ -14,13 +17,10 @@ require_relative 'pmdtester/resource_locator'
|
|
14
17
|
require_relative 'pmdtester/runner'
|
15
18
|
|
16
19
|
require_relative 'pmdtester/builders/simple_progress_logger'
|
17
|
-
require_relative 'pmdtester/builders/
|
18
|
-
require_relative 'pmdtester/builders/
|
19
|
-
require_relative 'pmdtester/builders/diff_report/violations'
|
20
|
-
require_relative 'pmdtester/builders/diff_report/configerrors'
|
21
|
-
require_relative 'pmdtester/builders/diff_report/errors'
|
22
|
-
require_relative 'pmdtester/builders/diff_report_builder'
|
20
|
+
require_relative 'pmdtester/builders/project_builder'
|
21
|
+
require_relative 'pmdtester/builders/project_hasher'
|
23
22
|
require_relative 'pmdtester/builders/pmd_report_builder'
|
23
|
+
require_relative 'pmdtester/builders/liquid_renderer'
|
24
24
|
require_relative 'pmdtester/builders/rule_set_builder'
|
25
25
|
require_relative 'pmdtester/builders/summary_report_builder'
|
26
26
|
|
@@ -32,9 +32,10 @@ require_relative 'pmdtester/parsers/projects_parser'
|
|
32
32
|
# and unexpected behaviors will not be introduced to PMD project
|
33
33
|
# after fixing an issue and new rules can work as expected.
|
34
34
|
module PmdTester
|
35
|
-
VERSION = '1.0
|
35
|
+
VERSION = '1.1.0'
|
36
36
|
BASE = 'base'
|
37
37
|
PATCH = 'patch'
|
38
|
+
PR_NUM_ENV_VAR = 'PMD_CI_PULL_REQUEST_NUMBER' # see PmdBranchDetail
|
38
39
|
|
39
40
|
def logger
|
40
41
|
PmdTester.logger
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'liquid'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
module PmdTester
|
7
|
+
# A module to include in classes that use a Liquid template
|
8
|
+
# to generate content.
|
9
|
+
module LiquidRenderer
|
10
|
+
include PmdTester
|
11
|
+
|
12
|
+
def render_liquid(template_path, env)
|
13
|
+
to_render = File.read(ResourceLocator.resource(template_path))
|
14
|
+
includes = Liquid::LocalFileSystem.new(ResourceLocator.resource('_includes'), '%s.html')
|
15
|
+
Liquid::Template.file_system = includes
|
16
|
+
template = Liquid::Template.parse(to_render, error_mode: :strict)
|
17
|
+
template.render!(env, { strict_variables: true })
|
18
|
+
end
|
19
|
+
|
20
|
+
def render_and_write(template_path, target_file, env)
|
21
|
+
write_file(target_file, render_liquid(template_path, env))
|
22
|
+
end
|
23
|
+
|
24
|
+
def write_file(target_file, contents)
|
25
|
+
dir = File.dirname(target_file)
|
26
|
+
FileUtils.mkdir_p(dir) unless File.directory?(dir)
|
27
|
+
|
28
|
+
index = File.new(target_file, 'w')
|
29
|
+
index&.puts contents # may be nil when stubbing
|
30
|
+
logger&.info "Written #{target_file}"
|
31
|
+
ensure
|
32
|
+
index&.close
|
33
|
+
end
|
34
|
+
|
35
|
+
def copy_resource(dir, to_root)
|
36
|
+
src = ResourceLocator.resource(dir)
|
37
|
+
dest = "#{to_root}/#{dir}"
|
38
|
+
FileUtils.copy_entry(src, dest)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Renders the index of a project diff report.
|
43
|
+
class LiquidProjectRenderer
|
44
|
+
include PmdTester
|
45
|
+
include ProjectHasher
|
46
|
+
include LiquidRenderer
|
47
|
+
|
48
|
+
def write_project_index(project, root)
|
49
|
+
liquid_env = {
|
50
|
+
'diff' => report_diff_to_h(project.report_diff),
|
51
|
+
'error_diffs' => errors_to_h(project),
|
52
|
+
'configerror_diffs' => configerrors_to_h(project),
|
53
|
+
'project_name' => project.name
|
54
|
+
}
|
55
|
+
|
56
|
+
# Renders index.html using liquid
|
57
|
+
write_file("#{root}/index.html", render_liquid('project_diff_report.html', liquid_env))
|
58
|
+
# generate array of violations in json
|
59
|
+
write_file("#{root}/project_data.js", dump_violations_json(project))
|
60
|
+
end
|
61
|
+
|
62
|
+
def dump_violations_json(project)
|
63
|
+
h = {
|
64
|
+
'source_link_base' => project.webview_url,
|
65
|
+
'source_link_template' => link_template(project),
|
66
|
+
**violations_to_hash(project)
|
67
|
+
}
|
68
|
+
|
69
|
+
project_data = JSON.fast_generate(h)
|
70
|
+
"let project = #{project_data}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -8,92 +8,70 @@ module PmdTester
|
|
8
8
|
# projects and branch of pmd source code
|
9
9
|
class PmdReportBuilder
|
10
10
|
include PmdTester
|
11
|
-
|
12
|
-
|
11
|
+
|
12
|
+
def initialize(projects, options, branch_config, branch_name)
|
13
13
|
@projects = projects
|
14
|
-
@local_git_repo = local_git_repo
|
15
|
-
@
|
16
|
-
@
|
14
|
+
@local_git_repo = options.local_git_repo
|
15
|
+
@threads = options.threads
|
16
|
+
@error_recovery = options.error_recovery
|
17
|
+
@branch_config = branch_config
|
18
|
+
@pmd_branch_name = branch_name
|
17
19
|
@pwd = Dir.getwd
|
18
20
|
|
19
|
-
@pmd_branch_details = PmdBranchDetail.new(pmd_branch_name)
|
20
|
-
|
21
|
-
|
22
|
-
def execute_reset_cmd(type, tag)
|
23
|
-
case type
|
24
|
-
when 'git'
|
25
|
-
reset_cmd = "git reset --hard #{tag}"
|
26
|
-
when 'hg'
|
27
|
-
reset_cmd = "hg up #{tag}"
|
28
|
-
end
|
29
|
-
|
30
|
-
Cmd.execute(reset_cmd)
|
31
|
-
end
|
32
|
-
|
33
|
-
def clone_projects
|
34
|
-
logger.info 'Cloning projects started'
|
35
|
-
|
36
|
-
@projects.each do |project|
|
37
|
-
logger.info "Start cloning #{project.name} repository"
|
38
|
-
path = project.local_source_path
|
39
|
-
clone_cmd = "#{project.type} clone #{project.connection} #{path}"
|
40
|
-
if File.exist?(path)
|
41
|
-
logger.warn "Skipping clone, project path #{path} already exists"
|
42
|
-
else
|
43
|
-
Cmd.execute(clone_cmd)
|
44
|
-
end
|
45
|
-
|
46
|
-
Dir.chdir(path) do
|
47
|
-
execute_reset_cmd(project.type, project.tag)
|
48
|
-
end
|
49
|
-
logger.info "Cloning #{project.name} completed"
|
50
|
-
end
|
51
|
-
|
52
|
-
logger.info 'Cloning projects completed'
|
21
|
+
@pmd_branch_details = PmdBranchDetail.new(@pmd_branch_name)
|
22
|
+
@project_builder = ProjectBuilder.new(@projects)
|
53
23
|
end
|
54
24
|
|
55
25
|
def get_pmd_binary_file
|
56
26
|
logger.info "#{@pmd_branch_name}: Start packaging PMD"
|
57
27
|
Dir.chdir(@local_git_repo) do
|
58
|
-
|
59
|
-
|
28
|
+
build_branch_sha = Cmd.execute("git rev-parse #{@pmd_branch_name}^{commit}")
|
29
|
+
|
30
|
+
checkout_build_branch # needs a clean working tree, otherwise fails
|
60
31
|
|
61
|
-
|
32
|
+
raise "Wrong branch #{get_last_commit_sha}" unless build_branch_sha == get_last_commit_sha
|
62
33
|
|
63
|
-
#
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
logger.
|
68
|
-
"#{
|
34
|
+
logger.debug "#{@pmd_branch_name}: PMD Version is #{@pmd_version} " \
|
35
|
+
"(sha=#{build_branch_sha})"
|
36
|
+
distro_path = saved_distro_path(build_branch_sha)
|
37
|
+
if File.directory?(distro_path)
|
38
|
+
logger.info "#{@pmd_branch_name}: Skipping packaging - saved version exists " \
|
39
|
+
" in #{distro_path}"
|
69
40
|
else
|
70
|
-
build_pmd
|
41
|
+
build_pmd(into_dir: distro_path)
|
71
42
|
end
|
72
43
|
|
73
|
-
|
44
|
+
# we're still on the build branch
|
45
|
+
@pmd_branch_details.branch_last_sha = build_branch_sha
|
74
46
|
@pmd_branch_details.branch_last_message = get_last_commit_message
|
75
|
-
|
76
|
-
logger.info "#{@pmd_branch_name}: Extracting the zip"
|
77
|
-
unzip_cmd = "unzip -qo pmd-dist/target/pmd-bin-#{@pmd_version}.zip -d #{@pwd}/target"
|
78
|
-
Cmd.execute(unzip_cmd)
|
79
47
|
end
|
80
48
|
logger.info "#{@pmd_branch_name}: Packaging PMD completed"
|
81
49
|
end
|
82
50
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
#
|
89
|
-
|
51
|
+
# builds pmd on currently checked out branch
|
52
|
+
def build_pmd(into_dir:)
|
53
|
+
# in CI there might have been a build performed already. In that case
|
54
|
+
# we reuse the build result, otherwise we build PMD freshly
|
55
|
+
pmd_dist_target = "pmd-dist/target/pmd-bin-#{@pmd_version}.zip"
|
56
|
+
if File.exist?("#{@local_git_repo}/#{pmd_dist_target}")
|
57
|
+
# that's a warning, because we don't know, whether this build really
|
58
|
+
# belongs to the current branch or whether it's from a previous branch.
|
59
|
+
# In CI, that's not a problem, because the workspace is always fresh.
|
60
|
+
logger.warn "#{@pmd_branch_name}: Reusing already existing #{pmd_dist_target}"
|
61
|
+
else
|
62
|
+
logger.info "#{@pmd_branch_name}: Building PMD #{@pmd_version}..."
|
63
|
+
package_cmd = './mvnw clean package' \
|
64
|
+
' -Dmaven.test.skip=true' \
|
65
|
+
' -Dmaven.javadoc.skip=true' \
|
66
|
+
' -Dmaven.source.skip=true' \
|
67
|
+
' -Dcheckstyle.skip=true' \
|
68
|
+
' -T1C'
|
69
|
+
Cmd.execute(package_cmd)
|
70
|
+
end
|
90
71
|
|
91
|
-
logger.info "#{@pmd_branch_name}:
|
92
|
-
|
93
|
-
|
94
|
-
' -Dmaven.javadoc.skip=true' \
|
95
|
-
' -Dmaven.source.skip=true'
|
96
|
-
Cmd.execute(package_cmd)
|
72
|
+
logger.info "#{@pmd_branch_name}: Extracting the zip"
|
73
|
+
Cmd.execute("unzip -qo #{pmd_dist_target} -d pmd-dist/target/exploded")
|
74
|
+
Cmd.execute("mv pmd-dist/target/exploded/pmd-bin-#{@pmd_version} #{into_dir}")
|
97
75
|
end
|
98
76
|
|
99
77
|
def determine_pmd_version
|
@@ -103,7 +81,7 @@ module PmdTester
|
|
103
81
|
end
|
104
82
|
|
105
83
|
def get_last_commit_sha
|
106
|
-
get_last_commit_sha_cmd = 'git rev-parse HEAD'
|
84
|
+
get_last_commit_sha_cmd = 'git rev-parse HEAD^{commit}'
|
107
85
|
Cmd.execute(get_last_commit_sha_cmd)
|
108
86
|
end
|
109
87
|
|
@@ -113,27 +91,39 @@ module PmdTester
|
|
113
91
|
end
|
114
92
|
|
115
93
|
def generate_pmd_report(project)
|
116
|
-
|
117
|
-
|
94
|
+
error_recovery_options = @error_recovery ? 'PMD_JAVA_OPTS="-Dpmd.error_recovery -ea" ' : ''
|
95
|
+
run_path = "#{saved_distro_path(@pmd_branch_details.branch_last_sha)}/bin/run.sh"
|
96
|
+
pmd_cmd = "#{error_recovery_options}" \
|
97
|
+
"#{run_path} pmd -d #{project.local_source_path} -f xml " \
|
118
98
|
"-R #{project.get_config_path(@pmd_branch_name)} " \
|
119
99
|
"-r #{project.get_pmd_report_path(@pmd_branch_name)} " \
|
120
|
-
"-failOnViolation false -t #{@threads}"
|
100
|
+
"-failOnViolation false -t #{@threads} " \
|
101
|
+
"#{project.auxclasspath}"
|
121
102
|
start_time = Time.now
|
122
|
-
|
103
|
+
if File.exist?(project.get_pmd_report_path(@pmd_branch_name))
|
104
|
+
logger.warn "#{@pmd_branch_name}: Skipping PMD run - report " \
|
105
|
+
"#{project.get_pmd_report_path(@pmd_branch_name)} already exists"
|
106
|
+
else
|
107
|
+
Cmd.execute(pmd_cmd)
|
108
|
+
end
|
123
109
|
end_time = Time.now
|
124
110
|
[end_time - start_time, end_time]
|
125
111
|
end
|
126
112
|
|
127
113
|
def generate_config_for(project)
|
114
|
+
logger.debug "Generating ruleset with excludes from #{@branch_config}"
|
128
115
|
doc = Nokogiri::XML(File.read(@branch_config))
|
129
116
|
ruleset = doc.at_css('ruleset')
|
117
|
+
ruleset.add_child("\n")
|
130
118
|
project.exclude_pattern.each do |exclude_pattern|
|
131
|
-
ruleset.add_child("<exclude-pattern>#{exclude_pattern}</exclude-pattern
|
119
|
+
ruleset.add_child(" <exclude-pattern>#{exclude_pattern}</exclude-pattern>\n")
|
132
120
|
end
|
133
121
|
|
134
122
|
File.open(project.get_config_path(@pmd_branch_name), 'w') do |x|
|
135
123
|
x << doc.to_s
|
136
124
|
end
|
125
|
+
|
126
|
+
logger.debug "Created file #{project.get_config_path(@pmd_branch_name)}"
|
137
127
|
end
|
138
128
|
|
139
129
|
def generate_pmd_reports
|
@@ -141,16 +131,14 @@ module PmdTester
|
|
141
131
|
|
142
132
|
sum_time = 0
|
143
133
|
@projects.each do |project|
|
144
|
-
progress_logger = SimpleProgressLogger.new(project.name)
|
134
|
+
progress_logger = SimpleProgressLogger.new("generating #{project.name}'s PMD report")
|
145
135
|
progress_logger.start
|
146
136
|
generate_config_for(project)
|
147
137
|
execution_time, end_time = generate_pmd_report(project)
|
148
138
|
progress_logger.stop
|
149
139
|
sum_time += execution_time
|
150
140
|
|
151
|
-
report_details = PmdReportDetail.new
|
152
|
-
report_details.execution_time = execution_time
|
153
|
-
report_details.timestamp = end_time
|
141
|
+
report_details = PmdReportDetail.new(execution_time: execution_time, timestamp: end_time)
|
154
142
|
report_details.save(project.get_report_info_path(@pmd_branch_name))
|
155
143
|
logger.info "#{project.name}'s PMD report was generated successfully"
|
156
144
|
end
|
@@ -161,10 +149,46 @@ module PmdTester
|
|
161
149
|
@pmd_branch_details
|
162
150
|
end
|
163
151
|
|
152
|
+
# returns the branch details
|
164
153
|
def build
|
165
|
-
clone_projects
|
154
|
+
@project_builder.clone_projects
|
155
|
+
@project_builder.build_projects
|
166
156
|
get_pmd_binary_file
|
167
157
|
generate_pmd_reports
|
168
158
|
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
def checkout_build_branch
|
163
|
+
logger.info "#{@pmd_branch_name}: Checking out the branch"
|
164
|
+
# note that this would fail if the tree is dirty
|
165
|
+
Cmd.execute("git checkout #{@pmd_branch_name}")
|
166
|
+
|
167
|
+
# determine the version
|
168
|
+
@pmd_version = determine_pmd_version
|
169
|
+
|
170
|
+
return unless wd_has_dirty_git_changes
|
171
|
+
|
172
|
+
# working dir is dirty....
|
173
|
+
# we don't allow this because we need the SHA to address the zip file
|
174
|
+
logger.error "#{@pmd_branch_name}: Won\'t build without a clean working tree, " \
|
175
|
+
'commit your changes'
|
176
|
+
end
|
177
|
+
|
178
|
+
def work_dir
|
179
|
+
"#{@pwd}/target"
|
180
|
+
end
|
181
|
+
|
182
|
+
# path to the unzipped distribution
|
183
|
+
# e.g. <cwd>/pmd-bin-<version>-<branch>-<sha>
|
184
|
+
def saved_distro_path(build_sha)
|
185
|
+
"#{work_dir}/pmd-bin-#{@pmd_version}" \
|
186
|
+
"-#{PmdBranchDetail.branch_filename(@pmd_branch_name)}" \
|
187
|
+
"-#{build_sha}"
|
188
|
+
end
|
189
|
+
|
190
|
+
def wd_has_dirty_git_changes
|
191
|
+
!Cmd.execute('git status --porcelain').empty?
|
192
|
+
end
|
169
193
|
end
|
170
194
|
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'tempfile'
|
5
|
+
|
6
|
+
module PmdTester
|
7
|
+
# Clones and builds the projects, that are configured in the project-list.xml
|
8
|
+
class ProjectBuilder
|
9
|
+
include PmdTester
|
10
|
+
|
11
|
+
def initialize(projects)
|
12
|
+
@projects = projects
|
13
|
+
end
|
14
|
+
|
15
|
+
def clone_projects
|
16
|
+
logger.info 'Cloning projects started'
|
17
|
+
|
18
|
+
@projects.each do |project|
|
19
|
+
logger.info "Start cloning #{project.name} repository"
|
20
|
+
path = project.local_source_path
|
21
|
+
clone_cmd = "#{project.type} clone #{project.connection} #{path}"
|
22
|
+
if File.exist?(path)
|
23
|
+
logger.warn "Skipping clone, project path #{path} already exists"
|
24
|
+
else
|
25
|
+
Cmd.execute(clone_cmd)
|
26
|
+
end
|
27
|
+
|
28
|
+
Dir.chdir(path) do
|
29
|
+
execute_reset_cmd(project.type, project.tag)
|
30
|
+
end
|
31
|
+
logger.info "Cloning #{project.name} completed"
|
32
|
+
end
|
33
|
+
|
34
|
+
logger.info 'Cloning projects completed'
|
35
|
+
end
|
36
|
+
|
37
|
+
def build_projects
|
38
|
+
logger.info 'Building projects started'
|
39
|
+
|
40
|
+
@projects.each do |project|
|
41
|
+
path = project.local_source_path
|
42
|
+
Dir.chdir(path) do
|
43
|
+
progress_logger = SimpleProgressLogger.new("building #{project.name} in #{path}")
|
44
|
+
progress_logger.start
|
45
|
+
prepare_project(project)
|
46
|
+
progress_logger.stop
|
47
|
+
end
|
48
|
+
logger.info "Building #{project.name} completed"
|
49
|
+
end
|
50
|
+
|
51
|
+
logger.info 'Building projects completed'
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def prepare_project(project)
|
57
|
+
# Note: current working directory is the project directory,
|
58
|
+
# where the source code has been cloned to
|
59
|
+
if project.build_command
|
60
|
+
logger.debug "Executing build-command: #{project.build_command}"
|
61
|
+
run_as_script(Dir.getwd, project.build_command)
|
62
|
+
end
|
63
|
+
if project.auxclasspath_command
|
64
|
+
logger.debug "Executing auxclasspath-command: #{project.auxclasspath_command}"
|
65
|
+
auxclasspath = run_as_script(Dir.getwd, project.auxclasspath_command)
|
66
|
+
project.auxclasspath = "-auxclasspath #{auxclasspath}"
|
67
|
+
else
|
68
|
+
project.auxclasspath = ''
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def run_as_script(path, command)
|
73
|
+
script = Tempfile.new(['pmd-regression-', '.sh'], path)
|
74
|
+
logger.debug "Creating script #{script.path}"
|
75
|
+
begin
|
76
|
+
script.write(command)
|
77
|
+
script.close
|
78
|
+
shell = 'sh -xe'
|
79
|
+
if command.start_with?('#!')
|
80
|
+
shell = command.lines[0].chomp[2..] # remove leading "#!"
|
81
|
+
end
|
82
|
+
stdout = Cmd.execute("#{shell} #{script.path}")
|
83
|
+
ensure
|
84
|
+
script.unlink
|
85
|
+
end
|
86
|
+
stdout
|
87
|
+
end
|
88
|
+
|
89
|
+
def execute_reset_cmd(type, tag)
|
90
|
+
case type
|
91
|
+
when 'git'
|
92
|
+
reset_cmd = "git checkout #{tag}; git reset --hard #{tag}"
|
93
|
+
when 'hg'
|
94
|
+
reset_cmd = "hg up #{tag}"
|
95
|
+
end
|
96
|
+
|
97
|
+
Cmd.execute(reset_cmd)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|