homebrew_automation 0.0.9 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bdaeff9e52d6b0ddeefead7ebced2d97dcde3ae8e6535648c5758ad218b8d42b
4
- data.tar.gz: bdf140bc9b706c81ee09344bcb6c36bd8d7679f84fb0757db01fb7df78b0a019
3
+ metadata.gz: 240ff77ce84a9af442b04b396ddba4f32014d95d02ebf7fda5ff5904e71aa8bf
4
+ data.tar.gz: 898384c47dbfee5484b26d4faa5ee2352398c8b8fa2f26b500adcff9e1c1182d
5
5
  SHA512:
6
- metadata.gz: 77b8a3c5fbf0bf8488ebd6a39b2d493beb99b1ac2d2a6bfc64336cdacac2ae352dac3cd30ce62130c2de0bd898f8f9b9dcffce97bb69f6017f7110b2db5374cb
7
- data.tar.gz: bb9add2b195407088552da55a35df30a0170fec173c437d97ef15db3cdb1237a4fb4b31b1d37f37edfaa9d124abe13beadab0ac6639048f0fdad4fffff9cb1f8
6
+ metadata.gz: ffc1fbb67e9b31b5aeca7b0b11c2f5c6ef6c694e4e4af9bcb1ffbc4a27e20f2be1bbcb1416f4735176543d0ab929519c01e15c51a096fa0400195e796bee97af
7
+ data.tar.gz: f6c5a599c570f9183201101fb9197fbf063bffb845bdf343ddf00e91687c41d565f482d2290c46002f0ddb7c2ff24feb6b74a1df6a77e73a8731ae3141665199
@@ -1,99 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'thor'
4
-
5
- require_relative '../lib/homebrew_automation.rb'
6
-
7
- class FormulaCommands < Thor
8
-
9
- desc 'put-sdist', 'Update the URL and sha256 checksum of the source tarball'
10
- option :url, :required => true
11
- option :sha256, :required => true
12
- def put_sdist
13
- before = HomebrewAutomation::Formula.parse_string($stdin.read)
14
- after = before.put_sdist options[:url], options[:sha256]
15
- $stdout.write after
16
- end
17
-
18
- desc 'put-bottle', 'Insert or update a bottle reference for a given OS'
19
- option :os, :required => true
20
- option :sha256, :required => true
21
- def put_bottle
22
- before = HomebrewAutomation::Formula.parse_string($stdin.read)
23
- after = before.put_bottle(options[:os], options[:sha256])
24
- $stdout.write after
25
- end
26
-
27
- end
28
-
29
- class WorkflowCommands < Thor
30
- class_option :tap_user, :required => true
31
- class_option :tap_repo, :required => true
32
- class_option :tap_token, :required => true
33
- class_option :bintray_user, :required => true
34
- class_option :bintray_token, :required => true
35
-
36
- desc 'build-and-upload', 'Build binary tarball from source tarball, then upload to Bintray'
37
- long_desc <<-HERE_HERE
38
- Since we're uploading to Bintray, we need a Bintray API KEY at `bintray_token`.
39
-
40
- `formula_name` defaults to the same as `source_repo`.
41
- `formula_version` defaults to `source_tag` with a leading `v` stripped off.
42
- HERE_HERE
43
- option :source_user, :required => true
44
- option :source_repo, :required => true
45
- option :source_tag, :required => true
46
- option :formula_name
47
- option :formula_version
48
- def build_and_upload
49
- workflow.build_and_upload_bottle(
50
- HomebrewAutomation::SourceDist.new(
51
- options[:source_user],
52
- options[:source_repo],
53
- options[:source_tag]),
54
- formula_name: options[:formula_name],
55
- version_name: options[:formula_version])
56
- end
57
-
58
- desc 'gather-and-publish', 'Make the Tap aware of new Bottles'
59
- long_desc <<-HERE_HERE
60
- See what bottles have been built and uploaded to Bintray, then publish them into the Tap.
61
-
62
- Since we're publishing updates to the Formula in our Tap, we need Git push access to the
63
- Tap repo on Github via a Github OAuth token via `tap_token`.
64
-
65
- `formula-name` should be both the formula name as appears in the Tap and also the Bintray package name.
66
- `formula-version` should be the Bintray "Version" name.
67
- HERE_HERE
68
- option :formula_name, :required => true
69
- option :formula_version, :required => true
70
- def gather_and_publish
71
- workflow.gather_and_publish_bottles(
72
- options[:formula_name],
73
- options[:formula_version])
74
- end
75
-
76
- private
77
-
78
- def workflow
79
- HomebrewAutomation::Workflow.new(
80
- HomebrewAutomation::Tap.new(options[:tap_user], options[:tap_repo], options[:tap_token]),
81
- HomebrewAutomation::Bintray.new(options[:bintray_user], options[:bintray_token]))
82
- end
83
-
84
- end
85
-
86
- class MyCliApp < Thor
87
-
88
- desc 'formula (...)', 'Modify Formula DSL source (read stdin, write stdout)'
89
- subcommand "formula", FormulaCommands
90
-
91
- desc 'bottle (...)', 'Workflows for dealing with binary artifacts'
92
- subcommand "bottle", WorkflowCommands
93
-
94
- end
95
-
96
-
97
- MyCliApp.start(ARGV)
98
-
3
+ require_relative '../lib/homebrew_automation/cli.rb'
99
4
 
