homebrew_automation 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 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