semverve 0.1.0 → 0.2.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 +4 -4
- data/.gitignore +1 -0
- data/CONTRIBUTING.md +22 -1
- data/Gemfile.lock +2 -2
- data/README.md +168 -46
- data/lib/semverve/configuration.rb +74 -0
- data/lib/semverve/generator.rb +30 -10
- data/lib/semverve/published_version.rb +117 -0
- data/lib/semverve/task.rb +117 -14
- data/lib/semverve/version.rb +2 -2
- data/lib/semverve/version_code_references.rb +40 -3
- data/lib/semverve/version_references.rb +9 -2
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b04f97b571e0eed652d155221cddb5afe06d703f2a27546f15c11e3d26a3d214
|
|
4
|
+
data.tar.gz: 6c824db22d1967e9daa8de369ca199b6cc7969f6ab2179933600fbba34d1aa6e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 31208572bd96d1d1bb00537673e9960594501a2b4226f821114d8cb624965fd0cd7282722d6284cf0666f80a908706174a3ca3d0bb4109a3b18dc882e9a26ecd
|
|
7
|
+
data.tar.gz: 8deb952db13cfdf0f8a13fbbcffb07afc23c402ece2efc3d50899d4158ea7455a6bedc993cb79c9d3de8dfc83c8142981f87f52777ee79a8dba1c1b09bc58dcd
|
data/.gitignore
CHANGED
data/CONTRIBUTING.md
CHANGED
|
@@ -100,6 +100,27 @@ When changing behavior, update the README at the same time. The README is the
|
|
|
100
100
|
primary user guide, so examples should match real task names, configuration
|
|
101
101
|
names, defaults, and output.
|
|
102
102
|
|
|
103
|
+
## Rake Task Interface Design
|
|
104
|
+
Semverve should feel natural from a shell while staying Rake-native. Prefer
|
|
105
|
+
Rake task arguments for direct task inputs:
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
bundle exec rake 'semverve:set[x.y.z]'
|
|
109
|
+
bundle exec rake 'semverve:generate[simple,force]'
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
For tasks with more than one optional value, prefer meaning-bearing tokens over
|
|
113
|
+
strict positional placeholders. For example, `semverve:generate` treats semantic
|
|
114
|
+
versions as the generated version, `module` or `simple` as the format, and
|
|
115
|
+
`force` as the overwrite mode. That keeps invocations like
|
|
116
|
+
`rake 'semverve:generate[simple]'` and `rake 'semverve:generate[force]'`
|
|
117
|
+
readable without requiring awkward empty slots.
|
|
118
|
+
|
|
119
|
+
Reserve environment variables for cross-cutting runtime toggles that compose
|
|
120
|
+
across related tasks, such as `SEMVERVE_REPORT_IGNORED=true rake
|
|
121
|
+
semverve:check`. Avoid generic environment variables like `VERSION`, `FORMAT`,
|
|
122
|
+
or `FORCE`; they can collide with a user's shell, CI, or parent build process.
|
|
123
|
+
|
|
103
124
|
## Versioning and Release Checks
|
|
104
125
|
Semverve uses Semverve to maintain itself, which doubles as useful
|
|
105
126
|
smoke-testing. The project Rakefile requires `lib/semverve/task` and installs
|
|
@@ -123,7 +144,7 @@ bundle exec rake semverve:current
|
|
|
123
144
|
bundle exec rake semverve:increment:patch
|
|
124
145
|
bundle exec rake semverve:increment:minor
|
|
125
146
|
bundle exec rake semverve:increment:major
|
|
126
|
-
bundle exec rake semverve:set
|
|
147
|
+
bundle exec rake 'semverve:set[x.y.z]'
|
|
127
148
|
bundle exec rake semverve:check
|
|
128
149
|
bundle exec rake semverve:fix
|
|
129
150
|
```
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
semverve (0.1
|
|
4
|
+
semverve (0.2.1)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
@@ -84,10 +84,10 @@ PLATFORMS
|
|
|
84
84
|
DEPENDENCIES
|
|
85
85
|
rake (~> 13.0, >= 13.0.1)
|
|
86
86
|
rdoc
|
|
87
|
+
semverve!
|
|
87
88
|
simplecov
|
|
88
89
|
standard (~> 1.54.0)
|
|
89
90
|
test-unit (~> 3.3, >= 3.3.5)
|
|
90
|
-
semverve!
|
|
91
91
|
|
|
92
92
|
BUNDLED WITH
|
|
93
93
|
4.0.10
|
data/README.md
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
# Semverve
|
|
2
|
+
[](https://actions-badge.atrox.dev/evanthegrayt/semverve/goto?ref=master)
|
|
3
|
+
[](https://www.ruby-lang.org/)
|
|
4
|
+
[](https://rubygems.org/gems/semverve)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
|
|
2
7
|
Rake tasks for handling the tedium surrounding maintaining a version number in
|
|
3
8
|
your Ruby project, with gusto!
|
|
4
9
|
|
|
@@ -26,6 +31,9 @@ tasks can update safe references and run `bundle lock` for generated lockfile
|
|
|
26
31
|
drift. Specific findings can be skipped with magic comments, similar to RuboCop
|
|
27
32
|
and RDoc.
|
|
28
33
|
|
|
34
|
+
You can view the documentation
|
|
35
|
+
[here](https://evanthegrayt.github.io/semverve/).
|
|
36
|
+
|
|
29
37
|
## Installation
|
|
30
38
|
Add the gem to your Gemfile:
|
|
31
39
|
|
|
@@ -47,7 +55,7 @@ rake semverve:increment:patch
|
|
|
47
55
|
rake semverve:increment:minor
|
|
48
56
|
rake semverve:increment:major
|
|
49
57
|
rake semverve:generate
|
|
50
|
-
rake semverve:set
|
|
58
|
+
rake 'semverve:set[1.2.3]'
|
|
51
59
|
rake semverve:check
|
|
52
60
|
rake semverve:fix
|
|
53
61
|
rake semverve:check:references
|
|
@@ -56,6 +64,8 @@ rake semverve:check:code
|
|
|
56
64
|
rake semverve:fix:code
|
|
57
65
|
rake semverve:check:metadata
|
|
58
66
|
rake semverve:fix:metadata
|
|
67
|
+
rake semverve:check:rubygems
|
|
68
|
+
rake semverve:check:release
|
|
59
69
|
```
|
|
60
70
|
|
|
61
71
|
## Configuration
|
|
@@ -81,6 +91,8 @@ Semverve.configure do |config|
|
|
|
81
91
|
config.version_file = "lib/my_gem/version.rb"
|
|
82
92
|
config.module_name = "MyGem"
|
|
83
93
|
config.version_checks = [:doc_references, :code_references, :metadata]
|
|
94
|
+
config.release_checks = [:rubygems]
|
|
95
|
+
config.rubygems_host = "https://rubygems.org"
|
|
84
96
|
config.version_code_reference_files.append("lib/**/*.rb")
|
|
85
97
|
config.version_doc_reference_files.append("doc/**/*.md")
|
|
86
98
|
config.version_reference_mode = :non_current
|
|
@@ -95,6 +107,8 @@ Semverve.configure do |config|
|
|
|
95
107
|
config.bundle_lock = false
|
|
96
108
|
config.root = Dir.pwd
|
|
97
109
|
config.version_checks = [:doc_references, :code_references, :metadata]
|
|
110
|
+
config.release_checks = []
|
|
111
|
+
config.rubygems_host = "https://rubygems.org"
|
|
98
112
|
config.version_reference_mode = :older
|
|
99
113
|
config.version_code_reference_files = Rake::FileList[]
|
|
100
114
|
config.version_code_reference_pattern =
|
|
@@ -111,6 +125,23 @@ end
|
|
|
111
125
|
The empty `version_code_reference_files` default only applies to arbitrary code
|
|
112
126
|
literal scanning. `rake semverve:check` still checks the resolved `.gemspec`
|
|
113
127
|
version and matching `Gemfile.lock` entry through its default metadata check.
|
|
128
|
+
Release checks are empty by default because they may make network requests and
|
|
129
|
+
are intended for release pipelines rather than every local or pull-request run.
|
|
130
|
+
|
|
131
|
+
Semverve tasks use Rake task arguments for values:
|
|
132
|
+
|
|
133
|
+
```sh
|
|
134
|
+
rake 'semverve:set[1.2.3]'
|
|
135
|
+
rake 'semverve:generate[1.0.0,simple]'
|
|
136
|
+
rake 'semverve:generate[simple]'
|
|
137
|
+
rake 'semverve:generate[force]'
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Quote task invocations that include square brackets. Shells such as zsh may
|
|
141
|
+
otherwise treat brackets as glob patterns before Rake sees them. Flag syntax
|
|
142
|
+
such as `rake semverve:set --version 1.2.3` is not used because `--version` is
|
|
143
|
+
already a Rake option; Semverve stays within Rake's native argument syntax
|
|
144
|
+
instead.
|
|
114
145
|
|
|
115
146
|
The gem name, module name, and version-file path are inferred by default:
|
|
116
147
|
|
|
@@ -138,48 +169,6 @@ Semverve::Task.new do |config|
|
|
|
138
169
|
end
|
|
139
170
|
```
|
|
140
171
|
|
|
141
|
-
## Publishing generated docs
|
|
142
|
-
Semverve also includes an optional GitHub Pages publishing task for generated
|
|
143
|
-
documentation. It builds docs on your current branch, opens the publishing
|
|
144
|
-
branch in a temporary Git worktree, copies the generated docs there, commits any
|
|
145
|
-
changes, and pushes the publishing branch.
|
|
146
|
-
|
|
147
|
-
Add this to your Rakefile:
|
|
148
|
-
|
|
149
|
-
```ruby
|
|
150
|
-
require "semverve/docs_publisher/task"
|
|
151
|
-
|
|
152
|
-
Semverve::DocsPublisher::Task.new
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
This defines:
|
|
156
|
-
|
|
157
|
-
```text
|
|
158
|
-
rake docs:publish
|
|
159
|
-
rake docs:publish:dry_run
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
The defaults are equivalent to:
|
|
163
|
-
|
|
164
|
-
```ruby
|
|
165
|
-
Semverve::DocsPublisher::Task.new do |task|
|
|
166
|
-
task.root = Dir.pwd
|
|
167
|
-
task.build_task = "rerdoc"
|
|
168
|
-
task.source_dir = "docs"
|
|
169
|
-
task.target_dir = "docs"
|
|
170
|
-
task.branch = "gh-pages"
|
|
171
|
-
task.remote = "origin"
|
|
172
|
-
task.commit_message = "Update generated documentation"
|
|
173
|
-
task.allow_dirty = false
|
|
174
|
-
task.push = true
|
|
175
|
-
task.output = $stdout
|
|
176
|
-
end
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
`docs:publish` requires a clean working tree by default. Set
|
|
180
|
-
`task.allow_dirty = true` only when you intentionally want to publish generated
|
|
181
|
-
documentation from uncommitted source changes.
|
|
182
|
-
|
|
183
172
|
## Rails apps
|
|
184
173
|
Rails applications do not need gem-style version files, but an application
|
|
185
174
|
version can still be useful for release notes, support/debug screens,
|
|
@@ -261,13 +250,25 @@ rake semverve:generate
|
|
|
261
250
|
Generate a specific version or format:
|
|
262
251
|
|
|
263
252
|
```sh
|
|
264
|
-
rake semverve:generate
|
|
253
|
+
rake 'semverve:generate[1.0.0,simple]'
|
|
254
|
+
rake 'semverve:generate[simple]'
|
|
265
255
|
```
|
|
266
256
|
|
|
267
257
|
Generation fails if the target file already exists. To replace it:
|
|
268
258
|
|
|
269
259
|
```sh
|
|
270
|
-
rake semverve:generate
|
|
260
|
+
rake 'semverve:generate[force]'
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
`semverve:generate` accepts optional tokens for version, format, and force.
|
|
264
|
+
Token order does not matter: semantic versions set the generated version,
|
|
265
|
+
`module` or `simple` sets the format, and `force` overwrites an existing version
|
|
266
|
+
file.
|
|
267
|
+
|
|
268
|
+
```sh
|
|
269
|
+
rake 'semverve:generate[1.0.0,force]'
|
|
270
|
+
rake 'semverve:generate[simple,force]'
|
|
271
|
+
rake 'semverve:generate[1.0.0,simple,force]'
|
|
271
272
|
```
|
|
272
273
|
|
|
273
274
|
## Incrementing
|
|
@@ -293,7 +294,7 @@ your gem's version in `Gemfile.lock`.
|
|
|
293
294
|
Set an exact version without incrementing:
|
|
294
295
|
|
|
295
296
|
```sh
|
|
296
|
-
rake semverve:set
|
|
297
|
+
rake 'semverve:set[1.2.3]'
|
|
297
298
|
```
|
|
298
299
|
|
|
299
300
|
Successful updates print the version change:
|
|
@@ -325,6 +326,9 @@ Run every version check with:
|
|
|
325
326
|
rake semverve:check
|
|
326
327
|
```
|
|
327
328
|
|
|
329
|
+
This task is designed for normal CI. It uses local project files, prints
|
|
330
|
+
parseable findings, and exits non-zero when it finds drift.
|
|
331
|
+
|
|
328
332
|
By default, this checks:
|
|
329
333
|
|
|
330
334
|
- README version references, plus any configured docs or comment files
|
|
@@ -430,6 +434,13 @@ same line or the preceding nonblank line.
|
|
|
430
434
|
This migration note intentionally mentions 1.0.0. <!-- semverve:ignore-version-reference -->
|
|
431
435
|
```
|
|
432
436
|
|
|
437
|
+
Audit ignored references by setting `SEMVERVE_REPORT_IGNORED=true` when running
|
|
438
|
+
check tasks:
|
|
439
|
+
|
|
440
|
+
```sh
|
|
441
|
+
SEMVERVE_REPORT_IGNORED=true rake semverve:check
|
|
442
|
+
```
|
|
443
|
+
|
|
433
444
|
### Code version literals
|
|
434
445
|
Code scanning is opt-in to avoid false positives. This is for arbitrary project
|
|
435
446
|
code, not gem metadata. The default is:
|
|
@@ -463,6 +474,13 @@ APP_VERSION = "1.2.2"
|
|
|
463
474
|
spec.version = "1.2.2"
|
|
464
475
|
```
|
|
465
476
|
|
|
477
|
+
Ignore an intentional code literal with `semverve:ignore-version-reference` on
|
|
478
|
+
the same line or the preceding nonblank line.
|
|
479
|
+
|
|
480
|
+
Set `SEMVERVE_REPORT_IGNORED=true` with `semverve:check` or
|
|
481
|
+
`semverve:check:code` to report ignored stale literals without changing
|
|
482
|
+
`semverve:fix` behavior.
|
|
483
|
+
|
|
466
484
|
The default pattern is Ruby-oriented. Semverve does not inspect file extensions
|
|
467
485
|
or parse other languages for code literals; non-Ruby files are scanned as plain
|
|
468
486
|
text with the same pattern. If a JavaScript, Python, or other source file uses a
|
|
@@ -536,6 +554,110 @@ end
|
|
|
536
554
|
`rake semverve:fix:metadata` updates safe literal gemspec assignments and
|
|
537
555
|
runs `bundle lock` when the lockfile has drifted.
|
|
538
556
|
|
|
557
|
+
## Checking release readiness
|
|
558
|
+
Release checks are separate from `rake semverve:check`. They are useful in CI,
|
|
559
|
+
but they are meant for release workflows, tag builds, or pre-publish jobs rather
|
|
560
|
+
than every pull request.
|
|
561
|
+
|
|
562
|
+
Enable the RubyGems published-version check:
|
|
563
|
+
|
|
564
|
+
```ruby
|
|
565
|
+
Semverve.configure do |config|
|
|
566
|
+
config.release_checks = [:rubygems]
|
|
567
|
+
end
|
|
568
|
+
```
|
|
569
|
+
|
|
570
|
+
Then run:
|
|
571
|
+
|
|
572
|
+
```sh
|
|
573
|
+
rake semverve:check:release
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
With `:rubygems` enabled, `semverve:check:release` asks the configured
|
|
577
|
+
RubyGems-compatible host whether the current version already exists. If it does,
|
|
578
|
+
the task exits non-zero with a message like:
|
|
579
|
+
|
|
580
|
+
```text
|
|
581
|
+
my_gem 1.2.3 already exists on https://rubygems.org.
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
If all configured release checks pass, it prints:
|
|
585
|
+
|
|
586
|
+
```text
|
|
587
|
+
Release checks passed.
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
You can also run the RubyGems check directly without changing
|
|
591
|
+
`config.release_checks`:
|
|
592
|
+
|
|
593
|
+
```sh
|
|
594
|
+
rake semverve:check:rubygems
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
When the current version is not published, the focused task prints:
|
|
598
|
+
|
|
599
|
+
```text
|
|
600
|
+
my_gem 1.2.3 is not published on https://rubygems.org.
|
|
601
|
+
```
|
|
602
|
+
|
|
603
|
+
Use `config.rubygems_host` for a private RubyGems-compatible server:
|
|
604
|
+
|
|
605
|
+
```ruby
|
|
606
|
+
Semverve.configure do |config|
|
|
607
|
+
config.release_checks = [:rubygems]
|
|
608
|
+
config.rubygems_host = "https://gems.example.com"
|
|
609
|
+
end
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
The published-version check treats a missing gem as unpublished. It fails closed
|
|
613
|
+
on registry errors, malformed responses, and network failures because release
|
|
614
|
+
pipelines should not silently publish after an inconclusive preflight.
|
|
615
|
+
|
|
616
|
+
For ordinary CI, keep using the local checks:
|
|
617
|
+
|
|
618
|
+
```sh
|
|
619
|
+
bundle exec rake test semverve:check
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
For release CI, run the release check before building or pushing:
|
|
623
|
+
|
|
624
|
+
```sh
|
|
625
|
+
bundle exec rake semverve:check:release build
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
## Vim
|
|
629
|
+
While there's no official vim support (yet), you can add the following to
|
|
630
|
+
`~/.vim/plugin/semverve.vim`.
|
|
631
|
+
|
|
632
|
+
```vim
|
|
633
|
+
command! -bang SemverveAudit call <SID>semverve_audit(<bang>0)
|
|
634
|
+
function! s:semverve_audit(report_ignored) abort
|
|
635
|
+
let l:old_efm = &errorformat
|
|
636
|
+
try
|
|
637
|
+
let &errorformat = '%f:%l:%c:%m'
|
|
638
|
+
let l:string = ""
|
|
639
|
+
if !a:report_ignored
|
|
640
|
+
let l:string .= 'SEMVERVE_REPORT_IGNORED=true '
|
|
641
|
+
endif
|
|
642
|
+
let l:string .= 'bundle exec rake semverve:check 2>/dev/null'
|
|
643
|
+
cexpr systemlist(l:string)
|
|
644
|
+
if v:shell_error != 0
|
|
645
|
+
copen
|
|
646
|
+
else
|
|
647
|
+
cclose
|
|
648
|
+
echo 'Semverve checks passed.'
|
|
649
|
+
endif
|
|
650
|
+
finally
|
|
651
|
+
let &errorformat = l:old_efm
|
|
652
|
+
endtry
|
|
653
|
+
endfunction
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
You can then call `:SemverveAudit`, which will call `bundle exec rake
|
|
657
|
+
semverve:check`, and `:SemverveAudit!` which will call the same command with
|
|
658
|
+
`SEMVERVE_REPORT_IGNORED=true`, and populate and open the quickfix list if any
|
|
659
|
+
offenses are found.
|
|
660
|
+
|
|
539
661
|
## Reporting Bugs and Requesting Features
|
|
540
662
|
If you have an idea or find a bug, please [create an
|
|
541
663
|
issue](https://github.com/evanthegrayt/semverve/issues/new). Just make sure
|
|
@@ -16,6 +16,12 @@ module Semverve
|
|
|
16
16
|
# @return [Array<Symbol>]
|
|
17
17
|
VALID_VERSION_CHECKS = [:doc_references, :code_references, :metadata].freeze
|
|
18
18
|
|
|
19
|
+
##
|
|
20
|
+
# Release-readiness surfaces supported by release check tasks.
|
|
21
|
+
#
|
|
22
|
+
# @return [Array<Symbol>]
|
|
23
|
+
VALID_RELEASE_CHECKS = [:rubygems].freeze
|
|
24
|
+
|
|
19
25
|
##
|
|
20
26
|
# Default Ruby pattern for code version literals that are safe to rewrite.
|
|
21
27
|
#
|
|
@@ -58,12 +64,24 @@ module Semverve
|
|
|
58
64
|
# @return [Symbol, String, nil]
|
|
59
65
|
attr_reader :preset
|
|
60
66
|
|
|
67
|
+
##
|
|
68
|
+
# Release-readiness surfaces run by the release check task.
|
|
69
|
+
#
|
|
70
|
+
# @return [Array<Symbol, String>]
|
|
71
|
+
attr_reader :release_checks
|
|
72
|
+
|
|
61
73
|
##
|
|
62
74
|
# Project root used when inferring metadata and expanding paths.
|
|
63
75
|
#
|
|
64
76
|
# @return [String, nil]
|
|
65
77
|
attr_reader :root
|
|
66
78
|
|
|
79
|
+
##
|
|
80
|
+
# RubyGems-compatible host used for published-version checks.
|
|
81
|
+
#
|
|
82
|
+
# @return [String]
|
|
83
|
+
attr_accessor :rubygems_host
|
|
84
|
+
|
|
67
85
|
##
|
|
68
86
|
# Explicit version-file path relative to the project root.
|
|
69
87
|
#
|
|
@@ -110,6 +128,7 @@ module Semverve
|
|
|
110
128
|
@command_runner = ->(command) { system(command) }
|
|
111
129
|
@format = :module
|
|
112
130
|
@preset = nil
|
|
131
|
+
@rubygems_host = "https://rubygems.org"
|
|
113
132
|
@version_code_reference_files = Rake::FileList[]
|
|
114
133
|
self.version_code_reference_pattern = DEFAULT_VERSION_CODE_REFERENCE_PATTERN
|
|
115
134
|
@version_doc_reference_files = Rake::FileList["README*", "**/README*"].exclude(
|
|
@@ -119,6 +138,7 @@ module Semverve
|
|
|
119
138
|
"vendor/**/*"
|
|
120
139
|
)
|
|
121
140
|
@version_reference_mode = :older
|
|
141
|
+
self.release_checks = []
|
|
122
142
|
self.version_checks = VALID_VERSION_CHECKS
|
|
123
143
|
end
|
|
124
144
|
|
|
@@ -135,7 +155,9 @@ module Semverve
|
|
|
135
155
|
format: normalized_format,
|
|
136
156
|
gem_name: metadata.gem_name,
|
|
137
157
|
module_name: metadata.module_name,
|
|
158
|
+
release_checks: normalized_release_checks,
|
|
138
159
|
root: expanded_root,
|
|
160
|
+
rubygems_host: rubygems_host,
|
|
139
161
|
version_file: metadata.version_file,
|
|
140
162
|
version_checks: normalized_version_checks,
|
|
141
163
|
version_code_reference_files: version_code_reference_files,
|
|
@@ -186,6 +208,16 @@ module Semverve
|
|
|
186
208
|
@preset = preset.nil? ? nil : Presets.fetch(preset).name
|
|
187
209
|
end
|
|
188
210
|
|
|
211
|
+
##
|
|
212
|
+
# Sets the release-readiness surfaces run by the release check task.
|
|
213
|
+
#
|
|
214
|
+
# @param [Array<Symbol, String>] checks
|
|
215
|
+
#
|
|
216
|
+
# @return [Array<Symbol>]
|
|
217
|
+
def release_checks=(checks)
|
|
218
|
+
@release_checks = normalize_release_checks(checks)
|
|
219
|
+
end
|
|
220
|
+
|
|
189
221
|
##
|
|
190
222
|
# Sets the project root used when expanding paths.
|
|
191
223
|
#
|
|
@@ -243,6 +275,14 @@ module Semverve
|
|
|
243
275
|
resolved_value(:format).to_sym
|
|
244
276
|
end
|
|
245
277
|
|
|
278
|
+
##
|
|
279
|
+
# Configured release checks normalized for lookup.
|
|
280
|
+
#
|
|
281
|
+
# @return [Array<Symbol>]
|
|
282
|
+
def normalized_release_checks
|
|
283
|
+
normalize_release_checks(release_checks)
|
|
284
|
+
end
|
|
285
|
+
|
|
246
286
|
##
|
|
247
287
|
# Resolved value for a configurable attribute before metadata inference.
|
|
248
288
|
#
|
|
@@ -290,6 +330,22 @@ module Semverve
|
|
|
290
330
|
raise Error, "Unknown version check #{invalid_checks.map(&:inspect).join(", ")}. Use #{valid_checks}."
|
|
291
331
|
end
|
|
292
332
|
|
|
333
|
+
##
|
|
334
|
+
# Normalizes and validates release checks.
|
|
335
|
+
#
|
|
336
|
+
# @param [Array<Symbol, String>] checks
|
|
337
|
+
#
|
|
338
|
+
# @return [Array<Symbol>]
|
|
339
|
+
def normalize_release_checks(checks)
|
|
340
|
+
normalized_checks = Array(checks).map do |check|
|
|
341
|
+
check.respond_to?(:to_sym) ? check.to_sym : check
|
|
342
|
+
end
|
|
343
|
+
return normalized_checks if normalized_checks.all? { |check| VALID_RELEASE_CHECKS.include?(check) }
|
|
344
|
+
|
|
345
|
+
invalid_checks = normalized_checks.reject { |check| VALID_RELEASE_CHECKS.include?(check) }
|
|
346
|
+
raise Error, "Unknown release check #{invalid_checks.map(&:inspect).join(", ")}. Use :rubygems."
|
|
347
|
+
end
|
|
348
|
+
|
|
293
349
|
##
|
|
294
350
|
# Validates the configured code reference pattern.
|
|
295
351
|
#
|
|
@@ -373,12 +429,24 @@ module Semverve
|
|
|
373
429
|
# @return [String]
|
|
374
430
|
attr_reader :module_name
|
|
375
431
|
|
|
432
|
+
##
|
|
433
|
+
# Resolved release-readiness surfaces run by the release check task.
|
|
434
|
+
#
|
|
435
|
+
# @return [Array<Symbol>]
|
|
436
|
+
attr_reader :release_checks
|
|
437
|
+
|
|
376
438
|
##
|
|
377
439
|
# Absolute project root.
|
|
378
440
|
#
|
|
379
441
|
# @return [String]
|
|
380
442
|
attr_reader :root
|
|
381
443
|
|
|
444
|
+
##
|
|
445
|
+
# Resolved RubyGems-compatible host used for published-version checks.
|
|
446
|
+
#
|
|
447
|
+
# @return [String]
|
|
448
|
+
attr_reader :rubygems_host
|
|
449
|
+
|
|
382
450
|
##
|
|
383
451
|
# Resolved version-file path relative to the project root.
|
|
384
452
|
#
|
|
@@ -423,7 +491,9 @@ module Semverve
|
|
|
423
491
|
# @param [Symbol] format
|
|
424
492
|
# @param [String] gem_name
|
|
425
493
|
# @param [String] module_name
|
|
494
|
+
# @param [Array<Symbol>] release_checks
|
|
426
495
|
# @param [String] root
|
|
496
|
+
# @param [String] rubygems_host
|
|
427
497
|
# @param [String] version_file
|
|
428
498
|
# @param [Array<Symbol>] version_checks
|
|
429
499
|
# @param [Rake::FileList] version_code_reference_files
|
|
@@ -438,7 +508,9 @@ module Semverve
|
|
|
438
508
|
format:,
|
|
439
509
|
gem_name:,
|
|
440
510
|
module_name:,
|
|
511
|
+
release_checks:,
|
|
441
512
|
root:,
|
|
513
|
+
rubygems_host:,
|
|
442
514
|
version_file:,
|
|
443
515
|
version_checks:,
|
|
444
516
|
version_code_reference_files:,
|
|
@@ -451,7 +523,9 @@ module Semverve
|
|
|
451
523
|
@format = format
|
|
452
524
|
@gem_name = gem_name
|
|
453
525
|
@module_name = module_name
|
|
526
|
+
@release_checks = release_checks
|
|
454
527
|
@root = root
|
|
528
|
+
@rubygems_host = rubygems_host
|
|
455
529
|
@version_file = version_file
|
|
456
530
|
@version_checks = version_checks
|
|
457
531
|
@version_code_reference_files = version_code_reference_files
|
data/lib/semverve/generator.rb
CHANGED
|
@@ -11,21 +11,25 @@ module Semverve
|
|
|
11
11
|
# Generates new Ruby version files from Semverve configuration.
|
|
12
12
|
class Generator
|
|
13
13
|
##
|
|
14
|
-
# Default version used when
|
|
14
|
+
# Default version used when a version argument is not provided.
|
|
15
15
|
#
|
|
16
16
|
# @return [String]
|
|
17
|
-
DEFAULT_VERSION = "0.1.0"
|
|
17
|
+
DEFAULT_VERSION = "0.1.0" # semverve:ignore-version-reference
|
|
18
18
|
|
|
19
19
|
##
|
|
20
20
|
# Initializes a version-file generator.
|
|
21
21
|
#
|
|
22
22
|
# @param [Semverve::ResolvedConfiguration] configuration
|
|
23
|
-
# @param [
|
|
23
|
+
# @param [String, nil] version
|
|
24
|
+
# @param [String, Symbol, nil] format
|
|
25
|
+
# @param [Boolean] force
|
|
24
26
|
#
|
|
25
27
|
# @return [Semverve::Generator]
|
|
26
|
-
def initialize(configuration,
|
|
28
|
+
def initialize(configuration, version: nil, format: nil, force: false)
|
|
27
29
|
@configuration = configuration
|
|
28
|
-
@
|
|
30
|
+
@version = version
|
|
31
|
+
@format = format
|
|
32
|
+
@force = force
|
|
29
33
|
end
|
|
30
34
|
|
|
31
35
|
##
|
|
@@ -33,12 +37,12 @@ module Semverve
|
|
|
33
37
|
#
|
|
34
38
|
# @return [String]
|
|
35
39
|
def generate
|
|
36
|
-
version = SemanticVersion.parse(
|
|
37
|
-
format = Formats.fetch(
|
|
40
|
+
version = SemanticVersion.parse(requested_version)
|
|
41
|
+
format = Formats.fetch(requested_format)
|
|
38
42
|
path = configuration.absolute_version_file
|
|
39
43
|
|
|
40
44
|
if File.exist?(path) && !force?
|
|
41
|
-
raise Error, "Version file already exists at #{path}.
|
|
45
|
+
raise Error, "Version file already exists at #{path}. Run rake 'semverve:generate[force]' to overwrite it."
|
|
42
46
|
end
|
|
43
47
|
|
|
44
48
|
FileUtils.mkdir_p(File.dirname(path))
|
|
@@ -53,14 +57,30 @@ module Semverve
|
|
|
53
57
|
# Resolved configuration used for generation.
|
|
54
58
|
#
|
|
55
59
|
# @return [Semverve::ResolvedConfiguration]
|
|
56
|
-
attr_reader :configuration, :
|
|
60
|
+
attr_reader :configuration, :version, :format, :force
|
|
61
|
+
|
|
62
|
+
##
|
|
63
|
+
# Requested version or default.
|
|
64
|
+
#
|
|
65
|
+
# @return [String]
|
|
66
|
+
def requested_version
|
|
67
|
+
version || DEFAULT_VERSION
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
##
|
|
71
|
+
# Requested format or configured default.
|
|
72
|
+
#
|
|
73
|
+
# @return [String, Symbol]
|
|
74
|
+
def requested_format
|
|
75
|
+
format || configuration.format
|
|
76
|
+
end
|
|
57
77
|
|
|
58
78
|
##
|
|
59
79
|
# Whether generation should overwrite an existing version file.
|
|
60
80
|
#
|
|
61
81
|
# @return [Boolean]
|
|
62
82
|
def force?
|
|
63
|
-
|
|
83
|
+
force
|
|
64
84
|
end
|
|
65
85
|
end
|
|
66
86
|
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "net/http"
|
|
5
|
+
require "timeout"
|
|
6
|
+
require "uri"
|
|
7
|
+
|
|
8
|
+
require_relative "error"
|
|
9
|
+
|
|
10
|
+
module Semverve
|
|
11
|
+
##
|
|
12
|
+
# Checks whether the current gem version already exists on a
|
|
13
|
+
# RubyGems-compatible host.
|
|
14
|
+
class PublishedVersion
|
|
15
|
+
class << self
|
|
16
|
+
##
|
|
17
|
+
# Callable used to fetch RubyGems-compatible API responses.
|
|
18
|
+
#
|
|
19
|
+
# @return [#call]
|
|
20
|
+
attr_writer :http_getter
|
|
21
|
+
|
|
22
|
+
##
|
|
23
|
+
# Returns the HTTP response fetcher.
|
|
24
|
+
#
|
|
25
|
+
# @return [#call]
|
|
26
|
+
def http_getter
|
|
27
|
+
@http_getter ||= ->(uri) { Net::HTTP.get_response(uri) }
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
##
|
|
32
|
+
# Initializes a published-version check.
|
|
33
|
+
#
|
|
34
|
+
# @param [Semverve::ResolvedConfiguration] configuration
|
|
35
|
+
# @param [Semverve::SemanticVersion] current_version
|
|
36
|
+
#
|
|
37
|
+
# @return [Semverve::PublishedVersion]
|
|
38
|
+
def initialize(configuration, current_version)
|
|
39
|
+
@configuration = configuration
|
|
40
|
+
@current_version = current_version
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
##
|
|
44
|
+
# Whether the current version already exists on the configured host.
|
|
45
|
+
#
|
|
46
|
+
# @return [Boolean]
|
|
47
|
+
def published?
|
|
48
|
+
versions.any? { |version| version.fetch("number", nil).to_s == current_version.to_s }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
##
|
|
52
|
+
# Raises if the current version already exists.
|
|
53
|
+
#
|
|
54
|
+
# @return [void]
|
|
55
|
+
def check
|
|
56
|
+
if published?
|
|
57
|
+
raise Error, "#{configuration.gem_name} #{current_version} already exists on #{configuration.rubygems_host}."
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
##
|
|
64
|
+
# Resolved Semverve configuration.
|
|
65
|
+
#
|
|
66
|
+
# @return [Semverve::ResolvedConfiguration]
|
|
67
|
+
attr_reader :configuration
|
|
68
|
+
|
|
69
|
+
##
|
|
70
|
+
# Current gem version.
|
|
71
|
+
#
|
|
72
|
+
# @return [Semverve::SemanticVersion]
|
|
73
|
+
attr_reader :current_version
|
|
74
|
+
|
|
75
|
+
##
|
|
76
|
+
# Published versions from the configured RubyGems-compatible host.
|
|
77
|
+
#
|
|
78
|
+
# @return [Array<Hash>]
|
|
79
|
+
def versions
|
|
80
|
+
response = self.class.http_getter.call(versions_uri)
|
|
81
|
+
|
|
82
|
+
case response.code.to_i
|
|
83
|
+
when 200
|
|
84
|
+
parse_versions(response.body)
|
|
85
|
+
when 404
|
|
86
|
+
[]
|
|
87
|
+
else
|
|
88
|
+
raise Error, "Could not check #{configuration.gem_name} on #{configuration.rubygems_host}: HTTP #{response.code}."
|
|
89
|
+
end
|
|
90
|
+
rescue JSON::ParserError => error
|
|
91
|
+
raise Error, "Could not parse published versions for #{configuration.gem_name}: #{error.message}"
|
|
92
|
+
rescue SystemCallError, Timeout::Error, SocketError, URI::Error => error
|
|
93
|
+
raise Error, "Could not check #{configuration.gem_name} on #{configuration.rubygems_host}: #{error.message}"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
##
|
|
97
|
+
# Endpoint for a gem's published versions.
|
|
98
|
+
#
|
|
99
|
+
# @return [URI::HTTP, URI::HTTPS]
|
|
100
|
+
def versions_uri
|
|
101
|
+
URI("#{configuration.rubygems_host.chomp("/")}/api/v1/versions/#{URI.encode_www_form_component(configuration.gem_name)}.json")
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
##
|
|
105
|
+
# Parsed version response.
|
|
106
|
+
#
|
|
107
|
+
# @param [String] body
|
|
108
|
+
#
|
|
109
|
+
# @return [Array<Hash>]
|
|
110
|
+
def parse_versions(body)
|
|
111
|
+
versions = JSON.parse(body)
|
|
112
|
+
return versions if versions.is_a?(Array)
|
|
113
|
+
|
|
114
|
+
raise Error, "Could not parse published versions for #{configuration.gem_name}: expected an array."
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
data/lib/semverve/task.rb
CHANGED
|
@@ -4,6 +4,7 @@ require "rake"
|
|
|
4
4
|
|
|
5
5
|
require_relative "../semverve"
|
|
6
6
|
require_relative "generator"
|
|
7
|
+
require_relative "published_version"
|
|
7
8
|
require_relative "semantic_version"
|
|
8
9
|
require_relative "version_file"
|
|
9
10
|
require_relative "version_code_references"
|
|
@@ -98,13 +99,19 @@ module Semverve
|
|
|
98
99
|
end
|
|
99
100
|
|
|
100
101
|
desc "Generate a version.rb file"
|
|
101
|
-
task :generate do
|
|
102
|
-
|
|
102
|
+
task :generate, [:version, :format, :force] do |_task, args|
|
|
103
|
+
generator_options = generate_options(args)
|
|
104
|
+
puts "Generated #{Generator.new(
|
|
105
|
+
Semverve.configuration.resolved,
|
|
106
|
+
version: generator_options[:version],
|
|
107
|
+
format: generator_options[:format],
|
|
108
|
+
force: generator_options[:force]
|
|
109
|
+
).generate}"
|
|
103
110
|
end
|
|
104
111
|
|
|
105
|
-
desc "Set the version.rb file to
|
|
106
|
-
task :set do
|
|
107
|
-
set
|
|
112
|
+
desc "Set the version.rb file to version"
|
|
113
|
+
task :set, [:version] do |_task, args|
|
|
114
|
+
set(args)
|
|
108
115
|
end
|
|
109
116
|
|
|
110
117
|
desc "Check version references, code literals, and metadata"
|
|
@@ -127,6 +134,16 @@ module Semverve
|
|
|
127
134
|
task :metadata do
|
|
128
135
|
check_metadata
|
|
129
136
|
end
|
|
137
|
+
|
|
138
|
+
desc "Check whether the current gem version is already published"
|
|
139
|
+
task :rubygems do
|
|
140
|
+
check_rubygems
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
desc "Check configured release-readiness surfaces"
|
|
144
|
+
task :release do
|
|
145
|
+
check_release
|
|
146
|
+
end
|
|
130
147
|
end
|
|
131
148
|
|
|
132
149
|
desc "Fix version references, code literals, and metadata"
|
|
@@ -169,14 +186,14 @@ module Semverve
|
|
|
169
186
|
end
|
|
170
187
|
|
|
171
188
|
##
|
|
172
|
-
# Sets the version to the value from the +
|
|
189
|
+
# Sets the version to the value from the Rake +version+ argument.
|
|
190
|
+
#
|
|
191
|
+
# @param [Rake::TaskArguments] args
|
|
173
192
|
#
|
|
174
193
|
# @return [void]
|
|
175
|
-
def set
|
|
194
|
+
def set(args)
|
|
176
195
|
configuration = Semverve.configuration.resolved
|
|
177
|
-
requested_version = SemanticVersion.parse(
|
|
178
|
-
ENV.fetch("VERSION") { raise Error, "Set VERSION=MAJOR.MINOR.PATCH." }
|
|
179
|
-
)
|
|
196
|
+
requested_version = SemanticVersion.parse(requested_version_argument(args))
|
|
180
197
|
update = VersionFile.new(configuration).set(requested_version)
|
|
181
198
|
|
|
182
199
|
report(update, configuration)
|
|
@@ -211,7 +228,7 @@ module Semverve
|
|
|
211
228
|
def check_references
|
|
212
229
|
configuration, current_version = check_context
|
|
213
230
|
report_findings(
|
|
214
|
-
[["version reference", VersionReferences.new(configuration, current_version).findings]],
|
|
231
|
+
[["version reference", VersionReferences.new(configuration, current_version, include_ignored: report_ignored?).findings]],
|
|
215
232
|
current_version,
|
|
216
233
|
clean_message: "Version references are current."
|
|
217
234
|
)
|
|
@@ -236,7 +253,7 @@ module Semverve
|
|
|
236
253
|
def check_code
|
|
237
254
|
configuration, current_version = check_context
|
|
238
255
|
report_findings(
|
|
239
|
-
[["code version literal", VersionCodeReferences.new(configuration, current_version).findings]],
|
|
256
|
+
[["code version literal", VersionCodeReferences.new(configuration, current_version, include_ignored: report_ignored?).findings]],
|
|
240
257
|
current_version,
|
|
241
258
|
clean_message: "Code version literals are current."
|
|
242
259
|
)
|
|
@@ -267,6 +284,31 @@ module Semverve
|
|
|
267
284
|
)
|
|
268
285
|
end
|
|
269
286
|
|
|
287
|
+
##
|
|
288
|
+
# Checks whether the current gem version is already published.
|
|
289
|
+
#
|
|
290
|
+
# @return [void]
|
|
291
|
+
def check_rubygems
|
|
292
|
+
configuration, current_version = check_context
|
|
293
|
+
PublishedVersion.new(configuration, current_version).check
|
|
294
|
+
|
|
295
|
+
puts "#{configuration.gem_name} #{current_version} is not published on #{configuration.rubygems_host}."
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
##
|
|
299
|
+
# Checks configured release-readiness surfaces.
|
|
300
|
+
#
|
|
301
|
+
# @return [void]
|
|
302
|
+
def check_release
|
|
303
|
+
configuration, current_version = check_context
|
|
304
|
+
|
|
305
|
+
if configuration.release_checks.include?(:rubygems)
|
|
306
|
+
PublishedVersion.new(configuration, current_version).check
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
puts "Release checks passed."
|
|
310
|
+
end
|
|
311
|
+
|
|
270
312
|
##
|
|
271
313
|
# Fixes safe gem metadata version mismatches.
|
|
272
314
|
#
|
|
@@ -298,10 +340,10 @@ module Semverve
|
|
|
298
340
|
def check_groups(configuration, current_version)
|
|
299
341
|
groups = []
|
|
300
342
|
if configuration.version_checks.include?(:doc_references)
|
|
301
|
-
groups << ["version reference", VersionReferences.new(configuration, current_version).findings]
|
|
343
|
+
groups << ["version reference", VersionReferences.new(configuration, current_version, include_ignored: report_ignored?).findings]
|
|
302
344
|
end
|
|
303
345
|
if configuration.version_checks.include?(:code_references)
|
|
304
|
-
groups << ["code version literal", VersionCodeReferences.new(configuration, current_version).findings]
|
|
346
|
+
groups << ["code version literal", VersionCodeReferences.new(configuration, current_version, include_ignored: report_ignored?).findings]
|
|
305
347
|
end
|
|
306
348
|
if configuration.version_checks.include?(:metadata)
|
|
307
349
|
groups << [nil, VersionMetadata.new(configuration, current_version).findings]
|
|
@@ -309,6 +351,67 @@ module Semverve
|
|
|
309
351
|
groups
|
|
310
352
|
end
|
|
311
353
|
|
|
354
|
+
##
|
|
355
|
+
# Whether check tasks should report references hidden by ignore markers.
|
|
356
|
+
#
|
|
357
|
+
# @return [Boolean]
|
|
358
|
+
def report_ignored?
|
|
359
|
+
ENV.fetch("SEMVERVE_REPORT_IGNORED", "false").match?(/\A(true|1|yes)\z/i)
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
##
|
|
363
|
+
# Parsed arguments for +semverve:generate+.
|
|
364
|
+
#
|
|
365
|
+
# @param [Rake::TaskArguments] args
|
|
366
|
+
#
|
|
367
|
+
# @return [Hash]
|
|
368
|
+
def generate_options(args)
|
|
369
|
+
args.to_a.each_with_object({force: false}) do |value, options|
|
|
370
|
+
assign_generate_option(value, options)
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
##
|
|
375
|
+
# Assigns a single +semverve:generate+ token by meaning.
|
|
376
|
+
#
|
|
377
|
+
# @param [String] value
|
|
378
|
+
# @param [Hash] options
|
|
379
|
+
#
|
|
380
|
+
# @return [void]
|
|
381
|
+
def assign_generate_option(value, options)
|
|
382
|
+
case value
|
|
383
|
+
when nil, ""
|
|
384
|
+
nil
|
|
385
|
+
when "force"
|
|
386
|
+
raise Error, "Duplicate generate option force." if options[:force]
|
|
387
|
+
|
|
388
|
+
options[:force] = true
|
|
389
|
+
when SemanticVersion::PATTERN
|
|
390
|
+
raise Error, "Duplicate generate version #{value.inspect}." if options[:version]
|
|
391
|
+
|
|
392
|
+
options[:version] = value
|
|
393
|
+
when "module", "simple"
|
|
394
|
+
raise Error, "Duplicate generate format #{value.inspect}." if options[:format]
|
|
395
|
+
|
|
396
|
+
options[:format] = value
|
|
397
|
+
else
|
|
398
|
+
raise Error, "Unknown generate option #{value.inspect}. Use a semantic version, module, simple, or force."
|
|
399
|
+
end
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
##
|
|
403
|
+
# Required version argument for +semverve:set+.
|
|
404
|
+
#
|
|
405
|
+
# @param [Rake::TaskArguments] args
|
|
406
|
+
#
|
|
407
|
+
# @return [String]
|
|
408
|
+
def requested_version_argument(args)
|
|
409
|
+
version = args[:version]
|
|
410
|
+
raise Error, "Run rake 'semverve:set[MAJOR.MINOR.PATCH]'." if version.nil? || version.empty?
|
|
411
|
+
|
|
412
|
+
version
|
|
413
|
+
end
|
|
414
|
+
|
|
312
415
|
##
|
|
313
416
|
# Fix results enabled for the umbrella fix task.
|
|
314
417
|
#
|
data/lib/semverve/version.rb
CHANGED
|
@@ -8,6 +8,12 @@ module Semverve
|
|
|
8
8
|
##
|
|
9
9
|
# Finds and updates safe version literals in configured code files.
|
|
10
10
|
class VersionCodeReferences
|
|
11
|
+
##
|
|
12
|
+
# Marker that suppresses version-reference findings.
|
|
13
|
+
#
|
|
14
|
+
# @return [String]
|
|
15
|
+
IGNORE_MARKER = "semverve:ignore-version-reference"
|
|
16
|
+
|
|
11
17
|
##
|
|
12
18
|
# Ruby assignments that are safe enough to rewrite automatically.
|
|
13
19
|
#
|
|
@@ -93,9 +99,10 @@ module Semverve
|
|
|
93
99
|
# @param [Semverve::SemanticVersion] current_version
|
|
94
100
|
#
|
|
95
101
|
# @return [Semverve::VersionCodeReferences]
|
|
96
|
-
def initialize(configuration, current_version)
|
|
102
|
+
def initialize(configuration, current_version, include_ignored: false)
|
|
97
103
|
@configuration = configuration
|
|
98
104
|
@current_version = current_version
|
|
105
|
+
@include_ignored = include_ignored
|
|
99
106
|
end
|
|
100
107
|
|
|
101
108
|
##
|
|
@@ -142,6 +149,12 @@ module Semverve
|
|
|
142
149
|
# @return [Semverve::SemanticVersion]
|
|
143
150
|
attr_reader :current_version
|
|
144
151
|
|
|
152
|
+
##
|
|
153
|
+
# Whether ignored code literals should be included in findings.
|
|
154
|
+
#
|
|
155
|
+
# @return [Boolean]
|
|
156
|
+
attr_reader :include_ignored
|
|
157
|
+
|
|
145
158
|
##
|
|
146
159
|
# Absolute configured project root.
|
|
147
160
|
#
|
|
@@ -176,7 +189,11 @@ module Semverve
|
|
|
176
189
|
#
|
|
177
190
|
# @return [Array<Semverve::VersionCodeReferences::Finding>]
|
|
178
191
|
def findings_for_file(path)
|
|
179
|
-
File.readlines(path)
|
|
192
|
+
lines = File.readlines(path)
|
|
193
|
+
|
|
194
|
+
lines.filter_map.with_index(1) do |line, line_number|
|
|
195
|
+
next if !include_ignored && ignored_line?(line_number, lines)
|
|
196
|
+
|
|
180
197
|
match = line.match(pattern)
|
|
181
198
|
next unless match
|
|
182
199
|
|
|
@@ -200,8 +217,11 @@ module Semverve
|
|
|
200
217
|
# @return [Array(String, Integer)]
|
|
201
218
|
def fixed_content(content)
|
|
202
219
|
replacement_count = 0
|
|
220
|
+
lines = content.lines
|
|
221
|
+
|
|
222
|
+
fixed = lines.map.with_index(1) do |line, line_number|
|
|
223
|
+
next line if ignored_line?(line_number, lines)
|
|
203
224
|
|
|
204
|
-
fixed = content.lines.map do |line|
|
|
205
225
|
match = line.match(pattern)
|
|
206
226
|
next line unless match
|
|
207
227
|
|
|
@@ -215,6 +235,23 @@ module Semverve
|
|
|
215
235
|
[fixed, replacement_count]
|
|
216
236
|
end
|
|
217
237
|
|
|
238
|
+
##
|
|
239
|
+
# Whether findings on a line should be ignored.
|
|
240
|
+
#
|
|
241
|
+
# @param [Integer] line_number
|
|
242
|
+
# @param [Array<String>] lines
|
|
243
|
+
#
|
|
244
|
+
# @return [Boolean]
|
|
245
|
+
def ignored_line?(line_number, lines)
|
|
246
|
+
return true if lines.fetch(line_number - 1).include?(IGNORE_MARKER)
|
|
247
|
+
|
|
248
|
+
# Ruby 3.2 and 3.3 do not support Array#rfind.
|
|
249
|
+
# rubocop:disable Style/ReverseFind
|
|
250
|
+
previous_nonblank_line = lines[0...(line_number - 1)].reverse_each.find { |candidate| !candidate.strip.empty? }
|
|
251
|
+
# rubocop:enable Style/ReverseFind
|
|
252
|
+
previous_nonblank_line&.include?(IGNORE_MARKER)
|
|
253
|
+
end
|
|
254
|
+
|
|
218
255
|
##
|
|
219
256
|
# Replaces only the named version capture in the first pattern match.
|
|
220
257
|
#
|
|
@@ -107,9 +107,10 @@ module Semverve
|
|
|
107
107
|
# @param [Semverve::SemanticVersion] current_version
|
|
108
108
|
#
|
|
109
109
|
# @return [Semverve::VersionReferences]
|
|
110
|
-
def initialize(configuration, current_version)
|
|
110
|
+
def initialize(configuration, current_version, include_ignored: false)
|
|
111
111
|
@configuration = configuration
|
|
112
112
|
@current_version = current_version
|
|
113
|
+
@include_ignored = include_ignored
|
|
113
114
|
end
|
|
114
115
|
|
|
115
116
|
##
|
|
@@ -156,6 +157,12 @@ module Semverve
|
|
|
156
157
|
# @return [Semverve::SemanticVersion]
|
|
157
158
|
attr_reader :current_version
|
|
158
159
|
|
|
160
|
+
##
|
|
161
|
+
# Whether ignored references should be included in findings.
|
|
162
|
+
#
|
|
163
|
+
# @return [Boolean]
|
|
164
|
+
attr_reader :include_ignored
|
|
165
|
+
|
|
159
166
|
##
|
|
160
167
|
# Absolute configured project root.
|
|
161
168
|
#
|
|
@@ -346,7 +353,7 @@ module Semverve
|
|
|
346
353
|
#
|
|
347
354
|
# @return [Array<Hash>]
|
|
348
355
|
def references_for_segment(segment, content)
|
|
349
|
-
return [] if ignored_line?(segment[:line], content)
|
|
356
|
+
return [] if !include_ignored && ignored_line?(segment[:line], content)
|
|
350
357
|
|
|
351
358
|
segment[:text].to_enum(:scan, VERSION_PATTERN).filter_map do
|
|
352
359
|
match = Regexp.last_match
|
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.1
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Evan Gray
|
|
@@ -119,6 +119,7 @@ files:
|
|
|
119
119
|
- lib/semverve/generator.rb
|
|
120
120
|
- lib/semverve/presets.rb
|
|
121
121
|
- lib/semverve/project_metadata.rb
|
|
122
|
+
- lib/semverve/published_version.rb
|
|
122
123
|
- lib/semverve/railtie.rb
|
|
123
124
|
- lib/semverve/semantic_version.rb
|
|
124
125
|
- lib/semverve/task.rb
|