5
+ HomebrewAutomation::CLI::MyCliApp.start(ARGV)
@@ -1,13 +1,10 @@
1
1
 
2
2
  # Help you manipulate Homebrew Formula files, Bottles etc.
3
- module HomebrewAutomation
4
- end
5
3
 
6
4
  require_relative 'homebrew_automation/bintray.rb'
7
5
  require_relative 'homebrew_automation/bottle.rb'
8
- require_relative 'homebrew_automation/bottle_gatherer.rb'
9
6
  require_relative 'homebrew_automation/formula.rb'
10
- require_relative 'homebrew_automation/mac-os.rb'
7
+ require_relative 'homebrew_automation/mac_os.rb'
11
8
  require_relative 'homebrew_automation/source_dist.rb'
12
9
  require_relative 'homebrew_automation/tap.rb'
13
10
  require_relative 'homebrew_automation/version.rb'
@@ -1,122 +1,3 @@
1
1
 
2
- require 'json'
3
- require 'base64'
4
- require 'uri'
5
- require 'rest-client'
6
-
7
- module HomebrewAutomation
8
-
9
- # A bare-bones Bintray API client that implements only the methods needed for
10
- # Homebrew things.
11
- class Bintray
12
-
13
- # @param username [String] Bintray username; for me this was not my email address
14
- # @param api_key [String] Bearer-token-like key; generated in the Bintray web UI
15
- # @param http [RestClient.Class] The +RestClient+ class itself
16
- # @param base_url [String] Include the +https://+; exclude the trailing slash.
17
- def initialize(
18
- username,
19
- api_key,
20
- http: RestClient,
21
- base_url: "https://bintray.com/api/v1"
22
- )
23
- @username = username
24
- @api_key = api_key
25
- @base_url = base_url
26
- @http = http # allow injecting mocks for testing
27
- end
28
-
29
- # <tt>POST /packages/:subject/:repo/:package/versions</tt>
30
- #
31
- # Redundant: Bintray seems to create nonexistant versions for you if you
32
- # just try to upload files into it.
33
- #
34
- # @param repo_name [String]
35
- # @param package_name [String]
36
- # @param version_name [String]
37
- # @return [RestClient::Response]
38
- def create_version(repo_name, package_name, version_name)
39
- safe_repo = URI.escape(repo_name)
40
- safe_pkg = URI.escape(package_name)
41
- @http.post(
42
- rel("/packages/#{safe_username}/#{safe_repo}/#{safe_pkg}/versions"),
43
- { name: version_name }.to_json,
44
- api_headers
45
- )
46
- end
47
-
48
- # <tt>PUT /content/:subject/:repo/:package/:version/:file_path[?publish=0/1][?override=0/1][?explode=0/1]</tt>
49
- #
50
- # Bintray seems to expect the byte sequence of the file to be written straight out into the
51
- # HTTP request body, optionally via <tt>Transfer-Encoding: chunked</tt>. So we pass the +content+ String
52
- # straight through to RestClient
53
- #
54
- # @param repo_name [String]
55
- # @param package_name [String]
56
- # @param version_name [String]
57
- # @param filename [String] The filename within one Bintray repository, e.g. +hack-assembler-0.1.1.17.high_sierra.bottle.tar.gz+
58
- # @param content [String] The bytes for the file, e.g. from a +File.read+
59
- # @return [RestClient::Response]
60
- def upload_file(repo_name, package_name, version_name, filename, content, publish: 1)
61
- safe_repo = URI.escape(repo_name)
62
- safe_pkg = URI.escape(package_name)
63
- safe_ver = URI.escape(version_name)
64
- safe_filename = URI.escape(filename)
65
- safe_publish = URI.escape(publish.to_s)
66
- @http.put(
67
- rel("/content/#{safe_username}/#{safe_repo}/#{safe_pkg}/#{safe_ver}/#{safe_filename}?publish=#{safe_publish}"),
68
- content,
69
- auth_headers
70
- )
71
- end
72
-
73
- # <tt>GET /packages/:subject/:repo/:package/versions/:version/files[?include_unpublished=0/1]</tt>
74
- #
75
- # Useful when seeing what bottles have already been built.
76
- #
77
- # @param repo_name [String]
78
- # @param package_name [String]
79
- # @param version_name [String]
80
- # @return [RestClient::Response]
81
- def get_all_files_in_version(repo_name, package_name, version_name)
82
- safe_repo = URI.escape(repo_name)
83
- safe_pkg = URI.escape(package_name)
84
- safe_ver = URI.escape(version_name)
85
- @http.get(
86
- rel("/packages/#{safe_username}/#{safe_repo}/#{safe_pkg}/versions/#{safe_ver}/files"),
87
- auth_headers)
88
- end
89
-
90
- # Bintray username, URI-escaped.
91
- #
92
- # @return [String]
93
- def safe_username
94
- URI.escape(@username)
95
- end
96
-
97
- # Resolve a relative path into a URL using the current base_url
98
- #
99
- # @param slash_subpath [String]
100
- # @return [String]
101
- def rel(slash_subpath)
102
- @base_url + slash_subpath
103
- end
104
-
105
- # @return [Hash]
106
- def api_headers
107
- { "Content-Type" => "application/json" }.update auth_headers
108
- end
109
-
110
- # Implement HTTP Basich Auth, as per RFC 7617.
111
- #
112
- # Let's not bring in a library just for these two lines.
113
- #
114
- # @return [Hash]
115
- def auth_headers
116
- cred = Base64.strict_encode64("#{@username}:#{@api_key}")
117
- { Authorization: "Basic #{cred}" }
118
- end
119
-
120
- end
121
-
122
- end
2
+ require_relative 'bintray/client.rb'
3
+ require_relative 'bintray/version.rb'
@@ -0,0 +1,125 @@
1
+
2
+ require 'json'
3
+ require 'base64'
4
+ require 'uri'
5
+ require 'rest-client'
6
+
7
+ module HomebrewAutomation
8
+ end
9
+
10
+ module HomebrewAutomation::Bintray
11
+
12
+ # A bare-bones Bintray API client that implements only the methods needed for
13
+ # Homebrew things.
14
+ class Client
15
+
16
+ # @param username [String] Bintray username; for me this was not my email address
17
+ # @param api_key [String] Bearer-token-like key; generated in the Bintray web UI
18
+ # @param http [RestClient.Class] The +RestClient+ class itself
19
+ # @param base_url [String] Include the +https://+; exclude the trailing slash.
20
+ def initialize(
21
+ username,
22
+ api_key,
23
+ http: RestClient,
24
+ base_url: "https://bintray.com/api/v1"
25
+ )
26
+ @username = username
27
+ @api_key = api_key
28
+ @base_url = base_url
29
+ @http = http # allow injecting mocks for testing
30
+ end
31
+
32
+ # <tt>POST /packages/:subject/:repo/:package/versions</tt>
33
+ #
34
+ # Redundant: Bintray seems to create nonexistant versions for you if you
35
+ # just try to upload files into it.
36
+ #
37
+ # @param repo_name [String]
38
+ # @param package_name [String]
39
+ # @param version_name [String]
40
+ # @return [RestClient::Response]
41
+ def create_version(repo_name, package_name, version_name)
42
+ safe_repo = URI.escape(repo_name)
43
+ safe_pkg = URI.escape(package_name)
44
+ @http.post(
45
+ rel("/packages/#{safe_username}/#{safe_repo}/#{safe_pkg}/versions"),
46
+ { name: version_name }.to_json,
47
+ api_headers
48
+ )
49
+ end
50
+
51
+ # <tt>PUT /content/:subject/:repo/:package/:version/:file_path[?publish=0/1][?override=0/1][?explode=0/1]</tt>
52
+ #
53
+ # Bintray seems to expect the byte sequence of the file to be written straight out into the
54
+ # HTTP request body, optionally via <tt>Transfer-Encoding: chunked</tt>. So we pass the +content+ String
55
+ # straight through to RestClient
56
+ #
57
+ # @param repo_name [String]
58
+ # @param package_name [String]
59
+ # @param version_name [String]
60
+ # @param filename [String] The filename within one Bintray repository, e.g. +hack-assembler-0.1.1.17.high_sierra.bottle.tar.gz+
61
+ # @param content [String] The bytes for the file, e.g. from a +File.read+
62
+ # @return [RestClient::Response]
63
+ def upload_file(repo_name, package_name, version_name, filename, content, publish: 1)
64
+ safe_repo = URI.escape(repo_name)
65
+ safe_pkg = URI.escape(package_name)
66
+ safe_ver = URI.escape(version_name)
67
+ safe_filename = URI.escape(filename)
68
+ safe_publish = URI.escape(publish.to_s)
69
+ @http.put(
70
+ rel("/content/#{safe_username}/#{safe_repo}/#{safe_pkg}/#{safe_ver}/#{safe_filename}?publish=#{safe_publish}"),
71
+ content,
72
+ auth_headers
73
+ )
74
+ end
75
+
76
+ # <tt>GET /packages/:subject/:repo/:package/versions/:version/files[?include_unpublished=0/1]</tt>
77
+ #
78
+ # Useful when seeing what bottles have already been built.
79
+ #
80
+ # @param repo_name [String]
81
+ # @param package_name [String]
82
+ # @param version_name [String]
83
+ # @return [RestClient::Response]
84
+ def get_all_files_in_version(repo_name, package_name, version_name)
85
+ safe_repo = URI.escape(repo_name)
86
+ safe_pkg = URI.escape(package_name)
87
+ safe_ver = URI.escape(version_name)
88
+ @http.get(
89
+ rel("/packages/#{safe_username}/#{safe_repo}/#{safe_pkg}/versions/#{safe_ver}/files"),
90
+ auth_headers)
91
+ end
92
+
93
+ # Bintray username, URI-escaped.
94
+ #
95
+ # @return [String]
96
+ def safe_username
97
+ URI.escape(@username)
98
+ end
99
+
100
+ # Resolve a relative path into a URL using the current base_url
101
+ #
102
+ # @param slash_subpath [String]
103
+ # @return [String]
104
+ def rel(slash_subpath)
105
+ @base_url + slash_subpath
106
+ end
107
+
108
+ # @return [Hash]
109
+ def api_headers
110
+ { "Content-Type" => "application/json" }.update auth_headers
111
+ end
112
+
113
+ # Implement HTTP Basich Auth, as per RFC 7617.
114
+ #
115
+ # Let's not bring in a library just for these two lines.
116
+ #
117
+ # @return [Hash]
118
+ def auth_headers
119
+ cred = Base64.strict_encode64("#{@username}:#{@api_key}")
120
+ { Authorization: "Basic #{cred}" }
121
+ end
122
+
123
+ end
124
+
125
+ end
@@ -0,0 +1,83 @@
1
+
2
+ require 'json'
3
+
4
+ module HomebrewAutomation
5
+ end
6
+
7
+ module HomebrewAutomation::Bintray
8
+
9
+ # A representation of a Bintray +Version+
10
+ #
11
+ # As per Bintray, a +Version+ is part of a +Package+ is part of a +Repository+.
12
+ class Version
13
+
14
+ # @param client [Client] Connection to Bintray servers
15
+ # @param repo_name [String]
16
+ # @param package_name [String]
17
+ # @param version_name [String]
18
+ def initialize(client, repo_name, package_name, version_name)
19
+ @client = client
20
+ @repo_name = repo_name
21
+ @package_name = package_name
22
+ @version_name = version_name
23
+ end
24
+
25
+ attr_reader :repo_name, :package_name, :version_name
26
+
27
+ # Create this +Version+
28
+ #
29
+ # This assumes the +Package+ and +Repository+ already exists. If they do
30
+ # not, consider creating them manually via the Bintray web UI.
31
+ def create!
32
+ @client.create_version(@repo_name, @package_name, @version_name)
33
+ end
34
+
35
+ # Upload a file to be part of this +Version+
36
+ #
37
+ # This is probably your Homebrew Bottle binary tarball.
38
+ #
39
+ # @param filename [String]
40
+ # @param content [String] the bytes in the file
41
+ def upload_file!(filename, content)
42
+ @client.upload_file(
43
+ @repo_name,
44
+ @package_name,
45
+ @version_name,
46
+ filename,
47
+ content)
48
+ end
49
+
50
+ # Download metadata about files that exist on Bintray for this +Version+
51
+ #
52
+ # @return [Hash] mapping from OS (as appears in part of the filenames) to sha256 checksum
53
+ def gather_bottles
54
+ resp = @client.get_all_files_in_version(@repo_name, @package_name, @version_name)
55
+ _assert_match((200..207), resp.code)
56
+ json = JSON.parse(resp.body)
57
+ _assert_match(Array, json)
58
+ pairs = json.map do |f|
59
+ os = _parse_for_os(f['name'])
60
+ checksum = f['sha256']
61
+ [os, checksum]
62
+ end
63
+ Hash[pairs]
64
+ end
65
+
66
+ def _assert_match(cond, x)
67
+ unless cond === x
68
+ p x
69
+ raise StandardError.new(x)
70
+ end
71
+ end
72
+
73
+ # @param bottle_filename [String] filename
74
+ # @return [String] OS name
75
+ def _parse_for_os(bottle_filename)
76
+ File.extname(
77
+ File.basename(bottle_filename, '.bottle.tar.gz')).
78
+ sub(/^\./, '')
79
+ end
80
+
81
+ end
82
+
83
+ end
@@ -1,4 +1,5 @@
1
1
 
