diff --git a/lib/releaseme/project.rb b/lib/releaseme/project.rb index 6b5f484..b641b5e 100644 --- a/lib/releaseme/project.rb +++ b/lib/releaseme/project.rb @@ -1,125 +1,125 @@ #-- # Copyright (C) 2014-2017 Harald Sitter # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License or (at your option) version 3 or any later version # accepted by the membership of KDE e.V. (or its successor approved # by the membership of KDE e.V.), which shall act as a proxy # defined in Section 14 of version 3 of the license. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . #++ require 'net/http' require 'rexml/document' require 'yaml' require_relative 'git' require_relative 'projectsfile' require_relative 'project_api_overlay' require_relative 'project_projectsfile_overlay' module ReleaseMe class Project if ENV.fetch('RELEASEME_PROJECTSFILE', false) prepend ProjectProjectsfileOverlay else prepend ProjectAPIOverlay end @@configdir = "#{File.dirname(File.dirname(File.expand_path(__dir__)))}/projects/" # Project identifer found. nil if not resolved. attr_reader :identifier # VCS to use for this project attr_reader :vcs # Branch used for i18n trunk attr_reader :i18n_trunk # Branch used for i18n stable attr_reader :i18n_stable # Branch used for i18n lts (same as stable except for Plasma) attr_reader :i18n_lts # Path used for i18n. attr_reader :i18n_path # Creates a new Project. Identifier can be nil but must be set manually # before calling resolve. def initialize(project_element: nil, identifier: nil, vcs: nil, i18n_trunk: nil, i18n_stable: nil, i18n_lts: nil, i18n_path: nil) unless project_element || (identifier && vcs) raise 'Project construction either needs to happen with a' \ ' project_element or all other values being !nil' end @identifier = identifier @vcs = vcs @i18n_trunk = i18n_trunk @i18n_stable = i18n_stable @i18n_lts = i18n_lts @i18n_path = i18n_path @project_element = project_element end # Constructs a Project instance from the definition placed in # projects/project_name.yml # @param project_name name of the yml file to look for. This is not reflected # in the actual Project.identifier, just like the original xpath when using # from_xpath. # @return Project never empty, raises exceptions when something goes wrong # @raise RuntimeError on every occasion ever. Unless something goes wrong deep # inside. def self.from_config(project_name) ymlfile = "#{@@configdir}/#{project_name}.yml" unless File.exist?(ymlfile) raise "Project file for #{project_name} not found [#{ymlfile}]." end data = YAML.load(File.read(ymlfile)) data = data.inject({}) do |tmphsh, (key, value)| key = key.downcase.to_sym if key == :vcs raise 'Vcs configuration has no type key.' unless value.key?('type') begin vcs_type = value.delete('type') require_relative vcs_type.downcase.to_s value = ReleaseMe.const_get(vcs_type).from_hash(value) rescue LoadError, RuntimeError => e raise "Failed to resolve the Vcs values #{value} -->\n #{e}" end end tmphsh[key] = value next tmphsh end - Project.new(data) + Project.new(**data) end def plasma_lts self.class.plasma_lts end class << self def plasma_lts ymlfile = "#{@@configdir}/plasma.yml" unless File.exist?(ymlfile) raise "Project file for Plasma not found [#{ymlfile}]." end data = YAML.load_file(ymlfile) data['i18n_lts'] end end end end diff --git a/lib/releaseme/projects_api.rb b/lib/releaseme/projects_api.rb index 9297883..4ef332a 100644 --- a/lib/releaseme/projects_api.rb +++ b/lib/releaseme/projects_api.rb @@ -1,142 +1,142 @@ #-- # Copyright (C) 2017 Harald Sitter # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License or (at your option) version 3 or any later version # accepted by the membership of KDE e.V. (or its successor approved # by the membership of KDE e.V.), which shall act as a proxy # defined in Section 14 of version 3 of the license. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . #++ require 'net/http' require 'open-uri' require 'json' require_relative 'logable' module ReleaseMe # projects.kde.org API. module ProjectsAPI # Converts a Hash recursively to snake case keys. module Snake module_function def it(obj) if obj.is_a?(Array) snake_array(obj) elsif obj.is_a?(Hash) snake_hash(obj) else obj end end def snake_array(array) array.map { |x| Snake.it(x) } end def snake_hash(hash) Hash[hash.map { |k, v| [underscore(k), Snake.it(v)] }] end def underscore(k) return underscore_it(k.to_s).to_sym if k.is_a?(Symbol) return underscore_it(k.to_s).to_s if k.is_a?(String) k end def underscore_it(str) # Grab all lower case alphas (+digits) followed by an upcase alpha and # inject an underscore before the upcase. # Then downcase everything. # (e.g. stableKF5 => stable_KF5 => stable_kf5) str.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase end end # Connection wrapper. class Connection prepend Logable def initialize @uri = URI.parse('https://projects.kde.org/api/v1') end def uri(path, **query) uri = @uri.dup path = path[0] == '/' ? path : path[1..-1] uri.path = "#{uri.path}#{path}" uri.query = URI.encode_www_form(query) unless query.empty? log_debug uri uri end def get(path, **query) - data = JSON.parse(uri(path, query).open.read, symbolize_names: true) + data = JSON.parse(uri(path, **query).open.read, symbolize_names: true) Snake.it(data) end end # OStruct-like helper to expose a hash as methods. module MethodStruct attr_reader :data def method_missing(name, *args) @data.fetch(name) { super } end def respond_to_missing?(name) @data.key?(name) || super end end # API Project model. class Project include MethodStruct # I18n model of API. class I18n include MethodStruct def initialize(data) @data = data # Convert none to more idiomatic nil. @data = @data.collect { |k, v| [k, v == 'none' ? nil : v] }.to_h end end def initialize(data, _connection) @data = data @data[:i18n] = I18n.new(data[:i18n]) end end class << self def get(path, connection = Connection.new) Project.new(connection.get("/project/#{path}"), connection) end def get_by_repo(repo, connection = Connection.new) Project.new(connection.get("/repo/#{repo}"), connection) end def find(connection = Connection.new, **kwords) connection.get('/find', **kwords) end def list(path, connection = Connection.new) connection.get("/projects/#{path}") end end end end diff --git a/test/project_test.rb b/test/project_test.rb index 106a069..2368084 100644 --- a/test/project_test.rb +++ b/test/project_test.rb @@ -1,401 +1,401 @@ #-- # Copyright (C) 2014-2015 Harald Sitter # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License or (at your option) version 3 or any later version # accepted by the membership of KDE e.V. (or its successor approved # by the membership of KDE e.V.), which shall act as a proxy # defined in Section 14 of version 3 of the license. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . #++ require 'fileutils' require_relative 'lib/testme' require_relative '../lib/releaseme/project' require_relative '../lib/releaseme/vcs' def j(*args) JSON.generate(*args) end def default_i18n { stable: nil, stableKF5: nil, trunk: nil, trunkKF5: 'master', component: 'default' } end def stub_projects_single(url) path = url.gsub('https://projects.kde.org/api/v1/projects/', '') stub_request(:get, url).to_return(body: j([path])) end def git_stubs # Do not let us hit live repos. # We do repo progint to determine whether to use invent.kde.org or git.kde.org ReleaseMe::Git.any_instance.expects(:run).never # Pretend everything exists on invent success_status = mock() success_status.responds_like_instance_of(Process::Status) success_status.stubs(:success?).returns(true) ReleaseMe::Git.any_instance.stubs(:run).with do |args| next false unless args.include?('ls-remote') true end.returns(['', success_status]) end # FIXME: this should go somewhere central or into a class. having a meth in global scope sucks def stub_api git_stubs stub_request(:get, 'https://projects.kde.org/api/v1/projects/extragear/utils') .to_return(body: JSON.generate(%w[extragear/utils/yakuake extragear/utils/krusader extragear/utils/krecipes])) # Invalid. stub_request(:get, 'https://projects.kde.org/api/v1/projects/kitten') .to_return(status: 404) stub_request(:get, 'https://projects.kde.org/api/v1/find?id=kitten') .to_return(status: 404) stub_request(:get, 'https://projects.kde.org/api/v1/projects/utils') .to_return(status: 404) stub_request(:get, 'https://projects.kde.org/api/v1/find?id=utils') .to_return(status: 404) stub_request(:get, 'https://projects.kde.org/api/v1/projects/yakuake') .to_return(status: 404) stub_request(:get, 'https://projects.kde.org/api/v1/find?id=yakuake') .to_return(body: j(%w[extragear/utils/yakuake])) stub_request(:get, 'https://projects.kde.org/api/v1/project/networkmanager-qt') .to_return(status: 404) stub_request(:get, 'https://projects.kde.org/api/v1/find?id=networkmanager-qt') .to_return(body: j(%w[frameworks/networkmanager-qt])) stub_request(:get, 'https://projects.kde.org/api/v1/projects/ktp-contact-runner') .to_return(status: 404) stub_request(:get, 'https://projects.kde.org/api/v1/find?id=ktp-contact-runner') .to_return(body: j(%w[kde/kdenetwork/ktp-contact-runner])) stub_request(:get, 'https://projects.kde.org/api/v1/projects/extragear') .to_return(body: j(%w[extragear/utils/yakuake extragear/utils/krusader extragear/utils/krecipes extragear/network/telepathy/ktp1 extragear/network/telepathy/ktp2])) stub_request(:get, 'https://projects.kde.org/api/v1/projects/extragear/network/telepathy') .to_return(body: j(%w[extragear/network/telepathy/ktp1 extragear/network/telepathy/ktp2])) stub_projects_single('https://projects.kde.org/api/v1/projects/kde/kdegraphics/libs/libksane') stub_projects_single('https://projects.kde.org/api/v1/projects/extragear/network/telepathy/ktp1') stub_projects_single('https://projects.kde.org/api/v1/projects/extragear/network/telepathy/ktp2') stub_projects_single('https://projects.kde.org/api/v1/projects/networkmanager-qt') stub_projects_single('https://projects.kde.org/api/v1/projects/extragear/utils/yakuake') # By Project Path stub_request(:get, 'https://projects.kde.org/api/v1/project/extragear/utils/yakuake') .to_return(body: j(path: 'extragear/utils/yakuake', repo: 'yakuake', i18n: { stable: nil, stableKF5: 'notmaster', trunk: nil, trunkKF5: 'master', component: 'extragear-utils' })) stub_request(:get, 'https://projects.kde.org/api/v1/project/extragear/utils/krusader') .to_return(body: j(path: 'extragear/utils/krusader', repo: 'krusader', i18n: default_i18n)) stub_request(:get, 'https://projects.kde.org/api/v1/project/extragear/utils/krecipes') .to_return(body: j(path: 'extragear/utils/krecipes', repo: 'krecipes', i18n: default_i18n)) stub_request(:get, 'https://projects.kde.org/api/v1/project/extragear/network/telepathy/ktp1') .to_return(body: j(path: 'extragear/network/telepathy/ktp1', repo: 'ktp1', i18n: default_i18n)) stub_request(:get, 'https://projects.kde.org/api/v1/project/extragear/network/telepathy/ktp2') .to_return(body: j(path: 'extragear/network/telepathy/ktp2', repo: 'ktp2', i18n: default_i18n)) stub_request(:get, 'https://projects.kde.org/api/v1/project/kde/kdenetwork/ktp-contact-runner') .to_return(body: j(path: 'kde/kdenetwork/ktp-contact-runner', repo: 'ktp-contact-runner', i18n: default_i18n)) stub_request(:get, 'https://projects.kde.org/api/v1/project/frameworks/networkmanager-qt') .to_return(body: j(path: 'frameworks/networkmanager-qt', repo: 'networkmanager-qt', i18n: default_i18n)) # By Repo stub_request(:get, 'https://projects.kde.org/api/v1/repo/kfilemetadata') .to_return(body: j(path: 'frameworks/kfilemetadata', repo: 'kfilemetadata', i18n: default_i18n)) end class TestProjectResolver < Testme def setup # Project uses ProjectsFile to read data, so we need to make sure it # uses our dummy file. ReleaseMe::ProjectsFile.xml_path = data('kde_projects_advanced.xml') ReleaseMe::ProjectsFile.load! stub_api end def assert_valid_project(project_array, expected_identifier) refute_nil(project_array) assert_equal(project_array.size, 1) assert_equal(project_array[0].identifier, expected_identifier) end def test_real_project pr = ReleaseMe::Project.from_xpath('yakuake') assert_valid_project(pr, 'yakuake') end def test_real_project_with_full_path pr = ReleaseMe::Project.from_xpath('extragear/utils/yakuake') assert_valid_project(pr, 'yakuake') end def test_module_as_project pr = ReleaseMe::Project.from_xpath('networkmanager-qt') assert_valid_project(pr, 'networkmanager-qt') end #### def assert_valid_array(project_array, matches) refute_nil(project_array) assert_equal(matches.size, project_array.size) project_array.each do |project| matches.delete(project.identifier) end assert(matches.empty?, "One or more sub-projects did not get resolved correctly: #{matches}") end ####### nested resolution def assert_valid_extragear_utils_array(project_array) assert_valid_array(project_array, %w[yakuake krusader krecipes]) end def test_module pr = ReleaseMe::Project.from_xpath('utils') assert_equal([], pr) end def test_module_with_full_path pr = ReleaseMe::Project.from_xpath('extragear/utils') assert_valid_extragear_utils_array(pr) end ####### super nested resolution def assert_valid_telepathy_array(project_array) assert_valid_array(project_array, %w[ktp1 ktp2]) end def test_project_with_subprojects pr = ReleaseMe::Project.from_xpath('extragear/network/telepathy') assert_valid_telepathy_array(pr) pr = ReleaseMe::Project.from_xpath('extragear/network/telepathy/ktp1') refute_nil(pr) assert_equal('ktp1', pr[0].identifier) end def assert_valid_extragear_array(project_array) assert_valid_array(project_array, %w[yakuake krusader krecipes ktp1 ktp2]) end def test_component pr = ReleaseMe::Project.from_xpath('extragear') assert_valid_extragear_array(pr) end end class TestProjectConfig < Testme def setup # Project uses ProjectsFile to read data, so we need to make sure it # uses our dummy file. stub_api end def test_invalid_name name = 'kittens' assert_raises do ReleaseMe::Project.from_config(name) end end def test_construction_git ReleaseMe::Project.class_variable_set(:@@configdir, data('projects/')) name = 'valid' pr = ReleaseMe::Project.from_config(name) refute_nil(pr) assert_equal('yakuake', pr.identifier) assert_equal('git://anongit.kde.org/yakuake', pr.vcs.repository) assert_equal('master', pr.i18n_trunk) assert_equal('notmaster', pr.i18n_stable) assert_nil(pr.i18n_lts) assert_equal('extragear-utils', pr.i18n_path) end def test_valid_svn ReleaseMe::Project.class_variable_set(:@@configdir, data('projects/')) name = 'valid-svn' pr = ReleaseMe::Project.from_config(name) refute_nil(pr) assert_equal('svn://anonsvn.kde.org/home', pr.vcs.repository) end def test_invalid_vcs ReleaseMe::Project.class_variable_set(:@@configdir, data('projects/')) name = 'invalid-vcs' assert_raises NoMethodError do ReleaseMe::Project.from_config(name) end end def test_invalid_vcs_type ReleaseMe::Project.class_variable_set(:@@configdir, data('projects/')) name = 'invalid-vcs-type' assert_raises RuntimeError do ReleaseMe::Project.from_config(name) end end def test_plasma_lts ReleaseMe::Project.class_variable_set(:@@configdir, data('projects/')) projects = ReleaseMe::Project.from_xpath('yakuake') assert_equal(projects.size, 1) pr = projects.shift assert_equal(pr.plasma_lts, 'Plasma/5.8') end end class TestProject < Testme def setup # Project uses ProjectsFile to read data, so we need to make sure it # uses our dummy file. ReleaseMe::ProjectsFile.xml_path = data('kde_projects.xml') ReleaseMe::ProjectsFile.load! stub_api end def teardown end def test_manual_construction_fail assert_raises do # Refuse to new because we need all arguments. ReleaseMe::Project.new(identifier: 'a', vcs: nil) end end def test_manual_construction_success data = { :identifier => 'yakuake', :vcs => ReleaseMe::Vcs.new, :i18n_trunk => 'master', :i18n_stable => 'master', :i18n_path => 'extragear-utils' } - pr = ReleaseMe::Project.new(data) + pr = ReleaseMe::Project.new(**data) refute_nil(pr) assert_equal(pr.identifier, data[:identifier]) assert_equal(pr.vcs, data[:vcs]) assert_equal(pr.i18n_trunk, data[:i18n_trunk]) assert_equal(pr.i18n_stable, data[:i18n_stable]) assert_equal(pr.i18n_path, data[:i18n_path]) end def test_resolve_valid projects = ReleaseMe::Project.from_xpath('yakuake') assert_equal(projects.size, 1) pr = projects.shift assert_equal('yakuake', pr.identifier) assert_equal('master', pr.i18n_trunk) assert_equal('notmaster', pr.i18n_stable) assert_equal('extragear-utils', pr.i18n_path) end def test_resolve_valid_i18n_path_with_sub_project # ktp things are in extragear/network/telepathy/ktp*, yet their # translation path is component-module. Make sure that we get the correct # path for this. # Other example would be extragear/graphics/libs/kdiagram. projects = ReleaseMe::Project.from_xpath('ktp-contact-runner') assert_equal(1, projects.size) pr = projects.shift assert_equal('ktp-contact-runner', pr.identifier) end def test_resolve_invalid projects = ReleaseMe::Project.from_xpath('kitten') assert_equal(projects, []) end def test_vcs projects = ReleaseMe::Project.from_xpath('yakuake') assert_equal(projects.size, 1) pr = projects.shift vcs = pr.vcs assert_equal(vcs.repository, 'git@invent.kde.org:kde/yakuake') assert_nil(vcs.branch) # project on its own should not set a branch end def test_from_repo_url # Mock Git internals to make this repo default to git.kde.org instead # of invent.kde.org by pretending the ls-remote fails. fail_status = mock() fail_status.responds_like_instance_of(Process::Status) fail_status.stubs(:success?).returns(false) ReleaseMe::Git.any_instance.stubs(:run).with do |args| next false unless args.include?('ls-remote') next false unless args.include?('git@invent.kde.org:kde/kfilemetadata') true end.returns(['', fail_status]) projects = ReleaseMe::Project.from_repo_url('git://anongit.kde.org/kfilemetadata') assert_equal(1, projects.size) pr = projects.shift assert_equal('kfilemetadata', pr.identifier) assert_equal('git@git.kde.org:kfilemetadata', pr.vcs.repository) end def test_projectsfile_removal # TODO: drop project_element once projectsfile support is entirely removed # - this test can also be dropped then # - project.xml test data in test/data can also be dropped # - overlay class as well # - api overlay can be merged into project # - api overlay's from_data can be merged into initialize data = { :identifier => 'yakuake', :vcs => ReleaseMe::Vcs.new, :i18n_trunk => 'master', :i18n_stable => 'master', :i18n_path => 'extragear-utils' } - pr = ReleaseMe::Project.new(data) + pr = ReleaseMe::Project.new(**data) assert_includes ReleaseMe.constants, :ProjectsFile assert_includes ReleaseMe.constants, :ProjectProjectsfileOverlay assert_includes pr.instance_variables, :@project_element end end diff --git a/test/release_test.rb b/test/release_test.rb index 71f25fb..26cd899 100644 --- a/test/release_test.rb +++ b/test/release_test.rb @@ -1,261 +1,261 @@ require_relative 'lib/testme' require_relative '../lib/releaseme/git' require_relative '../lib/releaseme/origin' require_relative '../lib/releaseme/project' require_relative '../lib/releaseme/release' class TestRelease < Testme module Silencer module_function def run(cmd) `#{cmd} 2>&1` end end attr_reader :remotedir def `(other) Silencer.run(other) end def setup_repo_content `git clone #{@remotedir} clone` Dir.chdir('clone') do File.write('file', 'content') `git add file` `git commit -a -m 'import'` `git push origin master` end ensure FileUtils.rm_rf('clone') end # FIXME: this needs putting in a module or something for reuse here, in source # and in git def setup # Create a test remote Dir.mkdir('remote') Dir.chdir('remote') do `git init --bare .` end @remotedir = "#{Dir.pwd}/remote" setup_repo_content stub_request(:get, 'https://build.kde.org/api/json?tree=jobs%5Bname,url%5D,views%5Bname%5D') .to_return(body: JSON.generate(jobs: [])) WebMock.enable! # Disable all SVN nonesense so we don't hit live servers. fake_svn = mock('svn') fake_svn.stubs(:repository=) fake_svn.stubs(:cat).returns('') fake_svn.stubs(:list).returns('') fake_svn.stubs(:get).returns(true) ReleaseMe::Svn.stubs(:new).returns(fake_svn) # Teardown happens automatically when the @tmpdir is torn down end def teardown WebMock.reset! end def new_test_release data = { :identifier => 'clone', :vcs => ReleaseMe::Git.new, :i18n_trunk => 'master', :i18n_stable => 'master', :i18n_path => '' } - project = ReleaseMe::Project.new(data) + project = ReleaseMe::Project.new(**data) project.vcs.repository = @remotedir r = ReleaseMe::Release.new(project, :trunk, '1.0') refute_nil(r) assert_equal(project, r.project) assert_equal(:trunk, r.origin) assert_equal('1.0', r.version) assert_equal('clone-1.0', r.source.target) r end def new_test_release_svn data = { :identifier => 'clone', :vcs => ReleaseMe::Svn.new, :i18n_trunk => 'master', :i18n_stable => 'master', :i18n_path => '' } - project = ReleaseMe::Project.new(data) + project = ReleaseMe::Project.new(**data) project.vcs.repository = @remotedir ReleaseMe::Release.new(project, :trunk, '1.0') end def test_init new_test_release new_test_release_svn end def test_get_archive_cleanup r = new_test_release @dir = r.source.target refute_path_exist(@dir) r.get assert_path_exist(@dir) assert_path_exist("#{@dir}/file") refute_path_exist("#{@dir}.tar.xz") r.archive assert_path_exist("#{@dir}.tar.xz") assert_path_exist("#{@dir}.tar.xz.sig") assert_path_exist(@dir) r.source.cleanup refute_path_exist(@dir) end def test_kde4_origin data = { :identifier => 'clone', :vcs => ReleaseMe::Git.new, :i18n_trunk => 'master', :i18n_stable => 'master', :i18n_path => '' } - project = ReleaseMe::Project.new(data) + project = ReleaseMe::Project.new(**data) project.vcs.repository = @remotedir assert_raises do ReleaseMe::Release.new(project, Project::TRUNK_KDE4, '1.0') end end def test_ci_check_all_good # For now we can stub on a HTTP level, should the Jenkins classes become # too complex it will be better to moch the objects themself. Moddelling # the http interaction litters a lot. stub_request(:get, 'https://build.kde.org/api/json?tree=jobs%5Bname,url%5D,views%5Bname%5D') .to_return(body: JSON.generate( jobs: [ { name: 'clone master kf5-qt5', url: 'https://build.kde.org/job/clone/' } ] )) stub_request(:get, 'https://build.kde.org/job/clone/lastBuild/api/json') .to_return(body: JSON.generate(id: 17)) stub_request(:get, 'https://build.kde.org/job/clone/lastSuccessfulBuild/api/json') .to_return(body: JSON.generate(id: 17)) stub_request(:get, 'https://build.kde.org/job/clone/lastStableBuild/api/json') .to_return(body: JSON.generate(id: 17)) stub_request(:get, 'https://build.kde.org/job/clone/lastCompletedBuild/api/json') .to_return(body: JSON.generate(id: 17)) data = { identifier: 'clone', vcs: ReleaseMe::Git.new, i18n_trunk: 'master', i18n_stable: 'master', i18n_path: '' } - project = ReleaseMe::Project.new(data) + project = ReleaseMe::Project.new(**data) project.vcs.repository = @remotedir ReleaseMe::Release.new(project, ReleaseMe::Origin::TRUNK, '1.0').get end def test_ci_check_one_building_one_shitty # For now we can stub on a HTTP level, should the Jenkins classes become # too complex it will be better to moch the objects themself. Moddelling # the http interaction litters a lot. stub_request(:get, 'https://build.kde.org/api/json?tree=jobs%5Bname,url%5D,views%5Bname%5D') .to_return(body: JSON.generate( jobs: [ { name: 'clone master kf5-qt5', url: 'https://build.kde.org/job/clone/' }, { name: 'clone master kf5-qt5-kitten', url: 'https://build.kde.org/job/clone2/' } ] )) # clone is still building stub_request(:get, 'https://build.kde.org/job/clone/api/json') .to_return(body: JSON.generate(displayName: 'clone')) stub_request(:get, 'https://build.kde.org/job/clone/lastBuild/api/json') .to_return(body: JSON.generate(id: 17)) stub_request(:get, 'https://build.kde.org/job/clone/lastSuccessfulBuild/api/json') .to_return(body: JSON.generate(id: 16)) stub_request(:get, 'https://build.kde.org/job/clone/lastStableBuild/api/json') .to_return(body: JSON.generate(id: 16)) stub_request(:get, 'https://build.kde.org/job/clone/lastCompletedBuild/api/json') .to_return(body: JSON.generate(id: 16)) # clone2 has bad quality stub_request(:get, 'https://build.kde.org/job/clone2/api/json') .to_return(body: JSON.generate(displayName: 'clone2')) stub_request(:get, 'https://build.kde.org/job/clone2/lastBuild/api/json') .to_return(body: JSON.generate(id: 16)) stub_request(:get, 'https://build.kde.org/job/clone2/lastSuccessfulBuild/api/json') .to_return(body: JSON.generate(id: 15)) stub_request(:get, 'https://build.kde.org/job/clone2/lastStableBuild/api/json') .to_return(body: JSON.generate(id: 15)) stub_request(:get, 'https://build.kde.org/job/clone2/lastCompletedBuild/api/json') .to_return(body: JSON.generate(id: 16)) data = { identifier: 'clone', vcs: ReleaseMe::Git.new, i18n_trunk: 'master', i18n_stable: 'master', i18n_path: '' } - project = ReleaseMe::Project.new(data) + project = ReleaseMe::Project.new(**data) project.vcs.repository = @remotedir # Release.rb will call abort once we tell it to not ignore the shitty jobs. # We intercept this and instead raise a sytemcallerror to verify that this # is in fact what occured. ReleaseMe::Release.any_instance.expects(:abort).raises(SystemCallError.new('')) ReleaseMe::Release.any_instance.expects(:gets).returns("n\n") assert_raises SystemCallError do ReleaseMe::Release.new(project, ReleaseMe::Origin::TRUNK, '1.0').get end refute_path_exist('clone-1.0') end def test_help data = { identifier: 'clone', vcs: ReleaseMe::Git.new, i18n_trunk: 'master', i18n_stable: 'master', i18n_path: '' } - project = ReleaseMe::Project.new(data) + project = ReleaseMe::Project.new(**data) project.vcs.repository = @remotedir r = ReleaseMe::Release.new(project, :trunk, '1.0') r.get r.archive # We do not particularly care about the output at this time. What matters # is that it passes. r.help end end