yast-rake 0.2.39 → 0.2.43

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 971c835f94b481a390e75f0e7854926c3da4c8fba8aa31acc9a1ae1014aad44d
4
- data.tar.gz: 0343fe31d6fcde4d92824f8a0bba57e05108d0dac9e0b6d273aff150d9f93848
3
+ metadata.gz: 183bdc451acadf652d5ef8d5749b166770f3664b2f73139cadab86f59b35f9e7
4
+ data.tar.gz: 86a255dfe87bb4b38128568e04752e4a111c2840bbd880499a12f6f0447e3e71
5
5
  SHA512:
6
- metadata.gz: 6841283d6e2fa41e7307d688512a68ecc5dba4333b1394fa9f78bc18912f3f9514385e5dbe1ed8b46c0a7acec28d9f06556b289d587ede40a5382f981f6f5ac1
7
- data.tar.gz: ed3c444e2d3ca1f2f008889f8b1bbd6c5be8894a4526fb0e07d6aca80dadc870bd82a9a7fb3fd38f01661218104e98db1ffa18b9bfd167b3d2803ff4dc7830e4
6
+ metadata.gz: 778c1d1c7e5258ce439e0e6d16ec01b0eb20cbb1ac4a7260f497a1256b189865d5d594ba4f1dbf18b9dc6accbaf2430ccb4f3510b19c7a65ae0b56ff5a06c8c0
7
+ data.tar.gz: 848c641d6d94d8b40a610d575b4fc0f63df0942b5fe0987663511d11761278ddb560e8e86d1a20a19b3b5529be2b012c9cc4f7d593934613e6832366e1eaaa42
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.39
1
+ 0.2.43
data/data/targets.yml CHANGED
@@ -85,11 +85,21 @@
85
85
  obs_project: "Devel:YaST:SLE-15-SP3"
86
86
  obs_sr_project: "SUSE:SLE-15-SP3:Update"
87
87
  obs_target: "SUSE_SLE-15-SP3_Update"
88
+ :sle15sp4:
89
+ obs_api: "https://api.suse.de/"
90
+ obs_project: "Devel:YaST:SLE-15-SP4"
91
+ obs_sr_project: "SUSE:SLE-15-SP4:Update"
92
+ obs_target: "SUSE_SLE-15-SP4_Update"
93
+ :sle15sp5:
94
+ obs_api: "https://api.suse.de/"
95
+ obs_project: "Devel:YaST:SLE-15-SP5"
96
+ obs_sr_project: "SUSE:SLE-15-SP5:Update"
97
+ obs_target: "SUSE_SLE-15-SP5_Update"
88
98
  :sle_latest:
89
99
  obs_api: "https://api.suse.de/"
90
100
  obs_project: "Devel:YaST:Head"
91
- obs_sr_project: "SUSE:SLE-15-SP3:GA"
92
- obs_target: "SUSE_SLE-15-SP3_GA"
101
+ obs_sr_project: "SUSE:SLE-15-SP4:GA"
102
+ obs_target: "SUSE_SLE-15-SP4_GA"
93
103
  :factory:
94
104
  obs_project: "YaST:Head"
95
105
  obs_sr_project: "openSUSE:Factory"