2
+ require 'json'
2
3
 
3
4
  module HomebrewAutomation
4
5
 
@@ -0,0 +1,2 @@
1
+
2
+ require_relative 'cli/cli.rb'
@@ -0,0 +1,22 @@
1
+
2
+ require 'thor'
3
+
4
+ require_relative 'formula_commands.rb'
5
+ require_relative 'workflow_commands.rb'
6
+
7
+ module HomebrewAutomation
8
+ module CLI
9
+
10
+ class MyCliApp < Thor
11
+
12
+ desc 'formula (...)', 'Modify Formula DSL source (read stdin, write stdout)'
13
+ subcommand "formula", FormulaCommands
14
+
15
+ desc 'bottle (...)', 'Workflows for dealing with binary artifacts'
16
+ subcommand "bottle", WorkflowCommands
17
+
18
+ end
19
+
20
+ end
21
+ end
22
+
@@ -0,0 +1,31 @@
1
+
2
+ require 'thor'
3
+
4
+ require_relative '../../homebrew_automation/formula.rb'
5
+
6
+ module HomebrewAutomation
7
+ module CLI
8
+ end
9
+ end
10
+
11
+ class HomebrewAutomation::CLI::FormulaCommands < Thor
12
+
13
+ desc 'put-sdist', 'Update the URL and sha256 checksum of the source tarball'
14
+ option :url, :required => true
15
+ option :sha256, :required => true
16
+ def put_sdist
17
+ before = HomebrewAutomation::Formula.parse_string($stdin.read)
18
+ after = before.put_sdist options[:url], options[:sha256]
19
+ $stdout.write after
20
+ end
21
+
22
+ desc 'put-bottle', 'Insert or update a bottle reference for a given OS'
23
+ option :os, :required => true
24
+ option :sha256, :required => true
25
+ def put_bottle
26
+ before = HomebrewAutomation::Formula.parse_string($stdin.read)
27
+ after = before.put_bottle(options[:os], options[:sha256])
28
+ $stdout.write after
29
+ end
30
+
31
+ end
@@ -0,0 +1,84 @@
1
+
2
+ require 'thor'
3
+
4
+ require_relative '../../homebrew_automation.rb'
5
+
6
+ module HomebrewAutomation
7
+ module CLI
8
+ end
9
+ end
10
+
11
+ class HomebrewAutomation::CLI::WorkflowCommands < Thor
12
+ class_option :source_user, :required => true
13
+ class_option :source_repo, :required => true
14
+ class_option :source_tag, :required => true
15
+ class_option :tap_user, :required => true
16
+ class_option :tap_repo, :required => true
17
+ class_option :tap_token, :required => true
18
+ class_option :formula_name
19
+ class_option :bintray_user, :required => true
20
+ class_option :bintray_token, :required => true
21
+ class_option :bintray_repo
22
+ class_option :bintray_package
23
+ class_option :bintray_version
24
+
25
+ desc 'build-and-upload', 'Build binary tarball from source tarball, then upload to Bintray'
26
+ long_desc <<-HERE_HERE
27
+ Since we're uploading to Bintray, we need a Bintray API KEY at `bintray_token`.
28
+ HERE_HERE
29
+ def build_and_upload
30
+ workflow.build_and_upload_bottle(sdist, tap, formula_name, bintray_version)
31
+ end
32
+
33
+ desc 'gather-and-publish', 'Make the Tap aware of new Bottles'
34
+ long_desc <<-HERE_HERE
35
+ See what bottles have been built and uploaded to Bintray, then publish them into the Tap.
36
+
37
+ Since we're publishing updates to the Formula in our Tap, we need Git push access to the
38
+ Tap repo on Github via a Github OAuth token via `tap_token`.
39
+ HERE_HERE
40
+ def gather_and_publish
41
+ workflow.gather_and_publish_bottles(sdist, tap, formula_name, bintray_version)
42
+ end
43
+
44
+ private
45
+
46
+ def sdist
47
+ HomebrewAutomation::SourceDist.new(
48
+ options[:source_user],
49
+ options[:source_repo],
50
+ options[:source_tag])
51
+ end
52
+
53
+ def tap
54
+ HomebrewAutomation::Tap.new(
55
+ options[:tap_user],
56
+ options[:tap_repo],
57
+ options[:tap_token])
58
+ end
59
+
60
+ # DOC: default values here
61
+ def formula_name
62
+ options[:formula_name] || sdist.repo
63
+ end
64
+
65
+ def bintray_client
66
+ HomebrewAutomation::Bintray::Client.new(
67
+ options[:bintray_user],
68
+ options[:bintray_token])
69
+ end
70
+
71
+ # DOC: default values here
72
+ def bintray_version
73
+ HomebrewAutomation::Bintray::Version.new(
74
+ bintray_client,
75
+ options[:bintray_repo] || "homebrew-bottles",
76
+ options[:bintray_package] || sdist.repo,
77
+ options[:bintray_version] || sdist.tag.sub(/^v/, ''))
78
+ end
79
+
80
+ def workflow
81
+ HomebrewAutomation::Workflow.new
82
+ end
83
+
84
+ end
@@ -82,6 +82,20 @@ module HomebrewAutomation
82
82
  put_bottle_version(os, sha256))
