Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ReleaseCandidate releases feature #7

Open
wants to merge 36 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
7a73236
Run webpack rake task for v0.27
andreslucena Jul 15, 2024
c829d5f
Add i18n environment variables to local rspec run
andreslucena Jul 15, 2024
bdd28ce
Replace ByTitle with ByQuery
andreslucena Jul 15, 2024
3b011ef
Extract ReleasePatchVersion to its own class and ReleaserUtils module
andreslucena Jul 15, 2024
79562a1
Add ReleaseCandidateVersion class
andreslucena Jul 15, 2024
19c59a1
Refactor ReleasePatchVersion so it's consistent with ReleaseCandidate…
andreslucena Jul 15, 2024
9b6989f
Add throttling for GitHub REST API
andreslucena Jul 16, 2024
135e7e3
Fix requires
andreslucena Jul 16, 2024
76010d9
Fix markdownlint offense
andreslucena Jul 16, 2024
40c5e29
Raise exception if system command failed
andreslucena Jul 16, 2024
abc89d8
Merge branch 'main' into feature/release-candidate-version
andreslucena Jul 16, 2024
ef9807f
Init the spec_helper for rspec's configuration
andreslucena Jul 16, 2024
21a7497
Enable default recommeneded settings for rspec
andreslucena Jul 16, 2024
b6e8c6e
Use explicit RSpec call in specs
andreslucena Jul 16, 2024
10c512b
Add .rspec-failures as example status persistence file for rspec
andreslucena Jul 16, 2024
079dfec
Refactor bump_decidim_version method and extract it to ReleaserUtils
andreslucena Jul 16, 2024
edaa46f
Extract 'releaser repository' shared context
andreslucena Jul 16, 2024
a3ec237
Improve checks for branches and versions when releasing a RC
andreslucena Jul 16, 2024
15a8b53
fixup! Extract 'releaser repository' shared context
andreslucena Jul 16, 2024
b5dc3e1
Extract #release_branch spec to RC/Patch specs
andreslucena Jul 16, 2024
93726a4
Move #next_version_number_for_release_candidate method spec to Releas…
andreslucena Jul 16, 2024
d060c23
Move #next_version_number_for_patch_release method spec to ReleasePat…
andreslucena Jul 16, 2024
13e2d44
Move rest of the methods specs to ReleaserUtils spec
andreslucena Jul 16, 2024
5725152
Add specs for sanity checks and fix bug in release candidate checks
andreslucena Jul 16, 2024
8b7d92e
Improve legibility in the finish message
andreslucena Jul 16, 2024
ae2a225
Merge branch 'main' into 'feature/release-candidate-version'
andreslucena Feb 12, 2025
f45ddcc
Add ruby update instructions
andreslucena Feb 12, 2025
97b0fd1
Bump ruby version in CI
andreslucena Feb 12, 2025
df079a3
Update RSpec syntax call to describe
andreslucena Feb 12, 2025
16e3acb
Add missing argument from bad git conflict resolution
andreslucena Feb 12, 2025
2d69fab
Remove unecessary sleep for GH throttling prevention
andreslucena Feb 18, 2025
2269274
Prevent error for missing method in Hash
andreslucena Feb 18, 2025
8bc894c
Move checking for tests at the beggining of the RC process
andreslucena Feb 18, 2025
6f9eafa
Fix requires for `present?` method
andreslucena Feb 18, 2025
c604c5a
Fix typo in method name
andreslucena Feb 18, 2025
87219e0
Add missing require
andreslucena Feb 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci_maintainers_toolbox.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ on:
env:
CI: "true"
SIMPLECOV: "true"
RUBY_VERSION: 2.7.5
RUBY_VERSION: 3.0.2

concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
/pkg/
/spec/reports/
/tmp/
.rspec-failures
1 change: 1 addition & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--require spec_helper
3 changes: 3 additions & 0 deletions lib/decidim/maintainers_toolbox/changelog_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ def call

if type_prs.any?
type_prs.each do |_pr_title, data|
# Prevent throttling by GitHub REST API
sleep 1

process_single_pr(data, type_data)
end
else
Expand Down
333 changes: 333 additions & 0 deletions lib/decidim/maintainers_toolbox/release_candidate_version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,333 @@
# frozen_string_literal: true

require_relative "changelog_generator"
require_relative "releaser_utils"
require_relative "github_manager/poster"

