Skip to content

Commit

Permalink
[api] expand maintenance_incident for entire projects into package ac…
Browse files Browse the repository at this point in the history
…tions.
  • Loading branch information
adrianschroeter committed Mar 8, 2012
1 parent fd24bb8 commit d16e1ad
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 109 deletions.
174 changes: 71 additions & 103 deletions src/api/app/controllers/request_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -316,74 +316,10 @@ def create_create
:message => "Maintenance incident requests have to go to projects of type maintenance or maintenance_incident"
return
end

# validate release target project
targetproject = nil
if action.target.has_attribute? 'releaseproject'
targetproject = DbProject.get_by_name action.target.releaseproject
else
packages = []
if action.source.has_attribute? 'package'
packages << DbPackage.get_by_project_and_name( action.source.project, action.source.package )
else
packages = DbProject.get_by_name(action.source.project).db_packages
end
# follow link for all packages
packages.each do |pkg|
next if pkg.db_package_kinds.find_by_kind 'patchinfo'
tprj = pkg.db_project.name
ltpkg = pkg.name
while tprj == pkg.db_project.name
begin
data = REXML::Document.new( backend_get("/source/#{URI.escape(tprj)}/#{URI.escape(ltpkg)}") )
e = data.elements["directory/linkinfo"]
if e
tprj = e.attributes["project"]
ltpkg = e.attributes["package"]
else
tprj = nil
end
rescue ActiveXML::Transport::NotFoundError
tprj = nil
end
end
unless tprj
render_error :status => 400, :errorcode => 'no_maintenance_release_target',
:message => "Package #{pkg.name} is neither linked nor have a proper release target definition"
return
end
targetproject = DbProject.get_by_name tprj
unless targetproject.project_type == "maintenance_release"
render_error :status => 400, :errorcode => 'no_maintenance_release_target',
:message => "Maintenance incident request contains no proper defined release target project for package #{pkg.name}"
return
end
end
end

unless targetproject
render_error :status => 400, :errorcode => 'no_maintenance_release_target',
:message => "Maintenance incident request contains no release target project"
return
end

# Automatically switch to update project
if a = targetproject.find_attribute("OBS", "UpdateProject") and a.values[0]
targetproject = DbProject.get_by_name a.values[0].value
action.target.set_attribute("releaseproject", targetproject.name)
end

unless targetproject.project_type == "maintenance_release"
package = action.source.project
package += "/" + action.source.package if action.source.has_attribute? 'package'
render_error :status => 400, :errorcode => 'no_maintenance_release_target',
:message => "Maintenance incident request contains release target project '#{targetproject.name}' with wrong kind #{targetproject.project_type} for package #{package}"
return
end
end

