decidim-maintainers_toolbox 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +66 -0
- data/decidim-maintainers_toolbox.gemspec +47 -0
- data/exe/decidim-backporter +44 -0
- data/exe/decidim-backports-checker +48 -0
- data/exe/decidim-changelog-generator +46 -0
- data/exe/decidim-releaser +41 -0
- data/lib/decidim/maintainers_toolbox/backporter.rb +100 -0
- data/lib/decidim/maintainers_toolbox/backports_reporter/cli_report.rb +46 -0
- data/lib/decidim/maintainers_toolbox/backports_reporter/csv_report.rb +34 -0
- data/lib/decidim/maintainers_toolbox/backports_reporter/report.rb +67 -0
- data/lib/decidim/maintainers_toolbox/changelog_generator.rb +166 -0
- data/lib/decidim/maintainers_toolbox/git_backport_checker.rb +81 -0
- data/lib/decidim/maintainers_toolbox/git_backport_manager.rb +184 -0
- data/lib/decidim/maintainers_toolbox/github_manager/poster.rb +75 -0
- data/lib/decidim/maintainers_toolbox/github_manager/querier/base.rb +80 -0
- data/lib/decidim/maintainers_toolbox/github_manager/querier/by_issue_id.rb +48 -0
- data/lib/decidim/maintainers_toolbox/github_manager/querier/by_label.rb +97 -0
- data/lib/decidim/maintainers_toolbox/github_manager/querier/by_title.rb +59 -0
- data/lib/decidim/maintainers_toolbox/github_manager/querier/related_issues.rb +53 -0
- data/lib/decidim/maintainers_toolbox/github_manager/querier.rb +23 -0
- data/lib/decidim/maintainers_toolbox/releaser.rb +287 -0
- data/lib/decidim/maintainers_toolbox/version.rb +7 -0
- data/lib/decidim/maintainers_toolbox.rb +10 -0
- metadata +160 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 98bbc7bc7f2fe89db2430fe013218ed8f73139241148f81e2b836001341a9edb
|
4
|
+
data.tar.gz: b2fcf684927d644818e40a3b47542bc9e71159ff8a220de40f45f7c02d479d90
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e9fcb49b88f506a3d8522ed38afe5253bb6cbdff6f66287ce9e5d9b24800f37d10756784999b9ef3944c7a338ffb088d0216da9232d2b77f604a36dbb40cb7d9
|
7
|
+
data.tar.gz: 919e40cba79bb9d64c4cdaf6a7ec485423ffb64017f063ea696be0a5249e9d9eafd4bbf68c7cc85ee7aaf2059c3e083a637273e7f8b132953294f1fdc07c6c7b
|
data/README.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# Decidim::MaintainersToolbox
|
2
|
+
|
3
|
+
Release related tools for the Decidim project.
|
4
|
+
|
5
|
+
Tools for releasing, backporting, changelog generating, and working with GitHub
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
This gem is meant to be used outside of bundler/Gemfile so we do not need to bump the version every time we release a new one to each of the releases branch.
|
10
|
+
|
11
|
+
```console
|
12
|
+
gem install decidim-maintainers_toolbox
|
13
|
+
```
|
14
|
+
|
15
|
+
## Usage
|
16
|
+
|
17
|
+
This gem allows preparing and working with Decidim releases. Is it meant to be used by maintainers of the project. In the near future most of these tools will be used by `decidim-bot`.
|
18
|
+
|
19
|
+
There are a couple differences with the rest of the gems of this repository:
|
20
|
+
|
21
|
+
* About the versioning: as it has not decidim nor decidim-core as dependencies, and to keep it easy to work with, we will not have the same versioning as the others gems.
|
22
|
+
* About the ruby version: to make it possible to work with older decidim versions, we will support the lowest supported ruby version.
|
23
|
+
|
24
|
+
This is the reason why its in a different repository and not in the decidim repository.
|
25
|
+
|
26
|
+
The main scripts are `decidim-backporter`, `decidim-backports-checker`, `decidim-changelog-generator` and `decidim-releaser`.
|
27
|
+
|
28
|
+
### decidim-backporter
|
29
|
+
|
30
|
+
See [Backports documentation](https://docs.decidim.org/en/develop/develop/backports)
|
31
|
+
|
32
|
+
### decidim-backports-checker
|
33
|
+
|
34
|
+
See [Backports documentation](https://docs.decidim.org/en/develop/develop/backports)
|
35
|
+
|
36
|
+
### decidim-changelog-generator
|
37
|
+
|
38
|
+
Used for generating the changelog with all the Pull Requests that goes to the current release. To be used automatically by the `releaser` script.
|
39
|
+
|
40
|
+
### decidim-releaser
|
41
|
+
|
42
|
+
See [Releasing new versions documentation](https://docs.decidim.org/en/develop/develop/maintainers/releases)
|
43
|
+
|
44
|
+
## Development
|
45
|
+
|
46
|
+
After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
47
|
+
|
48
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
49
|
+
|
50
|
+
## Releases
|
51
|
+
|
52
|
+
As this gem is meant to be used outside of the main decidim gems, we will not follow the same versioning. We will release a new version of this gem every time we have a new feature or bugfix that we need to use. This also means that we will not follow the same release process.
|
53
|
+
|
54
|
+
To release this gem, follow these steps:
|
55
|
+
|
56
|
+
1. Bump the version number in `lib/decidim/maintainers_toolbox/version.rb` following [Semantic Versioning](https://semver.org/).
|
57
|
+
1. Update the `CHANGELOG.md` with the new version and the changes.
|
58
|
+
1. Commit the changes.
|
59
|
+
1. Create a new tag with the version number.
|
60
|
+
1. Push the changes and the tag to the repository.
|
61
|
+
1. Run `rake build` to build the gem.
|
62
|
+
1. Run `rake release` to publish the gem to [rubygems.org](https://rubygems.org).
|
63
|
+
|
64
|
+
## Contributing
|
65
|
+
|
66
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/decidim/decidim.
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/decidim/maintainers_toolbox/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "decidim-maintainers_toolbox"
|
7
|
+
spec.version = Decidim::MaintainersToolbox::VERSION
|
8
|
+
spec.authors = ["Andrés Pereira de Lucena"]
|
9
|
+
spec.email = ["andreslucena@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "Release related tools for the Decidim project"
|
12
|
+
spec.description = "Tools for releasing, backporting, changelog generating, and working with GitHub"
|
13
|
+
|
14
|
+
spec.license = "AGPL-3.0"
|
15
|
+
spec.homepage = "https://decidim.org"
|
16
|
+
spec.metadata = {
|
17
|
+
"bug_tracker_uri" => "https://github.com/decidim/decidim/issues",
|
18
|
+
"documentation_uri" => "https://docs.decidim.org/",
|
19
|
+
"funding_uri" => "https://opencollective.com/decidim",
|
20
|
+
"homepage_uri" => "https://decidim.org",
|
21
|
+
"source_code_uri" => "https://github.com/decidim/decidim"
|
22
|
+
}
|
23
|
+
spec.required_ruby_version = ">= 2.7.5"
|
24
|
+
|
25
|
+
spec.files = Dir.chdir(__dir__) do
|
26
|
+
`git ls-files -z`.split("\x0").select do |f|
|
27
|
+
(File.expand_path(f) == __FILE__) ||
|
28
|
+
f.start_with?(*%w(
|
29
|
+
exe/
|
30
|
+
lib/
|
31
|
+
README.md
|
32
|
+
))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
spec.bindir = "exe"
|
37
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
38
|
+
spec.require_paths = ["lib"]
|
39
|
+
|
40
|
+
spec.add_dependency "faraday", "~> 1.10"
|
41
|
+
spec.add_dependency "ruby-progressbar", "~> 1.7"
|
42
|
+
spec.add_dependency "thor", "~> 1.0"
|
43
|
+
|
44
|
+
spec.add_development_dependency "activesupport", "~> 6.1.7"
|
45
|
+
spec.add_development_dependency "rspec", "~> 3.12"
|
46
|
+
spec.add_development_dependency "webmock", "~> 3.18"
|
47
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "thor"
|
5
|
+
|
6
|
+
require_relative "../lib/decidim/maintainers_toolbox/github_manager/querier"
|
7
|
+
require_relative "../lib/decidim/maintainers_toolbox/github_manager/poster"
|
8
|
+
require_relative "../lib/decidim/maintainers_toolbox/git_backport_manager"
|
9
|
+
require_relative "../lib/decidim/maintainers_toolbox/backporter"
|
10
|
+
|
11
|
+
class BackporterCLI < Thor
|
12
|
+
desc "", "Backport a pull request to another branch"
|
13
|
+
option :github_token, required: true, desc: <<~HELP
|
14
|
+
Required. Github Personal Access Token (PAT). It can be obtained from https://github.com/settings/tokens/new. You will need to create one with `public_repo` access.
|
15
|
+
Alternatively, you can use the `gh` CLI tool to authenticate with `gh auth token` (i.e. --github-token=$(gh auth token))
|
16
|
+
HELP
|
17
|
+
option :version_number, required: true, desc: "Required. The version number that you want to do the backport to. It must have the format MAJOR.MINOR."
|
18
|
+
option :pull_request_id, required: true, desc: "Required. The ID of the pull request that you want to make the backport from. It should have the \"type: fix\" label."
|
19
|
+
option :exit_with_unstaged_changes, type: :boolean, default: true, desc: <<~HELP
|
20
|
+
Optional. Whether the script should exit with an error if there are unstaged changes in the current project.
|
21
|
+
HELP
|
22
|
+
default_task :backport
|
23
|
+
|
24
|
+
def backport
|
25
|
+
Decidim::MaintainersToolbox::Backporter.new(
|
26
|
+
token: options[:github_token],
|
27
|
+
pull_request_id: options[:pull_request_id],
|
28
|
+
version_number: options[:version_number],
|
29
|
+
exit_with_unstaged_changes: options[:exit_with_unstaged_changes]
|
30
|
+
).call
|
31
|
+
rescue Decidim::MaintainersToolbox::GithubManager::Querier::Base::InvalidMetadataError
|
32
|
+
puts "Metadata was not returned from the server. Please check that the provided pull request ID and GitHub token are correct."
|
33
|
+
end
|
34
|
+
|
35
|
+
def help
|
36
|
+
super("backport")
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.exit_on_failure?
|
40
|
+
true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
BackporterCLI.start(ARGV)
|
@@ -0,0 +1,48 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "thor"
|
5
|
+
|
6
|
+
require_relative "../lib/decidim/maintainers_toolbox/git_backport_checker"
|
7
|
+
|
8
|
+
class BackportsCheckerCLI < Thor
|
9
|
+
desc "", <<~HELP
|
10
|
+
Backports checker. Shows the status of the pull requests opened in the last days
|
11
|
+
|
12
|
+
The output by default is for the terminal. It uses a color code to differentiate the status of the Pull Requests, following the colors of GitHub:
|
13
|
+
- \e[34mPurple\e[0m: closed with a merge
|
14
|
+
- \e[35mRed\e[0m: closed without being merge
|
15
|
+
- \e[32mGreen\e[0m: opened without being merge
|
16
|
+
HELP
|
17
|
+
option :github_token, required: true, desc: <<~HELP
|
18
|
+
Required. Github Personal Access Token (PAT). It can be obtained from https://github.com/settings/tokens/new. You will need to create one with `public_repo` access.
|
19
|
+
Alternatively, you can use the `gh` CLI tool to authenticate with `gh auth token` (i.e. --github-token=$(gh auth token))
|
20
|
+
HELP
|
21
|
+
option :last_version_number, required: true, desc: <<~HELP
|
22
|
+
Required. The version number of the last supported version that you want to do the backports to. It must have the format MAJOR.MINOR.
|
23
|
+
HELP
|
24
|
+
option :days_to_check_from, required: false, default: 90, type: :numeric, desc: "How many days since the pull requests were merged we will check from."
|
25
|
+
default_task :backports_checker
|
26
|
+
|
27
|
+
def backports_checker
|
28
|
+
checker = Decidim::MaintainersToolbox::GitBackportChecker.new(
|
29
|
+
token: options[:github_token],
|
30
|
+
last_version_number: options[:last_version_number],
|
31
|
+
days_to_check_from: options[:days_to_check_from]
|
32
|
+
)
|
33
|
+
checker.call
|
34
|
+
puts checker.cli_report
|
35
|
+
rescue Decidim::MaintainersToolbox::GithubManager::Querier::Base::InvalidMetadataError
|
36
|
+
puts "Metadata was not returned from the server. Please check that the provided GitHub token is correct."
|
37
|
+
end
|
38
|
+
|
39
|
+
def help
|
40
|
+
super("backports_checker")
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.exit_on_failure?
|
44
|
+
true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
BackportsCheckerCLI.start(ARGV)
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "thor"
|
5
|
+
|
6
|
+
require_relative "../lib/decidim/maintainers_toolbox/changelog_generator"
|
7
|
+
|
8
|
+
class ChangeLogGeneratorCLI < Thor
|
9
|
+
desc "", <<~HELP
|
10
|
+
Decidim's changelog generator. It will generate a changelog based on the pull requests merged since a given SHA
|
11
|
+
This script will generate the sections needed for the changelog, using the
|
12
|
+
labels of the merged PRs as a source of truth. It will add a section at the
|
13
|
+
end, "Unsorted", with the list of PRs that could not be classified.
|
14
|
+
It ignores any Crowdin PR.
|
15
|
+
HELP
|
16
|
+
|
17
|
+
option :github_token, required: true, desc: <<~HELP
|
18
|
+
Required. Github Personal Access Token (PAT). It can be obtained from https://github.com/settings/tokens/new. You will need to create one with `public_repo` access.
|
19
|
+
Alternatively, you can use the `gh` CLI tool to authenticate with `gh auth token` (i.e. --github-token=$(gh auth token))
|
20
|
+
HELP
|
21
|
+
option :since_sha, required: true, desc: <<~HELP
|
22
|
+
Required. The git commit SHA from which to consider the changes. It is
|
23
|
+
usually the last commit that modified the `.decidim_version` file.
|
24
|
+
HELP
|
25
|
+
|
26
|
+
default_task :changelog_generator
|
27
|
+
|
28
|
+
def changelog_generator
|
29
|
+
Decidim::MaintainersToolbox::ChangeLogGenerator.new(
|
30
|
+
token: options[:github_token],
|
31
|
+
since_sha: options[:since_sha]
|
32
|
+
).call
|
33
|
+
rescue Decidim::MaintainersToolbox::ChangeLogGenerator::InvalidMetadataError
|
34
|
+
puts "Metadata was not returned from the server. Please check that the provided GitHub token is correct."
|
35
|
+
end
|
36
|
+
|
37
|
+
def help
|
38
|
+
super("changelog_generator")
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.exit_on_failure?
|
42
|
+
true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
ChangeLogGeneratorCLI.start(ARGV)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "thor"
|
5
|
+
|
6
|
+
require_relative "../lib/decidim/maintainers_toolbox/releaser"
|
7
|
+
|
8
|
+
class ReleaserCLI < Thor
|
9
|
+
desc "", "Make the branch for preparing a release"
|
10
|
+
option :github_token, required: true, desc: <<~HELP
|
11
|
+
Required. Github Personal Access Token (PAT). It can be obtained from https://github.com/settings/tokens/new. You will need to create one with `public_repo` access.
|
12
|
+
Alternatively, you can use the `gh` CLI tool to authenticate with `gh auth token` (i.e. --github-token=$(gh auth token))
|
13
|
+
HELP
|
14
|
+
option :version_type, enum: %w(rc minor patch), required: true, desc: <<~HELP
|
15
|
+
Required. The kind of release that you want to prepare.
|
16
|
+
HELP
|
17
|
+
option :exit_with_unstaged_changes, type: :boolean, default: true, desc: <<~HELP
|
18
|
+
Optional. Whether the script should exit with an error if there are unstaged changes in the current project.
|
19
|
+
HELP
|
20
|
+
default_task :releaser
|
21
|
+
|
22
|
+
def releaser
|
23
|
+
Decidim::MaintainersToolbox::Releaser.new(
|
24
|
+
token: options[:github_token],
|
25
|
+
version_type: options[:version_type],
|
26
|
+
exit_with_unstaged_changes: options[:exit_with_unstaged_changes]
|
27
|
+
).call
|
28
|
+
rescue Decidim::MaintainersToolbox::Releaser::InvalidMetadataError
|
29
|
+
puts "Metadata was not returned from the server. Please check that the GitHub token is correct."
|
30
|
+
end
|
31
|
+
|
32
|
+
def help
|
33
|
+
super("releaser")
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.exit_on_failure?
|
37
|
+
true
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
ReleaserCLI.start(ARGV)
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module MaintainersToolbox
|
5
|
+
class Backporter
|
6
|
+
class InvalidMetadataError < StandardError; end
|
7
|
+
|
8
|
+
# @param token [String] token for GitHub authentication
|
9
|
+
# @param pull_request_id [String] the ID of the pull request that we want to backport
|
10
|
+
# @param version_number [String] the version number of the release that we want to make the backport to
|
11
|
+
# @param exit_with_unstaged_changes [Boolean] wheter we should exit cowardly if there is any unstaged change
|
12
|
+
def initialize(token:, pull_request_id:, version_number:, exit_with_unstaged_changes:)
|
13
|
+
@token = token
|
14
|
+
@pull_request_id = pull_request_id
|
15
|
+
@version_number = version_number
|
16
|
+
@exit_with_unstaged_changes = exit_with_unstaged_changes
|
17
|
+
end
|
18
|
+
|
19
|
+
# Handles the different tasks to create a backport:
|
20
|
+
# * Gets the metadata of a pull request on GitHub
|
21
|
+
# * Appls thi commit to another brach and push it to the remote repository
|
22
|
+
# * Creates the pull request on GitHub
|
23
|
+
#
|
24
|
+
# @raise [InvalidMetadataError] if we could not get the information of this pull quest
|
25
|
+
# @return [void]
|
26
|
+
def call
|
27
|
+
metadata = pull_request_metadata
|
28
|
+
make_cherrypick_and_branch(metadata)
|
29
|
+
create_pull_request(metadata)
|
30
|
+
Decidim::MaintainersToolbox::GitBackportManager.checkout_develop
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
attr_reader :token, :pull_request_id, :version_number, :exit_with_unstaged_changes
|
36
|
+
|
37
|
+
# Asks the metadata for a given issue or pull request on GitHub API
|
38
|
+
#
|
39
|
+
# @return [Faraday::Response] An instance that represents an HTTP response from making an HTTP request
|
40
|
+
def pull_request_metadata
|
41
|
+
Decidim::MaintainersToolbox::GithubManager::Querier::ByIssueId.new(
|
42
|
+
token: token,
|
43
|
+
issue_id: pull_request_id
|
44
|
+
).call
|
45
|
+
end
|
46
|
+
|
47
|
+
# Handles all the different tasks involved on a backport with the git command line utility
|
48
|
+
#
|
49
|
+
# @return [void]
|
50
|
+
def make_cherrypick_and_branch(metadata)
|
51
|
+
Decidim::MaintainersToolbox::GitBackportManager.new(
|
52
|
+
pull_request_id: pull_request_id,
|
53
|
+
release_branch: release_branch,
|
54
|
+
backport_branch: backport_branch(metadata[:title]),
|
55
|
+
exit_with_unstaged_changes: exit_with_unstaged_changes
|
56
|
+
).call
|
57
|
+
end
|
58
|
+
|
59
|
+
# Creates the pull request with GitHub API
|
60
|
+
#
|
61
|
+
# @return [Faraday::Response] An instance that represents an HTTP response from making an HTTP request
|
62
|
+
def create_pull_request(metadata)
|
63
|
+
params = {
|
64
|
+
title: "Backport '#{metadata[:title]}' to v#{version_number}",
|
65
|
+
body: "#### :tophat: What? Why?\n\nBackport ##{pull_request_id} to v#{version_number}\n\n:hearts: Thank you!",
|
66
|
+
labels: (metadata[:labels] << "backport"),
|
67
|
+
head: backport_branch(metadata[:title]),
|
68
|
+
base: release_branch
|
69
|
+
}
|
70
|
+
|
71
|
+
Decidim::MaintainersToolbox::GithubManager::Poster.new(
|
72
|
+
token: token,
|
73
|
+
params: params
|
74
|
+
).call
|
75
|
+
end
|
76
|
+
|
77
|
+
# Name of the release branch
|
78
|
+
#
|
79
|
+
# @return [String] name of the release branch
|
80
|
+
def release_branch
|
81
|
+
"release/#{version_number}-stable"
|
82
|
+
end
|
83
|
+
|
84
|
+
# Name of the backport branch
|
85
|
+
#
|
86
|
+
# @return [String] name of the backport branch
|
87
|
+
def backport_branch(pull_request_title)
|
88
|
+
"backport/#{version_number}/#{slugify(pull_request_title).slice!(0, 30)}-#{pull_request_id}"
|
89
|
+
end
|
90
|
+
|
91
|
+
# Converts a string with spaces to a slug
|
92
|
+
# It changes it to lowercase and removes spaces
|
93
|
+
#
|
94
|
+
# @return [String] slugged string
|
95
|
+
def slugify(string)
|
96
|
+
string.downcase.strip.gsub(" ", "-").gsub(/[^\w-]/, "")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/string/filters"
|
4
|
+
require_relative "report"
|
5
|
+
|
6
|
+
module Decidim
|
7
|
+
module MaintainersToolbox
|
8
|
+
module BackportsReporter
|
9
|
+
class CLIReport < Decidim::MaintainersToolbox::BackportsReporter::Report
|
10
|
+
private
|
11
|
+
|
12
|
+
def output_head
|
13
|
+
head = "| #{"ID".center(6)} | #{"Title".center(83)} | Backport v#{last_version_number} | Backport v#{penultimate_version_number} |\n"
|
14
|
+
head += "|#{"-" * 8}|#{"-" * 85}|#{"-" * 16}|#{"-" * 16}|\n"
|
15
|
+
head
|
16
|
+
end
|
17
|
+
|
18
|
+
def output_line(line)
|
19
|
+
output = "| ##{line[:id].to_s.center(5)} "
|
20
|
+
output += "| #{line[:title].truncate(83).ljust(84, " ")}"
|
21
|
+
output += "| #{format_backport(line[:related_issues], "v#{last_version_number}")}"
|
22
|
+
output += "| #{format_backport(line[:related_issues], "v#{penultimate_version_number}")}|\n"
|
23
|
+
output
|
24
|
+
end
|
25
|
+
|
26
|
+
def format_backport(related_issues, version)
|
27
|
+
none = "None".center(15, " ")
|
28
|
+
return none if related_issues.empty?
|
29
|
+
|
30
|
+
pull_request = extract_backport_pull_request_for_version(related_issues, version)
|
31
|
+
return none if pull_request.nil?
|
32
|
+
|
33
|
+
"\e[#{state_color(pull_request[:state])}m##{pull_request[:id]}\e[0m".center(24, " ")
|
34
|
+
end
|
35
|
+
|
36
|
+
def state_color(state)
|
37
|
+
{
|
38
|
+
closed: "35",
|
39
|
+
merged: "34",
|
40
|
+
open: "32"
|
41
|
+
}[state.to_sym]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "report"
|
4
|
+
|
5
|
+
module Decidim
|
6
|
+
module MaintainersToolbox
|
7
|
+
module BackportsReporter
|
8
|
+
class CSVReport < Decidim::MaintainersToolbox::BackportsReporter::Report
|
9
|
+
private
|
10
|
+
|
11
|
+
def output_head
|
12
|
+
"ID;Title;Backport v#{last_version_number};Backport v#{penultimate_version_number}\n"
|
13
|
+
end
|
14
|
+
|
15
|
+
def output_line(line)
|
16
|
+
output = "#{line[:id]};"
|
17
|
+
output += "#{line[:title]};"
|
18
|
+
output += "#{format_backport(line[:related_issues], "v#{last_version_number}")};"
|
19
|
+
output += "#{format_backport(line[:related_issues], "v#{penultimate_version_number}")}\n"
|
20
|
+
output
|
21
|
+
end
|
22
|
+
|
23
|
+
def format_backport(related_issues, version)
|
24
|
+
return if related_issues.empty?
|
25
|
+
|
26
|
+
pull_request = extract_backport_pull_request_for_version(related_issues, version)
|
27
|
+
return if pull_request.nil?
|
28
|
+
|
29
|
+
"#{pull_request[:state]}|#{pull_request[:id]}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module MaintainersToolbox
|
5
|
+
module BackportsReporter
|
6
|
+
# Abstract class for the different formats
|
7
|
+
class Report
|
8
|
+
attr_reader :report, :last_version_number
|
9
|
+
|
10
|
+
def initialize(report:, last_version_number:)
|
11
|
+
@report = report
|
12
|
+
@last_version_number = last_version_number
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
output_report
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def penultimate_version_number
|
22
|
+
major, minor = last_version_number.split(".")
|
23
|
+
|
24
|
+
"#{major}.#{minor.to_i - 1}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def output_report
|
28
|
+
output = output_head
|
29
|
+
report.each do |line|
|
30
|
+
next if backports_merged?(line[:related_issues])
|
31
|
+
|
32
|
+
output += output_line(line)
|
33
|
+
end
|
34
|
+
output
|
35
|
+
end
|
36
|
+
|
37
|
+
def output_head
|
38
|
+
raise "Called abstract method: output_head"
|
39
|
+
end
|
40
|
+
|
41
|
+
def output_line(_line)
|
42
|
+
raise "Called abstract method: output_line"
|
43
|
+
end
|
44
|
+
|
45
|
+
def extract_backport_pull_request_for_version(related_issues, version)
|
46
|
+
related_issues = related_issues.select do |pull_request|
|
47
|
+
pull_request[:title].start_with?("Backport") && pull_request[:title].include?(version)
|
48
|
+
end
|
49
|
+
return if related_issues.empty?
|
50
|
+
|
51
|
+
related_issues.first
|
52
|
+
end
|
53
|
+
|
54
|
+
def backports_merged?(related_issues)
|
55
|
+
return if related_issues.empty?
|
56
|
+
|
57
|
+
latest_pr = extract_backport_pull_request_for_version(related_issues, "v#{last_version_number}")
|
58
|
+
penultimate_pr = extract_backport_pull_request_for_version(related_issues, "v#{penultimate_version_number}")
|
59
|
+
|
60
|
+
return unless [latest_pr, penultimate_pr].all?
|
61
|
+
|
62
|
+
latest_pr[:state] == "merged" && penultimate_pr[:state] == "merged"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|