module Decidim
module MaintainersToolbox
# Creates a release candidate version for this branch
#
# If we are in develop (i.e. v0.30.0.dev) it will create the rc1 (i.e. v0.30.0.rc1)
# If we are in the stable release with an rc (i.e. v0.30.0.rc1) it will create the next rc (i.e. v0.30.0.rc2)
# If we are in the stable release with a patch (i.e. v0.30.0) it will bail out
class ReleaseCandidateVersion
include Decidim::MaintainersToolbox::ReleaserUtils

# @param token [String] token for GitHub authentication
# @param working_dir [String] current working directory. Useful for testing purposes
def initialize(token:, working_dir: Dir.pwd)
@token = token
@working_dir = working_dir
@old_version_number = old_version_number
end

def call
check_branch_and_version_sanity

prepare_next_development_version
prepare_next_release_candidate_version
end

# The version number for the release that we are preparing
#
# @return [String] the version number
def version_number
@version_number ||= next_version_number_for_release_candidate(@old_version_number)
end

private

# Returns the next branch that needs to be created for the RC.
#
# @return [String]
def release_branch
@release_branch ||= begin
major, minor, _patch = parsed_version_number(version_number)

"release/#{major}.#{minor}-stable"
end
end

def check_branch_and_version_sanity
return if develop_branch? && dev_version_number?
return if release_branch? && rc_version_number?

error_message = <<-EOERROR
Check if the branch is valid for a release candidate. It should be:
- develop with a dev version (i.e. develop branch with 0.30.0.dev decidim version)
- stable branch with a release candidate version (i.e. release/0.30-stable branch with 0.30.rc1 decidim version)
EOERROR
exit_with_errors(error_message)
end

def develop_branch?
branch == "develop"
end

def dev_version_number?
@old_version_number.match? /dev$/
end

def release_branch?
branch.start_with?("release/")
end

def rc_version_number?
@old_version_number.match? /rc.$/
end

def prepare_next_development_version
return unless develop_branch? || dev_version_number?

run("git pull origin develop")

run("git checkout -b #{release_branch}")
run("git push origin #{release_branch}")

puts "*" * 80
puts "Create the stable branch in Crowdin and exit this shell to continue the release process"
puts "https://docs.decidim.org/en/develop/develop/maintainers/releases.html#_create_the_stable_branch_in_crowdin"
puts "*" * 80
system ENV.fetch("SHELL")

run("git checkout develop")

next_dev_version = next_version_number_for_dev(@old_version_number)
prepare_branch = "chore/prepare/#{next_dev_version}"
run("git checkout -b #{prepare_branch}")

bump_decidim_version(next_version_number_for_dev(@old_version_number))

run("bin/rake update_versions")
run("bin/rake patch_generators")
run("bin/rake bundle")
run("npm install")
run("bin/rake webpack") if Dir.exist?("decidim_app-design")

generate_empty_changelog
generate_empty_release_notes

run("git add .")
run("git commit -m 'Bump develop to next release version'")
run("git push origin #{prepare_branch}")

create_develop_pull_request(prepare_branch, next_dev_version)
end

def prepare_next_release_candidate_version
run("git checkout #{release_branch}")
run("git checkout -b chore/prepare/#{version_number}")

bump_decidim_version(version_number)

run("bin/rake update_versions")
run("bin/rake patch_generators")
run("bin/rake bundle")

run("npm install")
run("bin/rake webpack") if Dir.exist?("decidim_app-design")

check_tests

generate_changelog

run("git add .")
run("git commit -m 'Bump to #{version_number} version'")
run("git push origin chore/prepare/#{version_number}")

create_pull_request

finish_message = <<~EOMESSAGE
Finished the release process
Next steps:

1. Wait for the tests to finish and check that everything is passing before releasing the version.
NOTE: When you bump the version, the generator tests will fail because the gems and NPM packages
have not been actually published yet (as in sent to rubygems/npm). You may see errors such as
No matching version found for @decidim/browserslist-config@~0.xx.y in the CI logs. This should
be fine as long as you have ensured that the generators tests passed in the previous commit.
2. Review and merge this PR
3. Once that PR is merged, run the following commands to create the tags and push the gems to RubyGems and the packages to NPM:
> git pull
> bin/rake release_all
4. Usually, at this point, the release branch is deployed to Metadecidim during, at least, one week to validate the stability of the version.
EOMESSAGE

puts "*" * 80
puts finish_message
end

