Class: PmdTester::PmdReportBuilder

Inherits:
Object
  • Object
show all
Includes:
PmdTester
Defined in:
lib/pmdtester/builders/pmd_report_builder.rb

Overview

Building pmd xml reports according to a list of standard projects and branch of pmd source code

Constant Summary

Constants included from PmdTester

BASE, PATCH, PR_NUM_ENV_VAR, VERSION

Instance Method Summary collapse

Methods included from PmdTester

#logger, logger

Constructor Details

#initialize(projects, options, branch_config, branch_name) ⇒ PmdReportBuilder

Returns a new instance of PmdReportBuilder.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/pmdtester/builders/pmd_report_builder.rb', line 12

def initialize(projects, options, branch_config, branch_name)
  @projects = projects
  @local_git_repo = options.local_git_repo
  @threads = options.threads
  @error_recovery = options.error_recovery
  @branch_config = branch_config
  @pmd_branch_name = branch_name
  @pwd = Dir.getwd

  @pmd_branch_details = PmdBranchDetail.new(@pmd_branch_name)
  @project_builder = ProjectBuilder.new(@projects)
  @run_pmd = options.run_pmd
  @run_cpd = options.run_cpd
end

Instance Method Details

#buildObject

returns the branch details



201
202
203
204
205
206
207
208
209
210
# File 'lib/pmdtester/builders/pmd_report_builder.rb', line 201

def build
  @project_builder.clone_projects
  @project_builder.build_projects
  create_pmd_package
  @pmd_branch_details.execution_time = 0
  generate_pmd_reports if @run_pmd
  generate_cpd_reports if @run_cpd
  @pmd_branch_details.save
  @pmd_branch_details
end

#build_pmd(into_dir:) ⇒ Object

builds pmd on currently checked out branch



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/pmdtester/builders/pmd_report_builder.rb', line 64

def build_pmd(into_dir:)
  # in CI there might have been a build performed already. In that case
  # we reuse the build result, otherwise we build PMD freshly
  pmd_dist_target, binary_exists = find_pmd_dist_target
  if binary_exists
    # that's a warning, because we don't know, whether this build really
    # belongs to the current branch or whether it's from a previous branch.
    # In CI, that's not a problem, because the workspace is always fresh.
    logger.warn "#{@pmd_branch_name}: Reusing already existing #{pmd_dist_target}"
  else
    build_pmd_with_maven
    pmd_dist_target, binary_exists = find_pmd_dist_target
    unless binary_exists
      logger.error "#{@pmd_branch_name}: Dist zip not found at #{pmd_dist_target}!"
      raise "No Dist zip found at #{pmd_dist_target}"
    end
  end

  logger.info "#{@pmd_branch_name}: Extracting the zip"
  Cmd.execute_successfully("unzip -qo #{pmd_dist_target} -d pmd-dist/target/exploded")
  Cmd.execute_successfully("mv pmd-dist/target/exploded/pmd-bin-#{@pmd_version} #{into_dir}")
end

#create_pmd_packageObject



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/pmdtester/builders/pmd_report_builder.rb', line 33

def create_pmd_package
  logger.info "#{@pmd_branch_name}: Start packaging PMD"
  Dir.chdir(@local_git_repo) do
    checkout_build_branch # needs a clean working tree, otherwise fails

    # first checkout the build branch - that might create a local branch from remote, if
    # a local branch doesn't exist yet. The following "git rev-parse" command only works
    # for local branches.
    build_branch_sha = Cmd.execute_successfully("git rev-parse #{@pmd_branch_name}^{commit}")

    raise "Wrong branch #{determine_last_commit_sha}" unless build_branch_sha == determine_last_commit_sha

    distro_path = saved_distro_path(build_branch_sha)
    logger.debug "#{@pmd_branch_name}: PMD Version is #{@pmd_version} " \
                 "(sha=#{build_branch_sha})"
    logger.debug "#{@pmd_branch_name}: distro_path=#{distro_path}"
    if File.directory?(distro_path)
      logger.info "#{@pmd_branch_name}: Skipping packaging - saved version exists " \
                  "in #{distro_path}"
    else
      build_pmd(into_dir: distro_path)
    end

    # we're still on the build branch
    @pmd_branch_details.branch_last_sha = build_branch_sha
    @pmd_branch_details.branch_last_message = determine_last_commit_message
  end
  logger.info "#{@pmd_branch_name}: Packaging PMD completed"
end

#determine_last_commit_messageObject



98
99
100
101
# File 'lib/pmdtester/builders/pmd_report_builder.rb', line 98

def determine_last_commit_message
  last_commit_message_cmd = 'git log -1 --pretty=%B'
  Cmd.execute_successfully(last_commit_message_cmd)
end

#determine_last_commit_shaObject



93
94
95
96
# File 'lib/pmdtester/builders/pmd_report_builder.rb', line 93

def determine_last_commit_sha
  last_commit_sha_cmd = 'git rev-parse HEAD^{commit}'
  Cmd.execute_successfully(last_commit_sha_cmd)
end

#determine_pmd_versionObject



87
88
89
90
91
# File 'lib/pmdtester/builders/pmd_report_builder.rb', line 87