if [ "submit", "maintenance_release" ].include?(action.value("type"))
unless action.has_element? 'target'
if [ "submit", "maintenance_release", "maintenance_incident" ].include?(action.value("type"))
unless action.has_element? 'target' and action.target.has_attribute? 'package'
packages = Array.new
if action.source.has_attribute? 'package'
packages << DbPackage.get_by_project_and_name( action.source.project, action.source.package )
Expand Down Expand Up @@ -440,6 +376,33 @@ def create_create
end
tpkg = tpkg.gsub(/#{suffix}$/, '') # strip distro specific extension

# maintenance incidents need a releasetarget
releaseproject = nil
if action.value("type") == "maintenance_incident"

unless pkg.db_package_kinds.find_by_kind 'patchinfo'
if action.target.has_attribute? "releaseproject"
releaseproject = DbProject.get_by_name action.target.releaseproject
else
# Automatically switch to update project
unless tprj
render_error :status => 400, :errorcode => 'no_maintenance_release_target',
:message => "Maintenance incident request contains no defined release target project for package #{pkg.name}"
return
end
releaseproject = DbProject.get_by_name tprj
end
if a = releaseproject.find_attribute("OBS", "UpdateProject") and a.values[0]
releaseproject = DbProject.get_by_name a.values[0].value
end
unless releaseproject.project_type == "maintenance_release"
render_error :status => 400, :errorcode => 'no_maintenance_release_target',
:message => "Maintenance incident request contains release target project #{releaseproject.name} with invalid type #{releaseproject.project_type} for package #{pkg.name}"
return
end
end
end

# do not allow release requests without binaries
if action.value("type") == "maintenance_release" and data and params["ignore_build_state"].nil?
entries = data.get_elements("directory/entry")
Expand Down Expand Up @@ -486,7 +449,7 @@ def create_create
end
end
next
else
elsif action.value("type") != "maintenance_incident"
render_error :status => 400, :errorcode => 'unknown_target_package',
:message => "target package does not exist"
return
Expand Down Expand Up @@ -514,8 +477,12 @@ def create_create
newAction = ActiveXML::XMLNode.new(action.dump_xml)
newAction.add_element 'target' unless newAction.has_element? 'target'
newAction.source.set_attribute("package", pkg.name)
newAction.target.set_attribute("project", tprj )
newAction.target.set_attribute("package", tpkg + incident_suffix)
if action.value("type") == 'maintenance_incident'
newAction.target.set_attribute("releaseproject", releaseproject.name ) if releaseproject
else
newAction.target.set_attribute("project", tprj )
newAction.target.set_attribute("package", tpkg + incident_suffix)
end
newAction.source.set_attribute("rev", rev) if rev
req.add_node newAction.dump_xml
end
Expand All @@ -532,8 +499,10 @@ def create_create
newAction = ActiveXML::XMLNode.new(action.dump_xml)
newAction.add_element 'target' unless newAction.has_element? 'target'
newAction.source.set_attribute("package", pkg)
newAction.target.set_attribute("project", p)
newAction.target.set_attribute("package", pkg + incident_suffix)
unless action.value("type") == 'maintenance_incident'
newAction.target.set_attribute("project", p)
newAction.target.set_attribute("package", pkg + incident_suffix) unless action.value("type") == 'maintenance_incident'
end
req.add_node newAction.dump_xml
end
end
Expand Down Expand Up @@ -1383,8 +1352,9 @@ def command_changestate

# special command defining an incident to be merged
check_for_patchinfo = false
# all maintenance_incident actions go into the same incident project
incident_project = nil
req.each_action do |action|
incident_project = nil
if action.value("type") == "maintenance_incident"
tprj = DbProject.get_by_name action.target.project

Expand Down Expand Up @@ -1430,8 +1400,6 @@ def command_changestate

# have a unique time stamp for release
acceptTimeStamp = Time.now.utc.strftime "%Y-%m-%d %H:%M:%S"
# all maintenance_incident actions go into the same incident project
incident_project = nil
projectCommit = {}

# use the request description as comments for history
Expand Down Expand Up @@ -1596,35 +1564,6 @@ def command_changestate
action.target.set_attribute("project", incident_project.name)
req.save

# create a patchinfo if missing and incident has just been created
if check_for_patchinfo
unless DbPackage.find_by_project_and_kind incident_project.name, "patchinfo"
patchinfo = DbPackage.new(:name => "patchinfo", :title => "Patchinfo", :description => "Collected packages for update")
incident_project.db_packages << patchinfo
patchinfo.add_flag("build", "enable", nil, nil)
patchinfo.add_flag("publish", "enable", nil, nil)
patchinfo.add_flag("useforbuild", "disable", nil, nil)
patchinfo.store

# create patchinfo XML file
node = Builder::XmlMarkup.new(:indent=>2)
xml = node.patchinfo() do |n|
node.packager req.creator
node.category "recommended"
node.rating "low"
node.summary req.description
node.description req.description
end
data = ActiveXML::Base.new(node.target!)
# xml = update_patchinfo( data, pkg )
p={ :user => @http_user.login, :comment => "generated by request id #{req.id} accept call" }
patchinfo_path = "/source/#{CGI.escape(patchinfo.db_project.name)}/patchinfo/_patchinfo"
patchinfo_path << build_query_from_hash(p, [:user, :comment])
backend_put( patchinfo_path, data.dump_xml )
patchinfo.sources_changed
end
end

elsif action.value("type") == "maintenance_release"
pkg = DbPackage.get_by_project_and_name(action.source.project, action.source.package)
#FIXME2.5: support limiters to specified repositories
Expand Down Expand Up @@ -1677,6 +1616,35 @@ def command_changestate
Suse::Backend.post commit_path, nil
end

# create a patchinfo if missing and incident has just been created
if check_for_patchinfo
unless DbPackage.find_by_project_and_kind incident_project.name, "patchinfo"
patchinfo = DbPackage.new(:name => "patchinfo", :title => "Patchinfo", :description => "Collected packages for update")
incident_project.db_packages << patchinfo
patchinfo.add_flag("build", "enable", nil, nil)
patchinfo.add_flag("publish", "enable", nil, nil)
patchinfo.add_flag("useforbuild", "disable", nil, nil)
patchinfo.store

# create patchinfo XML file
node = Builder::XmlMarkup.new(:indent=>2)
xml = node.patchinfo() do |n|
node.packager req.creator
node.category "recommended"
node.rating "low"
node.summary req.description
node.description req.description
end
data = ActiveXML::Base.new(node.target!)
# xml = update_patchinfo( data, pkg )
p={ :user => @http_user.login, :comment => "generated by request id #{req.id} accept call" }
patchinfo_path = "/source/#{CGI.escape(patchinfo.db_project.name)}/patchinfo/_patchinfo"
patchinfo_path << build_query_from_hash(p, [:user, :comment])
backend_put( patchinfo_path, data.dump_xml )
patchinfo.sources_changed
end
end

pass_to_backend path
end
end
11 changes: 8 additions & 3 deletions src/api/app/helpers/maintenance_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,13 @@ def merge_into_maintenance_incident(incidentProject, base, releaseproject=nil, r
# local link, skip it, it will come via branch command
next
end
# patchinfos are handled as new packages
if pkg.db_package_kinds.find_by_kind 'patchinfo'
new_pkg = incidentProject.db_packages.create(:name => pkg.name, :title => pkg.title, :description => pkg.description)
new_pkg.store

# use specified release project if defined
if releaseproject
elsif releaseproject
if e
package_name = e.attributes["package"]
else
Expand Down Expand Up @@ -112,8 +116,9 @@ def merge_into_maintenance_incident(incidentProject, base, releaseproject=nil, r
ret = do_branch branch_params
new_pkg = DbPackage.get_by_project_and_name(ret[:data][:targetproject], ret[:data][:targetpackage])
else
# no linked package found, so check for patchinfo or new package and re-create that
if pkg.db_package_kinds.find_by_kind 'patchinfo' or (e and e.attributes["package"])

# a new package for all targets
if e and e.attributes["package"]
new_pkg = DbPackage.new(:name => pkg.name, :title => pkg.title, :description => pkg.description)
incidentProject.db_packages << new_pkg
new_pkg.store
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<request>
<action type='submit'>
<source project='home:coolo:test' package='kdelibs_DEVEL_package' />
<target project='kde4' />
<target project='kde4' package='kdelibs' />
<options>
<sourceupdate>cleanup</sourceupdate>
</options>
Expand Down
10 changes: 8 additions & 2 deletions src/api/test/functional/maintenance_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,12 @@ def test_mbranch_and_maintenance_entire_project_request
node = ActiveXML::XMLNode.new(@response.body)
assert node.has_attribute?(:id)
id = node.value(:id)
assert_tag( :tag => "request", :children => { :count => 8, :only => { :tag => "action" } })
assert_tag( :tag => "source", :attributes => { :project => "home:tom:branches:OBS_Maintained:pack2" } )
assert_tag( :tag => "target", :attributes => { :project => "My:Maintenance" } )
assert_tag( :tag => "target", :attributes => { :releaseproject => "BaseDistro3" } )
assert_tag( :tag => "target", :attributes => { :releaseproject => "BaseDistro2.0:LinkedUpdateProject" } )
assert_tag( :tag => "target", :attributes => { :releaseproject => "BaseDistro:Update" } )

# validate that request is diffable (not broken)
post "/request/#{id}?cmd=diff&view=xml", nil
Expand Down Expand Up @@ -1152,11 +1158,11 @@ def test_create_invalid_patchinfo

def test_create_invalid_submit_request
prepare_request_with_user "tom", "thunder"
# without specifing target, the default target must get found via attribute
# submit requests are not allowed against release projects
post "/request?cmd=create", '<request>
<action type="submit">
<source project="BaseDistro2.0" package="pack2" />
<target project="BaseDistro2.0:LinkedUpdateProject" />
<target project="BaseDistro2.0:LinkedUpdateProject" package="pack2" />
</action>
<state name="new" />
</request>'
Expand Down

0 comments on commit d16e1ad

Please sign in to comment.