stove 1.0.1 → 1.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 +4 -4
- data/README.md +28 -3
- data/Rakefile +1 -1
- data/features/changelog.feature +0 -4
- data/features/cli.feature +0 -4
- data/features/devodd.feature +19 -0
- data/features/git.feature +6 -4
- data/features/rake.feature +16 -0
- data/features/step_definitions/cli_steps.rb +10 -5
- data/features/step_definitions/community_site_steps.rb +2 -2
- data/features/step_definitions/git_steps.rb +8 -0
- data/features/support/env.rb +11 -3
- data/features/upload.feature +0 -4
- data/lib/stove.rb +1 -0
- data/lib/stove/cli.rb +21 -10
- data/lib/stove/cookbook.rb +123 -77
- data/lib/stove/error.rb +9 -1
- data/lib/stove/git.rb +8 -0
- data/lib/stove/github.rb +43 -0
- data/lib/stove/rake_task.rb +63 -0
- data/lib/stove/uploader.rb +2 -11
- data/lib/stove/version.rb +1 -1
- data/spec/support/git.rb +1 -0
- data/stove.gemspec +2 -0
- metadata +36 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6543792d8f0805391fd56ad612836f4413ebdd0
|
4
|
+
data.tar.gz: b67ea0a0cd771ef510e11bc2cbe2ea46e6caacdb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: abfe99a45ed6757bff3e795689ab838cb1672d8c55013219d78ba890804e6aae0456d1c79891d41430dbc60d95614e235431b23e7872761d4bc4e8c42149852b
|
7
|
+
data.tar.gz: 789afa789f2f99fd3573b6206374df791347223c556301e6fba5f60157724ea13612b09faea91ac4674cdb58f803335434d082cd761a7e98af88299bd71e5dca
|
data/README.md
CHANGED
@@ -11,7 +11,8 @@ A utility for releasing and managing Chef Cookbooks. It will:
|
|
11
11
|
- Create a CHANGELOG from JIRA tickets
|
12
12
|
- Commit and push these changes to git
|
13
13
|
- Create a git tag and push those changes to git
|
14
|
-
-
|
14
|
+
- Publish a release to GitHub releases
|
15
|
+
- Upload the cookbook to the Opscode Community Site
|
15
16
|
- Resolve (close) the JIRA tickets
|
16
17
|
|
17
18
|
|
@@ -39,10 +40,17 @@ Create a special JIRA credentials file at '~/.stove' that has the following JSON
|
|
39
40
|
"jira_username": "JIRA_USERNAME",
|
40
41
|
"jira_password": "JIRA_PASSWORD",
|
41
42
|
"opscode_username": "OPSCODE_USERNAME",
|
42
|
-
"opscode_pem_file": "OPSCODE_PEM_FILE"
|
43
|
+
"opscode_pem_file": "OPSCODE_PEM_FILE",
|
44
|
+
"github_access_token": "PERSONAL_API_TOKEN"
|
43
45
|
}
|
44
46
|
```
|
45
47
|
|
48
|
+
- `jira_username` - The username used to login to Opscode's JIRA
|
49
|
+
- `jira_password` - The password used to login to Opscode's JIRA
|
50
|
+
- `opscode_username` - The username used to login to Opscode's Community Site
|
51
|
+
- `opscode_password` - The password used to login to Opscode's Community Site
|
52
|
+
- `github_access_token` - Your personal access token for the GitHub API
|
53
|
+
|
46
54
|
For example:
|
47
55
|
|
48
56
|
```javascript
|
@@ -50,7 +58,8 @@ For example:
|
|
50
58
|
"jira_username": "sethvargo",
|
51
59
|
"jira_password": "bAc0ñ",
|
52
60
|
"opscode_username": "sethvargo",
|
53
|
-
"opscode_pem_file": "~/.chef/sethvargo.pem"
|
61
|
+
"opscode_pem_file": "~/.chef/sethvargo.pem",
|
62
|
+
"github_access_token": "abcdefg1234567"
|
54
63
|
}
|
55
64
|
```
|
56
65
|
|
@@ -67,8 +76,10 @@ Usage: bake x.y.z
|
|
67
76
|
-c, --category [CATEGORY] The category for the cookbook (optional for existing cookbooks)
|
68
77
|
-p, --path [PATH] The path to the cookbook to release (default: PWD)
|
69
78
|
--[no-]git Automatically tag and push to git (default: true)
|
79
|
+
--[no-]github Automatically release to GitHub (default: true)
|
70
80
|
-r, --remote The name of the git remote to push to
|
71
81
|
-b, --branch The name of the git branch to push to
|
82
|
+
--[no-]devodd Automatically bump the metadata for devodd releases
|
72
83
|
--[no-]jira Automatically populate the CHANGELOG from JIRA tickets and close them (default: false)
|
73
84
|
--[no-]upload Upload the cookbook to the Opscode Community Site (default: true)
|
74
85
|
--[no-]changelog Automatically generate a CHANGELOG (default: true)
|
@@ -77,6 +88,20 @@ Usage: bake x.y.z
|
|
77
88
|
```
|
78
89
|
|
79
90
|
|
91
|
+
Rake Task
|
92
|
+
---------
|
93
|
+
Stove also includes a Rake task you can include in your Rakefile:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
require 'stove/rake_task'
|
97
|
+
|
98
|
+
Stove::RakeTask.new do |stove|
|
99
|
+
stove.git = true
|
100
|
+
stove.devodd = true
|
101
|
+
end
|
102
|
+
```
|
103
|
+
|
104
|
+
|
80
105
|
Contributing
|
81
106
|
------------
|
82
107
|
1. Fork it
|
data/Rakefile
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
data/features/changelog.feature
CHANGED
data/features/cli.feature
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
Feature: Devodd
|
2
|
+
Background:
|
3
|
+
* the CLI options are all off
|
4
|
+
* I have a cookbook named "bacon"
|
5
|
+
|
6
|
+
Scenario: --no-devodd
|
7
|
+
* I successfully run `bake 1.0.0 --no-devodd`
|
8
|
+
|
9
|
+
Scenario: --devodd
|
10
|
+
* I successfully run `bake 1.0.0 --devodd`
|
11
|
+
* the file "metadata.rb" should contain:
|
12
|
+
"""
|
13
|
+
version '1.0.1'
|
14
|
+
"""
|
15
|
+
|
16
|
+
Scenario: --git --devodd
|
17
|
+
* I have a cookbook named "bacon" with git support
|
18
|
+
* I successfully run `bake 1.0.0 --devodd --git`
|
19
|
+
* the git remote will have the commit "Version bump to v1.0.1"
|
data/features/git.feature
CHANGED
@@ -1,8 +1,4 @@
|
|
1
1
|
Feature: Git
|
2
|
-
As a stove user
|
3
|
-
In order to have a useful git tree
|
4
|
-
I want to automatically tag and push to git
|
5
|
-
|
6
2
|
Background:
|
7
3
|
* the CLI options are all off
|
8
4
|
|
@@ -30,3 +26,9 @@ Feature: Git
|
|
30
26
|
* I have a cookbook named "bacon"
|
31
27
|
* I run `bake 1.0.0 --git`
|
32
28
|
* the exit status will be "GitError::NotARepo"
|
29
|
+
|
30
|
+
Scenario: Remote repository out of sync
|
31
|
+
* I have a cookbook named "bacon" with git support
|
32
|
+
* the remote repository has additional commits
|
33
|
+
* I run `bake 1.0.0 --git`
|
34
|
+
* the exit status will be "GitError::OutOfSync"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
@spawn
|
2
|
+
Feature: Rake Task
|
3
|
+
Background:
|
4
|
+
* I have a cookbook named "bacon"
|
5
|
+
|
6
|
+
Scenario: Using rake to publish a cookbook
|
7
|
+
* I write to "Rakefile" with:
|
8
|
+
"""
|
9
|
+
require 'stove/rake_task'
|
10
|
+
Stove::RakeTask.new
|
11
|
+
"""
|
12
|
+
* I successfully run `rake -T`
|
13
|
+
* the output should contain:
|
14
|
+
"""
|
15
|
+
rake publish # Publish this cookbook
|
16
|
+
"""
|
@@ -13,11 +13,16 @@ When /^the CLI options are all off$/ do
|
|
13
13
|
private
|
14
14
|
def options
|
15
15
|
@options ||= {
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
16
|
+
path: Dir.pwd,
|
17
|
+
git: false,
|
18
|
+
github: false,
|
19
|
+
devodd: false,
|
20
|
+
remote: 'origin',
|
21
|
+
branch: 'master',
|
22
|
+
jira: false,
|
23
|
+
upload: false,
|
24
|
+
changelog: false,
|
25
|
+
log_level: :fatal,
|
21
26
|
}
|
22
27
|
end
|
23
28
|
end
|
@@ -1,3 +1,11 @@
|
|
1
|
+
Given /^the remote repository has additional commits/ do
|
2
|
+
Dir.chdir(fake_git_remote) do
|
3
|
+
shellout 'touch myfile.txt'
|
4
|
+
git 'add myfile.txt'
|
5
|
+
git 'commit -m "Add a new file"'
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
1
9
|
Then /^the git remote will( not)? have the commit "(.+)"$/ do |negate, message|
|
2
10
|
commits = git_commits(fake_git_remote)
|
3
11
|
|
data/features/support/env.rb
CHANGED
@@ -10,13 +10,12 @@ require_relative '../../spec/support/git'
|
|
10
10
|
World(Aruba::Api)
|
11
11
|
World(Stove::RSpec::Git)
|
12
12
|
|
13
|
-
Aruba::InProcess.main_class = Stove::Cli
|
14
|
-
Aruba.process = Aruba::InProcess
|
15
|
-
|
16
13
|
Stove.set_formatter(:silent)
|
17
14
|
Stove::Config.instance_variable_set(:@instance, {
|
18
15
|
'jira_username' => 'default',
|
19
16
|
'jira_password' => 'default',
|
17
|
+
'github_usernmae' => 'default',
|
18
|
+
'github_password' => 'default',
|
20
19
|
'opscode_username' => 'stove',
|
21
20
|
'opscode_pem_file' => File.expand_path(File.join(__FILE__, '..', 'stove.pem')),
|
22
21
|
})
|
@@ -29,6 +28,15 @@ Before do
|
|
29
28
|
Stove::RSpec::CommunitySite.reset!
|
30
29
|
end
|
31
30
|
|
31
|
+
Before('~@spawn') do
|
32
|
+
Aruba::InProcess.main_class = Stove::Cli
|
33
|
+
Aruba.process = Aruba::InProcess
|
34
|
+
end
|
35
|
+
|
36
|
+
Before('@spawn') do
|
37
|
+
Aruba.process = Aruba::SpawnProcess
|
38
|
+
end
|
39
|
+
|
32
40
|
# The path to Aruba's "stuff"
|
33
41
|
def tmp_path
|
34
42
|
File.expand_path(@dirs.first.to_s)
|
data/features/upload.feature
CHANGED
data/lib/stove.rb
CHANGED
data/lib/stove/cli.rb
CHANGED
@@ -54,14 +54,23 @@ module Stove
|
|
54
54
|
options[:git] = v
|
55
55
|
end
|
56
56
|
|
57
|
-
opts.on('-
|
57
|
+
opts.on('--[no-]github', 'Automatically release to GitHub (default: true)') do |v|
|
58
|
+
options[:git] = v if v
|
59
|
+
options[:github] = v
|
60
|
+
end
|
61
|
+
|
62
|
+
opts.on('-r', '--remote [REMOTE]', String, 'The name of the git remote to push to') do |v|
|
58
63
|
options[:remote] = v
|
59
64
|
end
|
60
65
|
|
61
|
-
opts.on('-b', '--branch', String, 'The name of the git branch to push to') do |v|
|
66
|
+
opts.on('-b', '--branch [BRANCH]', String, 'The name of the git branch to push to') do |v|
|
62
67
|
options[:branch] = v
|
63
68
|
end
|
64
69
|
|
70
|
+
opts.on('--[no-]devodd', 'Automatically bump the metadata for devodd releases') do |v|
|
71
|
+
options[:devodd] = v
|
72
|
+
end
|
73
|
+
|
65
74
|
opts.on('--[no-]jira', 'Automatically populate the CHANGELOG from JIRA tickets and close them (default: false)') do |v|
|
66
75
|
options[:jira] = v
|
67
76
|
end
|
@@ -92,14 +101,16 @@ module Stove
|
|
92
101
|
# @return [Hash]
|
93
102
|
def options
|
94
103
|
@options ||= {
|
95
|
-
:
|
96
|
-
:
|
97
|
-
:
|
98
|
-
:
|
99
|
-
:
|
100
|
-
:
|
101
|
-
:
|
102
|
-
:
|
104
|
+
path: Dir.pwd,
|
105
|
+
git: true,
|
106
|
+
github: true,
|
107
|
+
devodd: false,
|
108
|
+
remote: 'origin',
|
109
|
+
branch: 'master',
|
110
|
+
jira: false,
|
111
|
+
upload: true,
|
112
|
+
changelog: true,
|
113
|
+
log_level: :warn,
|
103
114
|
}
|
104
115
|
end
|
105
116
|
|
data/lib/stove/cookbook.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'fileutils'
|
2
|
+
require 'retryable'
|
2
3
|
require 'time'
|
3
4
|
|
4
5
|
module Stove
|
@@ -86,43 +87,143 @@ module Stove
|
|
86
87
|
#
|
87
88
|
def release!
|
88
89
|
if options[:git]
|
90
|
+
Stove::Logger.info "Running validations"
|
89
91
|
validate_git_repo!
|
90
92
|
validate_git_clean!
|
93
|
+
validate_remote_updated!
|
91
94
|
end
|
92
95
|
|
96
|
+
Stove::Logger.info "Bumping version"
|
93
97
|
version_bump
|
94
98
|
|
95
99
|
if options[:changelog]
|
100
|
+
Stove::Logger.info "Updating changelog"
|
96
101
|
update_changelog
|
97
102
|
end
|
98
103
|
|
99
104
|
if options[:git]
|
100
105
|
Dir.chdir(path) do
|
106
|
+
Stove::Logger.info "Committing git changes in '#{path}'"
|
107
|
+
|
101
108
|
git "add metadata.rb"
|
102
109
|
git "add CHANGELOG.md"
|
103
|
-
git "commit -m 'Version bump to
|
104
|
-
git "push #{options[:remote]
|
105
|
-
|
106
|
-
|
107
|
-
|
110
|
+
git "commit -m 'Version bump to #{tag_version}'"
|
111
|
+
git "push #{options[:remote]} #{options[:branch]}"
|
112
|
+
|
113
|
+
if options[:github]
|
114
|
+
Stove::Logger.info "Pushing release to GitHub"
|
115
|
+
Stove::GitHub.new(self).publish_release!
|
116
|
+
else
|
117
|
+
Stove::Logger.info "Tagging a release"
|
118
|
+
git "tag #{tag_version}"
|
119
|
+
git "push #{options[:remote]} #{tag_version}"
|
120
|
+
end
|
108
121
|
end
|
109
122
|
end
|
110
123
|
|
111
124
|
if options[:upload]
|
112
|
-
|
125
|
+
Stove::Logger.info "Uploading cookbook"
|
126
|
+
retryable(tries: 3) do
|
127
|
+
upload
|
128
|
+
end
|
113
129
|
end
|
114
130
|
|
115
131
|
if options[:jira]
|
132
|
+
Stove::Logger.info "Resolving JIRA issues"
|
116
133
|
resolve_jira_issues
|
117
134
|
end
|
135
|
+
|
136
|
+
if options[:devodd]
|
137
|
+
Stove::Logger.info "Bumping devodd release"
|
138
|
+
split = version.split('.').map(&:to_i)
|
139
|
+
split[2] += 1
|
140
|
+
devodd = split.join('.')
|
141
|
+
|
142
|
+
version_bump(devodd)
|
143
|
+
|
144
|
+
if options[:git]
|
145
|
+
Dir.chdir(path) do
|
146
|
+
git "add metadata.rb"
|
147
|
+
git "commit -m 'Version bump to #{tag_version}'"
|
148
|
+
git "push #{options[:remote]} #{options[:branch]}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def tag_version
|
155
|
+
"v#{version}"
|
156
|
+
end
|
157
|
+
|
158
|
+
# So there's this really really crazy bug that the tmp directory could
|
159
|
+
# be deleted mid-request...
|
160
|
+
#
|
161
|
+
# @return [File]
|
162
|
+
def tarball
|
163
|
+
return @tarball if @tarball && File.exists?(@tarball)
|
164
|
+
|
165
|
+
begin
|
166
|
+
@tarball = Stove::Packager.new(self).package_path
|
167
|
+
end until File.exists?(@tarball)
|
168
|
+
@tarball
|
118
169
|
end
|
119
170
|
|
120
171
|
#
|
121
172
|
def upload
|
122
|
-
return true unless options[:upload]
|
123
173
|
Stove::Uploader.new(self).upload!
|
124
174
|
end
|
125
175
|
|
176
|
+
# The URL for this repository on GitHub. This method automatically
|
177
|
+
# translates SSH and git:// URLs to https:// URLs.
|
178
|
+
#
|
179
|
+
# @return [String]
|
180
|
+
def repository_url
|
181
|
+
@repository_url ||= git("config --get remote.#{options[:remote]}.url")
|
182
|
+
.strip
|
183
|
+
.gsub(/\.git$/, '')
|
184
|
+
.gsub(':', '/')
|
185
|
+
.gsub('@', '://')
|
186
|
+
.gsub('git://', 'https://')
|
187
|
+
end
|
188
|
+
|
189
|
+
# The set of changes for this diff/patch in markdown format.
|
190
|
+
#
|
191
|
+
# @return [String]
|
192
|
+
def changeset
|
193
|
+
return @changeset if @changeset
|
194
|
+
|
195
|
+
contents = []
|
196
|
+
contents << "v#{version}"
|
197
|
+
contents << '-'*(version.length+1)
|
198
|
+
|
199
|
+
if options[:jira]
|
200
|
+
by_type = unreleased_tickets.inject({}) do |hash, ticket|
|
201
|
+
issue_type = ticket.fields.current['issuetype']['name']
|
202
|
+
hash[issue_type] ||= []
|
203
|
+
hash[issue_type] << {
|
204
|
+
number: ticket.jira_key,
|
205
|
+
details: ticket.fields.current['summary'],
|
206
|
+
}
|
207
|
+
|
208
|
+
hash
|
209
|
+
end
|
210
|
+
|
211
|
+
by_type.each do |issue_type, tickets|
|
212
|
+
contents << "### #{issue_type}"
|
213
|
+
tickets.sort { |a,b| b[:number].to_i <=> a[:number].to_i }.each do |ticket|
|
214
|
+
contents << "- **[#{ticket[:number]}](#{Stove::JIRA::JIRA_URL}/browse/#{ticket[:number]})** - #{ticket[:details]}"
|
215
|
+
end
|
216
|
+
contents << ""
|
217
|
+
end
|
218
|
+
else
|
219
|
+
contents << "_Enter CHANGELOG for #{name} (#{version}) here_"
|
220
|
+
contents << ""
|
221
|
+
end
|
222
|
+
|
223
|
+
@changeset = contents.join("\n")
|
224
|
+
@changeset
|
225
|
+
end
|
226
|
+
|
126
227
|
private
|
127
228
|
# Load the metadata and set the @metadata instance variable.
|
128
229
|
#
|
@@ -142,42 +243,15 @@ module Stove
|
|
142
243
|
end
|
143
244
|
alias_method :reload_metadata!, :load_metadata!
|
144
245
|
|
145
|
-
# Create a new CHANGELOG in markdown format.
|
146
|
-
#
|
147
|
-
# @example given a cookbook named bacon
|
148
|
-
# cookbook.create_changelog #=> <<EOH
|
149
|
-
# bacon Cookbook CHANGELOG
|
150
|
-
# ------------------------
|
151
|
-
# EOH
|
152
|
-
#
|
153
|
-
# @return [String]
|
154
|
-
# the path to the new CHANGELOG
|
155
|
-
def create_changelog
|
156
|
-
destination = File.join(path, 'CHANGELOG.md')
|
157
|
-
|
158
|
-
# Be idempotent :)
|
159
|
-
return destination if File.exists?(destination)
|
160
|
-
|
161
|
-
header = "#{name} Cookbook CHANGELOG\n"
|
162
|
-
header << "#{'='*header.length}\n"
|
163
|
-
header << "This file is used to list changes made in each version of the #{cookbook.name} cookbook.\n\n"
|
164
|
-
|
165
|
-
File.open(destination, 'wb') do |file|
|
166
|
-
file.write(header)
|
167
|
-
end
|
168
|
-
|
169
|
-
destination
|
170
|
-
end
|
171
|
-
|
172
246
|
# Update the CHANGELOG with the new contents, but inserting
|
173
247
|
# the newest version's CHANGELOG at the top of the file (after
|
174
248
|
# the header)
|
175
249
|
def update_changelog
|
176
|
-
changelog =
|
250
|
+
changelog = File.join(path, 'CHANGELOG.md')
|
177
251
|
contents = File.readlines(changelog)
|
178
252
|
|
179
253
|
index = contents.find_index { |line| line =~ /(--)+/ } - 2
|
180
|
-
contents.insert(index, "\n" +
|
254
|
+
contents.insert(index, "\n" + changeset)
|
181
255
|
|
182
256
|
Dir.mktmpdir do |dir|
|
183
257
|
tmpfile = File.join(dir, 'CHANGELOG.md')
|
@@ -195,56 +269,18 @@ module Stove
|
|
195
269
|
raise Stove::UserCanceledError
|
196
270
|
end
|
197
271
|
|
198
|
-
# Generate a CHANGELOG in markdown format.
|
199
|
-
#
|
200
|
-
# @param [String] version
|
201
|
-
# the version string in x.y.z format
|
202
|
-
#
|
203
|
-
# @return [String]
|
204
|
-
def generate_changelog
|
205
|
-
contents = []
|
206
|
-
contents << "v#{version}"
|
207
|
-
contents << '-'*(version.length+1)
|
208
|
-
|
209
|
-
if options[:jira]
|
210
|
-
by_type = unreleased_tickets.inject({}) do |hash, ticket|
|
211
|
-
issue_type = ticket.fields.current['issuetype']['name']
|
212
|
-
hash[issue_type] ||= []
|
213
|
-
hash[issue_type] << {
|
214
|
-
number: ticket.jira_key,
|
215
|
-
details: ticket.fields.current['summary'],
|
216
|
-
}
|
217
|
-
|
218
|
-
hash
|
219
|
-
end
|
220
|
-
|
221
|
-
by_type.each do |issue_type, tickets|
|
222
|
-
contents << "### #{issue_type}"
|
223
|
-
tickets.sort { |a,b| b[:number].to_i <=> a[:number].to_i }.each do |ticket|
|
224
|
-
contents << "- **[#{ticket[:number]}](#{Stove::JIRA::JIRA_URL}/browse/#{ticket[:number]})** - #{ticket[:details]}"
|
225
|
-
end
|
226
|
-
contents << ""
|
227
|
-
end
|
228
|
-
else
|
229
|
-
contents << "_Enter CHANGELOG for #{name} (#{version}) here_"
|
230
|
-
contents << ""
|
231
|
-
end
|
232
|
-
|
233
|
-
contents.join("\n")
|
234
|
-
end
|
235
|
-
|
236
272
|
# Bump the version in the metdata.rb to the specified
|
237
273
|
# parameter.
|
238
274
|
#
|
239
275
|
# @return [String]
|
240
276
|
# the new version string
|
241
|
-
def version_bump
|
242
|
-
return true if
|
277
|
+
def version_bump(bump_version = new_version)
|
278
|
+
return true if bump_version.to_s == version.to_s
|
243
279
|
|
244
280
|
metadata_path = File.join(path, 'metadata.rb')
|
245
281
|
contents = File.read(metadata_path)
|
246
282
|
|
247
|
-
contents.sub!(/^version(\s+)('|")#{version.to_s}('|")/, "version\\1\\2#{
|
283
|
+
contents.sub!(/^version(\s+)('|")#{version.to_s}('|")/, "version\\1\\2#{bump_version.to_s}\\3")
|
248
284
|
|
249
285
|
File.open(metadata_path, 'w') { |f| f.write(contents) }
|
250
286
|
reload_metadata!
|
@@ -276,5 +312,15 @@ module Stove
|
|
276
312
|
raise Stove::GitError::DirtyRepo unless git_repo_clean?
|
277
313
|
end
|
278
314
|
end
|
315
|
+
|
316
|
+
# Validate that the remote git repository is up to date.
|
317
|
+
#
|
318
|
+
# @raise [Stove::GitError::OutOfSync]
|
319
|
+
# if the current git repo is not up to date with the remote
|
320
|
+
def validate_remote_updated!
|
321
|
+
Dir.chdir(path) do
|
322
|
+
raise Stove::GitError::OutOfSync unless git_remote_uptodate?(options)
|
323
|
+
end
|
324
|
+
end
|
279
325
|
end
|
280
326
|
end
|
data/lib/stove/error.rb
CHANGED
@@ -70,6 +70,14 @@ module Stove
|
|
70
70
|
'You have untracked files!'
|
71
71
|
end
|
72
72
|
end
|
73
|
+
|
74
|
+
class OutOfSync < GitError
|
75
|
+
set_exit_code 133
|
76
|
+
|
77
|
+
def message
|
78
|
+
'Your remote repository is out of sync!'
|
79
|
+
end
|
80
|
+
end
|
73
81
|
end
|
74
82
|
|
75
83
|
class UploadError < Error
|
@@ -81,7 +89,7 @@ module Stove
|
|
81
89
|
|
82
90
|
def message
|
83
91
|
"The following errors occured when uploading:\n" <<
|
84
|
-
@response.parsed_response['error_messages'].map do |error|
|
92
|
+
(@response.parsed_response['error_messages'] || []).map do |error|
|
85
93
|
" - #{error}"
|
86
94
|
end.join("\n")
|
87
95
|
end
|
data/lib/stove/git.rb
CHANGED
@@ -44,6 +44,14 @@ module Stove
|
|
44
44
|
false
|
45
45
|
end
|
46
46
|
|
47
|
+
def git_remote_uptodate?(options = {})
|
48
|
+
git('fetch')
|
49
|
+
local = git("rev-parse #{options[:branch]}").strip
|
50
|
+
remote = git("rev-parse #{options[:remote]}/#{options[:branch]}").strip
|
51
|
+
|
52
|
+
local == remote
|
53
|
+
end
|
54
|
+
|
47
55
|
def shellout(command)
|
48
56
|
out, err = Tempfile.new('shellout.stdout'), Tempfile.new('shellout.stderr')
|
49
57
|
|
data/lib/stove/github.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'octokit'
|
2
|
+
|
3
|
+
module Stove
|
4
|
+
class GitHub
|
5
|
+
attr_reader :cookbook
|
6
|
+
|
7
|
+
def initialize(cookbook)
|
8
|
+
@cookbook = cookbook
|
9
|
+
|
10
|
+
Octokit.configure do |config|
|
11
|
+
config.access_token = Stove::Config['github_access_token']
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def publish_release!
|
16
|
+
release = Octokit.create_release(repository, cookbook.tag_version,
|
17
|
+
name: cookbook.tag_version,
|
18
|
+
body: changeset,
|
19
|
+
)
|
20
|
+
asset = Octokit.upload_asset("repos/#{repository}/releases/#{release.id}", cookbook.tarball,
|
21
|
+
content_type: 'application/x-gzip',
|
22
|
+
name: filename,
|
23
|
+
)
|
24
|
+
Octokit.update_release_asset("repos/#{repository}/releases/assets/#{asset.id}",
|
25
|
+
name: filename,
|
26
|
+
label: 'Download Cookbook',
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def repository
|
32
|
+
@repository ||= Octokit::Repository.from_url(cookbook.repository_url)
|
33
|
+
end
|
34
|
+
|
35
|
+
def changeset
|
36
|
+
cookbook.changeset.split("\n")[2..-1].join("\n").strip
|
37
|
+
end
|
38
|
+
|
39
|
+
def filename
|
40
|
+
@filename ||= "#{cookbook.name}-#{cookbook.version}.tar.gz"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/tasklib'
|
3
|
+
|
4
|
+
module Stove
|
5
|
+
#
|
6
|
+
# Run Stove tasks from your +Rakefile+.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# desc "Run stove tasks"
|
10
|
+
# Stove::RakeTask.new(:release) do |stove|
|
11
|
+
# stove.git = true
|
12
|
+
# stove.devodd = true
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
class RakeTask < ::Rake::TaskLib
|
16
|
+
class << self
|
17
|
+
#
|
18
|
+
# Define a CLI option.
|
19
|
+
#
|
20
|
+
# @param [Symbol] option
|
21
|
+
#
|
22
|
+
def cli_option(option)
|
23
|
+
define_method("#{option}=".to_sym) do |value|
|
24
|
+
options[option] = value
|
25
|
+
end
|
26
|
+
|
27
|
+
define_method(option.to_sym) do
|
28
|
+
options[option]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [Symbol]
|
34
|
+
attr_accessor :name
|
35
|
+
|
36
|
+
# @return [Hash]
|
37
|
+
attr_reader :options
|
38
|
+
|
39
|
+
def initialize(task_name = nil)
|
40
|
+
@options = {}
|
41
|
+
@name = (task_name || :publish).to_sym
|
42
|
+
|
43
|
+
yield self if block_given?
|
44
|
+
|
45
|
+
desc 'Publish this cookbook' unless ::Rake.application.last_comment
|
46
|
+
task name do |t, args|
|
47
|
+
require 'stove'
|
48
|
+
Stove::Cookbook.new(options).release!
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
cli_option :branch
|
53
|
+
cli_option :category
|
54
|
+
cli_option :changelog
|
55
|
+
cli_option :devodd
|
56
|
+
cli_option :git
|
57
|
+
cli_option :jira
|
58
|
+
cli_option :log_level
|
59
|
+
cli_option :path
|
60
|
+
cli_option :remote
|
61
|
+
cli_option :upload
|
62
|
+
end
|
63
|
+
end
|
data/lib/stove/uploader.rb
CHANGED
@@ -24,7 +24,7 @@ module Stove
|
|
24
24
|
response = self.class.post(upload_url, {
|
25
25
|
:headers => headers,
|
26
26
|
:query => {
|
27
|
-
:tarball => File.new(tarball),
|
27
|
+
:tarball => File.new(cookbook.tarball),
|
28
28
|
:cookbook => { category: cookbook.category }.to_json,
|
29
29
|
},
|
30
30
|
})
|
@@ -45,19 +45,10 @@ module Stove
|
|
45
45
|
:timestamp => Time.now.utc.iso8601,
|
46
46
|
:user_id => username,
|
47
47
|
:path => URI.parse(upload_url).path,
|
48
|
-
:file => File.new(tarball),
|
48
|
+
:file => File.new(cookbook.tarball),
|
49
49
|
}).sign(pem_file))
|
50
50
|
end
|
51
51
|
|
52
|
-
# So there's this really really crazy bug that the tmp directory could
|
53
|
-
# be deleted mid-request...
|
54
|
-
def tarball
|
55
|
-
begin
|
56
|
-
tgz = Stove::Packager.new(cookbook).package_path
|
57
|
-
end until File.exists?(tgz)
|
58
|
-
tgz
|
59
|
-
end
|
60
|
-
|
61
52
|
def pem_file
|
62
53
|
OpenSSL::PKey::RSA.new(File.read(File.expand_path(Stove::Config['opscode_pem_file'])))
|
63
54
|
end
|
data/lib/stove/version.rb
CHANGED
data/spec/support/git.rb
CHANGED
data/stove.gemspec
CHANGED
@@ -23,6 +23,8 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_dependency 'jiralicious', '~> 0.3'
|
24
24
|
spec.add_dependency 'minitar', '~> 0.5'
|
25
25
|
spec.add_dependency 'mixlib-authentication', '~> 1.3'
|
26
|
+
spec.add_dependency 'octokit', '~> 2.2'
|
27
|
+
spec.add_dependency 'retryable', '~> 1.3'
|
26
28
|
spec.add_dependency 'solve', '~> 0.8'
|
27
29
|
|
28
30
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stove
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Seth Vargo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-10-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -80,6 +80,34 @@ dependencies:
|
|
80
80
|
- - ~>
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '1.3'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: octokit
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '2.2'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '2.2'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: retryable
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.3'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ~>
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '1.3'
|
83
111
|
- !ruby/object:Gem::Dependency
|
84
112
|
name: solve
|
85
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -183,7 +211,9 @@ files:
|
|
183
211
|
- bin/bake
|
184
212
|
- features/changelog.feature
|
185
213
|
- features/cli.feature
|
214
|
+
- features/devodd.feature
|
186
215
|
- features/git.feature
|
216
|
+
- features/rake.feature
|
187
217
|
- features/step_definitions/cli_steps.rb
|
188
218
|
- features/step_definitions/community_site_steps.rb
|
189
219
|
- features/step_definitions/cookbook_steps.rb
|
@@ -203,10 +233,12 @@ files:
|
|
203
233
|
- lib/stove/formatter/human.rb
|
204
234
|
- lib/stove/formatter/silent.rb
|
205
235
|
- lib/stove/git.rb
|
236
|
+
- lib/stove/github.rb
|
206
237
|
- lib/stove/jira.rb
|
207
238
|
- lib/stove/logger.rb
|
208
239
|
- lib/stove/mash.rb
|
209
240
|
- lib/stove/packager.rb
|
241
|
+
- lib/stove/rake_task.rb
|
210
242
|
- lib/stove/uploader.rb
|
211
243
|
- lib/stove/version.rb
|
212
244
|
- spec/support/community_site.rb
|
@@ -241,7 +273,9 @@ summary: A simple gem for packaging, releasing, and sanity-checking an Opscode c
|
|
241
273
|
test_files:
|
242
274
|
- features/changelog.feature
|
243
275
|
- features/cli.feature
|
276
|
+
- features/devodd.feature
|
244
277
|
- features/git.feature
|
278
|
+
- features/rake.feature
|
245
279
|
- features/step_definitions/cli_steps.rb
|
246
280
|
- features/step_definitions/community_site_steps.rb
|
247
281
|
- features/step_definitions/cookbook_steps.rb
|