Skip to content

Commit

Permalink
Merge pull request #4033 from ChrisBr/feature/multibuild_release
Browse files Browse the repository at this point in the history
Feature/multibuild release
  • Loading branch information
ChrisBr committed Oct 19, 2017
2 parents fda6749 + 6c29a4f commit a7f8cdb
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 23 deletions.
23 changes: 15 additions & 8 deletions src/api/app/controllers/source_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,11 @@ def package_command
end
unless PACKAGE_CREATING_COMMANDS.include?(@command) && !Project.exists_by_name(@target_project_name)
valid_project_name! params[:project]
valid_package_name! params[:package]
if @command == 'release' # wipe and rebuild should become supported as well
valid_multibuild_package_name!(params[:package])
else
valid_package_name!(params[:package])
end
# even when we can create the package, an existing instance must be checked if permissions are right
@project = Project.get_by_name @target_project_name
# rubocop:disable Metrics/LineLength
Expand Down Expand Up @@ -1443,31 +1447,34 @@ def reparse_backend_package(spackage, sproject)

# POST /source/<project>/<package>?cmd=release
def package_command_release
pkg = Package.get_by_project_and_name params[:project], params[:package], use_source: true, follow_project_links: false
pkg = Package.get_by_project_and_name params[:project], params[:package], use_source: true, follow_project_links: false, follow_multibuild: true
multibuild_container = nil
if params[:package].include?(":") && !params[:package].starts_with?('_product:')
multibuild_container = params[:package].gsub(/^.*:/, '')
end

# specified target
if params[:target_project]
# we do not create it ourself
Project.get_by_name(params[:target_project])
_package_command_release_manual_target(pkg)
_package_command_release_manual_target(pkg, multibuild_container)
else
spkg = Package.get_by_project_and_name(params[:project], params[:package])
verify_repos_match!(spkg.project)
verify_repos_match!(pkg.project)

# loop via all defined targets
pkg.project.repositories.each do |repo|
next if params[:repository] && params[:repository] != repo.name
repo.release_targets.each do |releasetarget|
# find md5sum and release source and binaries
release_package(pkg, releasetarget.target_repository, pkg.name, repo, nil, params[:setrelease], true)
release_package(pkg, releasetarget.target_repository, pkg.name, repo, multibuild_container, nil, params[:setrelease], true)
end
end
end

render_ok
end

def _package_command_release_manual_target(pkg)
def _package_command_release_manual_target(pkg, multibuild_container)
verify_can_modify_target!

if params[:target_repository].blank? || params[:repository].blank?
Expand All @@ -1480,7 +1487,7 @@ def _package_command_release_manual_target(pkg)
raise UnknownRepository, "Repository does not exist #{params[:repository]}" unless repo.count > 0
repo = repo.first

release_package(pkg, targetrepo, pkg.name, repo, nil, params[:setrelease], true)
release_package(pkg, targetrepo, pkg.name, repo, multibuild_container, nil, params[:setrelease], true)
end
private :_package_command_release_manual_target

