yast-rake 0.2.36 → 0.2.41
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/data/index.html +27 -0
- data/data/targets.yml +17 -2
- data/lib/tasks/actions.rake +44 -0
- data/lib/tasks/container_runner.rb +80 -0
- data/lib/tasks/github_actions/github_actions.rb +33 -0
- data/lib/tasks/github_actions/github_actions/colorizer.rb +80 -0
- data/lib/tasks/github_actions/github_actions/container.rb +162 -0
- data/lib/tasks/github_actions/github_actions/job.rb +50 -0
- data/lib/tasks/github_actions/github_actions/job_runner.rb +112 -0
- data/lib/tasks/github_actions/github_actions/step.rb +60 -0
- data/lib/tasks/github_actions/github_actions/workflow.rb +53 -0
- data/lib/tasks/github_actions/tasks.rb +24 -0
- data/lib/tasks/github_actions/tasks/details.rb +50 -0
- data/lib/tasks/github_actions/tasks/list.rb +37 -0
- data/lib/tasks/github_actions/tasks/run.rb +82 -0
- data/lib/tasks/github_actions/tasks/run_all.rb +111 -0
- data/lib/tasks/pot.rake +38 -15
- data/lib/tasks/run.rake +11 -0
- data/lib/tasks/server.rake +34 -0
- data/lib/yast/index_servlet.rb +36 -0
- data/lib/yast/servers_servlet.rb +47 -0
- data/lib/yast/tarball_server.rb +109 -0
- data/lib/yast/tarball_servlet.rb +55 -0
- metadata +24 -3
@@ -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
|
-
|
37
|
-
warn
|
38
|
-
|
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
|
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
|
-
|
91
|
+
report_pot_errors(interpolations, interpolation_message)
|
92
|
+
report_pot_errors(angle_brackets, angle_brackets_message)
|
67
93
|
|
68
|
-
|
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
|