83
83
  end
84
84
 
85
+ # Remove sha256 references to all bottles
86
+ #
87
+ # This may leave the Formula in a non-standard state. Please add at lease
88
+ # one bottle referene back, otherwise why are you even declaring a bottles block
89
+ # at all.
90
+ #
91
+ # @return [Formula] a new instance of Formula with the changes applied
92
+ def rm_all_bottles
93
+ Formula.new update(
94
+ @ast,
95
+ bot_begin_path,
96
+ rm_all_bottle_sha256s)
97
+ end
98
+
85
99
  # Both formulae are +==+, as per +Parser::AST::Node#==+.
86
100
  #
87
101
  # In practice, I think this means both formulae are equivalent in terms of
@@ -137,6 +151,18 @@ module HomebrewAutomation
137
151
  }
138
152
  end
139
153
 
154
+ # Drop all bottles
155
+ # rm_all_bottle_sha256s :: Proc (Node -> Node)
156
+ def rm_all_bottle_sha256s
157
+ -> (bot_begin) {
158
+ bot_begin.updated(
159
+ nil, # keep the node type unchanged
160
+ bot_begin.children.reject(
161
+ # Get ride of all bottles condtionlessly
162
+ &by_msg('sha256')))
163
+ }
164
+ end
165
+
140
166
  # Build a new AST Node