@@ -0,0 +1,44 @@
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/tasks"
22
+
23
+ # tasks related to GitHub Actions (https://docs.github.com/en/actions)
24
+ namespace :actions do
25
+ desc "List the GitHub Action jobs"
26
+ task :list do
27
+ GithubActions::Tasks::List.new.run
28
+ end
29
+
30
+ desc "Display GitHub Action job details"
31
+ task :details do
32
+ GithubActions::Tasks::Details.new.run
33
+ end
34
+
35
+ desc "Run locally the specified GitHub Action job (all jobs if \"job\" is empty)"
36
+ task :run, [:job] do |_task, args|
37
+ name = args[:job]
38
+ if name.nil? || name.empty?
39
+ GithubActions::Tasks::RunAll.new.run
40
+ else
41
+ GithubActions::Tasks::Run.new(name).run
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,95 @@
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/github_actions"
22
+
23
+ # Run a client in Docker container
24
+ class ContainerRunner
25
+ include GithubActions::Colorizer
26
+
27
+ # start a container, copy the sources there and run "rake run"
28
+ # @param client [String,nil] the client name, nil or empty string = find
29
+ # the client automatically
30
+ def run(client)
31
+ container = find_container
32
+ container.pull
33
+ container.start
34
+ container.copy_current_dir
35
+
36
+ cmd = client ? "rake run[#{client}]" : "rake run"
37
+ container.run(cmd)
38
+
39
+ container.stop
40
+ end
41
+
42
+ private
43
+
44
+ # find the Docker image to use in the container
45
+ # @return [String] the image name
46
+ def find_container
47
+ # explicitly requested image
48
+ image = ENV["DOCKER_IMAGE"]
49
+ return GithubActions::Container.new(image) if image && !image.empty?
50
+
51
+ # scan the Docker images used in the GitHub Actions
52
+ containers = workflow_containers
53
+ return containers.first if containers.size == 1
54
+
55
+ if containers.empty?
56
+ error("No Docker image was found in the GitHub Actions")
57
+ puts "Use DOCKER_IMAGE=<name> option for specifying the image name"
58
+ abort
59
+ end
60
+
61
+ # multiple images found
62
+ error("Found multiple Docker images in the GitHub Actions:")
63
+ error(containers.map { |c| [c.image, c.options] })
64
+ puts "Use DOCKER_IMAGE=<name> option for specifying the image name"
65
+ puts "and DOCKER_OPTIONS=<options> option for specifying the extra Docker"
66
+ puts "command line parameters."
67
+ abort
68
+ end
69
+
70
+ # extract the Docker images from the GitHub Actions,
71
+ # the duplicates are removed
72
+ # @return [Array<GithubActions::Container>] image names
73
+ def workflow_containers
74
+ ret = GithubActions::Workflow.read.each_with_object([]) do |workflow, containers|
75
+ workflow.jobs.each do |job|
76
+ container_data = job.container
77
+
78
+ if container_data.is_a?(String)
79
+ containers << GithubActions::Container.new(container_data)
80
+ elsif container_data.is_a?(Hash)
81
+ # to_s converts missing options (nil) to empty options ("")
82
+ # to treat these as equal in comparison
83
+ containers << GithubActions::Container.new(
84
+ container_data["image"],
85
+ container_data["options"].to_s
86
+ )
87
+ else
88
+ abort "Unsupported container definition: #{container_data.inspect}"
89
+ end
90
+ end
91
+ end
92
+
93
+ ret.uniq { |c| [c.image, c.options] }
94
+ end
95
+ end
@@ -0,0 +1,80 @@
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
+ module GithubActions
22
+ # helper methods for colorizing output, if the "rainbow" colorizing gem
23
+ # is not installed then it prints the original messages without any colorizing
24
+ module Colorizer
25
+ # print an error
26
+ # @param msg [Object] the text to print
27
+ def error(msg)
28
+ print_colored(msg, :red)
29
+ end
30
+
31
+ # print a success message
32
+ # @param msg [Object] the text to print
33
+ def success(msg)
34
+ print_colored(msg, :green)
35
+ end
36
+
37
+ # print a warning
38
+ # @param msg [Object] the text to print
39
+ def warning(msg)
40
+ print_colored(msg, :magenta)
41
+ end
42
+
43
+ # print a message
44
+ # @param msg [Object] the text to print
45
+ def info(msg)
46
+ print_colored(msg, :cyan)
47
+ end
48
+
49
+ # print the progress status
50
+ # @param msg [Object] the text to print
51
+ def stage(msg)
52
+ print_colored(msg, :yellow)
53
+ end
54
+
55
+ private
56
+
57
+ # helper for printing the text
58
+ # @param msg [Object] the text to print
59
+ # @param color [Symbol] the text color
60
+ def print_colored(msg, color)
61
+ puts rainbow? ? Rainbow(msg).color(color) : msg
62
+ end
63
+
64
+ # load the Rainbow colorizing library if present
65
+ # see https://github.com/sickill/rainbow
66
+ # @return Boolean `true` if Rainbow was successfully loaded, `false` otherwise
67
+ def rainbow?
68
+ return @rainbow_present unless @rainbow_present.nil?
69
+
70
+ begin
71
+ require "rainbow"
72
+ @rainbow_present = true
73
+ rescue LoadError
74
+ @rainbow_present = false
75
+ end
76
+
77
+ @rainbow_present
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,164 @@
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 "English"
22
+ require "shellwords"
23
+
24
+ module GithubActions
25
+ # Manage a Docker container
26
+ class Container
27
+ include Colorizer
28
+
29
+ attr_reader :image, :options, :container
30
+
31
+ # the default timeout in seconds, maximum time for the running container,
32
+ # after the time runs out the container is automatically stopped and removed
33
+ # unless `KEEP_CONTAINER` option is set
34
+ TIMEOUT = 3600
35
+
36
+ # the default environment variables in the container
37
+ ENV_VARIABLES = {
38
+ # this is a CI environment
39
+ "CI" => "true",
40
+ # skip the modified check in the "rake osc:build" task
41
+ "CHECK_MODIFIED" => "0"
42
+ }.freeze
43
+
44
+ # constructor
45
+ # @param image [String] name of the Docker image to use
46
+ # @param options [String, nil] extra docker options
47
+ def initialize(image, options = nil)
48
+ @image = image
49
+ @options = options
50
+ end
51
+
52
+ # pull the Docker image, ensure that the latest version is used
53
+ def pull
54
+ stage("Pulling the #{image} image...")
55
+ # if the latest image is already present it does nothing
56
+ system("docker pull #{image.shellescape}")
57
+ end
58
+
59
+ # start the container, runs "docker create" and "docker start"
60
+ def start
61
+ stage("Starting the container...")
62
+
63
+ # define the initial command for the container to start
64
+ if keep_container?
65
+ # running "tail -f /dev/null" does nothing and gets stuck forever,
66
+ # this ensures the container keeps running and we can execute
67
+ # the other commands there via "docker exec"
68
+ run = "tail"
69
+ args = "-f /dev/null"
70
+ else
71
+ # the "sleep" command ensures the container shuts down automatically after
72
+ # the timeout (to abort frozen jobs or avoid hanging containers after a crash)
73
+ run = "sleep"
74
+ args = TIMEOUT
75
+ end
76
+
77
+ cmd = "docker create #{env_options(ENV_VARIABLES)} --rm --entrypoint " \
78
+ "#{run} #{options} #{ENV["DOCKER_OPTIONS"]} #{image.shellescape} #{args}"
79
+
80
+ # contains the container ID
81
+ @container = `#{cmd}`.chomp
82
+ system("docker start #{container.shellescape} > /dev/null")
83
+ end
84
+
85
+ # stop and remove the container from the system, runs "docker rm"
86
+ def stop
87
+ if keep_container?
88
+ print_container_usage
89
+ else
90
+ stage("Stopping the container...")
91
+ system("docker rm --force #{container.shellescape} > /dev/null")
92
+ end
93
+ end
94
+
95
+ # run a command in the container, runs "docker exec"
96
+ # the command is executed in a shell, so shell metacharacters like "&&"
97
+ # can be used to join several commands
98
+ # @param cmd [String] the command to run, it is passed to a shell to it might
99
+ # contain multiple commands or shell meta characters
100
+ # @param env [Hash] optional environment variables (with mapping "name" => "value")
101
+ # @return [Boolean] `true` if the command succeeded (exit status 0),
102
+ # `false` otherwise
103
+ def run(cmd, env = {})
104
+ stage("Running command: #{cmd}")
105
+ system("docker exec -it #{env_options(env)} #{container.shellescape} " \
106
+ "sh -c #{cmd.shellescape}")
107
+ $CHILD_STATUS.success?
108
+ end
109
+
110
+ # get the current working directory in the container
111
+ # @return [String] the path
112
+ def cwd
113
+ `docker exec #{container.shellescape} pwd`.chomp
114
+ end
115
+
116
+ # copy the files from host into the container
117
+ # @param from [String] the source path, if it is a directory all content
118
+ # is copied (including subdirectories)
119
+ # @param to [String] the target location in the container
120
+ def copy_files(from, to)
121
+ stage("Copying #{from} to #{to} in the container...")
122
+
123
+ if File.directory?(from)
124
+ # Dir.children is similar to Dir.entries but it omits the "." and ".." values
125
+ Dir.children(from).each do |f|
126
+ system("docker cp #{f.shellescape} #{container.shellescape}:#{to.shellescape}")
127
+ end
128
+ else
129
+ system("docker cp #{from.shellescape} #{container.shellescape}:#{to.shellescape}")
130
+ end
131
+ end
132
+
133
+ # copy the current directory to the current directory in the container
134
+ def copy_current_dir
135
+ copy_files(Dir.pwd, cwd)
136
+ end
137
+
138
+ private
139
+
140
+ # should we keep the container at the end or remove it?
141
+ def keep_container?
142
+ ENV["KEEP_CONTAINER"] == "1" || ENV["KEEP_CONTAINER"] == "true"
143
+ end
144
+
145
+ # when we keep the container running print some hints how to use it
146
+ def print_container_usage
147
+ warning("The Docker container is still running!")
148
+ puts "Use this command to connect to it:"
149
+ # docker accepts shortened IDs, make the commands shorter
150
+ info(" docker exec -it #{container[0..16]} bash")
151
+ puts "To stop and remove the container run:"
152
+ info(" docker rm -f #{container[0..16]}")
153
+ end
154
+
155
+ # build the docker environment command line options
156
+ # @param mapping [Hash] environment variables
157
+ # @return [String] the built Docker options
158
+ def env_options(mapping)
159
+ mapping.map do |name, value|
160
+ "-e #{name.shellescape}=#{value.shellescape}"
161
+ end.join(" ")
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,50 @@
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
+ module GithubActions
22
+ # Github Actions job
23
+ # @see https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions
24
+ class Job
25
+ attr_reader :name, :steps, :runs_on, :container, :workflow
26
+
27
+ # @param name [String] name of the job
28
+ # @param data [Hash] data from the workflow YAML file
29
+ # @param workflow [GithubActions::Workflow] the parent workflow
30
+ def initialize(name, data, workflow)
31
+ @name = name
32
+ @runs_on = data["runs-on"]
33
+ @container = data["container"]
34
+ @workflow = workflow
35
+
36
+ @steps = data["steps"].map do |step|
37
+ Step.new(self, step)
38
+ end
39
+ end
40
+
41
+ # check if the defined steps can be used locally
42
+ # @return [Array<String>] the list of unsupported steps, returns empty
43
+ # list if all actions are supported
44
+ def unsupported_steps
45
+ steps.each_with_object([]) do |step, array|
46
+ array << step.name unless step.supported?
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,129 @@
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
+ module GithubActions
22
+ # Runs GitHub Actions job in a container locally
23
+ class JobRunner
24
+ include Colorizer
25
+
26
+ attr_reader :job, :image
27
+
28
+ # constructor
29
+ # @param job [GithubActions::Job] the job to run
30
+ # @param image [String,nil] override the Docker image to use,
31
+ # if `nil` it by default uses the image specified in the job
32
+ def initialize(job, image = nil)
33
+ @job = job
34
+ @image = image
35
+ end
36
+
37
+ # run the job in a container
38
+ # @return [Boolean] `true` if all steps were successfully executed,
39
+ # `false` otherwise
40
+ def run
41
+ stage("Running \"#{job.name}\" job from file #{job.workflow.file}")
42
+ start_container
43
+
44
+ result = true
45
+ job.steps.each do |step|
46
+ result &= run_step(step)
47
+ end
48
+
49
+ print_result(result)
50
+ container.stop
51
+ result
52
+ end
53
+
54
+ private
55
+
56
+ # GithubActions::Container
57
+ attr_reader :container
58
+
59
+ # pull the Docker image and start the container
60
+ def start_container
61
+ @container = find_container
62
+ container.pull
63
+ container.start
64
+ end
65
+
66
+ # Get the container configuration
67
+ # @return [Container] container which should run the job
68
+ def find_container
69
+ # prefer the custom image if requested
70
+ image_name = if image
71
+ image
72
+ elsif job.container.is_a?(String)
73
+ job.container
74
+ elsif job.container.is_a?(Hash)
75
+ options = job.container["options"]
76
+ job.container["image"]
77
+ else
78
+ abort "Unsupported container definition: #{job.container.inspect}"
79
+ end
80
+
81
+ Container.new(image_name, options.to_s)
82
+ end
83
+
84
+ # run a job step
85
+ # @param step [GithubActions::Step] the step to run
86
+ # @return [Boolean] `true` if the step succeeded, `false` otherwise
87
+ def run_step(step)
88
+ info("Step \"#{step.name}\"")
89
+
90
+ # run "uses" step if present
91
+ run_uses_step(step.uses) if step.uses
92
+
93
+ # run "run" step if present
94
+ return true unless step.run
95
+
96
+ container.run(step.run)
97
+ end
98
+
99
+ # print the job result
100
+ # @param success [Boolean] status of the job
101
+ def print_result(success)
102
+ if success
103
+ success("Job result: SUCCESS")
104
+ else
105
+ error("Job result: FAILURE!")
106
+ end
107
+ end
108
+
109
+ # workarounds for some special Javascript actions which are otherwise
110
+ # not supported in general
111
+ # @param uses [String] name of the "uses" action
112
+ def run_uses_step(uses)
113
+ case uses
114
+ when CHECKOUT_ACTION
115
+ # emulate the Git checkout action, just copy the current checkout
116
+ # into the current directory in the running container
117
+ container.copy_current_dir
118
+ when COVERALLS_ACTION
119
+ # skip the coveralls action, do not send the code coverage report
120
+ # when running locally
121
+ info("Skipping the Coveralls step")
122
+ else
123
+ # this should actually never happen, we already checked for
124
+ # the unsupported steps before starting the job
125
+ raise "Unsupported action \"#{uses}\""
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,60 @@
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
+ module GithubActions
22
+ # Github Actions step
23
+ # @see https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions
24
+ class Step
25
+ attr_reader :job, :name, :uses, :run, :env
26
+
27
+ # constructor
28
+ # @param job [GithubActions::Job] the parent job
29
+ # @param step [Hash] the step definition from the YAML file
30
+ def initialize(job, step)
31
+ @job = job
32
+ @name = step["name"]
33
+ @uses = step["uses"]
34
+ @run = step["run"]
35
+ @env = step["env"]
36
+ end
37
+
38
+ # we can run the step if it is just a plain command (not a Javascript or
39
+ # Docker container action) and the environment variables do not contain any
40
+ # expansions (usually used for Github secrets)
41
+ # @return [Boolean] `true` if the step is supported, `false` otherwise
42
+ def supported?
43
+ known_uses? && !expansion?
44
+ end
45
+
46
+ private
47
+
48
+ # Javascript or Docker actions are not supported
49
+ # @return [Boolean] `true` if there is a workaround defined for the step
50
+ def known_uses?
51
+ uses.nil? || uses.match?(CHECKOUT_ACTION) || uses.match?(COVERALLS_ACTION)
52
+ end
53
+
54
+ # we cannot expand the Github secrets
55
+ # @return [Boolean] `true` if an expansion is found, `false` otherwise
56
+ def expansion?
57
+ env&.any? { |_k, v| v.to_s.include?("${{") }
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,53 @@
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 "yaml"
22
+
23
+ module GithubActions
24
+ # Github Actions workflow
25
+ # @see https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions
26
+ class Workflow
27
+ attr_reader :file, :name, :on, :jobs
28
+
29
+ # load all defined workflows from all YAML files
30
+ # @return [Array<GithubActions::Workflow>]
31
+ def self.read
32
+ Dir[".github/workflows/*.{yml,yaml}"].map do |file|
33
+ new(file)
34
+ end
35
+ end
36
+
37
+ # load the workflow from an YAML file
38
+ # @param file [String] path to the YAML file
39
+ def initialize(file)
40
+ @file = file
41
+ yml = YAML.load_file(file)
42
+ @name = yml["name"]
43
+ # "on" is autoconverted to Boolean "true" for this line
44
+ # on: [push, pull_request]
45
+ # see https://medium.com/@lefloh/lessons-learned-about-yaml-and-norway-13ba26df680
46
+ @on = yml[true]
47
+
48
+ @jobs = yml["jobs"].map do |name, job|
49
+ Job.new(name, job, self)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,33 @@
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/colorizer"
22
+ require_relative "github_actions/container"
23
+ require_relative "github_actions/job"
24
+ require_relative "github_actions/job_runner"
25
+ require_relative "github_actions/step"
26
+ require_relative "github_actions/workflow"
27
+
28
+ # classes for running the Github Actions locally
29
+ module GithubActions
30
+ # regexps for some special actions which need to be handled differently
31
+ CHECKOUT_ACTION = /\Aactions\/checkout(|@.*)\z/.freeze
32
+ COVERALLS_ACTION = /\Acoverallsapp\/github-action(|@.*)\z/.freeze
33
+ end
@@ -0,0 +1,50 @@
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
+ # print the defined Github Actions jobs with details
26
+ class Details
27
+ include Colorizer
28
+
29
+ def run
30
+ Workflow.read.each_with_index do |workflow, index|
31
+ workflow.jobs.each do |job|
32
+ # empty line separator if multiple jobs are found
33
+ puts if index > 0
34
+
35
+ # print the job details
36
+ success(job.name)
37
+ puts " run: \"rake actions:run[#{job.name}]\""
38
+ puts " container: #{job.container}"
39
+ puts " steps:"
40
+ job.steps.each do |step|
41
+ puts " #{step.name}"
42
+ puts " #{step.run}" if step.run
43
+ puts " #{step.uses}" if step.uses
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,37 @@
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
+ # print the defined Github Actions jobs
26
+ class List
27
+ def run
28
+ Workflow.read.each do |workflow|
29
+ workflow.jobs.each do |job|
30
+ # print rake commands so users can easily copy&paste into terminal
31
+ puts "rake actions:run[#{job.name}]"
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,82 @@
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 the requested Github Actions job locally
26
+ class Run
27
+ include Colorizer
28
+
29
+ # the requested job name
30
+ attr_reader :name
31
+
32
+ # constructor
33
+ # @param name [String] name of the job to run
34
+ def initialize(name)
35
+ @name = name
36
+ end
37
+
38
+ # run the GitHub Action locally
39
+ def run
40
+ runner = GithubActions::JobRunner.new(find_job, ENV["DOCKER_IMAGE"])
41
+ abort unless runner.run
42
+ end
43
+
44
+ private
45
+
46
+ # read the job definition from YAML file
47
+ def find_job
48
+ job = nil
49
+ Workflow.read.each do |workflow|
50
+ # Note: in theory the same job name might be used in different files,
51
+ # but in YaST we use single YAML files and we can avoid duplicates,
52
+ # simply use the first found and avoid unnecessary complexity
53
+ job = workflow.jobs.find { |j| j.name == name }
54
+ end
55
+
56
+ check_job(job)
57
+
58
+ job
59
+ end
60
+
61
+ # check if the job is valid and can be run locally,
62
+ # it aborts when the job cannot be used
63
+ def check_job(job)
64
+ if job.nil?
65
+ error("ERROR: Job \"#{name}\" not found")
66
+ abort
67
+ end
68
+
69
+ unsupported = job.unsupported_steps
70
+ if !unsupported.empty?
71
+ error("ERROR: These steps are not supported: #{unsupported.inspect}")
72
+ abort
73
+ end
74
+
75
+ return if job.container && !job.container.empty?
76
+
77
+ error("ERROR: Docker image name is missing in the job definition")
78
+ abort
79
+ end
80
+ end
81
+ end
82
+ end
@@ -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
@@ -0,0 +1,24 @@
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 "tasks/details"
22
+ require_relative "tasks/list"
23
+ require_relative "tasks/run"
24
+ require_relative "tasks/run_all"
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
@@ -18,12 +18,16 @@
18
18
  # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
