diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..23c785e --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,26 @@ +stages: + - test + +default: + before_script: + - apt-get -qq update + - apt-get install -y gnupg2 gettext git subversion util-linux + - gem update --system --quiet + - gem update bundler + - bundle install + - gem install minitest-junit simplecov-cobertura + artifacts: + reports: + junit: report.xml + cobertura: coverage/coverage.xml + +variables: + TESTOPT: '--junit--pride' + LANG: 'C.UTF-8' # container has no LANG by default which messes with ruby's utf8 support + +test:2.4: + image: ruby:2.4 + script: + - echo $PATH + - whereis git + - rake test diff --git a/lib/releaseme/requirement_checker.rb b/lib/releaseme/requirement_checker.rb index 6058f4a..b3957fb 100644 --- a/lib/releaseme/requirement_checker.rb +++ b/lib/releaseme/requirement_checker.rb @@ -1,163 +1,170 @@ #-- # Copyright (C) 2015-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 . #++ # NB: cannot use other files as everything else is meant to load this first. require_relative 'silencer' module ReleaseMe # Makes sure the runtime requirements of releasme are met. class RequirementChecker # Finds executables. MakeMakefile is the only core ruby entity providing # PATH based executable lookup, unfortunately it is really not meant to be # used outside extconf.rb use cases as it mangles the main name scope by # injecting itself into it (which breaks for example the ffi gem). # The Shell interface's command-processor also has lookup code but it's not # Windows compatible. class Executable attr_reader :bin def initialize(bin) @bin = bin end # Finds the executable in PATH by joining it with all parts of PATH and # checking if the resulting absolute path exists and is an executable. # This also honor's Windows' PATHEXT to determine the list of potential # file extensions. So find('gpg2') will find gpg2 on POSIX and gpg2.exe # on Windows. def find # PATHEXT on Windows defines the valid executable extensions. + p ENV exts = ENV.fetch('PATHEXT', '').split(';') # On other systems we'll work with no extensions. exts << '' if exts.empty? + p ENV['PATH'] + ENV['PATH'].split(File::PATH_SEPARATOR).each do |path| + p ['split path', path] path = unescape_path(path) + p ['unex', path] exts.each do |ext| + p ['ext', ext] file = File.join(path, bin + ext) + p ['file', file, executable?(file)] return file if executable?(file) end end nil end private class << self def windows? @windows ||= ENV['RELEASEME_FORCE_WINDOWS'] || mswin? || mingw? end private def mswin? @mswin ||= /mswin/ =~ RUBY_PLATFORM end def mingw? @mingw ||= /mingw/ =~ RUBY_PLATFORM end end def windows? self.class.windows? end def executable?(path) stat = File.stat(path) rescue SystemCallError else return true if stat.file? && stat.executable? end def unescape_path(path) # Strip qutation. # NB: POSIX does not define any quoting mechanism so you simply cannot # have colons in PATH on POSIX systems as a side effect we mustn't # strip quotes as they have no syntactic meaning and instead are # assumed to be part of the path # http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03 return path.sub(/\A"(.*)"\z/m, '\1') if windows? path end end # NOTE: The versions are restricted upwards because behavior changes in the # language can result in unexpected outcome when using releaseme. i.e. # you may end up with a broken or malformed tar. To prevent this, a change # here must be followed by running `rake test` to pass the entire test suite # Also see the section on bumping versions in the REAMDE. COMPATIBLE_RUBIES = %w[2.3.0 2.4.0 2.5.0 2.6.0 2.7.0].freeze REQUIRED_BINARIES = %w[svn git tar xz msgfmt gpg2].freeze def initialize @ruby_version = RUBY_VERSION end def check raise 'Not all requirements met.' unless check_ruby && check_binaries end private def check_ruby return true if ruby_compatible? print "- Ruby #{COMPATIBLE_RUBIES.join(' or ')} required." print " Currently using: #{@ruby_version}" false end def check_binaries missing_binaries.each do |m| print "- Missing binary: #{m}." end.empty? end def print(*args) return if Silencer.shutup? puts(*args) end def ruby_compatible? COMPATIBLE_RUBIES.each do |v| return true if compatible?(v) end false end def missing_binaries missing_binaries = [] REQUIRED_BINARIES.each do |r| missing_binaries << missing?(r) end missing_binaries.compact end def compatible?(a) Gem::Dependency.new('', "~> #{a}").match?('', @ruby_version) end def missing?(bin) return bin unless Executable.new(bin).find nil end end end diff --git a/releaseme.gemspec b/releaseme.gemspec index e24c95a..2168874 100644 --- a/releaseme.gemspec +++ b/releaseme.gemspec @@ -1,58 +1,57 @@ # coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) Gem::Specification.new do |spec| spec.name = 'releaseme' spec.version = '0.0' spec.authors = ['Harald Sitter'] spec.email = ['sitter@kde.org'] spec.summary = 'KDE tarball release tool' spec.description = 'Helps with releasing KDE software as source code tarballs' spec.homepage = 'https://phabricator.kde.org/source/releaseme/' # Prevent pushing this gem to RubyGems.org. To allow pushes either set the # 'allowed_push_host' to allow pushing to a single host or delete this section # to allow pushing to any host. if spec.respond_to?(:metadata) spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'" else raise 'RubyGems 2.0 or newer is required to protect against ' \ 'public gem pushes.' end spec.files = `git ls-files -z`.split("\x0") rejected_files = spec.files.find_all do |f| f.match(%r{^(test|spec|features)/}) || (f.match(%r{^lib/[^/]+.rb}) && !f.match(%r{^lib/releaseme.rb})) end spec.files -= rejected_files # When run through bundler AND in a Gem search path mangle the working # directory. if File.basename($PROGRAM_NAME).include?('bundle') && (Gem.path.any? { |x| Dir.pwd.start_with?(x) } || Dir.pwd.include?('.bundler/') || Dir.pwd.include?('.bundle/')) warn "Mangling releaseme gem as it is in a gem search path #{Dir.pwd}" FileUtils.rm_rf(rejected_files, verbose: true) end spec.require_paths = ['lib'] spec.add_development_dependency 'bundler' # Development spec.add_development_dependency 'rake', '~> 10.0' # Documentation spec.add_development_dependency 'rdoc' spec.add_development_dependency 'yard' # Testing spec.add_development_dependency 'minitest' spec.add_development_dependency 'mocha' spec.add_development_dependency 'webmock' # Coverage - spec.add_development_dependency 'coveralls_reborn' spec.add_development_dependency 'simplecov', '>= 0.11' # Quality spec.add_development_dependency 'rubocop' end diff --git a/test/lib/testme.rb b/test/lib/testme.rb index 7b7f557..296649f 100644 --- a/test/lib/testme.rb +++ b/test/lib/testme.rb @@ -1,114 +1,114 @@ require 'tmpdir' require 'fileutils' require_relative '../test_helper' require 'minitest/unit' begin require 'mocha/minitest' rescue LoadError # 1.0 changed the name, try older name as well for good measure require 'mocha/mini_test' end require 'webmock/minitest' module TestMeExtension attr_reader :tmpdir attr_reader :testdir attr_reader :datadir def initialize(*args) @dir = nil @git_config_name = nil @git_config_email = nil super end def setup_git if `git config --global user.email`.strip.empty? @git_config_email = true `git config --global user.email "you@example.com"` end if `git config --global user.name`.strip.empty? @git_config_name = true `git config --global user.name "Your Name"` end end def teardown_git `git config --global --unset user.email` unless @git_config_email.nil? `git config --global --unset user.name` unless @git_config_name.nil? end def setup_env ENV['GNUPGHOME'] = data('keyring') end def before_setup @orig_env = ENV.to_h # to_h causes a full deserialization ENV['RELEASEME_SHUTUP'] = 'true' ENV['SANITIZED_PREFIX_SUFFIX'] = '1' @tmpdir = Dir.mktmpdir("testme-#{self.class.to_s.tr(':', '_')}") ENV['TEST_SETUP'] = nil @testdir = File.expand_path(File.dirname(File.dirname(__FILE__))).to_s @datadir = "#{@testdir}/data" @pwdir = Dir.pwd Dir.chdir(@tmpdir) setup_git setup_env super end def after_teardown - teardown_git Dir.chdir(@pwdir) FileUtils.rm_rf(@tmpdir) # Restore original env ## Explicitly clear to be on the safe side. Sometimes restoring the env ## may bug out slightly (on windows). ENV.clear ENV.replace(@orig_env) + teardown_git super end def data(path) path = path.partition('data/').last if path.start_with?('data/') "#{@datadir}/#{path}" end def assert_path_exist(path, msg = nil) msg = message(msg) { "Expected path '#{path}' to exist" } assert File.exist?(path), msg end def refute_path_exist(path, msg = nil) msg = message(msg) { "Expected path '#{path}' to NOT exist" } refute File.exist?(path), msg end end class Testme < Minitest::Test prepend TestMeExtension # WARNING: with minitest one should extend through a prepend otherwise hooks # such as mocha may not get properly applied and cause test malfunctions! end # Only set SANITIZED_PREFIX_SUFFIX in tests. Actual lib code mustn't ever # set it as that'd bypass the test. module MkTmpDirOverlay def mktmpdir(*) return super if ENV['SANITIZED_PREFIX_SUFFIX'] raise 'Dir.mktmpdir must not be used! Use Releaseme.mktmpdir!' ensure ENV['SANITIZED_PREFIX_SUFFIX'] = nil end end # Prevent tests from using mktmpdir directly and instead expect them to go # through our mktmpdir such that the prefix_suffix gets cleaned up. # https://bugs.kde.org/show_bug.cgi?id=393011 class Dir class << self prepend MkTmpDirOverlay end end diff --git a/test/test_helper.rb b/test/test_helper.rb index 71aea5b..9f9f39c 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,26 +1,26 @@ require 'simplecov' formatters = [] begin - require 'coveralls' - formatters << Coveralls::SimpleCov::Formatter + require 'simplecov-cobertura' + formatters << SimpleCov::Formatter::CoberturaFormatter rescue LoadError - warn 'coveralls reporter not available, not sending reports to server' + warn 'simplecov-cobertura reporter not available' end # HTML formatter. formatters << SimpleCov::Formatter::HTMLFormatter SimpleCov.start do formatter SimpleCov::Formatter::MultiFormatter.new(formatters) add_filter do |src| # Special compat file for testing the compat code itself. next false if File.basename(src.filename) == 'compat_compat.rb' next false if File.basename(src.filename) == 'releaseme.rb' src.filename.match(%r{.+/lib/[^/]+.rb}) end end # $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__) require 'minitest/autorun'