yast-rake 0.2.36 → 0.2.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # Yast rake
5
+ #
6
+ # Copyright (C) 2021 SUSE LLC
7
+ # This library is free software; you can redistribute it and/or modify
8
+ # it only under the terms of version 2.1 of the GNU Lesser General Public
9
+ # License as published by the Free Software Foundation.
10
+ #
11
+ # This library is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14
+ # details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this library; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ #++
20
+
21
+ require_relative "../github_actions"
22
+
23
+ module GithubActions
24
+ module Tasks
25
+ # run all supported Github Action jobs locally
26
+ class RunAll
27
+ include Colorizer
28
+
29
+ # run all jobs one by one, continue even if a job fails,
30
+ # print the summary in the end
31
+ def run
32
+ # collect failed jobs
33
+ failed_jobs = []
34
+ workflows = Workflow.read
35
+ # custom Docker image requested?
36
+ image = custom_image(workflows)
37
+
38
+ workflows.each do |workflow|
39
+ workflow.jobs.each do |job|
40
+ # skip unsupported jobs
41
+ next unless valid_job?(job)
42
+
43
+ runner = JobRunner.new(job, image)
44
+ failed_jobs << job.name if !runner.run
45
+ end
46
+ end
47
+
48
+ print_result(failed_jobs)
49
+ end
50
+
51
+ private
52
+
53
+ # check if a custom image can be used for all jobs,
54
+ # if more than one Docker image is used than it's unlikely that
55
+ # a same custom image will work for all jobs, rather abort in that case
56
+ # to avoid some strange errors when using incorrect image
57
+ # @param workflows [GithubActions::Workflow] all defined workflows
58
+ # @return [String,nil] the custom Docker image name or `nil` if not specified
59
+ def custom_image(workflows)
60
+ return nil unless ENV["DOCKER_IMAGE"]
61
+
62
+ images = workflows.each_with_object([]) do |workflow, arr|
63
+ workflow.jobs.each do |job|
64
+ arr << job.container if job.container && !arr.include?(job.container)
65
+ end
66
+ end
67
+
68
+ if images.size > 1
69
+ error("More than one Docker image is used in the workflows,")
70
+ error("DOCKER_IMAGE option cannot be used.")
71
+ puts "Use DOCKER_IMAGE option for each job separately."
72
+ abort
73
+ end
74
+
75
+ ENV["DOCKER_IMAGE"]
76
+ end
77
+
78
+ # print the final result
79
+ # @param failed_jobs [Array<String>] list of failed jobs
80
+ def print_result(failed_jobs)
81
+ if failed_jobs.empty?
82
+ success("Overall result: SUCCESS")
83
+ else
84
+ error("Failed jobs: #{failed_jobs.inspect}")
85
+ error("Overall result: FAILURE!")
86
+ abort
87
+ end
88
+ end
89
+
90
+ # check if the job is valid and can be run locally,
91
+ # if the job cannot be used it prints a warning
92
+ # @return [Boolean] `true` if the job is valid, `false` otherwise
93
+ def valid_job?(job)
94
+ unsupported = job.unsupported_steps
95
+ if !unsupported.empty?
96
+ warning("WARNING: Skipping job \"#{job.name}\", found " \
97
+ "unsupported steps: #{unsupported.inspect}")
98
+ return false
99
+ end
100
+
101
+ if job.container.nil? || job.container.empty?
102
+ warning("WARNING: Skipping job \"#{job.name}\", " \
103
+ "the Docker container in not specified")
104
+ return false
105
+ end
106
+
107
+ true
108
+ end
109
+ end
110
+ end
111
+ end
data/lib/tasks/pot.rake CHANGED
@@ -27,19 +27,36 @@ task :pot do
27
27
  end
28
28
 
29
29
  namespace :check do
30
+
31
+ def interpolation_message
32
+ <<~MSG
33
+ Note: \#{foo} substitution in translatable strings does
34
+ not work properly, use
35
+ _("foo %{bar} baz") % { :bar => bar }
36
+ or
37
+ _("foo %s baz") % bar
38
+ MSG
39
+ end
40
+
41
+ def angle_brackets_message
42
+ <<~MSG
43
+ Note: %<foo> placeholder should not be used in translatable strings
44
+ because GNU Gettext does not support any suitable language format for that,
45
+ use %{foo} instead.
46
+ MSG
47
+ end
48
+
30
49
  # print failed lines and a hint to STDERR
31
- def report_pot_errors(lines)
50
+ def report_pot_errors(lines, message)
51
+ return if lines.empty?
52
+
32
53
  warn "Failed lines:"
33
54
  warn "-" * 30
34
55
  warn lines
35
56
  warn "-" * 30
36
- $stderr.puts
37
- warn "Note: \#{foo} substitution in translatable strings does" \
38
- " not work properly, use"
39
- warn " _(\"foo %{bar} baz\") % { :bar => bar }"
40
- warn "or"
41
- warn " _(\"foo %s baz\") % bar"
42
- $stderr.puts
57
+ warn ""
58
+ warn message
59
+ warn ""
43
60
  end
