yast-rake 0.2.39 → 0.2.40

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 971c835f94b481a390e75f0e7854926c3da4c8fba8aa31acc9a1ae1014aad44d
4
- data.tar.gz: 0343fe31d6fcde4d92824f8a0bba57e05108d0dac9e0b6d273aff150d9f93848
3
+ metadata.gz: 2642c0e7364635725ef46461b0d6c816fd1ebca543b87a813292cb8b6092a392
4
+ data.tar.gz: de07ea039866173b29bf17d3e505ab9d3635ff4a7b50e65c4c9ee4f8da4fdec4
5
5
  SHA512:
6
- metadata.gz: 6841283d6e2fa41e7307d688512a68ecc5dba4333b1394fa9f78bc18912f3f9514385e5dbe1ed8b46c0a7acec28d9f06556b289d587ede40a5382f981f6f5ac1
7
- data.tar.gz: ed3c444e2d3ca1f2f008889f8b1bbd6c5be8894a4526fb0e07d6aca80dadc870bd82a9a7fb3fd38f01661218104e98db1ffa18b9bfd167b3d2803ff4dc7830e4
6
+ metadata.gz: cd3a1697577fb14c191261d5b953e123c8cf2052ddb58388d5836f6a0477b233903aab0f58663d723a9eb692d9e3319475e4f1db9878264288b39a9e1758eee5
7
+ data.tar.gz: b6153a3bfe3601cef2f3cfad9dfe899e80cbe11eb65563029a84c14a01fe9f8831fc0f8e1f270dd90975badd3abde483db0891f71ca619c5086ee653c9ef5ee1
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.39
1
+ 0.2.40
@@ -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,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
+ 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
+ image = find_image
32
+ container = GithubActions::Container.new(image)
33
+ container.pull
34
+ container.start
35
+ container.copy_current_dir
36
+
37
+ cmd = client ? "rake run[#{client}]" : "rake run"
38
+ container.run(cmd)
39
+
40
+ container.stop
41
+ end
42
+
43
+ private
44
+
45
+ # find the Docker image to use in the container
46
+ # @return [String] the image name
47
+ def find_image
48
+ # explicitly requested image
49
+ image = ENV["DOCKER_IMAGE"]
50
+ return image if image && !image.empty?
51
+
52
+ # scan the Docker images used in the GitHub Actions
53
+ images = workflow_images
54
+ return images.first if images.size == 1
55
+
56
+ if images.empty?
57
+ error("No Docker image was found in the GitHub Actions")
58
+ puts "Use DOCKER_IMAGE=<name> option for specifying the image name"
59
+ abort
60
+ end
61
+
62
+ # multiple images found
63
+ error("Found multiple Docker images in the GitHub Actions:")
64
+ error(images.inspect)
65
+ puts "Use DOCKER_IMAGE=<name> option for specifying the image name"
66
+ abort
67
+ end
68
+
69
+ # extract the Docker images from the GitHub Actions,
70
+ # the duplicates are removed
71
+ # @return [Array<String>] image names
72
+ def workflow_images
73
+ GithubActions::Workflow.read.each_with_object([]) do |workflow, images|
74
+ workflow.jobs.each do |job|
75
+ container = job.container
76
+ images << container if container && !images.include?(container)
77
+ end
78
+ end
79
+ end
80
+ 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,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,162 @@
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, :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
+ def initialize(image)
47
+ @image = image
48
+ end
49
+
50
+ # pull the Docker image, ensure that the latest version is used
51
+ def pull
52
+ stage("Pulling the #{image} image...")
53
+ # if the latest image is already present it does nothing
54
+ system("docker pull #{image.shellescape}")
55
+ end
56
+
57
+ # start the container, runs "docker create" and "docker start"
58
+ def start
59
+ stage("Starting the container...")
60
+
61
+ # define the initial command for the container to start
62
+ if keep_container?
63
+ # running "tail -f /dev/null" does nothing and gets stuck forever,
64
+ # this ensures the container keeps running and we can execute
65
+ # the other commands there via "docker exec"
66
+ run = "tail"
67
+ args = "-f /dev/null"
68
+ else
69
+ # the "sleep" command ensures the container shuts down automatically after
70
+ # the timeout (to abort frozen jobs or avoid hanging containers after a crash)
71
+ run = "sleep"
72
+ args = TIMEOUT
73
+ end
74
+
75
+ cmd = "docker create #{env_options(ENV_VARIABLES)} --rm --entrypoint " \
76
+ "#{run} #{image.shellescape} #{args}"
77
+
78
+ # contains the container ID
79
+ @container = `#{cmd}`.chomp
80
+ system("docker start #{container.shellescape} > /dev/null")
81
+ end
82
+
83
+ # stop and remove the container from the system, runs "docker rm"
84
+ def stop
85
+ if keep_container?
86
+ print_container_usage
87
+ else
88
+ stage("Stopping the container...")
89
+ system("docker rm --force #{container.shellescape} > /dev/null")
90
+ end
91
+ end
92
+
93
+ # run a command in the container, runs "docker exec"
94
+ # the command is executed in a shell, so shell metacharacters like "&&"
95
+ # can be used to join several commands
96
+ # @param cmd [String] the command to run, it is passed to a shell to it might
97
+ # contain multiple commands or shell meta characters
98
+ # @param env [Hash] optional environment variables (with mapping "name" => "value")
99
+ # @return [Boolean] `true` if the command succeeded (exit status 0),
100
+ # `false` otherwise
101
+ def run(cmd, env = {})
102
+ stage("Running command: #{cmd}")
103
+ system("docker exec -it #{env_options(env)} #{container.shellescape} " \
104
+ "sh -c #{cmd.shellescape}")
105
+ $CHILD_STATUS.success?
106
+ end
107
+
108
+ # get the current working directory in the container
109
+ # @return [String] the path
110
+ def cwd
111
+ `docker exec #{container.shellescape} pwd`.chomp
112
+ end
113
+
114
+ # copy the files from host into the container
115
+ # @param from [String] the source path, if it is a directory all content
116
+ # is copied (including subdirectories)
117
+ # @param to [String] the target location in the container
118
+ def copy_files(from, to)
119
+ stage("Copying #{from} to #{to} in the container...")
120
+
121
+ if File.directory?(from)
122
+ # Dir.children is similar to Dir.entries but it omits the "." and ".." values
123
+ Dir.children(from).each do |f|
124
+ system("docker cp #{f.shellescape} #{container.shellescape}:#{to.shellescape}")
125
+ end
126
+ else
127
+ system("docker cp #{from.shellescape} #{container.shellescape}:#{to.shellescape}")
128
+ end
129
+ end
130
+
131
+ # copy the current directory to the current directory in the container
132
+ def copy_current_dir
133
+ copy_files(Dir.pwd, cwd)
134
+ end
135
+
136
+ private
137
+
138
+ # should we keep the container at the end or remove it?
139
+ def keep_container?
140
+ ENV["KEEP_CONTAINER"] == "1" || ENV["KEEP_CONTAINER"] == "true"
141
+ end
142
+
143
+ # when we keep the container running print some hints how to use it
144
+ def print_container_usage
145
+ warning("The Docker container is still running!")
146
+ puts "Use this command to connect to it:"
147
+ # docker accepts shortened IDs, make the commands shorter
148
+ info(" docker exec -it #{container[0..16]} bash")
149
+ puts "To stop and remove the container run:"
150
+ info(" docker rm -f #{container[0..16]}")
151
+ end
152
+
153
+ # build the docker environment command line options
154
+ # @param mapping [Hash] environment variables
155
+ # @return [String] the built Docker options
156
+ def env_options(mapping)
157
+ mapping.map do |name, value|
158
+ "-e #{name.shellescape}=#{value.shellescape}"
159
+ end.join(" ")
160
+ end
161
+ end
162
+ 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,112 @@
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
+ # prefer the custom image if requested
62
+ @container = Container.new(image || job.container)
63
+ container.pull
64
+ container.start
65
+ end
66
+
67
+ # run a job step
68
+ # @param step [GithubActions::Step] the step to run
69
+ # @return [Boolean] `true` if the step succeeded, `false` otherwise
70
+ def run_step(step)
71
+ info("Step \"#{step.name}\"")
72
+
73
+ # run "uses" step if present
74
+ run_uses_step(step.uses) if step.uses
75
+
76
+ # run "run" step if present
77
+ return true unless step.run
78
+
79
+ container.run(step.run)
80
+ end
81
+
82
+ # print the job result
83
+ # @param success [Boolean] status of the job
84
+ def print_result(success)
85
+ if success
86
+ success("Job result: SUCCESS")
87
+ else
88
+ error("Job result: FAILURE!")
89
+ end
90
+ end
91
+
92
+ # workarounds for some special Javascript actions which are otherwise
93
+ # not supported in general
94
+ # @param uses [String] name of the "uses" action
95
+ def run_uses_step(uses)
96
+ case uses
97
+ when CHECKOUT_ACTION
98
+ # emulate the Git checkout action, just copy the current checkout
99
+ # into the current directory in the running container
100
+ container.copy_current_dir
101
+ when COVERALLS_ACTION
102
+ # skip the coveralls action, do not send the code coverage report
103
+ # when running locally
104
+ info("Skipping the Coveralls step")
105
+ else
106
+ # this should actually never happen, we already checked for
107
+ # the unsupported steps before starting the job
108
+ raise "Unsupported action \"#{uses}\""
109
+ end
110
+ end
111
+ end
112
+ 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,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"
@@ -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
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
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.40
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-03-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.2
90
105
  signing_key:
91
106
  specification_version: 4
92
107
  summary: Rake tasks providing basic work-flow for Yast development