pmdtester 1.0.1 → 1.1.0
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.
- 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
|