gembrew 0.1.1 → 0.2.0
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 +4 -4
- data/README.md +77 -30
- data/lib/gembrew/adder.rb +9 -5
- data/lib/gembrew/commands/build.rb +1 -1
- data/lib/gembrew/commands/shell.rb +1 -1
- data/lib/gembrew/config.rb +97 -17
- data/lib/gembrew/docker_check.rb +7 -4
- data/lib/gembrew/docker_runner.rb +10 -5
- data/lib/gembrew/generator.rb +22 -6
- data/lib/gembrew/github_archive_store.rb +51 -0
- data/lib/gembrew/initializer.rb +10 -0
- data/lib/gembrew/reporter.rb +1 -0
- data/lib/gembrew/resolver.rb +62 -8
- data/lib/gembrew/templates/README.md.erb +13 -0
- data/lib/gembrew/templates/formula.rb.erb +35 -7
- data/lib/gembrew/templates/gembrew.yml.erb +21 -6
- data/lib/gembrew/templates/test.yml +105 -0
- data/lib/gembrew/version.rb +1 -1
- data/lib/gembrew.rb +1 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1b5f610bdf10a353ade54ab13743f154b56d0af7e5aceac0d6b3364135520f97
|
|
4
|
+
data.tar.gz: dd0daaec17e0f724b80f477b0f2c0ab68e5e02ebfef7248ca5cb8a4cd1164390
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6a09ac710d80edfb925b6e8935df241c05b3cec090f9ae21c24fb19ab9b0d7fcb04ef867c8b6959303e4d276d00f82acfe65b1d31acf40d3eb81c030a6567ca6
|
|
7
|
+
data.tar.gz: a458d322068a01abbb692df5919efb9be8bec07edcf1e518d569bfa019befde0dd3d03e7916b7656f831de5a6391b7b402ab47b47ffc1a749bf610fc2aa92fdb
|
data/README.md
CHANGED
|
@@ -20,38 +20,51 @@ gembrew build
|
|
|
20
20
|
gembrew check
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
`init` creates a tap repository containing `README.md`, `gembrew/`,
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
`init` creates a tap repository containing `README.md`, `gembrew/`, `Formula/`,
|
|
24
|
+
and a GitHub Actions workflow that uses Homebrew's `test-bot` on Linux, Apple
|
|
25
|
+
Silicon, and Intel macOS. Pull requests test changed formulae; pushes, scheduled
|
|
26
|
+
runs, and manual runs test every formula. It accepts an empty directory or an
|
|
27
|
+
existing tap containing `Formula/`.
|
|
28
|
+
Supplying a gem name also creates its first configuration. The gem name is
|
|
29
|
+
optional, so `gembrew init` can prepare an empty tap or add Gembrew to an
|
|
30
|
+
existing one. Existing README and workflow files are never overwritten.
|
|
28
31
|
|
|
29
32
|
For example, `gembrew init example` generates:
|
|
30
33
|
|
|
31
34
|
```text
|
|
32
35
|
README.md
|
|
36
|
+
.github/
|
|
37
|
+
workflows/
|
|
38
|
+
test.yml
|
|
33
39
|
gembrew/
|
|
34
|
-
example
|
|
40
|
+
example/
|
|
41
|
+
formula.yml
|
|
42
|
+
test.rb
|
|
35
43
|
Formula/
|
|
36
44
|
```
|
|
37
45
|
|
|
38
|
-
`gembrew/example.yml` contains:
|
|
46
|
+
`gembrew/example/formula.yml` contains the gem metadata and source:
|
|
39
47
|
|
|
40
48
|
```yaml
|
|
41
49
|
gem: example
|
|
50
|
+
version: "" # required
|
|
51
|
+
source:
|
|
52
|
+
type: rubygems
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`gembrew/example/test.rb` contains the generated default test:
|
|
42
56
|
|
|
43
|
-
|
|
44
|
-
|
|
57
|
+
```ruby
|
|
58
|
+
system bin/"example", "--version"
|
|
45
59
|
```
|
|
46
60
|
|
|
47
|
-
Edit
|
|
61
|
+
Edit these files as needed, then generate `Formula/example.rb`:
|
|
48
62
|
|
|
49
63
|
```shell
|
|
50
64
|
gembrew build
|
|
51
65
|
```
|
|
52
66
|
|
|
53
|
-
Each
|
|
54
|
-
with:
|
|
67
|
+
Each directory under `gembrew/` describes one formula. Add more published gems with:
|
|
55
68
|
|
|
56
69
|
```shell
|
|
57
70
|
gembrew add another-gem
|
|
@@ -64,15 +77,15 @@ generate just one:
|
|
|
64
77
|
gembrew build example
|
|
65
78
|
```
|
|
66
79
|
|
|
67
|
-
The required settings
|
|
80
|
+
The required settings in `formula.yml` are `gem`, `version`, and `source`.
|
|
68
81
|
The output defaults to `Formula/NAME.rb`, where `NAME` is the configuration
|
|
69
|
-
|
|
82
|
+
directory name. Relative output paths are resolved from the tap root.
|
|
70
83
|
|
|
71
84
|
```yaml
|
|
72
85
|
gem: example
|
|
73
|
-
|
|
74
|
-
# Optional published gem version. The latest stable version is used by default.
|
|
75
86
|
version: "1.2.3"
|
|
87
|
+
source:
|
|
88
|
+
type: rubygems
|
|
76
89
|
|
|
77
90
|
# Optional gem metadata overrides:
|
|
78
91
|
desc: Example command-line application
|
|
@@ -80,16 +93,47 @@ homepage: https://example.com
|
|
|
80
93
|
license: MIT
|
|
81
94
|
executable: example
|
|
82
95
|
|
|
83
|
-
# Optional
|
|
96
|
+
# Optional additional Homebrew formula dependencies:
|
|
97
|
+
dependencies:
|
|
98
|
+
- bash
|
|
99
|
+
- bash :macos_only
|
|
100
|
+
- libffi :system_on_macos
|
|
101
|
+
|
|
102
|
+
# Optional output override. The default for gembrew/example is shown here.
|
|
84
103
|
output: Formula/example.rb
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Tag a dependency with `:system_on_macos` when macOS provides it and Homebrew
|
|
107
|
+
should install its formula only on other platforms. Tag it with `:macos_only`
|
|
108
|
+
when Homebrew should install it only on macOS.
|
|
85
109
|
|
|
86
|
-
|
|
87
|
-
system bin/"example", "--version"
|
|
110
|
+
You may add these optional Ruby hook files beside `formula.yml`:
|
|
88
111
|
|
|
89
|
-
|
|
90
|
-
|
|
112
|
+
```text
|
|
113
|
+
install_extra.rb Runs after the standard gem installation
|
|
114
|
+
test.rb Defines the formula test
|
|
91
115
|
```
|
|
92
116
|
|
|
117
|
+
Gembrew generates a basic `COMMAND --version` test when `test.rb` is absent.
|
|
118
|
+
`gembrew init GEM` and `gembrew add GEM` create that test file so it can be
|
|
119
|
+
replaced with a meaningful functional test. Gembrew inserts `install_extra.rb`
|
|
120
|
+
at the end of the formula's `install` method, after installing the gem and
|
|
121
|
+
creating its executable wrapper.
|
|
122
|
+
|
|
123
|
+
To build the root gem from a GitHub tag while continuing to fetch its
|
|
124
|
+
dependencies from RubyGems, use:
|
|
125
|
+
|
|
126
|
+
```yaml
|
|
127
|
+
source:
|
|
128
|
+
type: github
|
|
129
|
+
repo: owner/repository
|
|
130
|
+
# tag: v1.2.3
|
|
131
|
+
# gemspec: example.gemspec
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
The tag defaults to `vVERSION`; the gemspec path defaults to
|
|
135
|
+
`GEMNAME.gemspec`.
|
|
136
|
+
|
|
93
137
|
Gembrew resolves the generic Ruby dependency graph and generates a Homebrew
|
|
94
138
|
`resource` for every runtime dependency. Original `.gem` archives are reused
|
|
95
139
|
from RubyGems' local cache when available. Downloaded archives are retained in
|
|
@@ -105,14 +149,16 @@ The repository is mounted as a local tap, so formulae can be addressed by gem
|
|
|
105
149
|
name inside the shell:
|
|
106
150
|
|
|
107
151
|
```shell
|
|
108
|
-
brew style example
|
|
109
|
-
brew audit --new --online example
|
|
110
|
-
brew install --build-from-source example
|
|
111
|
-
brew test example
|
|
152
|
+
brew style gembrew/tap/example
|
|
153
|
+
brew audit --new --online gembrew/tap/example
|
|
154
|
+
brew install --build-from-source gembrew/tap/example
|
|
155
|
+
brew test gembrew/tap/example
|
|
156
|
+
brew linkage --test gembrew/tap/example
|
|
112
157
|
```
|
|
113
158
|
|
|
114
|
-
To
|
|
115
|
-
Homebrew
|
|
159
|
+
To use a stock, current Homebrew container without mounting the local
|
|
160
|
+
repository or changing Homebrew's update, API, or cleanup behavior, open a
|
|
161
|
+
pristine shell:
|
|
116
162
|
|
|
117
163
|
```shell
|
|
118
164
|
gembrew shell --pristine
|
|
@@ -125,9 +171,10 @@ gembrew check
|
|
|
125
171
|
```
|
|
126
172
|
|
|
127
173
|
This rebuilds every configured formula, then runs Homebrew style, online audit,
|
|
128
|
-
source installation,
|
|
129
|
-
Use `gembrew check example` to check only one formula.
|
|
130
|
-
directly; the tap does not need generated container
|
|
174
|
+
source installation, the formula test, and linkage validation in disposable
|
|
175
|
+
Homebrew containers. Use `gembrew check example` to check only one formula.
|
|
176
|
+
Gembrew invokes Docker directly; the tap does not need generated container
|
|
177
|
+
support files.
|
|
131
178
|
|
|
132
179
|
## Contributing / Support
|
|
133
180
|
|
data/lib/gembrew/adder.rb
CHANGED
|
@@ -18,18 +18,22 @@ module Gembrew
|
|
|
18
18
|
raise Error, "Directory is not a Homebrew tap: #{project_path} (Formula/ does not exist)"
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
raise Error, "Gem configuration already exists: #{
|
|
21
|
+
gembrew_directory.mkpath
|
|
22
|
+
raise Error, "Gem configuration already exists: #{config_directory}" if config_directory.exist?
|
|
23
23
|
|
|
24
|
+
config_directory.mkpath
|
|
24
25
|
config_path.write render
|
|
25
|
-
|
|
26
|
+
test_path.write %[system bin/"#{gem_name}", "--version"\n]
|
|
27
|
+
config_directory
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
private
|
|
29
31
|
|
|
30
32
|
def formula_path = project_path/'Formula'
|
|
31
|
-
def
|
|
32
|
-
def
|
|
33
|
+
def gembrew_directory = project_path/'gembrew'
|
|
34
|
+
def config_directory = gembrew_directory/gem_name
|
|
35
|
+
def config_path = config_directory/'formula.yml'
|
|
36
|
+
def test_path = config_directory/'test.rb'
|
|
33
37
|
|
|
34
38
|
def render
|
|
35
39
|
template = Pathname(__dir__)/'templates/gembrew.yml.erb'
|
|
@@ -4,7 +4,7 @@ require 'gembrew/generator'
|
|
|
4
4
|
module Gembrew
|
|
5
5
|
module Commands
|
|
6
6
|
class Build < MisterBin::Command
|
|
7
|
-
help 'Generate Homebrew formulae from gembrew
|
|
7
|
+
help 'Generate Homebrew formulae from gembrew/*/formula.yml'
|
|
8
8
|
|
|
9
9
|
usage 'gembrew build [GEM]'
|
|
10
10
|
usage 'gembrew build (-h|--help)'
|
|
@@ -9,7 +9,7 @@ module Gembrew
|
|
|
9
9
|
usage 'gembrew shell [--pristine]'
|
|
10
10
|
usage 'gembrew shell (-h|--help)'
|
|
11
11
|
|
|
12
|
-
option '-p --pristine', 'Open
|
|
12
|
+
option '-p --pristine', 'Open a stock, current Homebrew container'
|
|
13
13
|
|
|
14
14
|
def run
|
|
15
15
|
DockerShell.new.call pristine: args['--pristine']
|
data/lib/gembrew/config.rb
CHANGED
|
@@ -4,16 +4,23 @@ require 'gembrew/error'
|
|
|
4
4
|
|
|
5
5
|
module Gembrew
|
|
6
6
|
class Config
|
|
7
|
+
Dependency = Data.define(:name, :tags) do
|
|
8
|
+
def system_on_macos? = tags.include? :system_on_macos
|
|
9
|
+
def macos_only? = tags.include? :macos_only
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
DEPENDENCY_TAGS = %w[:macos_only :system_on_macos].freeze
|
|
7
13
|
DIRECTORY = 'gembrew'
|
|
14
|
+
FILENAME = 'formula.yml'
|
|
8
15
|
ALLOWED_KEYS = %w[
|
|
9
|
-
gem version output desc homepage license executable
|
|
16
|
+
gem version source output desc homepage license executable dependencies
|
|
10
17
|
].freeze
|
|
11
18
|
|
|
12
19
|
attr_reader :path, :project_path
|
|
13
20
|
|
|
14
21
|
def self.all(project_path = Pathname.pwd)
|
|
15
22
|
project_path = Pathname(project_path).expand_path
|
|
16
|
-
paths = (project_path/DIRECTORY).glob(
|
|
23
|
+
paths = (project_path/DIRECTORY).glob("*/#{FILENAME}").sort
|
|
17
24
|
raise Error, "No gem configurations found in #{project_path/DIRECTORY}" if paths.empty?
|
|
18
25
|
|
|
19
26
|
paths.map { |path| new path, project_path: project_path }
|
|
@@ -22,7 +29,7 @@ module Gembrew
|
|
|
22
29
|
def self.find(name, project_path = Pathname.pwd)
|
|
23
30
|
validate_name! name
|
|
24
31
|
project_path = Pathname(project_path).expand_path
|
|
25
|
-
new project_path/DIRECTORY/
|
|
32
|
+
new project_path/DIRECTORY/name/FILENAME, project_path: project_path
|
|
26
33
|
end
|
|
27
34
|
|
|
28
35
|
def self.validate_name!(name)
|
|
@@ -38,26 +45,27 @@ module Gembrew
|
|
|
38
45
|
validate
|
|
39
46
|
end
|
|
40
47
|
|
|
41
|
-
def name = path.basename
|
|
48
|
+
def name = path.dirname.basename.to_s
|
|
42
49
|
def gem_name = data.fetch('gem').to_s
|
|
43
50
|
def version = data['version']&.to_s
|
|
51
|
+
def source = data.fetch('source')
|
|
52
|
+
def source_type = source.fetch('type')
|
|
53
|
+
def source_repo = source['repo']
|
|
54
|
+
def source_tag = source['tag'] || "v#{version}"
|
|
55
|
+
def source_gemspec = source['gemspec'] || "#{gem_name}.gemspec"
|
|
44
56
|
def output_path = (project_path/(data['output'] || "Formula/#{name}.rb")).expand_path
|
|
45
57
|
def description = data['desc']
|
|
46
58
|
def homepage = data['homepage']
|
|
47
59
|
def license = data['license']
|
|
48
60
|
def executable = data['executable']
|
|
49
61
|
|
|
50
|
-
def
|
|
51
|
-
@
|
|
52
|
-
data.fetch('test').to_s
|
|
53
|
-
else
|
|
54
|
-
test_path = project_path/data.fetch('test_from_file')
|
|
55
|
-
raise Error, "Test file does not exist: #{test_path}" unless test_path.file?
|
|
56
|
-
|
|
57
|
-
test_path.read
|
|
58
|
-
end
|
|
62
|
+
def dependencies
|
|
63
|
+
@dependencies ||= data.fetch('dependencies', []).map { |value| parse_dependency value }
|
|
59
64
|
end
|
|
60
65
|
|
|
66
|
+
def install_extra_body = hook_body 'install_extra.rb'
|
|
67
|
+
def test_body = hook_body 'test.rb'
|
|
68
|
+
|
|
61
69
|
private
|
|
62
70
|
|
|
63
71
|
attr_reader :data
|
|
@@ -77,15 +85,87 @@ module Gembrew
|
|
|
77
85
|
raise Error, "Unknown configuration keys: #{unknown_keys.join(', ')}" if unknown_keys.any?
|
|
78
86
|
|
|
79
87
|
require_value 'gem'
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
88
|
+
require_value 'version'
|
|
89
|
+
require_value 'source'
|
|
90
|
+
validate_source
|
|
91
|
+
validate_dependencies
|
|
84
92
|
end
|
|
85
93
|
|
|
86
94
|
def require_value(key)
|
|
87
95
|
value = data[key]
|
|
88
96
|
raise Error, "#{key} is required" if value.nil? || value.to_s.empty?
|
|
89
97
|
end
|
|
98
|
+
|
|
99
|
+
def validate_source
|
|
100
|
+
raise Error, 'source must be a mapping' unless source.is_a?(Hash)
|
|
101
|
+
|
|
102
|
+
validate_source_keys
|
|
103
|
+
case source['type']&.to_s
|
|
104
|
+
when 'rubygems' then validate_rubygems_source
|
|
105
|
+
when 'github' then validate_github_source
|
|
106
|
+
else raise Error, 'source.type must be github or rubygems'
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def validate_source_keys
|
|
111
|
+
unknown_keys = source.keys - %w[type repo tag gemspec]
|
|
112
|
+
raise Error, "Unknown source keys: #{unknown_keys.join(', ')}" if unknown_keys.any?
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def validate_rubygems_source
|
|
116
|
+
extra_keys = source.keys - ['type']
|
|
117
|
+
raise Error, "source.#{extra_keys.first} is only valid for GitHub sources" if extra_keys.any?
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def validate_github_source
|
|
121
|
+
repo = source['repo']&.to_s
|
|
122
|
+
raise Error, 'source.repo is required for GitHub sources' if repo.nil? || repo.empty?
|
|
123
|
+
raise Error, 'source.repo must be in owner/repository form' unless repo.match?(%r{\A[^/\s]+/[^/\s]+\z})
|
|
124
|
+
|
|
125
|
+
validate_relative_source_path 'gemspec' if source.has_key?('gemspec')
|
|
126
|
+
raise Error, 'source.tag must not be empty' if source.has_key?('tag') && source['tag'].to_s.empty?
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def validate_relative_source_path(key)
|
|
130
|
+
value = source[key].to_s
|
|
131
|
+
path = Pathname(value)
|
|
132
|
+
valid = !value.empty? && !path.absolute? && path.each_filename.none?('..')
|
|
133
|
+
raise Error, "source.#{key} must be a relative path within the archive" unless valid
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def validate_dependencies
|
|
137
|
+
return unless data.has_key?('dependencies')
|
|
138
|
+
|
|
139
|
+
raise Error, 'dependencies must be a sequence' unless data['dependencies'].is_a?(Array)
|
|
140
|
+
|
|
141
|
+
dependencies
|
|
142
|
+
names = dependencies.map(&:name)
|
|
143
|
+
duplicate = names.find { |name| names.count(name) > 1 }
|
|
144
|
+
raise Error, "dependency #{duplicate.inspect} is specified more than once" if duplicate
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def parse_dependency(value)
|
|
148
|
+
raise Error, 'each dependency must be a name followed by optional tags' unless value.is_a?(String)
|
|
149
|
+
|
|
150
|
+
values = value.split
|
|
151
|
+
name = values.shift
|
|
152
|
+
unless name && !name.start_with?(':')
|
|
153
|
+
raise Error, 'dependency name must be a non-empty string'
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
invalid_tag = values.find { |tag| !tag.is_a?(String) || !DEPENDENCY_TAGS.include?(tag) }
|
|
157
|
+
raise Error, "unknown dependency tag: #{invalid_tag.inspect}" if invalid_tag
|
|
158
|
+
raise Error, "dependency #{name.inspect} has duplicate tags" unless values.uniq.length == values.length
|
|
159
|
+
|
|
160
|
+
Dependency.new(name:, tags: values.map { |tag| tag.delete_prefix(':').to_sym }.freeze)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def hook_body(filename)
|
|
164
|
+
hook_path = path.dirname/filename
|
|
165
|
+
return unless hook_path.file?
|
|
166
|
+
|
|
167
|
+
body = hook_path.read
|
|
168
|
+
body unless body.strip.empty?
|
|
169
|
+
end
|
|
90
170
|
end
|
|
91
171
|
end
|
data/lib/gembrew/docker_check.rb
CHANGED
|
@@ -24,14 +24,17 @@ module Gembrew
|
|
|
24
24
|
<<~BASH
|
|
25
25
|
caption() { printf '\\n\\033[1;34m==> gembrew: %s\\033[0m\\n' "$1"; }
|
|
26
26
|
formula=#{formula}
|
|
27
|
+
qualified_formula="gembrew/tap/$formula"
|
|
27
28
|
caption "styling $formula"
|
|
28
|
-
brew style "$
|
|
29
|
+
brew style "$qualified_formula"
|
|
29
30
|
caption "auditing $formula"
|
|
30
|
-
brew audit --new --online "$
|
|
31
|
+
brew audit --new --online "$qualified_formula"
|
|
31
32
|
caption "installing $formula"
|
|
32
|
-
brew install --build-from-source "$
|
|
33
|
+
brew install --build-from-source "$qualified_formula"
|
|
33
34
|
caption "testing $formula"
|
|
34
|
-
brew test "$
|
|
35
|
+
brew test "$qualified_formula"
|
|
36
|
+
caption "checking linkage for $formula"
|
|
37
|
+
brew linkage --test "$qualified_formula"
|
|
35
38
|
BASH
|
|
36
39
|
end
|
|
37
40
|
end
|
|
@@ -14,6 +14,7 @@ module Gembrew
|
|
|
14
14
|
|
|
15
15
|
def call(*command, interactive: false, pristine: false)
|
|
16
16
|
docker_command = ['docker', 'run', '--rm', '--init', '--name', container_name]
|
|
17
|
+
docker_command << '--pull=always' if pristine
|
|
17
18
|
docker_command << '-it' if interactive
|
|
18
19
|
docker_command.concat environment(interactive: interactive, pristine: pristine)
|
|
19
20
|
unless pristine
|
|
@@ -31,11 +32,15 @@ module Gembrew
|
|
|
31
32
|
attr_reader :command_runner
|
|
32
33
|
|
|
33
34
|
def environment(interactive:, pristine:)
|
|
34
|
-
result =
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
result = if pristine
|
|
36
|
+
[]
|
|
37
|
+
else
|
|
38
|
+
%w[
|
|
39
|
+
--env HOMEBREW_NO_AUTO_UPDATE=1
|
|
40
|
+
--env HOMEBREW_NO_INSTALL_CLEANUP=1
|
|
41
|
+
--env HOMEBREW_NO_INSTALL_FROM_API=1
|
|
42
|
+
]
|
|
43
|
+
end
|
|
39
44
|
prompt = pristine ? 'homebrew' : 'gembrew'
|
|
40
45
|
result.push '--env', "PS1=\\n\\n#{prompt} $ " if interactive
|
|
41
46
|
result
|
data/lib/gembrew/generator.rb
CHANGED
|
@@ -11,7 +11,7 @@ module Gembrew
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def call
|
|
14
|
-
resolution = resolver.resolve(config.gem_name, config.version)
|
|
14
|
+
resolution = resolver.resolve(config.gem_name, config.version, source: config.source)
|
|
15
15
|
output_path = config.output_path
|
|
16
16
|
output_path.dirname.mkpath
|
|
17
17
|
output_path.write renderer.render(formula_data(resolution))
|
|
@@ -35,14 +35,30 @@ module Gembrew
|
|
|
35
35
|
|
|
36
36
|
def metadata(spec)
|
|
37
37
|
{
|
|
38
|
-
description:
|
|
39
|
-
homepage:
|
|
40
|
-
license:
|
|
41
|
-
executable:
|
|
42
|
-
|
|
38
|
+
description: config.description || spec.summary,
|
|
39
|
+
homepage: config.homepage || inferred_homepage(spec),
|
|
40
|
+
license: config.license || spec.license || spec.licenses.first,
|
|
41
|
+
executable: executable(spec),
|
|
42
|
+
source_type: config.source_type,
|
|
43
|
+
source_repo: config.source_repo,
|
|
44
|
+
source_tag: config.source_tag,
|
|
45
|
+
source_gemspec: config.source_gemspec,
|
|
46
|
+
dependencies: formula_dependencies,
|
|
47
|
+
install_extra_body: config.install_extra_body,
|
|
48
|
+
test_body: config.test_body || %[system bin/#{executable(spec).inspect}, "--version"\n],
|
|
43
49
|
}
|
|
44
50
|
end
|
|
45
51
|
|
|
52
|
+
def executable(spec)
|
|
53
|
+
config.executable || spec.executables.first || spec.name
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def formula_dependencies
|
|
57
|
+
([Config::Dependency.new(name: 'ruby', tags: [])] + config.dependencies)
|
|
58
|
+
.uniq(&:name)
|
|
59
|
+
.sort_by(&:name)
|
|
60
|
+
end
|
|
61
|
+
|
|
46
62
|
def formula_name(gem_name)
|
|
47
63
|
gem_name.split(/[-_]/).map(&:capitalize).join
|
|
48
64
|
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
require 'open3'
|
|
3
|
+
require 'pathname'
|
|
4
|
+
require 'gembrew/error'
|
|
5
|
+
require 'gembrew/reporter'
|
|
6
|
+
|
|
7
|
+
module Gembrew
|
|
8
|
+
class GithubArchiveStore
|
|
9
|
+
def initialize(cache_path:, reporter: Reporter.new, command_runner: nil)
|
|
10
|
+
@cache_path = Pathname(cache_path)
|
|
11
|
+
@reporter = reporter
|
|
12
|
+
@command_runner = command_runner || method(:run_command)
|
|
13
|
+
@cache_path.mkpath
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def fetch(repository, tag)
|
|
17
|
+
name = repository.tr '/', '-'
|
|
18
|
+
path = @cache_path/"#{name}-#{tag.tr '/', '-'}.tar.gz"
|
|
19
|
+
if path.file? && !path.empty?
|
|
20
|
+
reporter.archive :github_cache, repository, tag
|
|
21
|
+
return path
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
reporter.archive :downloading, repository, tag
|
|
25
|
+
url = "https://github.com/#{repository}/archive/refs/tags/#{tag}.tar.gz"
|
|
26
|
+
command_runner.call 'curl', '--fail', '--location', '--silent', '--show-error',
|
|
27
|
+
'--output', path.to_s, url, chdir: @cache_path
|
|
28
|
+
raise Error, "GitHub archive is empty: #{url}" unless path.file? && !path.empty?
|
|
29
|
+
|
|
30
|
+
path
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def extract(archive, destination)
|
|
34
|
+
destination = Pathname(destination)
|
|
35
|
+
destination.mkpath
|
|
36
|
+
command_runner.call 'tar', '-xzf', archive.to_s, '-C', destination.to_s, chdir: destination
|
|
37
|
+
destination
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
attr_reader :reporter, :command_runner
|
|
43
|
+
|
|
44
|
+
def run_command(*command, chdir:)
|
|
45
|
+
result, status = Open3.capture2e(*command, chdir: chdir.to_s)
|
|
46
|
+
raise Error, result unless status.success?
|
|
47
|
+
|
|
48
|
+
result
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
data/lib/gembrew/initializer.rb
CHANGED
|
@@ -20,6 +20,8 @@ module Gembrew
|
|
|
20
20
|
formula_path.mkpath
|
|
21
21
|
config_directory.mkpath
|
|
22
22
|
readme_path.write render_readme unless readme_path.exist?
|
|
23
|
+
workflow_path.dirname.mkpath
|
|
24
|
+
workflow_path.write workflow_template.read unless workflow_path.exist?
|
|
23
25
|
Adder.new(gem_name, project_path: project_path).call if gem_name
|
|
24
26
|
|
|
25
27
|
project_path
|
|
@@ -39,6 +41,14 @@ module Gembrew
|
|
|
39
41
|
project_path/'README.md'
|
|
40
42
|
end
|
|
41
43
|
|
|
44
|
+
def workflow_path
|
|
45
|
+
project_path/'.github/workflows/test.yml'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def workflow_template
|
|
49
|
+
Pathname(__dir__)/'templates/test.yml'
|
|
50
|
+
end
|
|
51
|
+
|
|
42
52
|
def entries
|
|
43
53
|
@entries ||= project_path.children.reject { |path| path.basename.to_s == '.git' }
|
|
44
54
|
end
|
data/lib/gembrew/reporter.rb
CHANGED
data/lib/gembrew/resolver.rb
CHANGED
|
@@ -6,6 +6,7 @@ require 'rubygems/package'
|
|
|
6
6
|
require 'tmpdir'
|
|
7
7
|
require 'gembrew/archive_store'
|
|
8
8
|
require 'gembrew/error'
|
|
9
|
+
require 'gembrew/github_archive_store'
|
|
9
10
|
require 'gembrew/reporter'
|
|
10
11
|
|
|
11
12
|
module Gembrew
|
|
@@ -15,21 +16,22 @@ module Gembrew
|
|
|
15
16
|
class Resolver
|
|
16
17
|
attr_reader :cache_root
|
|
17
18
|
|
|
18
|
-
def initialize(cache_root: nil, reporter: Reporter.new, command_runner: nil, archive_store: nil
|
|
19
|
+
def initialize(cache_root: nil, reporter: Reporter.new, command_runner: nil, archive_store: nil,
|
|
20
|
+
github_archive_store: nil)
|
|
19
21
|
@cache_root = Pathname(cache_root || default_cache_root)
|
|
20
22
|
@reporter = reporter
|
|
21
23
|
@command_runner = command_runner || method(:run_command)
|
|
22
24
|
@archive_store = archive_store || ArchiveStore.new(
|
|
23
25
|
cache_path: @cache_root/'gems', reporter: reporter, command_runner: @command_runner
|
|
24
26
|
)
|
|
27
|
+
@github_archive_store = github_archive_store
|
|
25
28
|
temporary_root.mkpath
|
|
26
29
|
end
|
|
27
30
|
|
|
28
|
-
def resolve(name, version
|
|
31
|
+
def resolve(name, version, source:)
|
|
29
32
|
Dir.mktmpdir('build-', temporary_root.to_s) do |directory|
|
|
30
33
|
temporary = Pathname(directory)
|
|
31
|
-
root_archive =
|
|
32
|
-
root_spec = Gem::Package.new(root_archive.to_s).spec
|
|
34
|
+
root_archive, root_spec = root_source name, version, source, temporary
|
|
33
35
|
dependencies = dependency_specs(lock(root_spec, temporary), root_spec)
|
|
34
36
|
|
|
35
37
|
reporter.collecting dependencies.length
|
|
@@ -45,6 +47,57 @@ module Gembrew
|
|
|
45
47
|
|
|
46
48
|
attr_reader :reporter, :command_runner, :archive_store
|
|
47
49
|
|
|
50
|
+
def github_archive_store
|
|
51
|
+
@github_archive_store ||= GithubArchiveStore.new(
|
|
52
|
+
cache_path: cache_root/'github', reporter: reporter, command_runner: command_runner
|
|
53
|
+
)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def root_source(name, version, source_config, temporary)
|
|
57
|
+
return rubygems_root_source(name, version, temporary) if source_config.fetch('type') == 'rubygems'
|
|
58
|
+
|
|
59
|
+
github_root_source name, version, source_config, temporary
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def rubygems_root_source(name, version, temporary)
|
|
63
|
+
archive = archive_store.fetch(name, version, temporary)
|
|
64
|
+
[archive, Gem::Package.new(archive.to_s).spec]
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def github_root_source(name, version, source_config, temporary)
|
|
68
|
+
repository = source_config.fetch('repo')
|
|
69
|
+
tag = source_config['tag'] || "v#{version}"
|
|
70
|
+
gemspec_path = source_config['gemspec'] || "#{name}.gemspec"
|
|
71
|
+
archive = github_archive_store.fetch repository, tag
|
|
72
|
+
root = github_project_root archive, temporary
|
|
73
|
+
spec = load_github_spec root/gemspec_path, gemspec_path
|
|
74
|
+
validate_github_spec spec, name, version
|
|
75
|
+
|
|
76
|
+
[archive, spec]
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def github_project_root(archive, temporary)
|
|
80
|
+
extracted = github_archive_store.extract archive, temporary/'source'
|
|
81
|
+
roots = extracted.children.select(&:directory?)
|
|
82
|
+
raise Error, 'Expected one project directory in the GitHub archive' unless roots.one?
|
|
83
|
+
|
|
84
|
+
roots.first
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def load_github_spec(gemspec, gemspec_path)
|
|
88
|
+
raise Error, "Gemspec not found in GitHub archive: #{gemspec_path}" unless gemspec.file?
|
|
89
|
+
|
|
90
|
+
spec = Dir.chdir(gemspec.dirname) { Gem::Specification.load(gemspec.basename.to_s) }
|
|
91
|
+
raise Error, "Could not load gemspec from GitHub archive: #{gemspec_path}" unless spec
|
|
92
|
+
|
|
93
|
+
spec
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def validate_github_spec(spec, name, version)
|
|
97
|
+
raise Error, "Gemspec name #{spec.name} does not match configured gem #{name}" unless spec.name == name
|
|
98
|
+
raise Error, "GitHub gemspec version #{spec.version} does not match #{version}" unless spec.version == Gem::Version.new(version)
|
|
99
|
+
end
|
|
100
|
+
|
|
48
101
|
def resource(spec, temporary, index, total)
|
|
49
102
|
archive = archive_store.fetch spec.name, spec.version, temporary, index: index, total: total
|
|
50
103
|
Resource.new spec.name, spec.version.to_s, Digest::SHA256.file(archive).hexdigest
|
|
@@ -62,10 +115,11 @@ module Gembrew
|
|
|
62
115
|
def lock(root_spec, temporary)
|
|
63
116
|
gemfile = temporary/'Gemfile'
|
|
64
117
|
lockfile = temporary/'Gemfile.lock'
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
gem #{
|
|
68
|
-
|
|
118
|
+
dependencies = root_spec.runtime_dependencies.map do |dependency|
|
|
119
|
+
requirements = dependency.requirement.requirements.map { |operator, version| "#{operator} #{version}" }
|
|
120
|
+
"gem #{dependency.name.inspect}, #{requirements.map(&:inspect).join(', ')}"
|
|
121
|
+
end
|
|
122
|
+
gemfile.write([[%[source "https://rubygems.org"]], dependencies, ['']].flatten.join("\n"))
|
|
69
123
|
|
|
70
124
|
reporter.resolving root_spec.name, root_spec.version
|
|
71
125
|
command_runner.call(
|
|
@@ -23,6 +23,11 @@ Install [Gembrew](https://github.com/DannyBen/gembrew):
|
|
|
23
23
|
gem install gembrew
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
+
The generated GitHub Actions workflow uses Homebrew's `test-bot` on Linux,
|
|
27
|
+
Apple Silicon, and Intel macOS. Pull requests test changed formulae; pushes,
|
|
28
|
+
and manual runs test every formula. Homebrew style checks apply only to files in
|
|
29
|
+
`Formula/`; Gembrew's Ruby hook files are not standalone Homebrew formulae.
|
|
30
|
+
|
|
26
31
|
Generate all formulae:
|
|
27
32
|
|
|
28
33
|
```shell
|
|
@@ -48,6 +53,14 @@ Add another Ruby gem:
|
|
|
48
53
|
gembrew add another-gem
|
|
49
54
|
```
|
|
50
55
|
|
|
56
|
+
Each gem has a `gembrew/NAME/formula.yml` configuration. You may add these
|
|
57
|
+
optional Ruby hook files beside it:
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
install_extra.rb Runs after the standard gem installation
|
|
61
|
+
test.rb Defines the formula test
|
|
62
|
+
```
|
|
63
|
+
|
|
51
64
|
Open an interactive Homebrew environment:
|
|
52
65
|
|
|
53
66
|
```shell
|
|
@@ -1,16 +1,34 @@
|
|
|
1
|
-
# Generated by Gembrew: https://github.com/dannyben/gembrew
|
|
2
|
-
# Manual edits are not recommended. Update gembrew/*.yml and regenerate with:
|
|
3
|
-
# gem install gembrew
|
|
4
|
-
# gembrew build
|
|
5
|
-
|
|
6
1
|
class <%= formula_name %> < Formula
|
|
7
2
|
desc <%= description.inspect %>
|
|
8
3
|
homepage <%= homepage.inspect %>
|
|
4
|
+
<% if source_type == 'github' -%>
|
|
5
|
+
url "https://github.com/<%= source_repo %>/archive/refs/tags/<%= source_tag %>.tar.gz"
|
|
6
|
+
<% else -%>
|
|
9
7
|
url "https://rubygems.org/downloads/<%= gem_name %>-<%= version %>.gem"
|
|
8
|
+
<% end -%>
|
|
10
9
|
sha256 "<%= sha256 %>"
|
|
11
10
|
license <%= license.inspect %>
|
|
12
11
|
|
|
13
|
-
|
|
12
|
+
<% formula_dependencies = dependencies.reject { |dependency| dependency.system_on_macos? || dependency.macos_only? } -%>
|
|
13
|
+
<% macos_dependencies = dependencies.select(&:system_on_macos?) -%>
|
|
14
|
+
<% macos_only_dependencies = dependencies.select(&:macos_only?) -%>
|
|
15
|
+
<% formula_dependencies.each do |dependency| -%>
|
|
16
|
+
depends_on <%= dependency.name.inspect %>
|
|
17
|
+
<% end -%>
|
|
18
|
+
<% if formula_dependencies.any? && (macos_dependencies.any? || macos_only_dependencies.any?) -%>
|
|
19
|
+
|
|
20
|
+
<% end -%>
|
|
21
|
+
<% macos_dependencies.each do |dependency| -%>
|
|
22
|
+
uses_from_macos <%= dependency.name.inspect %>
|
|
23
|
+
<% end -%>
|
|
24
|
+
<% if macos_only_dependencies.any? -%>
|
|
25
|
+
|
|
26
|
+
on_macos do
|
|
27
|
+
<% macos_only_dependencies.each do |dependency| -%>
|
|
28
|
+
depends_on <%= dependency.name.inspect %>
|
|
29
|
+
<% end -%>
|
|
30
|
+
end
|
|
31
|
+
<% end -%>
|
|
14
32
|
<% resources.each do |resource| -%>
|
|
15
33
|
|
|
16
34
|
resource <%= resource.name.inspect %> do
|
|
@@ -27,13 +45,23 @@ class <%= formula_name %> < Formula
|
|
|
27
45
|
"--ignore-dependencies", "--install-dir", libexec, "--no-document"
|
|
28
46
|
end
|
|
29
47
|
|
|
48
|
+
<% if source_type == 'github' -%>
|
|
49
|
+
system "gem", "build", "<%= source_gemspec %>"
|
|
50
|
+
system "gem", "install", "--ignore-dependencies", "<%= gem_name %>-#{version}.gem",
|
|
51
|
+
"--install-dir", libexec, "--no-document"
|
|
52
|
+
<% else -%>
|
|
30
53
|
system "gem", "install", cached_download,
|
|
31
54
|
"--ignore-dependencies", "--install-dir", libexec, "--no-document"
|
|
55
|
+
<% end -%>
|
|
32
56
|
|
|
33
57
|
(bin/<%= executable.inspect %>).write_env_script libexec/"bin/<%= executable %>", GEM_HOME: ENV.fetch("GEM_HOME")
|
|
58
|
+
<% if install_extra_body -%>
|
|
59
|
+
|
|
60
|
+
<%= install_extra_body.lines(chomp: true).map { |line| line.strip.empty? ? '' : " #{line}" }.join("\n") %>
|
|
61
|
+
<% end -%>
|
|
34
62
|
end
|
|
35
63
|
|
|
36
64
|
test do
|
|
37
|
-
<%= test_body.lines.map { |line| " #{line}" }.join %>
|
|
65
|
+
<%= test_body.lines(chomp: true).map { |line| line.strip.empty? ? '' : " #{line}" }.join("\n") %>
|
|
38
66
|
end
|
|
39
67
|
end
|
|
@@ -1,14 +1,29 @@
|
|
|
1
1
|
gem: <%= gem_name %>
|
|
2
|
+
version: "" # required
|
|
2
3
|
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
# Required source. Use the published RubyGem:
|
|
5
|
+
source:
|
|
6
|
+
type: rubygems
|
|
5
7
|
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
+
# Or replace the source above with a GitHub tag archive:
|
|
9
|
+
# source:
|
|
10
|
+
# type: github
|
|
11
|
+
# repo: owner/repository # required for GitHub
|
|
12
|
+
# tag: v1.2.3 # optional; defaults to vVERSION
|
|
13
|
+
# gemspec: <%= gem_name %>.gemspec # optional; defaults to GEMNAME.gemspec
|
|
14
|
+
|
|
15
|
+
# Optional metadata and formula overrides:
|
|
8
16
|
# desc: Example command-line application
|
|
9
17
|
# homepage: https://example.com
|
|
10
18
|
# license: MIT
|
|
11
19
|
# executable: <%= gem_name %>
|
|
20
|
+
# output: Formula/<%= gem_name %>.rb
|
|
21
|
+
# dependencies:
|
|
22
|
+
# - bash
|
|
23
|
+
# - bash :macos_only
|
|
24
|
+
# - libffi :system_on_macos
|
|
12
25
|
|
|
13
|
-
#
|
|
14
|
-
#
|
|
26
|
+
# Optional Ruby hook files:
|
|
27
|
+
#
|
|
28
|
+
# install_extra.rb Runs after the standard gem installation
|
|
29
|
+
# test.rb Defines the formula test
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
name: Test Formulae
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
- master
|
|
8
|
+
pull_request:
|
|
9
|
+
workflow_dispatch:
|
|
10
|
+
|
|
11
|
+
permissions: {}
|
|
12
|
+
|
|
13
|
+
defaults:
|
|
14
|
+
run:
|
|
15
|
+
shell: bash -xeuo pipefail {0}
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
test-bot:
|
|
19
|
+
name: ${{ matrix.os }}
|
|
20
|
+
runs-on: ${{ matrix.os }}
|
|
21
|
+
timeout-minutes: 60
|
|
22
|
+
container: ${{ fromJSON(toJSON(matrix.container)) }} # zizmor: ignore[unpinned-images]
|
|
23
|
+
strategy:
|
|
24
|
+
fail-fast: false
|
|
25
|
+
matrix:
|
|
26
|
+
os:
|
|
27
|
+
- macos-26
|
|
28
|
+
- macos-15-intel
|
|
29
|
+
include:
|
|
30
|
+
- os: ubuntu-latest
|
|
31
|
+
container:
|
|
32
|
+
image: ghcr.io/homebrew/brew:main
|
|
33
|
+
options: --privileged
|
|
34
|
+
permissions:
|
|
35
|
+
actions: read
|
|
36
|
+
checks: read
|
|
37
|
+
contents: read
|
|
38
|
+
pull-requests: read
|
|
39
|
+
|
|
40
|
+
steps:
|
|
41
|
+
- name: Set up Homebrew
|
|
42
|
+
id: set-up-homebrew
|
|
43
|
+
uses: Homebrew/actions/setup-homebrew@b35a29a0f83ee8b8ca07b219fc8db3d7bb88ab49 # 2026.08.10.2
|
|
44
|
+
with:
|
|
45
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
46
|
+
|
|
47
|
+
- name: Cache Homebrew Bundler gems
|
|
48
|
+
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
|
49
|
+
with:
|
|
50
|
+
path: ${{ steps.set-up-homebrew.outputs.gems-path }}
|
|
51
|
+
key: ${{ matrix.os }}-rubygems-${{ steps.set-up-homebrew.outputs.gems-hash }}
|
|
52
|
+
restore-keys: ${{ matrix.os }}-rubygems-
|
|
53
|
+
|
|
54
|
+
- name: Clean runner
|
|
55
|
+
run: brew test-bot --only-cleanup-before
|
|
56
|
+
|
|
57
|
+
- name: Set up test-bot
|
|
58
|
+
run: brew test-bot --only-setup
|
|
59
|
+
|
|
60
|
+
- name: Check tap syntax
|
|
61
|
+
run: |
|
|
62
|
+
tap="${GITHUB_REPOSITORY/homebrew-/}"
|
|
63
|
+
tap_path="${{ steps.set-up-homebrew.outputs.repository-path }}"
|
|
64
|
+
brew style "$tap_path/Formula"
|
|
65
|
+
brew readall --aliases --os=all --arch=all "$tap"
|
|
66
|
+
brew audit --except=installed --tap="$tap"
|
|
67
|
+
|
|
68
|
+
- name: Test changed formulae
|
|
69
|
+
if: github.event_name == 'pull_request'
|
|
70
|
+
run: brew test-bot --only-formulae
|
|
71
|
+
|
|
72
|
+
- name: Collect all formulae
|
|
73
|
+
id: all-formulae
|
|
74
|
+
if: github.event_name != 'pull_request'
|
|
75
|
+
run: |
|
|
76
|
+
shopt -s nullglob
|
|
77
|
+
tap_path="${{ steps.set-up-homebrew.outputs.repository-path }}"
|
|
78
|
+
paths=("$tap_path"/Formula/*.rb)
|
|
79
|
+
|
|
80
|
+
if (( ${#paths[@]} == 0 )); then
|
|
81
|
+
echo "No formulae found in $tap_path/Formula/"
|
|
82
|
+
exit 1
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
formulae=()
|
|
86
|
+
for path in "${paths[@]}"; do
|
|
87
|
+
formula="${path##*/}"
|
|
88
|
+
formulae+=("${formula%.rb}")
|
|
89
|
+
done
|
|
90
|
+
|
|
91
|
+
joined=$(IFS=,; echo "${formulae[*]}")
|
|
92
|
+
echo "formulae=${joined}" >> "$GITHUB_OUTPUT"
|
|
93
|
+
|
|
94
|
+
- name: Test all formulae
|
|
95
|
+
if: github.event_name != 'pull_request'
|
|
96
|
+
run: >-
|
|
97
|
+
brew test-bot --only-formulae
|
|
98
|
+
--testing-formulae="${{ steps.all-formulae.outputs.formulae }}"
|
|
99
|
+
|
|
100
|
+
- name: Upload bottles as artifacts
|
|
101
|
+
if: always() && github.event_name == 'pull_request'
|
|
102
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
103
|
+
with:
|
|
104
|
+
name: bottles_${{ matrix.os }}
|
|
105
|
+
path: "*.bottle.*"
|
data/lib/gembrew/version.rb
CHANGED
data/lib/gembrew.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gembrew
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Danny Ben Shitrit
|
|
@@ -77,6 +77,7 @@ files:
|
|
|
77
77
|
- lib/gembrew/docker_shell.rb
|
|
78
78
|
- lib/gembrew/error.rb
|
|
79
79
|
- lib/gembrew/generator.rb
|
|
80
|
+
- lib/gembrew/github_archive_store.rb
|
|
80
81
|
- lib/gembrew/initializer.rb
|
|
81
82
|
- lib/gembrew/renderer.rb
|
|
82
83
|
- lib/gembrew/reporter.rb
|
|
@@ -84,6 +85,7 @@ files:
|
|
|
84
85
|
- lib/gembrew/templates/README.md.erb
|
|
85
86
|
- lib/gembrew/templates/formula.rb.erb
|
|
86
87
|
- lib/gembrew/templates/gembrew.yml.erb
|
|
88
|
+
- lib/gembrew/templates/test.yml
|
|
87
89
|
- lib/gembrew/version.rb
|
|
88
90
|
homepage: https://github.com/DannyBen/gembrew
|
|
89
91
|
licenses:
|