141
167
  # String -> String -> Node
142
168
  def new_sha256 sha256, os
@@ -11,7 +11,12 @@ module HomebrewAutomation
11
11
  #
12
12
  # @return [String]
13
13
  def self.identify_version
14
- version = `sw_vers -productVersion`
14
+ version =
15
+ begin
16
+ `sw_vers -productVersion`
17
+ rescue Errno::ENOENT # if we're not on a Mac
18
+ nil
19
+ end
15
20
  mac_to_homebrew.
16
21
  select { |pattern, _| pattern === version }.
17
22
  map { |_, description| description }.
@@ -7,10 +7,11 @@ module HomebrewAutomation
7
7
  class SourceDist
8
8
 
9
9
  # Assign args to attributes {#user}, {#repo}, {#tag}
10
- def initialize user, repo, tag
10
+ def initialize user, repo, tag, http: RestClient
11
11
  @user = user
12
12
  @repo = repo
13
13
  @tag = tag
14
+ @http = http
14
15
  end
15
16
 
16
17
  # Github username, as appears in Github URLs
@@ -41,12 +42,11 @@ module HomebrewAutomation
41
42
  #
42
43
  # Lazy and memoized.
43
44
  #
44
- # @param fake [String] inject fake file contents (for testing)
45
45
  # @return [String] contents of the file
