dco 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,230 @@
1
+ #
2
+ # Copyright 2016, Noah Kantrowitz
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'spec_helper'
18
+
19
+ describe 'dco sign' do
20
+ # Create a branch structure for all tests.
21
+ git_init
22
+ file 'testing', 'one'
23
+ before do
24
+ cmds = [
25
+ 'git add testing',
26
+ 'git commit -m "first commit"',
27
+ 'echo two > testing',
28
+ 'git commit -a -m "second commit"',
29
+ 'git checkout -b mybranch',
30
+ ]
31
+ command cmds.join(' && ')
32
+ end
33
+
34
+ context 'with no commits in the branch' do
35
+ dco_command 'sign -y mybranch'
36
+
37
+ it do
38
+ expect(subject.exitstatus).to eq 1
39
+ expect(subject.stderr).to eq "Branch mybranch has no commits which require sign-off\n"
40
+ end
41
+ end # /context with no commits in the branch
42
+
43
+ context 'with one commit in the branch' do
44
+ before do
45
+ command 'echo three > testing && git commit -a -m "first branch commit"'
46
+ end
47
+ dco_command 'sign -y mybranch'
48
+
49
+ it do
50
+ expect(subject.exitstatus).to eq 0
51
+ expect(subject.stdout).to match /^Developer's Certificate of Origin 1\.1$/
52
+ expect(subject.stdout).to match /^Going to sign-off the following commits:\n\* \h{7} Alan Smithee <asmithee@example\.com> first branch commit$/
53
+ expect(repo.log[0].message).to eq "first branch commit\n\nSigned-off-by: Alan Smithee <asmithee@example.com>"
54
+ expect(repo.log[1].message).to eq "second commit"
55
+ expect(repo.log[2].message).to eq "first commit"
56
+ end
57
+ end # /context with one commit in the branch
58
+
59
+ context 'with one commit in the branch without -y' do
60
+ before do
61
+ command 'echo three > testing && git commit -a -m "first branch commit"'
62
+ end
63
+ dco_command 'sign mybranch'
64
+
65
+ it do
66
+ expect(subject.exitstatus).to eq 1
67
+ expect(subject.stderr).to eq "Not signing off on commits without approval\n"
68
+ end
69
+ end # /context with one commit in the branch without -y
70
+
71
+ context 'with two commits in the branch' do
72
+ before do
73
+ command 'echo three > testing && git commit -a -m "first branch commit" && echo four > testing && git commit -a -m "second branch commit"'
74
+ end
75
+ dco_command 'sign -y mybranch'
76
+
77
+ it do
78
+ expect(subject.exitstatus).to eq 0
79
+ expect(subject.stdout).to match /^Developer's Certificate of Origin 1\.1$/
80
+ expect(subject.stdout).to match /^Going to sign-off the following commits:\n\* \h{7} Alan Smithee <asmithee@example\.com> second branch commit\n\* \h{7} Alan Smithee <asmithee@example\.com> first branch commit$/
81
+ expect(repo.log[0].message).to eq "second branch commit\n\nSigned-off-by: Alan Smithee <asmithee@example.com>"
82
+ expect(repo.log[1].message).to eq "first branch commit\n\nSigned-off-by: Alan Smithee <asmithee@example.com>"
83
+ expect(repo.log[2].message).to eq "second commit"
84
+ expect(repo.log[3].message).to eq "first commit"
85
+ end
86
+ end # /context with two commits in the branch
87
+
88
+ context 'with a branch that has a merge commit' do
89
+ before do
90
+ command('echo three > other && ' \
91
+ 'git add other && ' \
92
+ 'git commit -a -m "first branch commit" && ' \
93
+ 'git checkout master && ' \
94
+ 'echo three > testing && ' \
95
+ 'git commit -a -m "third commit" && ' \
96
+ 'git checkout mybranch && ' \
97
+ 'git merge master && ' \
98
+ 'echo four > other && ' \
99
+ 'git commit -a -m "second branch commit"')
100
+ end
101
+ dco_command 'sign -y mybranch'
102
+
103
+ it do
104
+ expect(subject.exitstatus).to eq 0
105
+ expect(subject.stdout).to match /^Developer's Certificate of Origin 1\.1$/
106
+ expect(subject.stdout).to match /^Going to sign-off the following commits:\n\* \h{7} Alan Smithee <asmithee@example\.com> second branch commit\n\* \h{7} Alan Smithee <asmithee@example\.com> Merge branch 'master' into mybranch\n\* \h{7} Alan Smithee <asmithee@example\.com> first branch commit$/
107
+ # Ordering is unstable because of the merge.
108
+ commits = repo.log.map {|c| c.message }
109
+ expect(commits.size).to eq 6
110
+ expect(commits).to include "second branch commit\n\nSigned-off-by: Alan Smithee <asmithee@example.com>"
111
+ expect(commits).to include "Merge branch 'master' into mybranch\n\nSigned-off-by: Alan Smithee <asmithee@example.com>"
112
+ expect(commits).to include "first branch commit\n\nSigned-off-by: Alan Smithee <asmithee@example.com>"
113
+ expect(commits).to include "third commit"
114
+ expect(commits).to include "second commit"
115
+ expect(commits).to include "first commit"
116
+ end
117
+ end # /context with a branch that has a merge commit
118
+
119
+ context 'with behalf mode enabled' do
120
+ before do
121
+ command 'echo three > testing && git commit -a -m "first branch commit" && echo four > testing && git commit -a -m "second branch commit"'
122
+ git_init(name: 'Commiter McCommiterface', email: 'other@example.com')
123
+ end
124
+ dco_command 'sign -y mybranch -b https://github.com/chef/chef/pulls/1234'
125
+
126
+ it do
127
+ expect(subject.exitstatus).to eq 0
128
+ expect(subject.stdout).to_not match /^Developer's Certificate of Origin 1\.1$/
129
+ expect(subject.stdout).to match /^Going to sign-off the following commits:\n\* \h{7} Alan Smithee <asmithee@example\.com> second branch commit\n\* \h{7} Alan Smithee <asmithee@example\.com> first branch commit$/
130
+ expect(repo.log[0].message).to eq "second branch commit\n\nSigned-off-by: Alan Smithee <asmithee@example.com>\nSign-off-executed-by: Commiter McCommiterface <other@example.com>\nApproved-at: https://github.com/chef/chef/pulls/1234"
131
+ expect(repo.log[1].message).to eq "first branch commit\n\nSigned-off-by: Alan Smithee <asmithee@example.com>\nSign-off-executed-by: Commiter McCommiterface <other@example.com>\nApproved-at: https://github.com/chef/chef/pulls/1234"
132
+ expect(repo.log[2].message).to eq "second commit"
133
+ expect(repo.log[3].message).to eq "first commit"
134
+ end
135
+ end # /context with behalf mode enabled
136
+
137
+ context 'with someone elses commits' do
138
+ before do
139
+ command 'echo three > testing && git commit -a -m "first branch commit" && echo four > testing && git commit -a -m "second branch commit"'
140
+ git_init(name: 'Commiter McCommiterface', email: 'other@example.com')
141
+ end
142
+ dco_command 'sign -y mybranch'
143
+
144
+ it do
145
+ expect(subject.exitstatus).to eq 1
146
+ expect(subject.stderr).to eq "Branch mybranch contains commits not authored by you. Please use the --behalf flag when signing off for another contributor\n"
147
+ end
148
+ end # /context with someone elses commits
149
+
150
+ context 'with an invalid branch' do
151
+ dco_command 'sign -y master'
152
+
153
+ it do
154
+ expect(subject.exitstatus).to eq 1
155
+ expect(subject.stderr).to eq "Cannot use master for both the base and target branch\n"
156
+ end
157
+ end # /context with an invalid branch
158
+
159
+ context 'with an implicit branch' do
160
+ before do
161
+ command 'echo three > testing && git commit -a -m "first branch commit"'
162
+ end
163
+ dco_command 'sign -y'
164
+
165
+ it do
166
+ expect(subject.exitstatus).to eq 0
167
+ expect(subject.stdout).to match /^Developer's Certificate of Origin 1\.1$/
168
+ expect(subject.stdout).to match /^Going to sign-off the following commits:\n\* \h{7} Alan Smithee <asmithee@example\.com> first branch commit$/
169
+ expect(repo.log[0].message).to eq "first branch commit\n\nSigned-off-by: Alan Smithee <asmithee@example.com>"
170
+ expect(repo.log[1].message).to eq "second commit"
171
+ expect(repo.log[2].message).to eq "first commit"
172
+ end
173
+ end # /context with an implicit branch
174
+
175
+ context 'with an implicit invalid branch' do
176
+ before { command 'git checkout master' }
177
+ dco_command 'sign -y'
178
+
179
+ it do
180
+ expect(subject.exitstatus).to eq 1
181
+ expect(subject.stderr).to eq "Cannot use master for both the base and target branch\n"
182
+ end
183
+ end # /context with an implicit invalid branch
184
+
185
+ context 'with an existing backup pointer' do
186
+ before do
187
+ command 'echo three > testing && git commit -a -m "first branch commit"'
188
+ dco_command 'sign -y mybranch'
189
+ command 'echo four > testing && git commit -a -m "second branch commit"'
190
+ end
191
+ dco_command 'sign -y mybranch'
192
+
193
+ it do
194
+ expect(subject.exitstatus).to eq 0
195
+ expect(subject.stdout).to match /^Developer's Certificate of Origin 1\.1$/
196
+ expect(subject.stdout).to match /^Going to sign-off the following commits:\n\* \h{7} Alan Smithee <asmithee@example\.com> second branch commit$/
197
+ expect(repo.log[0].message).to eq "second branch commit\n\nSigned-off-by: Alan Smithee <asmithee@example.com>"
198
+ expect(repo.log[1].message).to eq "first branch commit\n\nSigned-off-by: Alan Smithee <asmithee@example.com>"
199
+ expect(repo.log[2].message).to eq "second commit"
200
+ expect(repo.log[3].message).to eq "first commit"
201
+ end
202
+ end # /context with an existing backup pointer
203
+
204
+ context 'with an existing backup pointer without -y' do
205
+ before do
206
+ command 'echo three > testing && git commit -a -m "first branch commit"'
207
+ dco_command 'sign -y mybranch'
208
+ command 'echo four > testing && git commit -a -m "second branch commit"'
209
+ end
210
+ dco_command 'sign mybranch'
211
+
212
+ it do
213
+ expect(subject.exitstatus).to eq 1
214
+ expect(subject.stderr).to eq "Backup ref present, not continuing\n"
215
+ end
216
+ end # /context with an existing backup pointer without -y
217
+
218
+ context 'with uncommitted changes' do
219
+ before do
220
+ command 'echo three > testing && git commit -a -m "first branch commit" && echo four > testing'
221
+ end
222
+ dco_command 'sign -y mybranch'
223
+
224
+ it do
225
+ expect(subject.exitstatus).to eq 0
226
+ expect(subject.stdout).to match /^Stashing uncommited changes before continuing$/
227
+ expect(IO.read(File.join(temp_path, 'testing')).strip).to eq "four"
228
+ end
229
+ end # /context with uncommitted changes
230
+ end
@@ -0,0 +1,91 @@
1
+ #
2
+ # Copyright 2016, Noah Kantrowitz
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'rspec'
18
+ require 'rspec_command'
19
+ require 'simplecov'
20
+ require 'git'
21
+ require 'shellwords'
22
+
23
+ # Check for coverage stuffs
24
+ if ENV['CODECOV_TOKEN'] || ENV['TRAVIS']
25
+ require 'codecov'
26
+ SimpleCov.formatter = SimpleCov::Formatter::Codecov
27
+ end
28
+
29
+ SimpleCov.start do
30
+ # Don't get coverage on the test cases themselves.
31
+ add_filter '/spec/'
32
+ add_filter '/test/'
33
+ # Codecov doesn't automatically ignore vendored files.
34
+ add_filter '/vendor/'
35
+ end
36
+
37
+ require 'dco'
38
+
39
+ module DcoSpecHelper
40
+ extend RSpec::SharedContext
41
+
42
+ def dco_command *args
43
+ cwd = Dir.pwd
44
+ begin
45
+ Dir.chdir(temp_path)
46
+ capture_output do
47
+ args = Shellwords.split(args.first) if args.length == 1 && args.first.is_a?(String)
48
+ Dco::CLI.start(args)
49
+ end
50
+ ensure
51
+ Dir.chdir(cwd)
52
+ end
53
+ rescue Exception => e
54
+ status = e.is_a?(SystemExit) ? e.status : 1
55
+ e.output_so_far.define_singleton_method(:exitstatus) { status }
56
+ e.output_so_far
57
+ end
58
+
59
+ def git_init(name: 'Alan Smithee', email: 'asmithee@example.com')
60
+ command "git init && git config user.name \"#{name}\" && git config user.email \"#{email}\""
61
+ end
62
+
63
+ let(:repo) { Git.open(temp_path) }
64
+
65
+ module ClassMethods
66
+ def dco_command *args
67
+ subject { dco_command(*args) }
68
+ end
69
+
70
+ def git_init(*args)
71
+ before { git_init(*args) }
72
+ end
73
+ end
74
+ end
75
+
76
+ RSpec.configure do |config|
77
+ # Basic configuraiton
78
+ config.run_all_when_everything_filtered = true
79
+ config.filter_run(:focus)
80
+
81
+ # Run specs in random order to surface order dependencies. If you find an
82
+ # order dependency and want to debug it, you can fix the order by providing
83
+ # the seed, which is printed after each run.
84
+ # --seed 1234
85
+ config.order = 'random'
86
+
87
+ config.include RSpecCommand
88
+
89
+ config.include DcoSpecHelper
90
+ config.extend DcoSpecHelper::ClassMethods
91
+ end
metadata ADDED
@@ -0,0 +1,221 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dco
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Noah Kantrowitz
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-10-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: git
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.19'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.19'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '11.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '11.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-command
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: fuubar
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '2.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.9'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.9'
111
+ - !ruby/object:Gem::Dependency
112
+ name: yard
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.8'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.8'
125
+ - !ruby/object:Gem::Dependency
126
+ name: codecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.0'
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: 0.0.2
135
+ type: :development
136
+ prerelease: false
137
+ version_requirements: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - "~>"
140
+ - !ruby/object:Gem::Version
141
+ version: '0.0'
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: 0.0.2
145
+ - !ruby/object:Gem::Dependency
146
+ name: pry
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: '0'
159
+ description: A command line tool to help manage Developer Certificate of Origin projects.
160
+ email:
161
+ - noah@coderanger.net
162
+ executables:
163
+ - dco
164
+ extensions: []
165
+ extra_rdoc_files: []
166
+ files:
167
+ - ".gitignore"
168
+ - ".travis.yml"
169
+ - ".yardopts"
170
+ - CHANGELOG.md
171
+ - Gemfile
172
+ - LICENSE
173
+ - README.md
174
+ - Rakefile
175
+ - appveyor.yml
176
+ - bin/dco
177
+ - dco.gemspec
178
+ - gemfiles/master.gemfile
179
+ - gemfiles/release.gemfile
180
+ - lib/dco.rb
181
+ - lib/dco/cli.rb
182
+ - lib/dco/version.rb
183
+ - spec/baseline_spec.rb
184
+ - spec/check_spec.rb
185
+ - spec/disable_spec.rb
186
+ - spec/enable_spec.rb
187
+ - spec/process_commit_message_spec.rb
188
+ - spec/sign_spec.rb
189
+ - spec/spec_helper.rb
190
+ homepage: https://github.com/coderanger/dco
191
+ licenses:
192
+ - Apache-2.0
193
+ metadata: {}
194
+ post_install_message:
195
+ rdoc_options: []
196
+ require_paths:
197
+ - lib
198
+ required_ruby_version: !ruby/object:Gem::Requirement
199
+ requirements:
200
+ - - ">="
201
+ - !ruby/object:Gem::Version
202
+ version: '0'
203
+ required_rubygems_version: !ruby/object:Gem::Requirement
204
+ requirements:
205
+ - - ">="
206
+ - !ruby/object:Gem::Version
207
+ version: '0'
208
+ requirements: []
209
+ rubyforge_project:
210
+ rubygems_version: 2.6.4
211
+ signing_key:
212
+ specification_version: 4
213
+ summary: A command line tool to help manage Developer Certificate of Origin projects.
214
+ test_files:
215
+ - spec/baseline_spec.rb
216
+ - spec/check_spec.rb
217
+ - spec/disable_spec.rb
218
+ - spec/enable_spec.rb
219
+ - spec/process_commit_message_spec.rb
220
+ - spec/sign_spec.rb
221
+ - spec/spec_helper.rb