Skip to content

Commit

Permalink
#373 additional documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
yegor256 committed Jul 30, 2022
1 parent 373cebf commit 68bda01
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 47 deletions.
4 changes: 2 additions & 2 deletions 0pdd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@
end
)
github = GithubRepo.new(settings.github, json, settings.config)
return "I can't access #{github.repo.name}" unless github.exists?
return [400, "No access to #{github.repo.name}"] unless github.exists?
unless ENV['RACK_ENV'] == 'test'
process_request(github)
puts "GitHub hook from #{github.repo.name}"
Expand Down Expand Up @@ -385,7 +385,7 @@
end
)
gitlab = GitlabRepo.new(settings.gitlab, json, settings.config)
return "I can't access #{github.repo.name}" unless gitlab.exists?
return [400, "No access to #{gitlab.repo.name}"] unless gitlab.exists?
unless ENV['RACK_ENV'] == 'test'
process_request(gitlab)
puts "Gitlab hook from #{gitlab.repo.name}"
Expand Down
101 changes: 57 additions & 44 deletions objects/puzzles.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,28 @@ def initialize(repo, storage)
@threshold = t.positive? && t < 256 ? t : 256
end

# Find out which puzzles deservers to become new tickets and submit
# them to the repository (GitHub, for example). Also, find out which
# puzzles are no longer active and remove them from GitHub.
def deploy(tickets)
expose(
save(
group(
join(@storage.load, @repo.xml)
)
),
tickets
)
xml = join(@storage.load, @repo.xml)
xml = group(xml)
save(xml)
expose(xml, tickets)
end

private

# Save new XML into the storage, replacing the existing one.
def save(xml)
@storage.save(xml)
xml
end

# Join existing XML with the snapshot just arrived from PDD
# toolkit output after the analysis of the code base. New <puzzle>
# elements are added as <extra> elements. They later inside the
# method join() will be placed to the right positions and will
# either replace existing ones of will become new puzzles.
def join(before, snapshot)
after = Nokogiri::XML(before.to_s)
target = after.xpath('/puzzles')[0]
Expand All @@ -62,15 +66,57 @@ def join(before, snapshot)
after
end

# Merge <extra> elements with <puzzle> elements in the XML. Some
# extras will be simply deleted, while others will become new
# puzzles.
def group(xml)
Nokogiri::XSLT(File.read('assets/xsl/group.xsl')).transform(
Nokogiri::XSLT(File.read('assets/xsl/join.xsl')).transform(xml)
)
end

# Take some puzzles from the XML and either close their tickets in GitHub
# or create new tickets.
def expose(xml, tickets)
Kernel.loop do
puzzles = xml.xpath(
'//puzzle[@alive="false" and issue and issue != "unknown" and not(issue/@closed)]'
)
break if puzzles.empty?
puzzle = puzzles[0]
puzzle.search('issue')[0]['closed'] = Time.now.iso8601 if tickets.close(puzzle)
save(xml)
end
skip_model = xml.xpath('/puzzles[@model="true"]').empty?
return submit_ranked(xml, tickets) unless skip_model
seen = []
Kernel.loop do
puzzles = xml.xpath([
'//puzzle[@alive="true" and (not(issue) or issue="unknown")',
seen.map { |i| "and id != '#{i}'" }.join(' '),
']'
].join(' '))
break if puzzles.empty?
puzzle = puzzles[0]
id = puzzle.xpath('id')[0].text
seen << id
issue = tickets.submit(puzzle)
next if issue.nil?
puzzle.search('issue').remove
puzzle.add_child(
"<issue href='#{issue[:href]}'>#{issue[:number]}</issue>"
)
save(xml)
end
end

# Reads the list of all puzzles from the XML in the storage and then
# sorts them in the right order, in which they should be present in the
# backlog.
def rank(puzzles)
puzzles = puzzles.map { |puzzle| JSON.parse(Crack::XML.parse(puzzle.to_s).to_json)['puzzle'] }
LinearModel.new(@repo.name, @storage).predict(puzzles)
LinearModel.new(@repo.name, @storage).predict(
puzzles.map { |puzzle| JSON.parse(Crack::XML.parse(puzzle.to_s).to_json)['puzzle'] }
)
end

def submit_ranked(xml, tickets)
Expand Down Expand Up @@ -109,37 +155,4 @@ def submit_ranked(xml, tickets)
submitted += 1
end
end

