diff --git a/RELEASING_RAILS.md b/RELEASING_RAILS.md index 6e27d8ee5a..3ff28c29f5 100644 --- a/RELEASING_RAILS.md +++ b/RELEASING_RAILS.md @@ -1,35 +1,35 @@ # Releasing Rails -In this document, we'll cover the steps necessary to release Rails. Each -section contains steps to take during that time before the release. The times -suggested in each header are just that: suggestions. However, they should +In this document, we'll cover the steps necessary to release Rails. Each +section contains steps to take during that time before the release. The times +suggested in each header are just that: suggestions. However, they should really be considered as minimums. ## 10 Days before release -Today is mostly coordination tasks. Here are the things you must do today: +Today is mostly coordination tasks. Here are the things you must do today: -### Is the CI green? If not, make it green. (See "Fixing the CI") +### Is the CI green? If not, make it green. (See "Fixing the CI") -Do not release with a Red CI. You can find the CI status here: +Do not release with a Red CI. You can find the CI status here: ``` http://travis-ci.org/rails/rails ``` -### Is Sam Ruby happy? If not, make him happy. +### Is Sam Ruby happy? If not, make him happy. Sam Ruby keeps a [test suite](https://github.com/rubys/awdwr) that makes sure the code samples in his book ([Agile Web Development with Rails](https://pragprog.com/titles/rails5/agile-web-development-with-rails-5th-edition)) -all work. These are valuable system tests -for Rails. You can check the status of these tests here: +all work. These are valuable system tests +for Rails. You can check the status of these tests here: [http://intertwingly.net/projects/dashboard.html](http://intertwingly.net/projects/dashboard.html) Do not release with Red AWDwR tests. -### Do we have any Git dependencies? If so, contact those authors. +### Do we have any Git dependencies? If so, contact those authors. Having Git dependencies indicates that we depend on unreleased code. Obviously Rails cannot be released when it depends on unreleased code. @@ -38,12 +38,12 @@ suits them. ### Contact the security team (either tenderlove or rafaelfranca) -Let them know of your plans to release. There may be security issues to be +Let them know of your plans to release. There may be security issues to be addressed, and that can impact your release date. ### Notify implementors. -Ruby implementors have high stakes in making sure Rails works. Be kind and +Ruby implementors have high stakes in making sure Rails works. Be kind and give them a heads up that Rails will be released soonish. This is only required for major and minor releases, bugfix releases aren't a @@ -60,18 +60,18 @@ Implementors will love you and help you. ## 3 Days before release -This is when you should release the release candidate. Here are your tasks +This is when you should release the release candidate. Here are your tasks for today: -### Is the CI green? If not, make it green. +### Is the CI green? If not, make it green. -### Is Sam Ruby happy? If not, make him happy. +### Is Sam Ruby happy? If not, make him happy. -### Contact the security team. CVE emails must be sent on this day. +### Contact the security team. CVE emails must be sent on this day. ### Create a release branch. -From the stable branch, create a release branch. For example, if you're +From the stable branch, create a release branch. For example, if you're releasing Rails 3.0.10, do this: ``` @@ -82,7 +82,7 @@ Switched to a new branch '3-0-10' ### Update each CHANGELOG. -Many times commits are made without the CHANGELOG being updated. You should +Many times commits are made without the CHANGELOG being updated. You should review the commits since the last release, and fill in any missing information for each CHANGELOG. @@ -96,15 +96,15 @@ If you're doing a stable branch release, you should also ensure that all of the CHANGELOG entries in the stable branch are also synced to the master branch. -### Update the RAILS_VERSION file to include the RC. +### Put the new version in the RAILS_VERSION file. + +Include an RC number if appropriate, e.g. `6.0.0.rc1`. ### Build and test the gem. -Run `rake install` to generate the gems and install them locally. Then try -generating a new app and ensure that nothing explodes. - -Verify that Action Cable and Action View's package.json files are updated with -the RC version. +Run `rake verify` to generate the gems and install them locally. `verify` also +generates a Rails app with a migration and boots it to smoke test with in your +browser. This will stop you from looking silly when you push an RC to rubygems.org and then realize it is broken. @@ -117,37 +117,39 @@ as NPM packages, so you must have Node.js installed, have an NPM account check this via `npm owner ls actioncable` and `npm owner ls rails-ujs`) in order to do a full release. Do not release until you're set up with NPM! +The release task will sign the release tag. If you haven't got commit signing +set up, use https://git-scm.com/book/tr/v2/Git-Tools-Signing-Your-Work as a +guide. You can generate keys with the GPG suite from here: https://gpgtools.org. + +Run `rake changelog:header` to put a header with the new version in every +CHANGELOG. Don't commit this, the release task handles it. + Run `rake release`. This will populate the gemspecs and NPM package.json with the current RAILS_VERSION, commit the changes, tag it, and push the gems to rubygems.org. -Here are the commands that `rake release` uses so you can understand what to do -in case anything goes wrong: - -``` -$ rake all:build -$ git commit -am'updating RAILS_VERSION' -$ git tag -m 'v3.0.10.rc1 release' v3.0.10.rc1 -$ git push -$ git push --tags -$ for i in $(ls pkg); do gem push $i; npm publish; done -``` - ### Send Rails release announcements Write a release announcement that includes the version, changes, and links to -GitHub where people can find the specific commit list. Here are the mailing +GitHub where people can find the specific commit list. Here are the mailing lists where you should announce: * rubyonrails-core@googlegroups.com * rubyonrails-talk@googlegroups.com * ruby-talk@ruby-lang.org -Use Markdown format for your announcement. Remember to ask people to report +Use Markdown format for your announcement. Remember to ask people to report issues with the release candidate to the rails-core mailing list. +NOTE: For patch releases there's a `rake announce` task to generate the release +post. It supports multiple patch releases too: + +``` +VERSIONS="5.0.5.rc1,5.1.3.rc1" rake announce +``` + IMPORTANT: If any users experience regressions when using the release -candidate, you *must* postpone the release. Bugfix releases *should not* +candidate, you *must* postpone the release. Bugfix releases *should not* break existing applications. ### Post the announcement to the Rails blog. @@ -165,12 +167,12 @@ Check the rails-core mailing list and the GitHub issue list for regressions in the RC. If any regressions are found, fix the regressions and repeat the release -candidate process. We will not release the final until 72 hours after the -last release candidate has been pushed. This means that if users find +candidate process. We will not release the final until 72 hours after the +last release candidate has been pushed. This means that if users find regressions, the scheduled release date must be postponed. -When you fix the regressions, do not create a new branch. Fix them on the -stable branch, then cherry pick the commit to your release branch. No other +When you fix the regressions, do not create a new branch. Fix them on the +stable branch, then cherry pick the commit to your release branch. No other commits should be added to the release branch besides regression fixing commits. ## Day of release @@ -203,7 +205,7 @@ Email the security reports to: * oss-security@lists.openwall.com Be sure to note the security fixes in your announcement along with CVE numbers -and links to each patch. Some people may not be able to upgrade right away, +and links to each patch. Some people may not be able to upgrade right away, so we need to give them the security fixes in patch form. * Blog announcements diff --git a/Rakefile b/Rakefile index ae269fbce7..1421851900 100644 --- a/Rakefile +++ b/Rakefile @@ -7,6 +7,9 @@ require "railties/lib/rails/api/task" desc "Build gem files for all projects" task build: "all:build" +desc "Build, install and verify the gem files in a generated Rails app." +task verify: "all:verify" + desc "Prepare the release" task prep_release: "all:prep_release" diff --git a/tasks/release.rb b/tasks/release.rb index 038fdc584a..ac13612b91 100644 --- a/tasks/release.rb +++ b/tasks/release.rb @@ -142,7 +142,7 @@ namespace :all do task push: FRAMEWORKS.map { |f| "#{f}:push" } + ["rails:push"] task :ensure_clean_state do - unless `git status -s | grep -v 'RAILS_VERSION\\|CHANGELOG\\|Gemfile.lock\\|package.json\\|version.rb'`.strip.empty? + unless `git status -s | grep -v 'RAILS_VERSION\\|CHANGELOG\\|Gemfile.lock\\|package.json\\|version.rb\\|tasks/release.rb'`.strip.empty? abort "[ABORTING] `git status` reports a dirty tree. Make sure all changes are committed" end @@ -152,6 +152,27 @@ namespace :all do end end + task verify: :install do + app_name = "pkg/verify-#{version}-#{Time.now.to_i}" + sh "rails new #{app_name}" + cd app_name + sh "rails generate scaffold user name admin:boolean && rails db:migrate" + + puts "Booting a Rails server. Verify the release by:" + puts + puts "- Seeing the correct release number on the root page" + puts "- Viewing /users" + puts "- Creating a user" + puts "- Updating a user (e.g. disable the admin flag)" + puts "- Deleting a user on /users" + puts "- Whatever else you want." + begin + sh "rails server" + rescue Interrupt + # Server passes along interrupt. Prevent halting verify task. + end + end + task :bundle do sh "bundle check" end @@ -179,69 +200,47 @@ namespace :all do task release: %w(prep_release tag push) end -task :announce do - Dir.chdir("pkg/") do - if gem_version.segments[2] == 0 || gem_version.segments[3].is_a?(Integer) - # Not major releases, and not security releases - raise "Only valid for patch releases" +module Announcement + class Version + def initialize(version) + @version, @gem_version = version, Gem::Version.new(version) end - sums = "$ shasum -a 256 *-#{version}.gem\n" + `shasum -a 256 *-#{version}.gem` + def to_s + @version + end - puts "Hi everyone," - puts + def previous + @gem_version.segments[0, 3].tap { |v| v[2] -= 1 }.join(".") + end - puts "I am happy to announce that Rails #{version} has been released." - puts + def major_or_security? + @gem_version.segments[2].zero? || @gem_version.segments[3].is_a?(Integer) + end - previous_version = gem_version.segments[0, 3] - previous_version[2] -= 1 - previous_version = previous_version.join(".") + def rc? + @version =~ /rc/ + end + end +end - if version =~ /rc/ +task :announce do + Dir.chdir("pkg/") do + versions = ENV["VERSIONS"] ? ENV["VERSIONS"].split(",") : [ version ] + versions = versions.sort.map { |v| Announcement::Version.new(v) } + + raise "Only valid for patch releases" if versions.any?(&:major_or_security?) + + if versions.any?(&:rc?) require "date" future_date = Date.today + 5 future_date += 1 while future_date.saturday? || future_date.sunday? github_user = `git config github.user`.chomp - - puts <").result(binding) end end diff --git a/tasks/release_announcement_draft.erb b/tasks/release_announcement_draft.erb new file mode 100644 index 0000000000..65d121fd4b --- /dev/null +++ b/tasks/release_announcement_draft.erb @@ -0,0 +1,38 @@ +Hi everyone, + +I am happy to announce that Rails <%= versions.join(" and ") %> <%= versions.size > 1 ? "have" : "has" %> been released. + +<% if future_date %> +If no regressions are found, expect the final release on <%= future_date.strftime("%A, %B %-d, %Y") %>. +If you find one, please open an [issue on GitHub](https://github.com/rails/rails/issues/new) +<%= "and mention me (@github_user}) on it, " unless github_user.empty? %>so that we can fix it before the final release. +<% end %> +<% versions.each do |version| %> + +## CHANGES since <%= version.previous %> + +To view the changes for each gem, please read the changelogs on GitHub: + <% FRAMEWORKS.sort.each do |framework| %> +<%= "* [#{FRAMEWORK_NAMES[framework]} CHANGELOG](https://github.com/rails/rails/blob/v#{version}/#{framework}/CHANGELOG.md)" %> + <% end %> + +*Full listing* + +To see the full list of changes, [check out all the commits on +GitHub](https://github.com/rails/rails/compare/v<%= "#{version.previous}...v#{version}" %>). + <% end %> +## SHA-256 + +If you'd like to verify that your gem is the same as the one I've uploaded, +please use these SHA-256 hashes. + +<% versions.each do |version| %> +Here are the checksums for <%= version %>: + +``` +$ shasum -a 256 *-<%= version %>.gem +<%= `shasum -a 256 *-#{version}.gem` %> +``` + +<% end %> +As always, huge thanks to the many contributors who helped with this release.