toys-release 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a183392907cf0499a8abb4df7f675146d1b52f602551f140cf12111fd809149
4
- data.tar.gz: fbc2ca77613f5a9bc40c9d3fe89fc239d7feb0c43713cc4407f935abcf5b9a29
3
+ metadata.gz: e33fb9ef4abef51854357457ce113b6d73485817443740dbc099a621f7152929
4
+ data.tar.gz: 805f97a518378cec3cc02eca670957221a8b5d8cbabc6db83ed8211ca5602225
5
5
  SHA512:
6
- metadata.gz: 69fb1dc0ab0870f13ab1b6dcee252a31dc19aeeabc2d318c99baed7dd3dd45c6e7c5263090e749e00827e6f8d23c1342b4d8ee982e771c85026fe690b9770323
7
- data.tar.gz: 99cc97fd617ea40ec0c75ca3cd08ac89f362d29f530c907b3b9c9dab14452607cfc10a4bfcae9c1a694d19ab6a01e2869414fd6490a4eeadebc524483e8ffd16
6
+ metadata.gz: d1859d2f4ab07ed1c2a67f8d57bd8da3da421fa96b6dfe4c9ee37156fb16d7588e4d8593aeef705beec61b505e7a3df92e7c0796a45d3cb90f35189d2be9b532
7
+ data.tar.gz: 5ce0e152cb90285e69f0c014a98f3c6f080cdffc2eaffbc3bab1ed6077848426ec9c0ece6c1df9d2baa973d27306e290c65a91cc87f0e1e60323856ca4e2e062
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Release History
2
2
 
3
+ ### v0.8.0 / 2026-03-12
4
+
5
+ * ADDED: Add a command to reserve a gem
6
+ * ADDED: Create index redirects in the gh-pages deployment
7
+
3
8
  ### v0.7.0 / 2026-03-09
4
9
 
5
10
  * ADDED: Support updating dependencies among released components
data/README.md CHANGED
@@ -59,7 +59,7 @@ by closing the pull request without merging.
59
59
 
60
60
  ### System requirements
61
61
 
62
- Toys-Release requires Ruby 2.7 or later, and Toys 0.18 or later. We recommend
62
+ Toys-Release requires Ruby 2.7 or later, and Toys 0.20 or later. We recommend
63
63
  the latest version of the standard C implementation of Ruby. (JRuby or
64
64
  TruffleRuby _may_ work, but are unsupported.) The Ruby provided by the standard
65
65
  `setup-ruby` GitHub Action is sufficient.
data/docs/guide.md CHANGED
@@ -44,7 +44,8 @@ containing either a single package, or multiple packages (i.e. "**monorepos**")
44
44
  and can analyze a repository to identify changes applying to each package.
45
45
 
46
46
  Toys-Release can build **GitHub releases**, publish **RubyGems packages**, and
47
- build and publish documentation to **GitHub pages**.
47
+ build and publish documentation to **GitHub Pages**. (GitHub Pages integration
48
+ is currently experimental.)
48
49
 