Expand Down
33 changes: 22 additions & 11 deletions src/api/app/helpers/maintenance_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ def _release_package(source_package, target_project, target_package_name, action
end

def release_package(source_package, target, target_package_name,
filter_source_repository = nil, action = nil, setrelease = nil, manual = nil)
filter_source_repository = nil, multibuild_container = nil, action = nil,
setrelease = nil, manual = nil)
if target.kind_of? Repository
target_project = target.project
else
Expand All @@ -59,9 +60,9 @@ def release_package(source_package, target, target_package_name,

# copy binaries
if target.kind_of? Repository
u_ids = copy_binaries_to_repository(filter_source_repository, source_package, target, target_package_name, setrelease)
u_ids = copy_binaries_to_repository(filter_source_repository, source_package, target, target_package_name, multibuild_container, setrelease)
else
u_ids = copy_binaries(filter_source_repository, source_package, target_package_name, target_project, setrelease)
u_ids = copy_binaries(filter_source_repository, source_package, target_package_name, target_project, multibuild_container, setrelease)
end

# create or update main package linking to incident package
Expand Down Expand Up @@ -169,14 +170,16 @@ def release_package_copy_sources(action, source_package, target_package_name, ta
action.set_acceptinfo(result["acceptinfo"]) if action
end

def copy_binaries(filter_source_repository, source_package, target_package_name, target_project, setrelease)
def copy_binaries(filter_source_repository, source_package, target_package_name, target_project,
multibuild_container, setrelease)
update_ids = []
source_package.project.repositories.each do |source_repo|
next if filter_source_repository && filter_source_repository != source_repo
source_repo.release_targets.each do |releasetarget|
# FIXME: filter given release and/or target repos here
if releasetarget.target_repository.project == target_project
u_id = copy_binaries_to_repository(source_repo, source_package, releasetarget.target_repository, target_package_name, setrelease)
u_id = copy_binaries_to_repository(source_repo, source_package, releasetarget.target_repository,
target_package_name, multibuild_container, setrelease)
update_ids << u_id if u_id
end
# remove maintenance release trigger in source
Expand All @@ -190,27 +193,35 @@ def copy_binaries(filter_source_repository, source_package, target_package_name,
update_ids
end

def copy_binaries_to_repository(source_repository, source_package, target_repo, target_package_name, setrelease)
def copy_binaries_to_repository(source_repository, source_package, target_repo, target_package_name,
multibuild_container, setrelease)
u_id = get_updateinfo_id(source_package, target_repo)
source_package_name = source_package.name
unless multibuild_container.blank?
source_package_name << ":" << multibuild_container
target_package_name = target_package_name.gsub(/:.*/, '') << ":" << multibuild_container
end
source_repository.architectures.each do |arch|
# get updateinfo id in case the source package comes from a maintenance project
copy_single_binary(arch, target_repo, source_package, source_repository, target_package_name, u_id, setrelease)
copy_single_binary(arch, target_repo, source_package.project.name, source_package_name,
source_repository, target_package_name, u_id, setrelease)
end
u_id
end

def copy_single_binary(arch, target_repository, source_package, source_repo, target_package_name, update_info_id, setrelease)
def copy_single_binary(arch, target_repository, source_project_name, source_package_name, source_repo,
target_package_name, update_info_id, setrelease)
cp_params = {
cmd: "copy",
oproject: source_package.project.name,
opackage: source_package.name,
oproject: source_project_name,
opackage: source_package_name,
orepository: source_repo.name,
user: User.current.login,
multibuild: "1",
resign: "1"
}
cp_params[:setupdateinfoid] = update_info_id if update_info_id
cp_params[:setrelease] = setrelease if setrelease
cp_params[:multibuild] = "1" unless source_package_name.include? ':'
# rubocop:disable Metrics/LineLength
cp_path = "/build/#{CGI.escape(target_repository.project.name)}/#{URI.escape(target_repository.name)}/#{URI.escape(arch.name)}/#{URI.escape(target_package_name)}"
# rubocop:enable Metrics/LineLength
Expand Down
4 changes: 4 additions & 0 deletions src/api/app/helpers/validation_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ def valid_package_name!(package_name)
raise InvalidPackageNameError, "invalid package name '#{package_name}'" unless valid_package_name? package_name
end

def valid_multibuild_package_name!(package_name)
raise InvalidPackageNameError, "invalid package name '#{package_name}'" unless Package.valid_multibuild_name?(package_name)
end

# load last package meta file and just check if sourceaccess flag was used at all, no per user checking atm
def validate_read_access_of_deleted_package(project, name)
prj = Project.get_by_name project
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def execute_accept(opts)
# have a unique time stamp for release
opts[:acceptTimeStamp] ||= Time.now

opts[:updateinfoIDs] = release_package(pkg, Project.get_by_name(target_project), target_package, nil, self)
opts[:updateinfoIDs] = release_package(pkg, Project.get_by_name(target_project), target_package, nil, nil, self)
opts[:projectCommit] ||= {}
opts[:projectCommit][target_project] = source_project

Expand Down
10 changes: 8 additions & 2 deletions src/api/app/models/package.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1085,14 +1085,20 @@ def developed_packages
packages
end

def self.valid_name?(name)
def self.valid_multibuild_name?(name)
valid_name?(name, true)
end

def self.valid_name?(name, allow_multibuild = false)
return false unless name.kind_of? String
# this length check is duplicated but useful for other uses for this function
return false if name.length > 200
return false if name == "0"
return true if %w(_product _pattern _project _patchinfo).include?(name)
# _patchinfo: is obsolete, just for backward compatibility
name =~ /\A([a-zA-Z0-9]|(_product:|_patchinfo:)\w)[-+\w\.]*\z/ ? true : false
allowed_characters = /[-+\w\.#{ allow_multibuild ? ':' : '' }]/
reg_exp = /\A([a-zA-Z0-9]|(_product:|_patchinfo:)\w)#{allowed_characters}*\z/
reg_exp.match?(name)
end

def valid_name
Expand Down
2 changes: 1 addition & 1 deletion src/api/app/models/project.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,7 @@ def do_project_release( params )
next if params[:targetreposiory] && params[:targetreposiory] != releasetarget.target_repository.name
# release source and binaries
# permission checking happens inside this function
release_package(pkg, releasetarget.target_repository, pkg.name, repo, nil, params[:setrelease], true)
release_package(pkg, releasetarget.target_repository, pkg.name, repo, nil, nil, params[:setrelease], true)
end
end
end
Expand Down
23 changes: 23 additions & 0 deletions src/api/spec/controllers/source_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,27 @@
it { expect(response).to be_success }
it { expect(project.config.to_s).to include('Updated', 'by', 'test') }
end

describe "POST #package_command" do
let(:multibuild_package) { create(:package, name: 'multibuild') }
let(:multibuild_project) { multibuild_package.project }
let(:repository) { create(:repository) }
let(:target_repository) { create(:repository) }

before do
multibuild_project.repositories << repository
project.repositories << target_repository
login user
end

context "with 'diff' command for a multibuild package" do
before do
post :package_command, params: {
cmd: 'diff', package: "#{multibuild_package.name}:one", project: multibuild_project, target_project: project
}
end
it { expect(flash[:error]).to eq("invalid_package_name(invalid package name '#{multibuild_package.name}:one'): ") }
it { expect(response.status).to eq(302) }
end
end
end
87 changes: 87 additions & 0 deletions src/api/test/functional/source_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2812,6 +2812,93 @@ def test_release_package
assert_response :success
end

def test_release_multibuild_package
login_adrian
# define manual release target
put '/source/home:adrian:RT/_meta', params: "<project name='home:adrian:RT'> <title/> <description/>
<repository name='rt'>
<arch>i586</arch>
<arch>x86_64</arch>
</repository>
</project>"
assert_response :success

run_scheduler('i586')
run_scheduler('x86_64')

login_Iggy
get '/source/home:Iggy/_meta'
assert_response :success
orig_project_meta = @response.body
doc = REXML::Document.new(@response.body)
rt = doc.elements["/project/repository'"].add_element 'releasetarget'
rt.add_attribute REXML::Attribute.new('project', 'home:adrian:RT')
rt.add_attribute REXML::Attribute.new('repository', 'rt')
put '/source/home:Iggy/_meta', params: doc.to_s
assert_response :success

# add correct trigger
login_Iggy
rt.add_attribute REXML::Attribute.new('trigger', 'manual')
put '/source/home:Iggy/_meta', params: doc.to_s
assert_response :success

# release for real
login_adrian
post '/source/home:Iggy/TestPack:package?cmd=release'
assert_response :success
assert_xml_tag tag: 'status', attributes: { code: 'ok' }

# process events
run_scheduler('i586')

# verify result
get '/source/home:adrian:RT'
assert_response :success
assert_xml_tag tag: 'entry', attributes: { name: 'TestPack' }

# cleanup
login_Iggy
put '/source/home:Iggy/_meta', params: orig_project_meta
assert_response :success
login_adrian
delete '/source/home:adrian:RT'
assert_response :success
end

def test_manual_release_multibuild_package
login_adrian
# define manual release target
put '/source/home:adrian:RT/_meta', params: "<project name='home:adrian:RT'> <title/> <description/>
<repository name='rt'>
<arch>i586</arch>
<arch>x86_64</arch>
</repository>
</project>"
assert_response :success

run_scheduler('i586')
run_scheduler('x86_64')

# release for real
login_adrian
post '/source/home:Iggy/TestPack:package?cmd=release&target_project=home:adrian:RT&target_repository=rt&repository=10.2'
assert_response :success
assert_xml_tag tag: 'status', attributes: { code: 'ok' }

# process events
run_scheduler('i586')

# verify result
get '/source/home:adrian:RT'
assert_response :success
assert_xml_tag tag: 'entry', attributes: { name: 'TestPack' }

login_adrian
delete '/source/home:adrian:RT'
assert_response :success
end

def test_copy_package
# fred has maintainer permissions in this single package of Iggys home
# this is the osc way
Expand Down

0 comments on commit a7f8cdb

Please sign in to comment.