# Given a version number, returns the next release candidate
#
# If the current version number is `dev`, then we return the `rc1` version
# If the current version number is `rc`, then we return the next `rc` version
# Else, it means is a `minor` or `patch` version. On those cases we raise an Exception, as releases candidates should
# be only done from a `dev` or a `rc` version.
#
# @raise [InvalidVersionTypeError]
#
# @param current_version_number [String] - The version number of the current version
#
# @return [String] - the new version number
def next_version_number_for_release_candidate(current_version_number)
if current_version_number.include? "dev"
major, minor, patch = parsed_version_number(current_version_number)
new_version_number = "#{major}.#{minor}.#{patch}.rc1"
elsif current_version_number.include? "rc"
new_rc_number = current_version_number.match(/rc(\d)/)[1].to_i + 1
new_version_number = current_version_number.gsub(/rc\d/, "rc#{new_rc_number}")
else
error_message = <<-EOMESSAGE
Trying to do a release candidate version from patch release. Bailing out.
You need to do a release candidate from a `dev` or from another `rc` version
EOMESSAGE
raise InvalidVersionTypeError, error_message
end

new_version_number
end

def next_version_number_for_dev(current_version_number)
major, minor, patch = parsed_version_number(current_version_number)

"#{major}.#{minor.to_i + 1}.#{patch}.dev"
end

def generate_empty_changelog
major, minor, patch = parsed_version_number(@old_version_number)

changelog_contents = <<-EOCHANGELOG
# Changelog

## [Unreleased](https://github.com/decidim/decidim/tree/HEAD)

Nothing.

...

## Previous versions

Please check [#{major}.#{minor}-stable](https://github.com/decidim/decidim/blob/release/#{major}.#{minor}-stable/CHANGELOG.md) for previous changes.
EOCHANGELOG

File.write("CHANGELOG.md", changelog_contents)
end

def generate_empty_release_notes
release_notes_contents = <<-EORELEASE
# Release Notes

## 1. Upgrade notes

As usual, we recommend that you have a full backup, of the database, application code and static files.

To update, follow these steps:

### 1.1. Update your ruby version

If you're using rbenv, this is done with the following commands:

```console
rbenv install 3.x.x
rbenv local 3.x.x
```

You may need to change your `.ruby-version` file too.

If not, you need to adapt it to your environment, for instance by changing the decidim docker image to use ruby:3.x.x.

### 1.2. Update your Gemfile

```ruby
gem "decidim", github: "decidim/decidim"
gem "decidim-dev", github: "decidim/decidim"
```

### 1.3. Run these commands

```console
bundle update decidim
bin/rails decidim:upgrade
bin/rails db:migrate
```

### 1.4. Follow the steps and commands detailed in these notes

## 2. General notes

## 3. One time actions

These are one time actions that need to be done after the code is updated in the production database.

### 3.1. [[TITLE OF THE ACTION]]

You can read more about this change on PR [#XXXX](https://github.com/decidim/decidim/pull/XXXX).

## 4. Scheduled tasks

Implementers need to configure these changes it in your scheduler task system in the production server. We give the examples
with `crontab`, although alternatively you could use `whenever` gem or the scheduled jobs of your hosting provider.

### 4.1. [[TITLE OF THE TASK]]

```bash
4 0 * * * cd /home/user/decidim_application && RAILS_ENV=production bundle exec rails decidim:TASK
```

You can read more about this change on PR [#XXXX](https://github.com/decidim/decidim/pull/XXXX).

## 5. Changes in APIs

### 5.1. [[TITLE OF THE CHANGE]]

In order to [[REASONING (e.g. improve the maintenance of the code base)]] we have changed...

If you have used code as such:

```ruby
# Explain the usage of the API as it was in the previous version
result = 1 + 1 if before
```

You need to change it to:

```ruby
# Explain the usage of the API as it is in the new version
result = 1 + 1 if after
```
EORELEASE

File.write("RELEASE_NOTES.md", release_notes_contents)
end

# Creates the pull request for bumping the develop version
#
# @param head_branch [String] the branch that we want to merge to develop
# @param next_dev_version [String] the name of the next dev version (for instance 0.99.0.dev)
#
# @return [void]
def create_develop_pull_request(head_branch, next_dev_version)
base_branch = "develop"

params = {
title: "Bump develop to next release version (#{next_dev_version})",
body: "#### :tophat: What? Why?

This PR prepares the next develop version.

#### Testing

All the tests should pass

:hearts: Thank you!
",
labels: ["type: internal"],
head: head_branch,
base: base_branch
}
Decidim::MaintainersToolbox::GithubManager::Poster.new(token: @token, params: params).call
end
end
end
end
Loading