49
50
  Toys-Release uses the [Toys](https://dazuma.github.io/toys/gems/toys/latest)
50
51
  RubyGem, but does not require familiarity with Toys.
@@ -66,13 +67,13 @@ process requires these items to be installed locally, but normal operation
66
67
  happens in GitHub Actions and does not require any local installation.
67
68
 
68
69
  If you do not have Ruby or Toys installed locally, do so first. Install
69
- Ruby 3.0 or later, and then install the Toys RubyGem using:
70
+ Ruby 2.7 or later, and then install the Toys RubyGem using:
70
71
 
71
72
  ```sh
72
73
  gem install toys
73
74
  ```
74
75
 
75
- Toys-Release requires Toys 0.18 or later. If you have an older version of Toys,
76
+ Toys-Release requires Toys 0.20 or later. If you have an older version of Toys,
76
77
  update it using:
77
78
 
78
79
  ```sh
@@ -413,6 +414,9 @@ documentation for your Ruby gem on your GitHub Pages site, under github.io. As
413
414
  an example, of what this looks like you can see the reference documentation for
414
415
  the Toys gem at https://dazuma.github.io/toys/gems/toys.
415
416
 
417
+ **IMPORTANT: GitHub Pages publication is currently experimental. The feature
418
+ set is in flux, and breaking changes will be common.**
419
+
416
420
  The features of this system are:
417
421
 
418
422
  * Host generated Yardoc (or rdoc) documentation for every version of the gem.
@@ -6,6 +6,6 @@ module Toys
6
6
  # Current version of the Toys release system.
7
7
  # @return [String]
8
8
  #
9
- VERSION = "0.7.0"
9
+ VERSION = "0.8.0"
10
10
  end
11
11
  end
@@ -0,0 +1,27 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ </head>
6
+ <body>
7
+ <p>
8
+ <a href="<%= @default_redirect_url %>">Main documentation page</a>
9
+ </p>
10
+ </body>
11
+ <script>
12
+ <% @version_vars.each do |(name, value)| %> var <%= name %> = "<%= value %>";
13
+ <% end %> var location_updated = false;
14
+ <% @replacement_info.each do |comp_info| %> if (!location_updated) {
15
+ var loc = window.location.href.replace(
16
+ new RegExp(<%= comp_info.regexp_source.inspect %>),
17
+ "//<%= comp_info.base_path %>/v" + <%= comp_info.version_var %> + "/");
18
+ if (window.location.href != loc) {
19
+ window.location.replace(loc);
20
+ location_updated = true;
21
+ }
22
+ }
23
+ <% end %> if (!location_updated) {
24
+ window.location.replace("<%= @default_redirect_url %>");
25
+ }
26
+ </script>
27
+ </html>
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Redirecting...</title>
6
+ <link rel="canonical" href="<%= @redirect_url %>">
7
+ <meta http-equiv="refresh" content="0; url=<%= @redirect_url %>">
8
+ </head>
9
+ <body>
10
+ <p>
11
+ <a href="<%= @redirect_url %>">Documentation for latest version</a>
12
+ </p>
13
+ </body>
14
+ <script>
15
+ window.location.replace("<%= @redirect_url %>");
16
+ </script>
17
+ </html>
@@ -0,0 +1,9 @@
1
+ # Placeholder for <%= @gem_name %>
2
+
3
+ This is a placeholder gem, which was generated on <%= @date %> to
4
+ reserve the gem "<%= @gem_name %>".
5
+ The actual gem is planned for release in the near future.
6
+
7
+ If this is a problem, or if the actual gem has not been released
8
+ in a timely manner, you can contact the owner at
9
+ `<%= @contact %>`.
@@ -0,0 +1,8 @@
1
+ #
2
+ # This is a placeholder Ruby file for gem "<%= @gem_name %>".
3
+ # It was generated on <%= @date %> to reserve the gem name.
4
+ # The actual gem is planned for release in the near future.
5
+ # If this is a problem, or if the actual gem has not been
6
+ # released in a timely manner, you can contact the owner at
7
+ # <%= @contact %>
8
+ #
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ ::Gem::Specification.new do |spec|
4
+ spec.name = <%= @gem_name.inspect %>
5
+ spec.version = <%= @gem_version.inspect %>
6
+ spec.authors = [<%= @contact.inspect %>]
7
+
8
+ spec.summary = "Placeholder gem"
9
+ spec.description =
10
+ "This is a placeholder gem, which was generated on <%= @date %> to reserve the gem " +
11
+ <%= @gem_name.inspect %> + ". The actual gem is planned for release in the near future. " +
12
+ "If this is a problem, or if the actual gem has not been released in a timely manner, " +
13
+ "you can contact the owner at " + <%= @contact.inspect %> + "."
14
+
15
+ spec.files = ["README.md", "lib/<%= @gem_name %>.rb"]
16
+ spec.require_paths = ["lib"]
17
+ end
@@ -96,7 +96,7 @@ module Toys
96
96
  #
97
97
  def update_dependencies(constraint_updates)
98
98
  constraint_updates.each do |name, exprs|
99
- escaped_name = Regexp.escape(name)
99
+ escaped_name = ::Regexp.escape(name)
100
100
  regex = /\.(add(?:_runtime)?_dependency)(\(?\s*)(["'])#{escaped_name}["'](?:,\s*["'][^"',]+["'])*(\s*\)?)/
101
101
  content.sub!(regex) do
102
102
  match = ::Regexp.last_match
@@ -31,8 +31,8 @@ module Toys
31
31
  # @return [Semver] The semver level
32
32
  #
33
33
  def for_diff(version1, version2)
34
- segments1 = Gem::Version.create(version1 || "0.0.0").segments
35
- segments2 = Gem::Version.create(version2 || "0.0.0").segments
34
+ segments1 = ::Gem::Version.create(version1 || "0.0.0").segments
35
+ segments2 = ::Gem::Version.create(version2 || "0.0.0").segments
36
36
  size = segments1.size
37
37
  size = segments2.size if size < segments2.size
38
38
  (0...size).each do |index|
@@ -300,7 +300,8 @@ module Toys
300
300
  dest_dir = ::File.join(component_dir, "v#{step_context.release_version}")
301
301
  check_existence(step_context, dest_dir)
302
302
  copy_docs_dir(step_context, dest_dir)
303
- update_docs_404_page(step_context, gh_pages_dir)
303
+ update_404_page(step_context, gh_pages_dir)
304
+ update_index_pages(step_context, gh_pages_dir)
304
305
  push_docs_to_git(step_context, gh_pages_dir)
305
306
  end
306
307
 
@@ -340,15 +341,39 @@ module Toys
340
341
  ::FileUtils.cp_r(source_dir, dest_dir)
341
342
  end
342
343
 
343
- def update_docs_404_page(step_context, gh_pages_dir)
344
+ def update_404_page(step_context, gh_pages_dir)
344
345
  path = ::File.join(gh_pages_dir, "404.html")
346
+ unless ::File.file?(path)
347
+ step_context.warning("404.html not found. Skipping.")
348
+ return
349
+ end
345
350
  content = ::File.read(path)
346
351
  version_var = step_context.component.settings.gh_pages_version_var
347
- content.sub!(/#{version_var} = "[\w.]+";/,
352
+ content.sub!(/#{Regexp.escape(version_var)} = "[\w.]+";/,
348
353
  "#{version_var} = \"#{step_context.release_version}\";")
349
354
  ::File.write(path, content)
350
355
  end
351
356
 
357
+ def update_index_pages(step_context, gh_pages_dir)
358
+ subdir = step_context.component.settings.gh_pages_directory
359
+ dir_suffix = subdir == "." ? "" : "/#{subdir}"
360
+ settings = step_context.repository.settings
361
+ version = step_context.release_version
362
+ redirect_url = "https://#{settings.repo_owner}.github.io/#{settings.repo_name}#{dir_suffix}/v#{version}"
363
+ ["index.html", "latest/index.html"].each do |filename|
364
+ path = "#{gh_pages_dir}#{dir_suffix}/#{filename}"
365
+ unless ::File.file?(path)
366
+ step_context.warning("#{path} not found. Skipping.")
367
+ next
368
+ end
369
+ content = ::File.read(path)
370
+ content.gsub!(/ href="[^"]+"/, " href=\"#{redirect_url}\"")
371
+ content.gsub!(/ content="0; url=[^"]+"/, " content=\"0; url=#{redirect_url}\"")
372
+ content.gsub!(/window\.location\.replace\("[^"]+"\)/, "window.location.replace(\"#{redirect_url}\")")
373
+ ::File.write(path, content)
374
+ end
375
+ end
376
+
352
377
  def push_docs_to_git(step_context, gh_pages_dir)
353
378
  ::Dir.chdir(gh_pages_dir) do
354
379
  step_context.repository.git_commit("Generated docs for #{step_context.release_description}",
data/toys/.toys.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- toys_version!(">= 0.19", "< 2")
3
+ toys_version!(">= 0.20", "< 2")
4
4
 
5
5
  desc "Namespace for toys-release tools"
data/toys/gen-gh-pages.rb CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  desc "Generate gh-pages documentation site"
4
4
 
5
- long_desc "This tool generates an initial gh-pages documentation site."
5
+ long_desc \
6
+ "This tool generates an initial gh-pages documentation site.",
7
+ "Note: gh-pages generation is experimental."
6
8
 
7
9
  flag :working_dir, "--working-dir=PATH" do
8
10
  desc "Set the working directory for the gh-pages checkout"
@@ -23,6 +25,7 @@ include :terminal, styled: true
23
25
  class ErbContext
24
26
  def initialize(data)
25
27
  data.each { |name, value| instance_variable_set("@#{name}", value) }
28
+ freeze
26
29
  end
27
30
 
28
31
  def self.get(data)
@@ -54,99 +57,141 @@ def setup
54
57
  branch: "gh-pages", remote: git_remote, dir: @artifact_dir.get("gh-pages"),
55
58
  gh_token: ::ENV["GITHUB_TOKEN"], create: true
56
59
  )
60
+ @relevant_component_settings = @settings.all_component_settings.find_all(&:gh_pages_enabled)
61
+ if @relevant_component_settings.empty?
62
+ puts "No components have gh-pages enabled", :red, :bold
63
+ exit(1)
64
+ end
57
65
  end
58
66
 
59
67
  def cleanup
60
68
  @artifact_dir.cleanup
61
69
  end
62
70
 
71
+ CompInfo = ::Struct.new(:base_path, :regexp_source, :version_var)
72
+
63
73
  def generate_gh_pages
64
- relevant_component_settings = @settings.all_component_settings.find_all(&:gh_pages_enabled)
65
- url_base = "#{@settings.repo_owner}.github.io/#{@settings.repo_name}"
66
- comp_info = relevant_component_settings.to_h do |comp|
67
- [
68
- comp.gh_pages_directory == "." ? url_base : "#{url_base}/#{comp.gh_pages_directory}",
69
- comp.gh_pages_version_var,
70
- ]
74
+ ::Dir.chdir(@gh_pages_dir) do
75
+ @relevant_component_settings.each do |component_settings|
76
+ generate_component_files(component_settings)
77
+ end
78
+ generate_toplevel_files
79
+ generate_html404
71
80
  end
81
+ puts "Files generated into #{@gh_pages_dir}", :bold
82
+ end
72
83
 
73
- ::Dir.chdir(@gh_pages_dir) do
74
- ::File.write(".nojekyll", "")
75
- generate_file("gh-pages-gitignore.erb", ".gitignore", {})
84
+ def generate_component_files(comp_settings)
85
+ prepare_v0_directory("#{comp_settings.gh_pages_directory}/v0")
86
+ generate_file("#{comp_settings.gh_pages_directory}/v0/index.html",
87
+ "empty.html.erb", {name: comp_settings.name})
88
+ component_redirect_url = "https://#{component_base_path(comp_settings)}/v#{current_component_version(comp_settings)}"
89
+ generate_file("#{comp_settings.gh_pages_directory}/index.html",
90
+ "redirect.html.erb", {redirect_url: component_redirect_url})
91
+ generate_file("#{comp_settings.gh_pages_directory}/latest/index.html",
92
+ "redirect.html.erb", {redirect_url: component_redirect_url})
93
+ end
76
94
 
77
- generate_file("gh-pages-404.html.erb", "404.html",
78
- {comp_info: comp_info}) do |content, old_content|
79
- update_versions(content, old_content)
80
- end
95
+ def prepare_v0_directory(directory)
96
+ ::FileUtils.mkdir_p(directory)
97
+ children = ::Dir.children(directory) - ["index.html"]
98
+ return if children.empty?
99
+ puts "Non-index files exist in #{directory}.", :yellow, :bold
100
+ return unless yes || confirm("Remove? ", default: true)
101
+ children.each do |child|
102
+ ::FileUtils.remove_entry(::File.join(directory, child), true)
103
+ end
104
+ end
105
+
106
+ def current_component_version(comp_settings)
107
+ base_dir = comp_settings.gh_pages_directory
108
+ latest = ::Gem::Version.new("0")
109
+ return latest unless ::File.directory?(base_dir)
110
+ ::Dir.children(base_dir).each do |child|
111
+ next unless /^v\d+(\.\d+)*$/.match?(child)
112
+ next unless ::File.directory?(::File.join(base_dir, child))
113
+ version = ::Gem::Version.new(child[1..])
114
+ latest = version if version > latest
115
+ end
116
+ latest
117
+ end
81
118
 
82
- generate_file("gh-pages-index.html.erb", "index.html",
83
- {default_url: "https://#{comp_info.first.first}/latest"})
119
+ def generate_toplevel_files
120
+ ::File.write(".nojekyll", "")
121
+ generate_file(".gitignore", "gitignore.erb", {})
122
+ generate_file("index.html", "redirect.html.erb", {redirect_url: default_redirect_url})
123
+ end
84
124
 
85
- relevant_component_settings.each do |component_settings|
86
- generate_file("gh-pages-empty.html.erb", "#{component_settings.gh_pages_directory}/v0.0.0/index.html",
87
- {name: component_settings.name}, remove_dir: true)
88
- end
125
+ def generate_html404
126
+ version_vars = {}
127
+ replacement_info = @relevant_component_settings.map do |comp_settings|
128
+ version_vars[comp_settings.gh_pages_version_var] = current_component_version(comp_settings)
129
+ base_path = component_base_path(comp_settings)
130
+ regexp_source = "//#{::Regexp.escape(base_path)}/latest(/|$)"
131
+ CompInfo.new(base_path, regexp_source, comp_settings.gh_pages_version_var)
89
132
  end
90
- puts "Files generated into #{@gh_pages_dir}", :bold
133
+ template_params = {
134
+ default_redirect_url: default_redirect_url,
135
+ version_vars: version_vars,
136
+ replacement_info: replacement_info,
137
+ }
138
+ generate_file("404.html", "404.html.erb", template_params)
91
139
  end
92
140
 
93
- def push_gh_pages
94
- ::Dir.chdir(@gh_pages_dir) do
95
- if @repository.git_clean?
96
- puts "No changes made to gh-pages.", :yellow, :bold
97
- return
98
- end
99
- @repository.git_commit("Generated initial gh-pages", signoff: @settings.signoff_commits?)
100
- if dry_run
101
- puts "DRY RUN: Skipped git push.", :green, :bold
102
- else
103
- @utils.exec(["git", "push", git_remote, "gh-pages"], e: true)
104
- puts "Pushed gh-pages.", :green, :bold
105
- end
141
+ def url_base_path
142
+ @url_base_path ||= "#{@settings.repo_owner}.github.io/#{@settings.repo_name}"
143
+ end
144
+
145
+ def component_base_path(component_settings)
146
+ if component_settings.gh_pages_directory == "."
147
+ url_base_path
148
+ else
149
+ "#{url_base_path}/#{component_settings.gh_pages_directory}"
106
150
  end
107
151
  end
108
152
 
109
- def generate_file(template, destination, data, remove_dir: false)
110
- old_content = file_generation_confirmations(destination, remove_dir)
111
- return if old_content == :cancel
112
- template_path = find_data("templates/#{template}")
153
+ def default_redirect_url
154
+ @default_redirect_url ||= "https://#{component_base_path(@relevant_component_settings.first)}"
155
+ end
156
+
157
+ def generate_file(destination, template, data)
158
+ return unless file_generation_confirmations(destination)
159
+ template_path = find_data("gh-pages/#{template}")
113
160
  raise "Unable to find template #{template}" unless template_path
114
161
  erb = ::ERB.new(::File.read(template_path))
115
162
  content = erb.result(ErbContext.get(data))
116
- content = yield(content, old_content) if block_given? && old_content
163
+ ::FileUtils.mkdir_p(::File.dirname(destination))
117
164
  ::File.write(destination, content)
118
165
  puts "Wrote #{destination}.", :green
119
166
  end
120
167
 
121
- def file_generation_confirmations(destination, remove_dir)
122
- old_content = nil
123
- if ::File.readable?(destination)
124
- old_content = ::File.read(destination)
125
- puts "Destination file #{destination} exists.", :yellow, :bold
126
- return :cancel unless yes || confirm("Overwrite? ", default: true)
127
- else
128
- return :cancel unless yes || confirm("Create file #{destination}? ", default: true)
129
- end
130
- dir = ::File.dirname(destination)
131
- unless dir == "."
132
- if remove_dir && ::File.directory?(dir)
133
- puts "Old version directory #{dir} exists.", :yellow, :bold
134
- return :cancel unless yes || confirm("Remove? ", default: true)
135
- ::FileUtils.remove_entry(dir, true)
168
+ def file_generation_confirmations(destination)
169
+ if ::File.exist?(destination)
170
+ if ::File.directory?(destination)
171
+ puts "Destination #{destination} exists and is a DIRECTORY.", :yellow, :bold
172
+ else
173
+ puts "Destination file #{destination} exists.", :yellow, :bold
136
174
  end
137
- ::FileUtils.mkdir_p(dir)
175
+ return false unless yes || confirm("Overwrite? ", default: true)
176
+ ::FileUtils.remove_entry(destination)
177
+ else
178
+ return false unless yes || confirm("Create file #{destination}? ", default: true)
138
179
  end
139
- old_content
180
+ true
140
181
  end
141
182
 
142
- def update_versions(content, old_content)
143
- @settings.all_component_settings.each do |component_settings|
144
- next unless component_settings.gh_pages_enabled
145
- match = /#{component_settings.gh_pages_version_var} = "([\w.]+)";/.match(old_content)
146
- if match
147
- content.sub!("#{component_settings.gh_pages_version_var} = \"0.0.0\";",
148
- "#{component_settings.gh_pages_version_var} = \"#{match[1]}\";")
183
+ def push_gh_pages
184
+ ::Dir.chdir(@gh_pages_dir) do
185
+ if @repository.git_clean?
186
+ puts "No changes made to gh-pages.", :yellow, :bold
187
+ return
188
+ end
189
+ @repository.git_commit("Generated initial gh-pages", signoff: @settings.signoff_commits?)
190
+ if dry_run
191
+ puts "DRY RUN: Skipped git push.", :green, :bold
192
+ else
193
+ @utils.exec(["git", "push", git_remote, "gh-pages"], e: true)
194
+ puts "Pushed gh-pages.", :green, :bold
149
195
  end
150
196
  end
151
- content
152
197
  end
@@ -0,0 +1,143 @@
1
+ # frozen_string_literal: true
2
+
3
+ desc "Reserve a rubygem"
4
+
5
+ long_desc \
6
+ "This tool generates an empty placeholder rubygem, builds, and releases" \
7
+ " it. This effectively reserves the name, ensuring no one else squats it" \
8
+ " until a real release can be performed.",
9
+ "",
10
+ "Proper credentials for pushing to Rubygems must be present. The easiest" \
11
+ " way to do this is to set the `GEM_HOST_API_KEY` environment variable."
12
+
13
+ flag :directory, "-d", "--directory=PATH" do
14
+ desc "Where to build the placeholder gem. Defaults to a temporary directory."
15
+ end
16
+ flag :gem_version, "--gem-version=VERSION", default: "0.0.0" do
17
+ desc "Version to release. Defaults to 0.0.0"
18
+ end
19
+ flag :yes, "--yes", "-y" do
20
+ desc "Automatically answer yes to all confirmations"
21
+ end
22
+ flag :dry_run do
23
+ desc "Do not push the gem"
24
+ end
25
+
26
+ required_arg :gem_name, desc: "The name of the gem to reserve"
27
+ required_arg :contact, desc: "A contact email or URL"
28
+
29
+ include :exec, e: true
30
+ include :terminal, styled: true
31
+ include :fileutils
32
+
33
+ def run
34
+ check_inputs
35
+ cd(context_directory)
36
+ if directory
37
+ mkdir_p(directory)
38
+ reserve_gem(directory)
39
+ else
40
+ require "tmpdir"
41
+ ::Dir.mktmpdir { |dir| reserve_gem(dir) }
42
+ end
43
+ end
44
+
45
+ def check_inputs
46
+ unless /\A[\w-]+\z/.match?(gem_name)
47
+ logger.error("Illegal gem name: #{gem_name.inspect}")
48
+ exit(1)
49
+ end
50
+ if contact.strip.empty?
51
+ logger.error("Contact info is required")
52
+ exit(1)
53
+ end
54
+ unless /\A0(\.[0-9a-zA-Z]+)*\z/.match?(gem_version)
55
+ logger.error("Placeholder gem version must start with 0.")
56
+ exit(1)
57
+ end
58
+ end
59
+
60
+ def reserve_gem(dir)
61
+ cd(dir) do
62
+ generate_gem
63
+ build_gem
64
+ user_confirmation
65
+ push_gem
66
+ final_result
67
+ end
68
+ end
69
+
70
+ def generate_gem
71
+ require "erb"
72
+ logger.info("Generating placeholder gem into #{::Dir.getwd}")
73
+ generate_file("#{gem_name}.gemspec", "gemspec.erb")
74
+ generate_file("README.md")
75
+ generate_file("lib/#{gem_name}.rb", "entrypoint.rb.erb")
76
+ end
77
+
78
+ def generate_file(file_path, template_path = nil)
79
+ template_path ||= "#{file_path}.erb"
80
+ template_data_path = find_data("reserve-gem/#{template_path}")
81
+ raise "Unable to find template #{template_path}" unless template_data_path
82
+ erb = ::ERB.new(::File.read(template_data_path))
83
+ dir = ::File.dirname(file_path)
84
+ mkdir_p(dir) unless dir == "."
85
+ ::File.write(file_path, erb.result(ErbContext.get(gem_name, gem_version, contact)))
86
+ logger.info("Wrote #{file_path}")
87
+ end
88
+
89
+ def build_gem
90
+ mkdir_p("pkg")
91
+ logger.info("Building gem...")
92
+ exec(["gem", "build", "#{gem_name}.gemspec", "-o", pkg_path])
93
+ logger.info("Gem built to #{pkg_path}")
94
+ end
95
+
96
+ def user_confirmation
97
+ return if yes
98
+ dry_run_suffix = dry_run ? " in DRY RUN mode" : ""
99
+ unless confirm("Push gem #{gem_name} #{gem_version}#{dry_run_suffix}? ", default: false)
100
+ logger.error("Aborted")
101
+ exit(1)
102
+ end
103
+ end
104
+
105
+ def push_gem
106
+ logger.info("Pushing gem...")
107
+ if dry_run
108
+ logger.info("Pushed #{gem_name} #{gem_version} (DRY RUN)")
109
+ else
110
+ exec(["gem", "push", pkg_path])
111
+ logger.info("Pushed #{gem_name} #{gem_version}")
112
+ end
113
+ end
114
+
115
+ def final_result
116
+ if dry_run
117
+ puts("Reserved gem #{gem_name} #{gem_version} (DRY RUN)")
118
+ else
119
+ puts("Reserved gem #{gem_name} #{gem_version}")
120
+ end
121
+ end
122
+
123
+ def pkg_path
124
+ ::File.join("pkg", "#{gem_name}-#{gem_version}.gem")
125
+ end
126
+
127
+ # Context for ERB templates
128
+ class ErbContext
129
+ def initialize(gem_name, gem_version, contact)
130
+ @gem_name = gem_name
131
+ @gem_version = gem_version
132
+ @contact = contact
133
+ @date = ::Time.now.utc.strftime("%Y-%m-%d")
134
+ end
135
+
136
+ def __binding
137
+ binding
138
+ end
139
+
140
+ def self.get(gem_name, gem_version, contact)
141
+ new(gem_name, gem_version, contact).__binding
142
+ end
143
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toys-release
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Azuma
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: '0.19'
18
+ version: '0.20'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: '0.19'
25
+ version: '0.20'
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: base64
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -57,10 +57,13 @@ files:
57
57
  - docs/guide.md
58
58
  - lib/toys-release.rb
59
59
  - lib/toys/release/version.rb
60
- - toys/.data/templates/gh-pages-404.html.erb
61
- - toys/.data/templates/gh-pages-empty.html.erb
62
- - toys/.data/templates/gh-pages-gitignore.erb
63
- - toys/.data/templates/gh-pages-index.html.erb
60
+ - toys/.data/gh-pages/404.html.erb
61
+ - toys/.data/gh-pages/empty.html.erb
62
+ - toys/.data/gh-pages/gitignore.erb
63
+ - toys/.data/gh-pages/redirect.html.erb
64
+ - toys/.data/reserve-gem/README.md.erb
65
+ - toys/.data/reserve-gem/entrypoint.rb.erb
66
+ - toys/.data/reserve-gem/gemspec.erb
64
67
  - toys/.data/templates/release-hook-on-closed.yml.erb
65
68
  - toys/.data/templates/release-hook-on-push.yml.erb
66
69
  - toys/.data/templates/release-perform.yml.erb
@@ -92,15 +95,16 @@ files:
92
95
  - toys/gen-workflows.rb
93
96
  - toys/perform.rb
94
97
  - toys/request.rb
98
+ - toys/reserve-gem.rb
95
99
  - toys/retry.rb
96
100
  homepage: https://github.com/dazuma/toys
97
101
  licenses:
98
102
  - MIT
99
103
  metadata:
100
- changelog_uri: https://dazuma.github.io/toys/gems/toys-release/v0.7.0/file.CHANGELOG.html
101
- source_code_uri: https://github.com/dazuma/toys/tree/toys-release/v0.7.0/toys-release
104
+ changelog_uri: https://dazuma.github.io/toys/gems/toys-release/v0.8.0/file.CHANGELOG.html
105
+ source_code_uri: https://github.com/dazuma/toys/tree/toys-release/v0.8.0/toys-release
102
106
  bug_tracker_uri: https://github.com/dazuma/toys/issues
103
- documentation_uri: https://dazuma.github.io/toys/gems/toys-release/v0.7.0
107
+ documentation_uri: https://dazuma.github.io/toys/gems/toys-release/v0.8.0
104
108
  rdoc_options: []
105
109
  require_paths:
106
110
  - lib
@@ -1,25 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8">
5
- </head>
6
- <body>
7
- <p>
8
- <a href="https://<%= @comp_info.first.first %>/index.html">Main documentation page</a>
9
- </p>
10
- </body>
11
- <script>
12
- <% @comp_info.values.uniq.each do |version_var| %> var <%= version_var %> = "0.0.0";
13
- <% end %> var location_updated = false;
14
- <% @comp_info.each do |(url_base, version_var)| %> if (!location_updated && window.location.href.includes("//<%= url_base %>/latest")) {
15
- var loc = window.location.href.replace(
16
- "//<%= url_base %>/latest",
17
- "//<%= url_base %>/v" + <%= version_var %>);
18
- window.location.replace(loc);
19
- location_updated = true;
20
- }
21
- <% end %> if (!location_updated) {
22
- window.location.replace("https://<%= @comp_info.first.first %>/latest");
23
- }
24
- </script>
25
- </html>
@@ -1,15 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8">
5
- <meta http-equiv="refresh" content="0; url=<%= @default_url %>">
6
- </head>
7
- <body>
8
- <p>
9
- <a href="<%= @default_url %>">Documentation for latest version</a>
10
- </p>
11
- </body>
12
- <script>
13
- window.location.replace("<%= @default_url %>");
14
- </script>
15
- </html>