semverve 0.4.0 → 0.4.1

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: 9d9765e973d77ca7011cb819202246f5ea7ef2faef574c66a58fc6ad5c058988
4
- data.tar.gz: dea8769f32c6f6b70c81d05e2d46129cd9820a8289fbd032f42303dfc0b8dea3
3
+ metadata.gz: 91afb799328562d219bfe20353b21fd1158edaac251765ec88fd789fd17bdf5c
4
+ data.tar.gz: b5b4a04dab5c048344804256fb690de2d69155f311c77696e5b90f59d095f1d1
5
5
  SHA512:
6
- metadata.gz: 38b4aca2a29cfc750a7b6b7164219595ec35f76c9c5d526f441e469868686a6588170ee0e88c02942b97b59725d1c72c79b1496cad5880264042d99c8049846a
7
- data.tar.gz: 7cf79a5a6d90a0f454ce03272e5592b140fff266893fee323b6e831ab28956104e7865bb5a141614e6cae6466a4bacbbd738850f299fd98d7f1024f391d61b7c
6
+ metadata.gz: 7c15980531e364e12460998b7e0f8c0e2d7ae30829cf690dc5d93a2e57296a46b1b2c6a365c27093d89603e605bc9261a5ceaec0ec2014ef6f5b7deaaedbbff8
7
+ data.tar.gz: a3443c1637f4d382c7de5fab79da81e09422c4faeb09357b2d0da786212c3da23d9dd0aad45d420cf3b89ee0453fbf68ef0cc1cc4b6d7925e8556a131a5a926a
data/CONTRIBUTING.md CHANGED
@@ -75,26 +75,10 @@ bundle exec rake rdoc:coverage
75
75
 
76
76
  RDoc uses `README.md` as the main page and documents files under `lib/**/*.rb`.
77
77
  Generated documentation is written to `docs/`, which is ignored on development
78
- branches. The generated site is maintained on the `gh-pages` branch for GitHub
79
- Pages.
80
-
81
- Publish generated docs with:
82
-
83
- ```sh
84
- bundle exec rake docs:publish
85
- ```
86
-
87
- That task runs `rerdoc`, opens `gh-pages` in a temporary Git worktree, copies
88
- the generated `docs/` output there, commits changed docs, pushes to
89
- `origin/gh-pages`, and removes the temporary worktree. To preview whether
90
- publishing would change the docs branch without committing or pushing, run:
91
-
92
- ```sh
93
- bundle exec rake docs:publish:dry_run
94
- ```
78
+ branches.
95
79
 
96
80
  Keep public RDoc comments current as code changes so `bundle exec rake
97
- rdoc:coverage` stays clean and the published API docs remain useful.
81
+ rdoc:coverage` stays clean and the API docs remain useful.
98
82
 
99
83
  When changing behavior, update the README at the same time. The README is the
100
84
  primary user guide, so examples should match real task names, configuration
@@ -166,7 +150,6 @@ bundle exec rake standard
166
150
  bundle exec rake rdoc:coverage
167
151
  bundle exec rake rerdoc
168
152
  bundle exec rake build
169
- bundle exec rake docs:publish:dry_run
170
153
  ```
171
154
 
