gem_kit-release 0.1.0 → 0.2.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.
@@ -3,13 +3,13 @@
3
3
  The whole process, in order:
4
4
 
5
5
  ```sh
6
- <%= test.ljust(30) %># 1. green suite
7
- gem kit bump minor # 2. bump (prints: now run gem kit changelog --write)
8
- gem kit changelog --write # 3. write the entry
9
- gem kit changelog <VERSION> # 4. check it
10
- git commit -am "Release ..." # 5. commit the bump + changelog
11
- gem kit release # 6. build and push
12
- gem kit tag --push # 7. tag it
6
+ <%= step(test) %># 1. green suite
7
+ <%= step("gem kit bump#{gem_flag} minor") %># 2. bump (prints what to run next)
8
+ <%= step("gem kit changelog#{gem_flag} --write") %># 3. write the entry
9
+ <%= step("gem kit changelog#{gem_flag} <VERSION>") %># 4. check it
10
+ <%= step(%(git commit -am "Release ...")) %># 5. commit the bump + changelog
11
+ <%= step("gem kit release#{gem_flag}") %># 6. build and push
12
+ <%= step("gem kit tag#{gem_flag} --push") %># 7. tag it
13
13
  ```
14
14
 
15
15
  Steps 2 and 6 are gates: they refuse to proceed when something is missing.
@@ -18,7 +18,7 @@ Everything below is what they check and why.
18
18
  ## Versioning
19
19
 