46
- def contents fake: nil
47
- @contents = @contents || fake ||
46
+ def contents
47
+ @contents = @contents ||
48
48
  begin
49
- resp = RestClient.get url
49
+ resp = @http.get url
50
50
  case resp.code
51
51
  when 200
52
52
  resp.body.to_s
@@ -18,15 +18,15 @@ module HomebrewAutomation
18
18
  @keep_submodule = keep_submodule
19
19
  end
20
20
 
21
- # Github username, as appears in Github URLs
21
+ # Github repo name, as appears in Github URLs
22
22
  #
23
23
  # @return [String]
24
- attr_reader :user
24
+ attr_reader :repo
25
25
 
26
- # Github repo name, as appears in Github URLs
26
+ # Repo URL, as expected by Git
27
27
  #
28
28
  # @return [String]
29
- attr_reader :repo
29
+ attr_reader :url
30
30
 
31
31
  # Github OAuth token
32
32
  #
@@ -63,9 +63,9 @@ module HomebrewAutomation
63
63
  # @return [Formula] as returned from the block,
64
64
  # assuming it obediantly returns a {Formula}.
65
65
  def on_formula(formula, &block)
66
- name = "#{formula}.rb"
66
+ name = "#{formula}.rb" # DOC
67
67
  block ||= ->(n) { n }
68
- Dir.chdir 'Formula' do
68
+ Dir.chdir 'Formula' do # DOC
69
69
  File.open name, 'r' do |old_file|
70
70
  File.open "#{name}.new", 'w' do |new_file|