172
155
  The build task writes the packaged gem under `pkg/`. Inspect the package if you
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- semverve (0.4.0)
4
+ semverve (0.4.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/Rakefile CHANGED
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "lib/semverve/task"
4
- require_relative "lib/semverve/docs_publisher/task"
5
4
  require "bundler/gem_tasks"
6
5
  require "rdoc/task"
7
6
  require "rake/testtask"
@@ -24,8 +23,6 @@ Semverve::Task.new do |t|
24
23
  t.version_code_reference_files.append("lib/**/*.rb", "semverve.gemspec", "Rakefile")
25
24
  end
26
25
 
27
- Semverve::DocsPublisher::Task.new
28
-
29
26
  standardrb = ->(*args) do
30
27
  sh(["bundle", "exec", "standardrb", *args].join(" "))
31
28
  end
@@ -21,7 +21,7 @@ module Semverve
21
21
  # Patch version.
22
22
  #
23
23
  # @return [Integer]
24
- PATCH = 0
24
+ PATCH = 1
25
25
 
26
26
  module_function
27
27
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: semverve
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Evan Gray
@@ -111,8 +111,6 @@ files:
111
111
  - lib/semverve.rb
112
112
  - lib/semverve/adapters.rb
113
113
  - lib/semverve/configuration.rb
114
- - lib/semverve/docs_publisher.rb
115
- - lib/semverve/docs_publisher/task.rb
116
114
  - lib/semverve/error.rb
117
115
  - lib/semverve/file_list_resolver.rb
118
116
  - lib/semverve/finding.rb
@@ -1,166 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "rake"
4
-
5
- require_relative "../docs_publisher"
6
-
7
- module Semverve
8
- class DocsPublisher
9
- ##
10
- # Defines Rake tasks for publishing generated documentation.
11
- class Task
12
- include Rake::DSL
13
-
14
- ##
15
- # Source project root.
16
- #
17
- # @return [String]
18
- attr_accessor :root
19
-
20
- ##
21
- # Rake task that builds documentation before publishing.
22
- #
23
- # @return [String]
24
- attr_accessor :build_task
25
-
26
- ##
27
- # Directory containing generated documentation.
28
- #
29
- # @return [String]
30
- attr_accessor :source_dir
31
-
32
- ##
33
- # Documentation directory on the publishing branch.
34
- #
35
- # @return [String]
36
- attr_accessor :target_dir
37
-
38
- ##
39
- # Branch that receives generated documentation.
40
- #
41
- # @return [String]
42
- attr_accessor :branch
43
-
44
- ##
45
- # Remote used when pushing the publishing branch.
46
- #
47
- # @return [String]
48
- attr_accessor :remote
49
-
50
- ##
51
- # Commit message for generated documentation updates.
52
- #
53
- # @return [String]
54
- attr_accessor :commit_message
55
-
56
- ##
57
- # Optional path for the temporary worktree.
58
- #
59
- # @return [String, nil]
60
- attr_accessor :worktree_path
61
-
62
- ##
63
- # Whether dirty source working trees are allowed.
64
- #
65
- # @return [Boolean]
66
- attr_accessor :allow_dirty
67
-
68
- ##
69
- # Whether the publishing branch should be pushed.
70
- #
71
- # @return [Boolean]
72
- attr_accessor :push
73
-
74
- ##
75
- # Output stream for status messages.
76
- #
77
- # @return [#puts]
78
- attr_accessor :output
79
-
80
- ##
81
- # Namespace for the generated tasks.
82
- #
83
- # @return [Symbol, String]
84
- attr_accessor :task_namespace
85
-
86
- ##
87
- # Initializes and defines documentation publishing tasks.
88
- #
89
- # @yieldparam [Semverve::DocsPublisher::Task] task
90
- #
91
- # @return [Semverve::DocsPublisher::Task]
92
- def initialize
93
- @root = Dir.pwd
94
- @build_task = "rerdoc"
95
- @source_dir = "docs"
96
- @target_dir = "docs"
97
- @branch = "gh-pages"
98
- @remote = "origin"
99
- @commit_message = "Update generated documentation"
100
- @worktree_path = nil
101
- @allow_dirty = false
102
- @push = true
103
- @output = $stdout
104
- @task_namespace = :docs
105
-
106
- yield self if block_given?
107
-
108
- define
109
- end
110
-
111
- ##
112
- # Defines the documentation publishing tasks.
113
- #
114
- # @return [void]
115
- def define
116
- namespace namespace_name do
117
- desc "Publish generated documentation to #{branch}"
118
- task :publish do
119
- publish(dry_run: false)
120
- end
121
-
122
- namespace :publish do
123
- desc "Show whether generated documentation would change #{branch}"
124
- task :dry_run do
125
- publish(dry_run: true)
126
- end
127
- end
128
- end
129
- end
130
-
131
- private
132
-
133
- ##
134
- # Normalized namespace name.
135
- #
136
- # @return [Symbol]
137
- def namespace_name
138
- task_namespace.to_sym
139
- end
140
-
141
- ##
142
- # Builds and publishes documentation.
143
- #
144
- # @param [Boolean] dry_run
145
- #
146
- # @return [void]
147
- def publish(dry_run:)
148
- Rake::Task[build_task].invoke
149
-
150
- DocsPublisher.new do |publisher|
151
- publisher.root = root
152
- publisher.source_dir = source_dir
153
- publisher.target_dir = target_dir
154
- publisher.branch = branch
155
- publisher.remote = remote
156
- publisher.commit_message = commit_message
157
- publisher.worktree_path = worktree_path
158
- publisher.allow_dirty = allow_dirty
159
- publisher.push = push
160
- publisher.dry_run = dry_run
161
- publisher.output = output
162
- end.publish
163
- end
164
- end
165
- end
166
- end
@@ -1,370 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # TODO: Turn this into its own gem.
4
-
5
- require "fileutils"
6
- require "open3"
7
- require "tmpdir"
8
-
9
- require_relative "error"
10
-
11
- module Semverve
12
- ##
13
- # Publishes generated documentation to a Git branch through a temporary
14
- # worktree.
15
- class DocsPublisher
16
- ##
17
- # Small command runner used by the publisher.
18
- class Shell
19
- ##
20
- # Runs a command and raises when it fails.
21
- #
22
- # @param [Array<String>] command
23
- # @param [String, nil] chdir
24
- #
25
- # @return [String]
26
- def run(command, chdir: nil)
27
- stdout, stderr, status = capture_command(command, chdir: chdir)
28
- return stdout if status.success?
29
-
30
- raise Error, "Command failed: #{command.join(" ")}\n#{stderr}"
31
- end
32
-
33
- ##
34
- # Captures a command's standard output and raises when it fails.
35
- #
36
- # @param [Array<String>] command
37
- # @param [String, nil] chdir
38
- #
39
- # @return [String]
40
- def capture(command, chdir: nil)
41
- run(command, chdir: chdir)
42
- end
43
-
44
- ##
45
- # Whether a command exits successfully.
46
- #
47
- # @param [Array<String>] command
48
- # @param [String, nil] chdir
49
- #
50
- # @return [Boolean]
51
- def success?(command, chdir: nil)
52
- _stdout, _stderr, status = capture_command(command, chdir: chdir)
53
- status.success?
54
- end
55
-
56
- private
57
-
58
- ##
59
- # Captures a command, omitting +chdir+ when none was provided.
60
- #
61
- # @param [Array<String>] command
62
- # @param [String, nil] chdir
63
- #
64
- # @return [Array(String, String, Process::Status)]
65
- def capture_command(command, chdir:)
66
- options = chdir ? {chdir: chdir} : {}
67
-
68
- Open3.capture3(*command, **options)
69
- end
70
- end
71
-
72
- ##
73
- # Source project root.
74
- #
75
- # @return [String]
76
- attr_accessor :root
77
-
78
- ##
79
- # Directory containing generated documentation, relative to +root+.
80
- #
81
- # @return [String]
82
- attr_accessor :source_dir
83
-
84
- ##
85
- # Documentation directory on the publishing branch.
86
- #
87
- # @return [String]
88
- attr_accessor :target_dir
89
-
90
- ##
91
- # Branch that receives generated documentation.
92
- #
93
- # @return [String]
94
- attr_accessor :branch
95
-
96
- ##
97
- # Remote used when pushing the publishing branch.
98
- #
99
- # @return [String]
100
- attr_accessor :remote
101
-
102
- ##
103
- # Commit message for generated documentation updates.
104
- #
105
- # @return [String]
106
- attr_accessor :commit_message
107
-
108
- ##
109
- # Optional path for the temporary worktree.
110
- #
111
- # @return [String, nil]
112
- attr_accessor :worktree_path
113
-
114
- ##
115
- # Whether dirty source working trees are allowed.
116
- #
117
- # @return [Boolean]
118
- attr_accessor :allow_dirty
119
-
120
- ##
121
- # Whether the publishing branch should be pushed.
122
- #
123
- # @return [Boolean]
124
- attr_accessor :push
125
-
126
- ##
127
- # Whether to report changes without committing or pushing.
128
- #
129
- # @return [Boolean]
130
- attr_accessor :dry_run
131
-
132
- ##
133
- # Command runner used for Git commands.
134
- #
135
- # @return [#run, #capture, #success?]
136
- attr_accessor :command_runner
137
-
138
- ##
139
- # Output stream for status messages.
140
- #
141
- # @return [#puts]
142
- attr_accessor :output
143
-
144
- ##
145
- # Initializes a documentation publisher.
146
- #
147
- # @yieldparam [Semverve::DocsPublisher] publisher
148
- #
149
- # @return [Semverve::DocsPublisher]
150
- def initialize
151
- @root = Dir.pwd
152
- @source_dir = "docs"
153
- @target_dir = "docs"
154
- @branch = "gh-pages"
155
- @remote = "origin"
156
- @commit_message = "Update generated documentation"
157
- @worktree_path = nil
158
- @allow_dirty = false
159
- @push = true
160
- @dry_run = false
161
- @command_runner = Shell.new
162
- @output = $stdout
163
-
164
- yield self if block_given?
165
- end
166
-
167
- ##
168
- # Publishes generated documentation.
169
- #
170
- # @return [Boolean] whether documentation changes were found
171
- def publish
172
- validate!
173
- ensure_clean_source_worktree unless allow_dirty
174
-
175
- with_worktree do |worktree|
176
- sync_docs_to(worktree)
177
-
178
- unless publishing_worktree_changed?(worktree)
179
- output.puts "Documentation is already current on #{branch}."
180
- return false
181
- end
182
-
183
- if dry_run
184
- output.puts "Documentation changes detected for #{branch}; dry run did not commit or push."
185
- return true
186
- end
187
-
188
- commit_docs(worktree)
189
- push_docs(worktree) if push
190
- output.puts "Published documentation to #{remote}/#{branch}."
191
- true
192
- end
193
- end
194
-
195
- private
196
-
197
- ##
198
- # Validates publishing configuration.
199
- #
200
- # @return [void]
201
- def validate!
202
- raise Error, "Documentation source directory does not exist: #{source_path}." unless File.directory?(source_path)
203
-
204
- if target_dir.nil? || target_dir.empty? || target_dir == "." || target_dir.start_with?("/")
205
- raise Error, "target_dir must be a relative directory such as \"docs\"."
206
- end
207
- end
208
-
209
- ##
210
- # Absolute source project root.
211
- #
212
- # @return [String]
213
- def source_root
214
- @source_root ||= File.expand_path(root)
215
- end
216
-
217
- ##
218
- # Absolute source documentation directory.
219
- #
220
- # @return [String]
221
- def source_path
222
- File.expand_path(source_dir, source_root)
223
- end
224
-
225
- ##
226
- # Ensures the source working tree is clean.
227
- #
228
- # @return [void]
229
- def ensure_clean_source_worktree
230
- status = git_capture(source_root, "status", "--porcelain")
231
- return if status.empty?
232
-
233
- raise Error, "Working tree must be clean before publishing documentation. Commit, stash, or set allow_dirty."
234
- end
235
-
236
- ##
237
- # Yields a temporary publishing worktree and removes it afterward.
238
- #
239
- # @yieldparam [String] worktree
240
- #
241
- # @return [Object]
242
- def with_worktree
243
- temporary_path = worktree_path || Dir.mktmpdir("semverve-docs-publish-")
244
- temporary_worktree = worktree_path.nil?
245
- worktree_added = false
246
-
247
- if temporary_worktree
248
- FileUtils.rm_rf(temporary_path)
249
- elsif File.exist?(temporary_path)
250
- raise Error, "Worktree path already exists: #{temporary_path}."
251
- end
252
-
253
- add_worktree(temporary_path)
254
- worktree_added = true
255
- yield temporary_path
256
- ensure
257
- remove_worktree(temporary_path) if temporary_path && worktree_added
258
- FileUtils.rm_rf(temporary_path) if temporary_path && temporary_worktree
259
- end
260
-
261
- ##
262
- # Adds a worktree for the publishing branch.
263
- #
264
- # @param [String] path
265
- #
266
- # @return [void]
267
- def add_worktree(path)
268
- if local_branch?
269
- git_run(source_root, "worktree", "add", path, branch)
270
- elsif remote_branch?
271
- git_run(source_root, "worktree", "add", "-b", branch, path, "#{remote}/#{branch}")
272
- else
273
- raise Error, "Could not find #{branch} locally or at #{remote}/#{branch}."
274
- end
275
- end
276
-
277
- ##
278
- # Removes a worktree.
279
- #
280
- # @param [String] path
281
- #
282
- # @return [void]
283
- def remove_worktree(path)
284
- git_run(source_root, "worktree", "remove", "--force", path) if File.directory?(path)
285
- end
286
-
287
- ##
288
- # Whether the publishing branch exists locally.
289
- #
290
- # @return [Boolean]
291
- def local_branch?
292
- command_runner.success?(["git", "show-ref", "--verify", "--quiet", "refs/heads/#{branch}"], chdir: source_root)
293
- end
294
-
295
- ##
296
- # Whether the publishing branch exists as a remote-tracking branch.
297
- #
298
- # @return [Boolean]
299
- def remote_branch?
300
- command_runner.success?(["git", "show-ref", "--verify", "--quiet", "refs/remotes/#{remote}/#{branch}"], chdir: source_root)
301
- end
302
-
303
- ##
304
- # Copies generated documentation into the publishing worktree.
305
- #
306
- # @param [String] worktree
307
- #
308
- # @return [void]
309
- def sync_docs_to(worktree)
310
- target_path = File.expand_path(target_dir, worktree)
311
-
312
- FileUtils.rm_rf(target_path)
313
- FileUtils.mkdir_p(File.dirname(target_path))
314
- FileUtils.cp_r(source_path, target_path)
315
- end
316
-
317
- ##
318
- # Whether the publishing worktree has documentation changes.
319
- #
320
- # @param [String] worktree
321
- #
322
- # @return [Boolean]
323
- def publishing_worktree_changed?(worktree)
324
- !git_capture(worktree, "status", "--porcelain", "--", target_dir).empty?
325
- end
326
-
327
- ##
328
- # Commits documentation changes in the publishing worktree.
329
- #
330
- # @param [String] worktree
331
- #
332
- # @return [void]
333
- def commit_docs(worktree)
334
- git_run(worktree, "add", target_dir)
335
- git_run(worktree, "commit", "-m", commit_message)
336
- end
337
-
338
- ##
339
- # Pushes documentation changes.
340
- #
341
- # @param [String] worktree
342
- #
343
- # @return [void]
344
- def push_docs(worktree)
345
- git_run(worktree, "push", remote, branch)
346
- end
347
-
348
- ##
349
- # Runs a Git command in a directory.
350
- #
351
- # @param [String] directory
352
- # @param [Array<String>] arguments
353
- #
354
- # @return [String]
355
- def git_run(directory, *arguments)
356
- command_runner.run(["git", *arguments], chdir: directory)
357
- end
358
-
359
- ##
360
- # Captures a Git command in a directory.
361
- #
362
- # @param [String] directory
363
- # @param [Array<String>] arguments
364
- #
365
- # @return [String]
366
- def git_capture(directory, *arguments)
367
- command_runner.capture(["git", *arguments], chdir: directory)
368
- end
369
- end
370
- end