[SCM] ci-tooling packaging branch, master, updated. fcb5e71a1731be1b272c2fdc68623c4becd4013a
Harald Sitter
apachelogger-guest at moszumanska.debian.org
Fri May 8 10:42:39 UTC 2015
Gitweb-URL: http://git.debian.org/?p=pkg-kde/ci-tooling.git;a=commitdiff;h=db88ccf
The following commit has been merged in the master branch:
commit db88ccfa1a15aaac9d2b727a6dc4b243780965d2
Author: Harald Sitter <sitter at kde.org>
Date: Fri May 8 12:42:12 2015 +0200
try out a new approach to ppa promotion and launchpad oops on copies
instead of sequencing the entire copy which makes a whole run take about
an hour or two per type and series let's copy all on 8 threads and then
verify that they have appeared in the target PPA. if not sleep 5 minutes
and try again. this can be repated up to 10 times (i.e. 50 minutes worth
of waiting).
this commit also sees the introduction of two new helpers that might move
elsewhere...
- a Queue version that can init from an array and convert into
one (latter unfortunately twice as inefficient as former).
- a module to prepend on PPA rubbers to easily verify package presence.
this is mostly just convenience and threading isolation there isn't
any actual business logic. it's possibly that the lp api will need some
stronger type coercion/reflection than the generic rubber and grow actual
REST api design (i.e. ReflectionType + ConnectionType + RouteType)
---
kci/ppa_promote.rb | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 86 insertions(+), 6 deletions(-)
diff --git a/kci/ppa_promote.rb b/kci/ppa_promote.rb
index 2bf27f8..7e2c57b 100755
--- a/kci/ppa_promote.rb
+++ b/kci/ppa_promote.rb
@@ -1,5 +1,6 @@
#!/usr/bin/env ruby
+require 'date'
require 'json'
require 'logger'
require 'logger/colors'
@@ -14,9 +15,11 @@ require_relative 'lib/retry'
# Since waiting 20 and then doing it again would be slower than just copying one
# by one we instead do that by limiting our thread pool.
# https://bugs.launchpad.net/launchpad/+bug/1314569
-THREAD_COUNT = 1
+THREAD_COUNT = 8
# Wiping is unaffected as far as we can tell.
WIPE_THREAD_COUNT = 8
+# Polling isn't either.
+POLL_THREAD_COUNT = WIPE_THREAD_COUNT
# TODO: wait for wipe and publish to be done. fail if publish takes >40 minutes
@@ -28,6 +31,58 @@ LOG.warn 'PPA Promote'
Project = Struct.new(:series, :type)
project = Project.new(ENV.fetch('DIST'), ENV.fetch('TYPE'))
+class Queue
+ alias_method :super_init, :initialize
+
+ def initialize(array = nil)
+ super_init
+ return if array.nil?
+ fail 'Queue can only be constructed from an Array' unless array.is_a?(Array)
+ array.each { |i| self << i }
+ end
+
+ def to_a
+ # Queue isn't exactly the most nejoable thing in the world as it doesn't
+ # allow for random access so you cannot iterate over it, and it doesn't
+ # implement dup nor clone so you can't deep copy it either.
+ # Now since we need to iterate queue to convert it in an array and iteration
+ # means destructive popping we first need to pop it into an Array and then
+ # iterate over the array to push the values back into the queue. Quite mad.
+ ret = []
+ ret << pop until empty?
+ ret.each { |i| self << i }
+ ret
+ end
+end
+
+module VerifablePPA
+ EXISTING_STATES = %w(Pending Published)
+
+ # @param packages [Hash<String, String>] Hash of package-versions
+ # @return [Array<String>] array of source names that are existing
+ def existing_sources(packages)
+ source_queue = Queue.new(packages.to_a)
+ exist_queue = Queue.new
+ BlockingThreadPool.run(POLL_THREAD_COUNT) do
+ until source_queue.empty?
+ entry = source_queue.pop(true)
+ exist_queue << entry[0] if source_exist?(*entry)
+ end
+ end
+ exist_queue.to_a
+ end
+
+ def source_exist?(name, version)
+ sources = getPublishedSources(source_name: name, version: version)
+ sources.reject! { |s| !EXISTING_STATES.include?(s.status) }
+ return true if sources.size == 1
+ if sources.size > 1
+ fail "Found more than one matching source for #{name}=#{version}"
+ end
+ false
+ end
+end
+
class Archive
attr_accessor :ppa
@@ -42,8 +97,7 @@ class Archive
%i(Pending Published Superseded Obsolete).each do |status|
sources = @ppa.getPublishedSources(status: status,
distro_series: @series)
- source_queue = Queue.new
- sources.each { |s| source_queue << s }
+ source_queue = Queue.new(sources)
BlockingThreadPool.run(WIPE_THREAD_COUNT) do
until source_queue.empty?
source = source_queue.pop(true)
@@ -59,8 +113,35 @@ class Archive
end
def copy(packages, from_ppa)
- source_queue = Queue.new
- packages.each_pair { |a| source_queue << a }
+ # We are modifying, dup it first.
+ packages = packages.dup
+ make_ppa_verifable!
+ Retry.retry_it(times: 10, sleep: (60 * 5)) do
+ copy_internal(packages, from_ppa)
+ existing_sources = @ppa.existing_sources(packages)
+ packages.reject! do |p|
+ next true if existing_sources.include?(p)
+ LOG.warn "Package #{p} hasn't been copied. Going to try again shortly."
+ false
+ end
+ unless packages.empty?
+ fail "Not all packages copied successfully #{packages}"
+ end
+ end
+ end
+
+ private
+
+ def make_ppa_verifable!
+ eigenclass = (class << @ppa; self; end)
+ return if eigenclass.included_modules.include?(VerifablePPA)
+ class << @ppa
+ include VerifablePPA
+ end
+ end
+
+ def copy_internal(packages, from_ppa)
+ source_queue = Queue.new(packages.to_a)
BlockingThreadPool.run(THREAD_COUNT) do
until source_queue.empty?
entry = source_queue.pop(true)
@@ -74,7 +155,6 @@ class Archive
version: version,
to_pocket: 'Release',
include_binaries: true)
- sleep 5 # Force sleep to avoid a race in launchpad, see THREAD_COUNT.
end
end
end
--
ci-tooling packaging
More information about the pkg-kde-commits
mailing list