71
71
  new_file.write(
@@ -2,6 +2,6 @@
2
2
  module HomebrewAutomation
3
3
 
4
4
  # Yep.
5
- VERSION = '0.0.9'
5
+ VERSION = '0.1.0'
6
6
 
7
7
  end
@@ -1,6 +1,7 @@
1
1
 
2
- require_relative './mac-os.rb'
3
- require_relative './bottle_gatherer.rb'
2
+ require_relative './mac_os.rb'
3
+ require_relative './bintray.rb'
4
+ require_relative './source_dist.rb'
4
5
 
5
6
  module HomebrewAutomation
6
7
 
@@ -9,71 +10,31 @@ module HomebrewAutomation
9
10
  # Each method in this class probably makes sense to be exposed as a CLI command.
10
11
  class Workflow
11
12
 
12
- # Assign params to attributes.
13
- #
14
- # See {#tap} and {#bintray}.
15
- #
16
- # @param tap [Tap]
17
- # @param bintray [Bintray]
18
- # @param bintray_bottle_repo [String] Really should be somehow a part of the +bintray+ param
19
- def initialize(
20
- tap,
21
- bintray,
22
- bintray_bottle_repo: 'homebrew-bottles')
23
- @tap = tap
24
- @bintray = bintray
25
- @bintray_bottle_repo = bintray_bottle_repo
26
- end
27
-
28
- # The Tap holding the Formulae for which we might want to build or publish bottles.
29
- #
30
- # @return [Tap]
31
- attr_reader :tap
32
-
33
- # An API client
34
- #
35
- # @return [Bintray]
36
- attr_reader :bintray
37
-
38
13
  # Build and upload a bottle.
39
14
  #
40
- # The Formula source comes from +source_dist+, and the Bottle tarball that
41
- # is built goes to {#bintray}.
15
+ # The built Bottle tarball gets uploaded to Bintray.
42
16
  #
43
- # +source_dist+ not only specifies the source tarball, but it also implies:
44
- # - the formula name, as appears in the {#tap}, via {SourceDist#repo};
45
- # - the Bintray package version, as to be uploaded, via {SourceDist#tag}, with any leading +v+ stripped off.
46
- #
47
- # The optional params overwrite the above implication.
48
- #
49
- # @param source_dist [HomebrewAutomation::SourceDist] Source tarball
50
- # @param formula_name [String] Formula name as appears in the Tap, which should be the same as the Bintray "Package" name
51
- # @param version_name [String] Bintray package "Version" name; defaults to stripping leading `v` from the Git tag.
17
+ # @param sdist [SourceDist]
18
+ # @param tap [Tap]
19
+ # @param formula_name [String] the name of the formula in the Tap
20
+ # @param bversion [Bintray::Version]
52
21
  # @return [Bottle]
53
- def build_and_upload_bottle(source_dist, formula_name: nil, version_name: nil)
54
- formula_name ||= source_dist.repo
55
- version_name ||= source_dist.tag.sub(/^v/, '')
22
+ def build_and_upload_bottle(sdist, tap, formula_name, bversion)
56
23
  os_name = MacOS.identify_version
57
- @tap.with_git_clone do
58
- @tap.on_formula(formula_name) do |formula|
59
- formula.put_sdist(source_dist.url, source_dist.sha256)
24
+ tap.with_git_clone do
25
+ tap.on_formula(formula_name) do |formula|
26
+ formula.put_sdist(sdist.url, sdist.sha256)
60
27
  end
61
- @tap.git_commit_am "Throwaway commit; just for building bottles"
28
+ tap.git_commit_am "Throwaway commit; just for building bottles"
62
29
 
63
30
  local_tap_url = File.realpath('.')
64
31
  bottle = Bottle.new(local_tap_url, formula_name, os_name)
65
32
  bottle.build
66
33
 
67
- @bintray.create_version(
68
- @bintray_bottle_repo,
69
- formula_name,
70
- version_name)
71
- @bintray.upload_file(
72
- @bintray_bottle_repo,
73
- formula_name,
74
- version_name,
75
- bottle.filename,
76
- bottle.content)
34
+ # Bintray auto-creates Versions on file-upload.
35
+ # Re-creating an existing Version results in a 409.
36
+ #bversion.create!
37
+ bversion.upload_file!(bottle.filename, bottle.content)
77
38
 
78
39
  bottle
79
40
  end
@@ -86,34 +47,29 @@ module HomebrewAutomation
86
47
  # the {#tap} repository to make an existing Formula aware of the Bottles
87
48
  # we're gathered (as such "publishing" the bottles).
88
49
  #
89
- # @param formula_name [String] Both the Formula name in the Tap repo, and the Package name in the Bintray repo.
90
- # @param version_name [String] Bintray "Version" name; not a Git tag.
50
+ # @param sdist [SourceDist]
51
+ # @param tap [Tap]
52
+ # @param formula_name [String] the name of the formula in the Tap
53
+ # @param bversion [Bintray::Version]
91
54
  # @return [Formula]
92
- def gather_and_publish_bottles(formula_name, version_name)
93
- @tap.with_git_clone do
94
- resp = @bintray.get_all_files_in_version(
95
- @bintray_bottle_repo,
96
- formula_name,
97
- version_name)
98
- unless (200..207) === resp.code
99
- puts resp
100
- raise StandardError.new(resp)
55
+ def gather_and_publish_bottles(sdist, tap, formula_name, bversion)
56
+ tap.with_git_clone do
57
+ tap.on_formula(formula_name) do |formula|
58
+ bottles = bversion.gather_bottles
59
+ bottles.reduce(
60
+ formula.
61
+ put_sdist(sdist.url, sdist.sha256).
62
+ rm_all_bottles
63
+ ) do |f, (os, checksum)|
64
+ f.put_bottle(os, checksum)
65
+ end
101
66
  end
102
-
103
- json = JSON.parse(resp.body)
104
- gatherer = BottleGatherer.new(json)
105
-
106
- @tap.on_formula(formula_name) do |formula|
107
- gatherer.put_bottles_into(formula)
108
- end
109
-
110
- @tap.git_config
111
- @tap.git_commit_am "Add bottles for #{formula_name}@#{version_name}"
112
- @tap.git_push
67
+ tap.git_config
68
+ tap.git_commit_am "Add bottles for #{formula_name}@#{bversion.version_name}"
69
+ tap.git_push
113
70
  end
114
71
  end
115
72
 
116
-
117
73
  end
118
74
 
119
75
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: homebrew_automation
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - easoncxz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-03 00:00:00.000000000 Z
11
+ date: 2019-08-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: ripper-tags
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: thor
71
85
  requirement: !ruby/object:Gem::Requirement
@@ -132,10 +146,15 @@ files:
132
146
  - bin/homebrew_automation.rb
133
147
  - lib/homebrew_automation.rb
134
148
  - lib/homebrew_automation/bintray.rb
149
+ - lib/homebrew_automation/bintray/client.rb
150
+ - lib/homebrew_automation/bintray/version.rb
135
151
  - lib/homebrew_automation/bottle.rb
136
- - lib/homebrew_automation/bottle_gatherer.rb
152
+ - lib/homebrew_automation/cli.rb
153
+ - lib/homebrew_automation/cli/cli.rb
154
+ - lib/homebrew_automation/cli/formula_commands.rb
155
+ - lib/homebrew_automation/cli/workflow_commands.rb
137
156
  - lib/homebrew_automation/formula.rb
138
- - lib/homebrew_automation/mac-os.rb
157
+ - lib/homebrew_automation/mac_os.rb
139
158
  - lib/homebrew_automation/source_dist.rb
140
159
  - lib/homebrew_automation/tap.rb
141
160
  - lib/homebrew_automation/version.rb
@@ -160,7 +179,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
179
  - !ruby/object:Gem::Version
161
180
  version: '0'
162
181
  requirements: []
163
- rubygems_version: 3.0.2
182
+ rubyforge_project:
183
+ rubygems_version: 2.7.7
164
184
  signing_key:
165
185
  specification_version: 4
166
186
  summary: Build bottles and update Formulae
@@ -1,49 +0,0 @@
1
-
2
- require_relative './mac-os.rb'
3
- require_relative './formula.rb'
4
-
5
- module HomebrewAutomation
6
-
7
- # See what Bottles have already been built and uploaded to Bintray
8
- class BottleGatherer
9
-
10
- # @param json [Array<Hash>] JSON from a +RestClient::Response+ containing the list of files from Bintray
11
- def initialize(json)
12
- @json = json
13
- @bottles = nil
14
- end
15
-
16
- # The bottles gathered.
17
- #
18
- # @return [Hash<String, String>] with keys being OS names (in Homebrew-form) and values being SHA256 checksums
19
- def bottles
20
- return @bottles if @bottles
21
- pairs = @json.map do |f|
22
- os = _parse_for_os(f['name'])
23
- checksum = f['sha256']
24
- [os, checksum]
25
- end
26
- @bottles = Hash[pairs]
27
- end
28
-
29
- # Put all bottles gathered here into the given formula, then return the result
30
- #
31
- # @param formula [HomebrewAutomation::Formula]
32
- # @return [HomebrewAutomation::Formula]
33
- def put_bottles_into(formula)
34
- bottles.reduce(formula) do |formula, (os, checksum)|
35
- formula.put_bottle(os, checksum)
36
- end
37
- end
38
-
39
- # @param bottle_filename [String] filename
40
- # @return [String] OS name
41
- def _parse_for_os(bottle_filename)
42
- File.extname(
43
- File.basename(bottle_filename, '.bottle.tar.gz')).
44
- sub(/^\./, '')
45
- end
46
-
47
- end
48
-
49
- end