19
  #++
20
20
 
21
- require_relative "../yast/tarball_server"
22
-
23
21
  # Rake task for running a source code web server,
24
22
  # designed for the `yupdate` script.
25
23
  desc "Start an HTTP server providing dynamically generated source code tarball"
26
24
  task :server, [:port] do |_task, args|
25
+ begin
26
+ require_relative "../yast/tarball_server"
27
+ rescue LoadError
28
+ abort "Webrick server is not installed, please install the webrick Ruby gem"
29
+ end
30
+
27
31
  server = Yast::TarballServer.new(args[:port])
28
32
 
29
33
  puts "Starting tarball webserver:"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yast-rake
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.39
4
+ version: 0.2.43
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josef Reidinger
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-23 00:00:00.000000000 Z
11
+ date: 2021-11-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: packaging_rake_tasks
@@ -51,6 +51,20 @@ files:
51
51
  - VERSION
52
52
  - data/index.html
53
53
  - data/targets.yml
54
+ - lib/tasks/actions.rake
55
+ - lib/tasks/container_runner.rb
56
+ - lib/tasks/github_actions/github_actions.rb
57
+ - lib/tasks/github_actions/github_actions/colorizer.rb
58
+ - lib/tasks/github_actions/github_actions/container.rb
59
+ - lib/tasks/github_actions/github_actions/job.rb
60
+ - lib/tasks/github_actions/github_actions/job_runner.rb
61
+ - lib/tasks/github_actions/github_actions/step.rb
62
+ - lib/tasks/github_actions/github_actions/workflow.rb
63
+ - lib/tasks/github_actions/tasks.rb
64
+ - lib/tasks/github_actions/tasks/details.rb
65
+ - lib/tasks/github_actions/tasks/list.rb
66
+ - lib/tasks/github_actions/tasks/run.rb
67
+ - lib/tasks/github_actions/tasks/run_all.rb
54
68
  - lib/tasks/install.rake
55
69
  - lib/tasks/pot.rake
56
70
  - lib/tasks/rubocop.rake
@@ -86,7 +100,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
100
  - !ruby/object:Gem::Version
87
101
  version: '0'
88
102
  requirements: []
89
- rubygems_version: 3.1.2
103
+ rubyforge_project:
104
+ rubygems_version: 2.7.6.3
90
105
  signing_key:
91
106
  specification_version: 4
92
107
  summary: Rake tasks providing basic work-flow for Yast development