def determine_pmd_version
  version_cmd = "./mvnw -q -Dexec.executable=\"echo\" -Dexec.args='${project.version}' " \
                '--non-recursive org.codehaus.mojo:exec-maven-plugin:1.5.0:exec'
  Cmd.execute_successfully(version_cmd)
end

#generate_config_for(project) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/pmdtester/builders/pmd_report_builder.rb', line 120

def generate_config_for(project)
  logger.debug "Generating ruleset with excludes from #{@branch_config}"
  doc = Nokogiri::XML(File.read(@branch_config))
  ruleset = doc.at_css('ruleset')
  ruleset.add_child("\n")
  project.exclude_patterns.each do |exclude_pattern|
    ruleset.add_child("    <exclude-pattern>#{exclude_pattern}</exclude-pattern>\n")
  end

  File.open(project.get_config_path(@pmd_branch_name), 'w') do |x|
    x << doc.to_s
  end

  logger.debug "Created file #{project.get_config_path(@pmd_branch_name)}"
end

#generate_cpd_report(project) ⇒ Object



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/pmdtester/builders/pmd_report_builder.rb', line 184

def generate_cpd_report(project)
  start_time = Time.now
  exit_code = nil
  if File.exist?(project.get_cpd_report_path(@pmd_branch_name))
    logger.warn "#{@pmd_branch_name}: Skipping CPD run - report " \
                "#{project.get_cpd_report_path(@pmd_branch_name)} already exists"
  else
    cpd_cmd = create_cpd_command(project)
    status, stdout, stderr = Cmd.execute(cpd_cmd, debug_log_stdout: false)
    exit_code = status.exitstatus
  end
  stdout = filter_cpd_report_from_stdout(project, exit_code, stdout)
  end_time = Time.now
  [cpd_cmd, end_time - start_time, end_time, exit_code, stdout, stderr]
end

#generate_cpd_reportsObject



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/pmdtester/builders/pmd_report_builder.rb', line 161

def generate_cpd_reports
  logger.info "Generating CPD report started -- branch #{@pmd_branch_name}"

  sum_time = 0
  @projects.each do |project|
    progress_logger = SimpleProgressLogger.new("generating #{project.name}'s CPD report")
    progress_logger.start
    cpd_cmd, execution_time, end_time, exit_code, stdout, stderr = generate_cpd_report(project)
    progress_logger.stop
    sum_time += execution_time

    jfr_summary = JfrSummary.new.load("#{project.get_project_target_dir(@pmd_branch_name)}/cpd_recording.jfr")
    PmdReportDetail.create(execution_time: execution_time, timestamp: end_time,
                           cmdline: cpd_cmd, exit_code: exit_code, stdout: stdout, stderr: stderr,
                           oom: stderr.include?('java.lang.OutOfMemoryError'),
                           report_info_path: project.get_cpd_report_info_path(@pmd_branch_name),
                           jfr_summary: jfr_summary)
    logger.info "#{project.name}'s CPD report was generated successfully (exit code: #{exit_code})"
  end

  @pmd_branch_details.execution_time += sum_time
end

#generate_pmd_report(project) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/pmdtester/builders/pmd_report_builder.rb', line 103

def generate_pmd_report(project)
  start_time = Time.now
  exit_code = nil
  stdout = ''
  stderr = ''
  if File.exist?(project.get_pmd_report_path(@pmd_branch_name))
    logger.warn "#{@pmd_branch_name}: Skipping PMD run - report " \
                "#{project.get_pmd_report_path(@pmd_branch_name)} already exists"
  else
    pmd_cmd = create_pmd_command(project)
    status, stdout, stderr = Cmd.execute(pmd_cmd)
    exit_code = status.exitstatus
  end
  end_time = Time.now
  [pmd_cmd, end_time - start_time, end_time, exit_code, stdout, stderr]
end

#generate_pmd_reportsObject



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/pmdtester/builders/pmd_report_builder.rb', line 136

def generate_pmd_reports
  logger.info "Generating PMD report started -- branch #{@pmd_branch_name}"

  sum_time = 0
  @projects.each do |project|
    progress_logger = SimpleProgressLogger.new("generating #{project.name}'s PMD report")
    progress_logger.start
    generate_config_for(project)
    cmd_line, execution_time, end_time, exit_code, stdout, stderr = generate_pmd_report(project)
    progress_logger.stop
    sum_time += execution_time

    jfr_summary = JfrSummary.new.load("#{project.get_project_target_dir(@pmd_branch_name)}/pmd_recording.jfr")
    PmdReportDetail.create(execution_time: execution_time, timestamp: end_time,
                           cmdline: cmd_line, exit_code: exit_code, stdout: stdout, stderr: stderr,
                           oom: stderr.include?('java.lang.OutOfMemoryError'),
                           report_info_path: project.get_report_info_path(@pmd_branch_name),
                           jfr_summary: jfr_summary)
    logger.info "#{project.name}'s PMD report was generated successfully (exit code: #{exit_code})"
  end

  @pmd_branch_details.execution_time += sum_time
  FileUtils.cp(@branch_config, @pmd_branch_details.target_branch_config_path)
end

#with_changes(rules_changed, impl_changed) ⇒ Object



27
28
29
30
31
# File 'lib/pmdtester/builders/pmd_report_builder.rb', line 27

def with_changes(rules_changed, impl_changed)
  @run_pmd &&= rules_changed
  @run_cpd &&= impl_changed
  self
end