44
61
 
45
62
  # remove gettext keywords and extra quotes
@@ -53,7 +70,9 @@ namespace :check do
53
70
  end
54
71
 
55
72
  desc "Check translatable strings for common mistakes"
56
- # depends on the global "pot" task defined above
73
+ # depends on the global "pot" task defined above,
74
+ # this scans for the #{} interpolations (do not work in translations)
75
+ # and %<> (no compatible language format in Gettext)
57
76
  task pot: :"rake:pot" do
58
77
  Dir["*.pot"].each do |pot|
59
78
  puts "Checking #{pot}..."
@@ -61,14 +80,18 @@ namespace :check do
61
80
  # remove comments
62
81
  lines.reject! { |line| line.match(/^#/) }
63
82
  # Ruby substitution present?
64
- lines.select! { |line| line.include?("\#{") }
83
+ interpolations = lines.select { |line| line.include?("\#{") }
84
+ angle_brackets = lines.select { |line| line.include?("%<") }
85
+
86
+ next if interpolations.empty? && angle_brackets.empty?
87
+
88
+ clean_pot_lines(interpolations)
89
+ clean_pot_lines(angle_brackets)
65
90
 
66
- clean_pot_lines(lines)
91
+ report_pot_errors(interpolations, interpolation_message)
92
+ report_pot_errors(angle_brackets, angle_brackets_message)
67
93
 
68
- if !lines.empty?
69
- report_pot_errors(lines)
70
- raise "ERROR: Ruby substitution found in a translatable string"
71
- end
94
+ raise "ERROR: Found invalid or unsupported translatable string"
72
95
  end
73
96
  end
74
97
  end
data/lib/tasks/run.rake CHANGED
@@ -18,6 +18,8 @@
18
18
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
19
  #++
20
20
 
21
+ require_relative "container_runner"
22
+
21
23
  def set_y2dir
22
24
  dirs = Dir["**/src"]
23
25
  dirs << ENV["Y2DIR"] if ENV["Y2DIR"] && !ENV["Y2DIR"].empty?
@@ -46,6 +48,15 @@ task :run, :client do |_t, args|
46
48
  sh "/sbin/yast2 #{client}"
47
49
  end
48
50
 
51
+ desc "Run given client in a Docker container"
52
+ task :"run:container", :client do |_t, args|
53
+ args.with_defaults = { client: nil }
54
+ client = args[:client]
55
+
56
+ runner = ContainerRunner.new
57
+ runner.run(client)
58
+ end
59
+
49
60
  desc "Runs console with preloaded module directories"
50
61
  task :console do
51
62
  set_y2dir
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # Yast rake
5
+ #
6
+ # Copyright (C) 2020, SUSE LLC
7
+ # This library is free software; you can redistribute it and/or modify
8
+ # it only under the terms of version 2.1 of the GNU Lesser General Public
9
+ # License as published by the Free Software Foundation.
10
+ #
11
+ # This library is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14
+ # details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this library; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ #++
20
+
21
+ require_relative "../yast/tarball_server"
22
+
23
+ # Rake task for running a source code web server,
24
+ # designed for the `yupdate` script.
25
+ desc "Start an HTTP server providing dynamically generated source code tarball"
26
+ task :server, [:port] do |_task, args|
27
+ server = Yast::TarballServer.new(args[:port])
28
+
29
+ puts "Starting tarball webserver:"
30
+ server.addresses.each { |a| puts " * #{a}" }
31
+ puts
32
+
33
+ server.start
34
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # Yast rake
5
+ #
6
+ # Copyright (C) 2020, SUSE LLC
7
+ # This library is free software; you can redistribute it and/or modify
8
+ # it only under the terms of version 2.1 of the GNU Lesser General Public
9
+ # License as published by the Free Software Foundation.
10
+ #
11
+ # This library is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14
+ # details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this library; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ #++
20
+
21
+ require "webrick"
22
+
23
+ module Yast
24
+ # a webrick servlet which returns a basic HTML info about the server,
25
+ # just to avoid that nasty 404 error page when someone opens the
26
+ # server URL in a web browser
27
+ class IndexServlet < WEBrick::HTTPServlet::AbstractServlet
28
+ INDEX_FILE = File.expand_path("../../data/index.html", __dir__)
29
+
30
+ def do_GET(_request, response)
31
+ response.status = 200
32
+ response.content_type = "text/html"
33
+ response.body = File.read(INDEX_FILE)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # Yast rake
5
+ #
6
+ # Copyright (C) 2020, SUSE LLC
7
+ # This library is free software; you can redistribute it and/or modify
8
+ # it only under the terms of version 2.1 of the GNU Lesser General Public
9
+ # License as published by the Free Software Foundation.
10
+ #
11
+ # This library is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14
+ # details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this library; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ #++
20
+
21
+ require "json"
22
+ require "webrick"
23
+
24
+ module Yast
25
+ # a webrick servlet which lists all rake servers running on this machine
26
+ class ServersServlet < WEBrick::HTTPServlet::AbstractServlet
27
+ def do_GET(_request, response)
28
+ response.status = 200
29
+ response.content_type = "application/json"
30
+ response.body = servers.to_json
31
+ end
32
+
33
+ private
34
+
35
+ # find the locally running "rake server" processes
36
+ def servers
37
+ output = `pgrep -a -f "rake server \\([0-9]+,.*\\)"`
38
+ output.lines.map do |l|
39
+ l.match(/rake server \(([0-9]+),(.*)\)/)
40
+ {
41
+ port: Regexp.last_match[1],
42
+ dir: Regexp.last_match[2]
43
+ }
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ #--
4
+ # Yast rake
5
+ #
6
+ # Copyright (C) 2020, SUSE LLC
7
+ # This library is free software; you can redistribute it and/or modify
8
+ # it only under the terms of version 2.1 of the GNU Lesser General Public
9
+ # License as published by the Free Software Foundation.
10
+ #
11
+ # This library is distributed in the hope that it will be useful, but WITHOUT
12
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
+ # FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14
+ # details.
15
+ #
16
+ # You should have received a copy of the GNU Lesser General Public
17
+ # License along with this library; if not, write to the Free Software
18
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
+ #++
20
+
21
+ require "webrick"
22
+ require "socket"
23
+
24
+ require_relative "index_servlet"
25
+ require_relative "servers_servlet"
26
+ require_relative "tarball_servlet"
27
+
28
+ module Yast
29
+ # a webrick server which provides the source tarballs
30
+ #
31
+ # the server handles these URL paths:
32
+ # - "/archive/current.tar.gz" - the generated source code tarball
33
+ # - "/servers/index.json" - index of the tarball servers running on this machine
34
+ # - "/" - just a simple index page
35
+ #
36
+ # to stop the server press Ctrl+C
37
+ class TarballServer
38
+ # the default port number
39
+ DEFAULT_HTTP_PORT = 8000
40
+
41
+ attr_reader :port
42
+
43
+ # create all URLs valid for this machine, use all network interfaces
44
+ # (except the loop backs, the server will be used only from outside)
45
+ # @return [Array<String>] list of URLs
46
+ def addresses
47
+ # ignore the loopback addresses
48
+ hosts = Socket.ip_address_list.reject { |a| a.ipv4_loopback? || a.ipv6_loopback? }
49
+ # IPv6 addresses need to be closed in square brackets in URLs
50
+ hosts.map! { |a| a.ipv6? ? "[#{a.ip_address}]" : a.ip_address.to_s }
51
+ # include also the hostname to make it easier to write
52
+ hostname = Socket.gethostname
53
+ hosts << hostname if !hostname&.empty?
54
+ hosts.map! { |h| "http://#{h}:#{port}" }
55
+ end
56
+
57
+ # constructor
58
+ #
59
+ # @param port [Integer,nil] the port number, if nil the port will be found automatically
60
+ #
61
+ def initialize(port = nil)
62
+ @port = port || find_port
63
+ end
64
+
65
+ # start the webserver, it can be closed by pressing Ctrl+C or by sending SIGTERM signal
66
+ def start
67
+ dir = File.basename(Dir.pwd)
68
+ # change the process title so we can find the running
69
+ # servers and their ports just by simple grepping the running processes
70
+ Process.setproctitle("rake server (#{port},#{dir})")
71
+
72
+ # Use "*" to bind also the IPv6 addresses
73
+ server = WEBrick::HTTPServer.new(Port: port, BindAddress: "*")
74
+ server.mount("/archive/current.tar.gz", TarballServlet)
75
+ server.mount("/servers/index.json", ServersServlet)
76
+ server.mount("/", IndexServlet)
77
+
78
+ # stop the server when receiving a signal like Ctrl+C
79
+ # (inspired by the "un.rb" from the Ruby stdlib)
80
+ signals = ["TERM", "QUIT"]
81
+ signals.concat(["HUP", "INT"]) if $stdin.tty?
82
+ signals.each do |s|
83
+ trap(s) { server.shutdown }
84
+ end
85
+
86
+ server.start
87
+ end
88
+
89
+ private
90
+
91
+ # is the local port already taken by some other application?
92
+ # @param port [Integer] the port number
93
+ # @return [Boolean] true if the port is taken, false otherwise
94
+ def port_taken?(port)
95
+ # open the port and close it immediately, if that succeeds
96
+ # some other application is already using it
97
+ TCPSocket.new("localhost", port).close
98
+ true
99
+ rescue Errno::ECONNREFUSED
100
+ false
101
+ end
102
+
103
+ # find a free port starting from the default port number
104
+ # @return [Integer] the free port number
105
+ def find_port
106
+ DEFAULT_HTTP_PORT.step.find { |p| !port_taken?(p) }
107
+ end
108
+ end
109
+ end