def expose(xml, tickets)
Kernel.loop do
puzzles = xml.xpath(
'//puzzle[@alive="false" and issue and issue != "unknown" and not(issue/@closed)]'
)
break if puzzles.empty?
puzzle = puzzles[0]
puzzle.search('issue')[0]['closed'] = Time.now.iso8601 if tickets.close(puzzle)
save(xml)
end
skip_model = xml.xpath('/puzzles[@model="true"]').empty?
return submit_ranked(xml, tickets) unless skip_model
seen = []
Kernel.loop do
puzzles = xml.xpath([
'//puzzle[@alive="true" and (not(issue) or issue="unknown")',
seen.map { |i| "and id != '#{i}'" }.join(' '),
']'
].join(' '))
break if puzzles.empty?
puzzle = puzzles[0]
id = puzzle.xpath('id')[0].text
seen << id
issue = tickets.submit(puzzle)
next if issue.nil?
puzzle.search('issue').remove
puzzle.add_child(
"<issue href='#{issue[:href]}'>#{issue[:number]}</issue>"
)
save(xml)
end
end
end
2 changes: 1 addition & 1 deletion objects/tickets/logged_tickets.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def submit(puzzle)
This situation most probably means that \
this puzzle was already seen in the code and \
you're trying to create it again. We would recommend you to re-phrase \
the text of the puzzle and push again. If this doesn't work, pleas let us know \
the text of the puzzle and push again. If this doesn't work, please let us know \
in GitHub: https://github.com/yegor256/0pdd/issues. More details here: \
http://www.0pdd.com/log-item?repo=#{CGI.escape(@vcs.repo.name)}&tag=#{CGI.escape(tag)}&vcs=#{@vcs.name.downcase} ."
end
Expand Down

1 comment on commit 68bda01

@0pdd
Copy link
Collaborator

@0pdd 0pdd commented on 68bda01 Jul 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't able to retrieve PDD puzzles from the code base and submit them to GITHUB. If you think that it's a bug on our side, please submit it to yegor256/0pdd:

undefined method `repository' for #GithubRepo:0x000055a139b00b28 Did you mean? repository_link

Please, copy and paste this stack trace to GitHub:

NoMethodError
undefined method `repository' for #<GithubRepo:0x000055a139b00b28>
Did you mean?  repository_link
/app/objects/jobs/job_recorded.rb:32:in `proceed'
/app/objects/jobs/job_emailed.rb:33:in `proceed'
/app/objects/jobs/job_commiterrors.rb:33:in `proceed'
/app/objects/jobs/job_detached.rb:48:in `exclusive'
/app/objects/jobs/job_detached.rb:36:in `block in proceed'
/app/objects/jobs/job_detached.rb:36:in `fork'
/app/objects/jobs/job_detached.rb:36:in `proceed'
/app/0pdd.rb:519:in `process_request'
/app/0pdd.rb:356:in `block in <top (required)>'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1686:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1686:in `block in compile!'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1023:in `block (3 levels) in route!'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1042:in `route_eval'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1023:in `block (2 levels) in route!'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1071:in `block in process_route'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1069:in `catch'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1069:in `process_route'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1021:in `block in route!'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1018:in `each'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1018:in `route!'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1140:in `block in dispatch!'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1112:in `block in invoke'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1112:in `catch'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1112:in `invoke'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1135:in `dispatch!'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:949:in `block in call!'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1112:in `block in invoke'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1112:in `catch'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1112:in `invoke'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:949:in `call!'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:938:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/rack-protection-2.2.2/lib/rack/protection/xss_header.rb:18:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/rack-protection-2.2.2/lib/rack/protection/path_traversal.rb:16:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/rack-protection-2.2.2/lib/rack/protection/json_csrf.rb:26:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/rack-protection-2.2.2/lib/rack/protection/base.rb:50:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/rack-protection-2.2.2/lib/rack/protection/base.rb:50:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/rack-protection-2.2.2/lib/rack/protection/frame_options.rb:31:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/rack-2.2.4/lib/rack/logger.rb:17:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/rack-2.2.4/lib/rack/common_logger.rb:38:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:255:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:248:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/rack-2.2.4/lib/rack/head.rb:12:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/rack-2.2.4/lib/rack/method_override.rb:24:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:218:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1993:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1553:in `block in call'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1769:in `synchronize'
/app/vendor/bundle/ruby/2.7.0/gems/sinatra-2.2.2/lib/sinatra/base.rb:1553:in `call'
/app/vendor/bundle/ruby/2.7.0/gems/rack-2.2.4/lib/rack/handler/webrick.rb:95:in `service'
/app/vendor/ruby-2.7.5/lib/ruby/2.7.0/webrick/httpserver.rb:140:in `service'
/app/vendor/ruby-2.7.5/lib/ruby/2.7.0/webrick/httpserver.rb:96:in `run'
/app/vendor/ruby-2.7.5/lib/ruby/2.7.0/webrick/server.rb:307:in `block in start_thread'

Please sign in to comment.