20
20
  <%= name %> is [semver](https://semver.org/). The version lives in one place —
21
- `<%= version_file %>` — and is only ever changed by `gem kit bump`.
21
+ `<%= version_file %>` — and is only ever changed by `gem kit bump<%= gem_flag %>`.
22
22
 
23
23
  | Segment | When | What it may contain |
24
24
  | --- | --- | --- |
@@ -29,7 +29,7 @@ Everything below is what they check and why.
29
29
  Two rules follow from this, and both are enforced in code:
30
30
 
31
31
  - **Removals only ever land in a major version.** A name promised to disappear
32
- in <%= next_major %> disappears in <%= next_major %>.0.0, not in a patch.
32
+ in <%= next_major %> disappears in <%= next_major %>.0, not in a patch.
33
33
  - **Deprecating is a minor.** Adding a deprecation puts no obligation on the
34
34
  user *yet*, so it does not need a major — but it starts the clock. See
35
35
  [DEPRECATIONS.md](DEPRECATIONS.md).
@@ -45,7 +45,7 @@ A red suite is not a release candidate; nothing downstream checks this for you.
45
45
  ## 2. Bump
46
46
 
47
47
  ```sh
48
- gem kit bump <major|minor|patch>
48
+ gem kit bump<%= gem_flag %> <major|minor|patch>
49
49
  ```
50
50
 
51
51
  Rewrites `<%= version_file %>` — by rendering its `.erb` template if there is
@@ -55,7 +55,7 @@ transition:
55
55
  ```
56
56
  <%= version %> -> ...
57
57
 
58
- now run: gem kit changelog --write
58
+ now run: gem kit changelog<%= gem_flag %> --write
59
59
  ```
60
60
 
61
61
  **It refuses to bump onto a deprecation deadline.** If any registered
@@ -67,7 +67,7 @@ reported for information, not blocked on.
67
67
  ## 3. Changelog
68
68
 
69
69
  ```sh
70
- gem kit changelog --write
70
+ gem kit changelog<%= gem_flag %> --write
71
71
  ```
72
72
 
73
73
  Hands the entry to the AI CLI named by `config.changelog_writer` (default:
@@ -100,8 +100,8 @@ of anything that shipped.
100
100
  ## 4. Lint the changelog
101
101
 
102
102
  ```sh
103
- gem kit changelog # format only
104
- gem kit changelog <%= version %> # format, plus "is this version ready?"
103
+ gem kit changelog<%= gem_flag %> # format only
104
+ gem kit changelog<%= gem_flag %> <%= version %> # format, plus "is this version ready?"
105
105
  ```
106
106
 
107
107
  Checks the title, that every heading is `## [Unreleased]` or
@@ -119,7 +119,7 @@ unwritten in git is the failure this process exists to prevent.
119
119
  ## 6. Release
120
120
 
121
121
  ```sh
122
- gem kit release # or: gem kit release --dry-run, which is the CI check
122
+ gem kit release<%= gem_flag %> # or: gem kit release<%= gem_flag %> --dry-run, which is the CI check
123
123
  ```
124
124
 
125
125
  Two gates, both before `gem build` runs:
@@ -134,11 +134,11 @@ Then `gem build` and `gem push`. Requires RubyGems push credentials.
134
134
  ## 7. Tag
135
135
 
136
136
  ```sh
137
- gem kit tag --push
137
+ gem kit tag<%= gem_flag %> --push
138
138
  ```
139
139
 
140
- Creates `v<%= version %>`, refusing if it already exists. The tag is also what
141
- the next `gem kit changelog --write` uses to find the commit range, so a missing
140
+ Creates `<%= tag_prefix %><%= version %>`, refusing if it already exists. The tag is also what
141
+ the next `gem kit changelog<%= gem_flag %> --write` uses to find the commit range, so a missing
142
142
  one makes the following release's changelog harder to write.
143
143
 
144
144
  ## When something goes wrong
@@ -148,10 +148,10 @@ it is genuinely dangerous, otherwise ship a patch. Yanking a version other
148
148
  people have already locked to breaks their builds.
149
149
 
150
150
  **Bumped but the release failed.** The bump is just a file. Fix the cause and
151
- re-run `gem kit release`; there is no need to un-bump.
151
+ re-run `gem kit release<%= gem_flag %>`; there is no need to un-bump.
152
152
 
153
153
  **Changelog written for the wrong version.** Edit the heading and re-run
154
- `gem kit changelog <version>`. Nothing downstream caches it.
154
+ `gem kit changelog<%= gem_flag %> <version>`. Nothing downstream caches it.
155
155
 
156
156
  ## See also
157
157
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module GemKit
4
4
  module Release
5
- VERSION = "0.1.0"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "../gem_kit"
3
4
  require_relative "release/version"
4
- require_relative "release/deprecate"
5
5
  require_relative "release/changelog"
6
6
  require_relative "release/project"
7
7
  require_relative "release/version_file"
@@ -38,13 +38,14 @@ module GemKit
38
38
  config
39
39
  end
40
40
 
41
- # The project the tooling is running in.
42
- def self.project(dir = Dir.pwd)
43
- Project.detect(dir)
41
+ # The project the tooling is running in. `name` picks one out of a
42
+ # repository holding several gemspecs — this one, for instance.
43
+ def self.project(dir = Dir.pwd, name: nil)
44
+ Project.detect(dir, name: name)
44
45
  end
45
46
 
46
- def self.gate(dir = Dir.pwd)
47
- Gate.new(project(dir))
47
+ def self.gate(dir = Dir.pwd, name: nil)
48
+ Gate.new(project(dir, name: name))
48
49
  end
49
50
 
50
51
  # Reset configuration — for tests.
@@ -68,10 +69,21 @@ describe "gem_kit/release" do
68
69
  GemKit::Release.config.changelog.should.be.nil
69
70
  end
70
71
 
71
- it "detects itself as a project" do
72
- project = GemKit::Release.project(File.expand_path("../..", __dir__))
73
- project.name.should == "gem_kit-release"
74
- project.version.should == Gem::Version.new(GemKit::Release::VERSION)
75
- project.require_path.should == "gem_kit/release"
72
+ it "detects a named gem out of this repository" do
73
+ root = File.expand_path("../..", __dir__)
74
+
75
+ release = GemKit::Release.project(root, name: "gem_kit-release")
76
+ release.name.should == "gem_kit-release"
77
+ release.version.should == Gem::Version.new(GemKit::Release::VERSION)
78
+ release.require_path.should == "gem_kit/release"
79
+
80
+ runtime = GemKit::Release.project(root, name: "gem_kit")
81
+ runtime.name.should == "gem_kit"
82
+ runtime.require_path.should == "gem_kit"
83
+ end
84
+
85
+ it "refuses to guess which gem in this repository is meant" do
86
+ lambda { GemKit::Release.project(File.expand_path("../..", __dir__)) }
87
+ .should.raise(GemKit::Release::Project::Ambiguous)
76
88
  end
77
89
  end
@@ -60,7 +60,7 @@ module Gem
60
60
  # is installed, which keeps the command testable from the repo.
61
61
  require_relative "../../gem_kit/release/cli"
62
62
 
63
- terminate_interaction(GemKit::Release::CLI.run(@argv || []))
63
+ terminate_interaction(GemKit::Release.run(@argv || []))
64
64
  end
65
65
  end
66
66
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gem_kit-release
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Kidd
@@ -10,38 +10,69 @@ cert_chain: []
10
10
  date: 1980-01-01 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
- name: dry-cli
13
+ name: gem_kit
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - "~>"
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0.1'
19
+ - - "<"
17
20
  - !ruby/object:Gem::Version
18
21
  version: '1.0'
19
22
  type: :runtime
20
23
  prerelease: false
21
24
  version_requirements: !ruby/object:Gem::Requirement
22
25
  requirements:
23
- - - "~>"
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '0.1'
29
+ - - "<"
24
30
  - !ruby/object:Gem::Version
25
31
  version: '1.0'
26
- description: 'A deprecation is a dated promise: it names its replacement and the version
27
- the old name stops existing in. gem_kit-release makes that promise machine-checkable,
28
- and refuses to release a version that breaks one or ships without a changelog entry.'
32
+ - !ruby/object:Gem::Dependency
33
+ name: thor
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - "~>"
37
+ - !ruby/object:Gem::Version
38
+ version: '1.3'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - "~>"
44
+ - !ruby/object:Gem::Version
45
+ version: '1.3'
46
+ description: |
47
+ The maintainer's half of gem_kit: one RubyGems command, `gem kit`, with
48
+ subcommands for bumping the version, writing and linting the changelog,
49
+ listing outstanding deprecations, releasing and tagging.
50
+
51
+ It keeps the promises gem_kit records. `gem kit bump` refuses to move onto
52
+ a deprecation's removal version while the old name is still in the tree,
53
+ and `gem kit release` refuses to ship a version with an unkept promise or
54
+ no changelog entry of its own.
55
+
56
+ Everything is read from the .gemspec in the working directory, so the
57
+ normal case needs no configuration at all.
58
+ email: nathanblenheimkidd@gmail.com
29
59
  executables: []
30
60
  extensions: []
31
61
  extra_rdoc_files: []
32
62
  files:
63
+ - LICENSE
64
+ - README.md
33
65
  - lib/gem_kit/release.rb
34
66
  - lib/gem_kit/release/changelog.rb
35
67
  - lib/gem_kit/release/cli.rb
36
- - lib/gem_kit/release/cli/bump.rb
37
- - lib/gem_kit/release/cli/changelog.rb
38
- - lib/gem_kit/release/cli/command.rb
39
- - lib/gem_kit/release/cli/deprecations.rb
40
- - lib/gem_kit/release/cli/release.rb
41
- - lib/gem_kit/release/cli/setup.rb
42
- - lib/gem_kit/release/cli/tag.rb
43
- - lib/gem_kit/release/deprecate.rb
68
+ - lib/gem_kit/release/commands/bump.rb
69
+ - lib/gem_kit/release/commands/changelog.rb
70
+ - lib/gem_kit/release/commands/command.rb
71
+ - lib/gem_kit/release/commands/deprecations.rb
72
+ - lib/gem_kit/release/commands/release.rb
73
+ - lib/gem_kit/release/commands/tag.rb
44
74
  - lib/gem_kit/release/gate.rb
75
+ - lib/gem_kit/release/generators/setup.rb
45
76
  - lib/gem_kit/release/project.rb
46
77
  - lib/gem_kit/release/templates/DEPRECATIONS.md.erb
47
78
  - lib/gem_kit/release/templates/RELEASE.md.erb
@@ -49,13 +80,13 @@ files:
49
80
  - lib/gem_kit/release/version_file.rb
50
81
  - lib/rubygems/commands/kit_command.rb
51
82
  - lib/rubygems_plugin.rb
52
- homepage: https://github.com/n-at-han-k/gem_kit-release
83
+ homepage: https://github.com/n-at-han-k/gem_kit
53
84
  licenses:
54
85
  - MIT
55
86
  metadata:
56
- source_code_uri: https://github.com/n-at-han-k/gem_kit-release
57
- changelog_uri: https://github.com/n-at-han-k/gem_kit-release/blob/main/CHANGELOG.md
58
- bug_tracker_uri: https://github.com/n-at-han-k/gem_kit-release/issues
87
+ source_code_uri: https://github.com/n-at-han-k/gem_kit
88
+ changelog_uri: https://github.com/n-at-han-k/gem_kit/blob/main/CHANGELOG.md
89
+ bug_tracker_uri: https://github.com/n-at-han-k/gem_kit/issues
59
90
  rubygems_mfa_required: 'true'
60
91
  rdoc_options: []
61
92
  require_paths:
@@ -1,136 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "erb"
4
-
5
- require_relative "command"
6
-
7
- module GemKit
8
- module Release
9
- module CLI
10
- # Copies the two documents that describe this toolchain into the project,
11
- # rendered for its name and version.
12
- #
13
- # They are copies rather than links because a policy nobody can read in
14
- # their own repo is a policy nobody follows, and because the examples are
15
- # worth more when they use the project's real version numbers.
16
- class Setup < Command
17
- TEMPLATES = File.expand_path("../templates", __dir__)
18
-
19
- DOCUMENTS = %w[DEPRECATIONS.md RELEASE.md].freeze
20
-
21
- desc "Copy DEPRECATIONS.md and RELEASE.md into this project"
22
-
23
- option :force, type: :boolean, default: false, desc: "Overwrite documents that already exist"
24
-
25
- example [
26
- " # write the documents that are missing",
27
- "--force # refresh them all, e.g. after a major version",
28
- ]
29
-
30
- def call(**options)
31
- written, skipped = [], []
32
-
33
- DOCUMENTS.each do |document|
34
- destination = File.join(project.root, document)
35
-
36
- if File.exist?(destination) && !options[:force]
37
- skipped << document
38
- next
39
- end
40
-
41
- File.write(destination, render_document(document))
42
- written << document
43
- end
44
-
45
- written.each { |document| say("Wrote #{document}") }
46
-
47
- unless skipped.empty?
48
- say("Left alone (already present): #{skipped.join(", ")}")
49
- say("Pass --force to overwrite.")
50
- end
51
-
52
- say("Link them from your README and AGENTS.md so they are found.") unless written.empty?
53
- end
54
-
55
- private
56
-
57
- # Values the templates may use. Kept small and obvious — a template
58
- # needing more than this is documenting the tool, not the project.
59
- def render_document(document)
60
- name = project.name
61
- version = project.version.to_s
62
- next_major = project.next_major_version
63
- changelog = File.basename(project.changelog_path)
64
- version_file = relative(project.version_file)
65
- test = project.test_command
66
- today = Time.now.strftime("%Y-%m-%d")
67
-
68
- template = File.read(File.join(TEMPLATES, "#{document}.erb"))
69
- ERB.new(template, trim_mode: "-").result(binding)
70
- end
71
- end
72
- end
73
- end
74
- end
75
-
76
- __END__
77
-
78
- describe "gem_kit/release/cli/setup" do
79
- require_relative "../../../../spec/support/gem_kit_release_spec"
80
- extend GemKitReleaseSpec
81
-
82
- it "writes both documents into the project root" do
83
- with_gem do |dir|
84
- status, out, _err = invoke(["setup"], dir)
85
-
86
- status.should == 0
87
- out.should.match(/Wrote DEPRECATIONS\.md/)
88
- out.should.match(/Wrote RELEASE\.md/)
89
- File.exist?(File.join(dir, "DEPRECATIONS.md")).should.be.true
90
- File.exist?(File.join(dir, "RELEASE.md")).should.be.true
91
- end
92
- end
93
-
94
- it "renders them for this project's name and versions" do
95
- with_gem(version: "4.1.0") do |dir|
96
- invoke(["setup"], dir)
97
-
98
- deprecations = File.read(File.join(dir, "DEPRECATIONS.md"))
99
- deprecations.should.match(/A deprecation in demo is a \*\*dated promise\*\*/)
100
- deprecations.should.match(/4\.1\.0, so the usual deadline is 5/)
101
- deprecations.should.not.match(/<%=/)
102
-
103
- release = File.read(File.join(dir, "RELEASE.md"))
104
- release.should.match(/demo/)
105
- release.should.not.match(/<%=/)
106
- end
107
- end
108
-
109
- it "leaves existing documents alone and says so" do
110
- with_gem do |dir|
111
- File.write(File.join(dir, "RELEASE.md"), "mine\n")
112
-
113
- status, out, _err = invoke(["setup"], dir)
114
-
115
- status.should == 0
116
- out.should.match(/Left alone \(already present\): RELEASE\.md/)
117
- File.read(File.join(dir, "RELEASE.md")).should == "mine\n"
118
- end
119
- end
120
-
121
- it "--force overwrites them" do
122
- with_gem do |dir|
123
- File.write(File.join(dir, "RELEASE.md"), "mine\n")
124
-
125
- invoke(["setup", "--force"], dir).first.should == 0
126
- File.read(File.join(dir, "RELEASE.md")).should.not == "mine\n"
127
- end
128
- end
129
-
130
- it "is reachable by its alias" do
131
- with_gem do |dir|
132
- invoke(["init"], dir).first.should == 0
133
- File.exist?(File.join(dir, "RELEASE.md")).should.be.true
134
- end
135
- end
136
- end