decidim 0.28.4 → 0.29.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/decidim-core/lib/decidim/webpacker/esbuild.config.js +14 -0
- data/decidim-core/lib/decidim/webpacker/shakapacker.yml +2 -2
- data/decidim-core/lib/decidim/webpacker/tsconfig.json +11 -0
- data/decidim-core/lib/decidim/webpacker/webpack/custom.js +13 -35
- data/decidim.gemspec +2 -1
- data/docs/README.adoc +2 -2
- data/docs/antora.yml +1 -1
- data/docs/modules/configure/pages/environment_variables.adoc +6 -102
- data/docs/modules/configure/pages/index.adoc +1 -1
- data/docs/modules/configure/pages/initializer.adoc +1 -1
- data/docs/modules/customize/pages/admin_filters.adoc +32 -0
- data/docs/modules/customize/pages/data_consent.adoc +1 -1
- data/docs/modules/customize/pages/index.adoc +2 -1
- data/docs/modules/customize/pages/javascript.adoc +2 -2
- data/docs/modules/customize/pages/logic.adoc +1 -1
- data/docs/modules/customize/pages/social_shares.adoc +2 -2
- data/docs/modules/customize/pages/styles.adoc +3 -3
- data/docs/modules/customize/pages/views.adoc +1 -1
- data/docs/modules/develop/pages/authorable.adoc +3 -3
- data/docs/modules/develop/pages/backports.adoc +6 -5
- data/docs/modules/develop/pages/c4_component.adoc +2 -7
- data/docs/modules/develop/pages/c4_container.adoc +1 -3
- data/docs/modules/develop/pages/c4_context.adoc +0 -2
- data/docs/modules/develop/pages/classes/commands.adoc +204 -25
- data/docs/modules/develop/pages/components.adoc +5 -5
- data/docs/modules/develop/pages/custom_seed_data.adoc +1 -1
- data/docs/modules/develop/pages/embeddable.adoc +1 -1
- data/docs/modules/develop/pages/endorsable.adoc +2 -2
- data/docs/modules/develop/pages/guide_conventions.adoc +6 -6
- data/docs/modules/develop/pages/guide_development_app.adoc +2 -1
- data/docs/modules/develop/pages/guide_example_apps.adoc +1 -1
- data/docs/modules/develop/pages/guide_github_projects.adoc +1 -1
- data/docs/modules/develop/pages/guide_migrate_webpacker_app.adoc +2 -2
- data/docs/modules/develop/pages/guide_migrate_webpacker_module.adoc +1 -1
- data/docs/modules/develop/pages/maintainers/releases.adoc +2 -4
- data/docs/modules/develop/pages/managing_translations_i18n.adoc +2 -2
- data/docs/modules/develop/pages/maps.adoc +5 -5
- data/docs/modules/develop/pages/metrics.adoc +1 -1
- data/docs/modules/develop/pages/modules.adoc +1 -1
- data/docs/modules/develop/pages/newsletter_templates.adoc +2 -2
- data/docs/modules/develop/pages/notifications.adoc +124 -1
- data/docs/modules/develop/pages/reminders.adoc +2 -2
- data/docs/modules/develop/pages/reportable.adoc +1 -1
- data/docs/modules/develop/pages/testing.adoc +2 -2
- data/docs/modules/develop/pages/troubleshooting_metrics.adoc +2 -2
- data/docs/modules/develop/pages/view_models_aka_cells.adoc +1 -1
- data/docs/modules/install/pages/checklist.adoc +3 -2
- data/docs/modules/install/pages/empty-database.adoc +3 -3
- data/docs/modules/install/pages/index.adoc +5 -5
- data/docs/modules/install/pages/manual.adoc +3 -2
- data/docs/modules/install/pages/update.adoc +2 -2
- data/docs/modules/services/pages/activestorage.adoc +1 -1
- data/docs/modules/services/pages/index.adoc +0 -1
- data/docs/modules/services/pages/maps.adoc +2 -2
- data/docs/modules/services/pages/sms.adoc +1 -1
- data/docs/modules/services/pages/social_providers.adoc +3 -3
- data/lib/decidim/gem_manager.rb +2 -0
- data/lib/decidim/version.rb +1 -1
- data/package-lock.json +6359 -19611
- data/package.json +4 -6
- data/packages/browserslist-config/package.json +1 -1
- data/packages/core/package.json +11 -11
- data/packages/dev/package.json +1 -1
- data/packages/eslint-config/index.js +58 -82
- data/packages/eslint-config/package.json +1 -1
- data/packages/prettier-config/package.json +1 -1
- data/packages/stylelint-config/package.json +1 -1
- data/packages/webpacker/index.js +2 -1
- data/packages/webpacker/package.json +5 -11
- metadata +61 -61
- data/babel.config.json +0 -25
- data/docs/modules/develop/pages/consulations_removal.bash +0 -117
- data/docs/modules/services/pages/elections_bulletin_board.adoc +0 -55
- data/lib/decidim/backporter.rb +0 -98
- data/lib/decidim/backports_reporter/cli_report.rb +0 -44
- data/lib/decidim/backports_reporter/csv_report.rb +0 -32
- data/lib/decidim/backports_reporter/report.rb +0 -46
- data/lib/decidim/git_backport_checker.rb +0 -70
- data/lib/decidim/git_backport_manager.rb +0 -179
- data/lib/decidim/github_manager/poster.rb +0 -70
- data/lib/decidim/github_manager/querier/base.rb +0 -78
- data/lib/decidim/github_manager/querier/by_issue_id.rb +0 -46
- data/lib/decidim/github_manager/querier/by_label.rb +0 -95
- data/lib/decidim/github_manager/querier/related_issues.rb +0 -51
- data/lib/decidim/github_manager/querier.rb +0 -20
- data/packages/elections/package.json +0 -17
- data/packages/webpacker/package-lock.json +0 -18045
data/lib/decidim/backporter.rb
DELETED
@@ -1,98 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Decidim
|
4
|
-
class Backporter
|
5
|
-
class InvalidMetadataError < StandardError; end
|
6
|
-
|
7
|
-
# @param token [String] token for GitHub authentication
|
8
|
-
# @param pull_request_id [String] the ID of the pull request that we want to backport
|
9
|
-
# @param version_number [String] the version number of the release that we want to make the backport to
|
10
|
-
# @param exit_with_unstaged_changes [Boolean] wheter we should exit cowardly if there is any unstaged change
|
11
|
-
def initialize(token:, pull_request_id:, version_number:, exit_with_unstaged_changes:)
|
12
|
-
@token = token
|
13
|
-
@pull_request_id = pull_request_id
|
14
|
-
@version_number = version_number
|
15
|
-
@exit_with_unstaged_changes = exit_with_unstaged_changes
|
16
|
-
end
|
17
|
-
|
18
|
-
# Handles the different tasks to create a backport:
|
19
|
-
# * Gets the metadata of a pull request on GitHub
|
20
|
-
# * Appls thi commit to another brach and push it to the remote repository
|
21
|
-
# * Creates the pull request on GitHub
|
22
|
-
#
|
23
|
-
# @raise [InvalidMetadataError] if we could not get the information of this pull quest
|
24
|
-
# @return [void]
|
25
|
-
def call
|
26
|
-
metadata = pull_request_metadata
|
27
|
-
make_cherrypick_and_branch(metadata)
|
28
|
-
create_pull_request(metadata)
|
29
|
-
Decidim::GitBackportManager.checkout_develop
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
attr_reader :token, :pull_request_id, :version_number, :exit_with_unstaged_changes
|
35
|
-
|
36
|
-
# Asks the metadata for a given issue or pull request on GitHub API
|
37
|
-
#
|
38
|
-
# @return [Faraday::Response] An instance that represents an HTTP response from making an HTTP request
|
39
|
-
def pull_request_metadata
|
40
|
-
Decidim::GithubManager::Querier::ByIssueId.new(
|
41
|
-
token:,
|
42
|
-
issue_id: pull_request_id
|
43
|
-
).call
|
44
|
-
end
|
45
|
-
|
46
|
-
# Handles all the different tasks involved on a backport with the git command line utility
|
47
|
-
#
|
48
|
-
# @return [void]
|
49
|
-
def make_cherrypick_and_branch(metadata)
|
50
|
-
Decidim::GitBackportManager.new(
|
51
|
-
pull_request_id:,
|
52
|
-
release_branch:,
|
53
|
-
backport_branch: backport_branch(metadata[:title]),
|
54
|
-
exit_with_unstaged_changes:
|
55
|
-
).call
|
56
|
-
end
|
57
|
-
|
58
|
-
# Creates the pull request with GitHub API
|
59
|
-
#
|
60
|
-
# @return [Faraday::Response] An instance that represents an HTTP response from making an HTTP request
|
61
|
-
def create_pull_request(metadata)
|
62
|
-
params = {
|
63
|
-
title: "Backport '#{metadata[:title]}' to v#{version_number}",
|
64
|
-
body: "#### :tophat: What? Why?\n\nBackport ##{pull_request_id} to v#{version_number}\n\n:hearts: Thank you!",
|
65
|
-
labels: (metadata[:labels] << "backport"),
|
66
|
-
head: backport_branch(metadata[:title]),
|
67
|
-
base: release_branch
|
68
|
-
}
|
69
|
-
|
70
|
-
Decidim::GithubManager::Poster.new(
|
71
|
-
token:,
|
72
|
-
params:
|
73
|
-
).call
|
74
|
-
end
|
75
|
-
|
76
|
-
# Name of the release branch
|
77
|
-
#
|
78
|
-
# @return [String] name of the release branch
|
79
|
-
def release_branch
|
80
|
-
"release/#{version_number}-stable"
|
81
|
-
end
|
82
|
-
|
83
|
-
# Name of the backport branch
|
84
|
-
#
|
85
|
-
# @return [String] name of the backport branch
|
86
|
-
def backport_branch(pull_request_title)
|
87
|
-
"backport/#{version_number}/#{slugify(pull_request_title).slice!(0, 30)}-#{pull_request_id}"
|
88
|
-
end
|
89
|
-
|
90
|
-
# Converts a string with spaces to a slug
|
91
|
-
# It changes it to lowercase and removes spaces
|
92
|
-
#
|
93
|
-
# @return [String] slugged string
|
94
|
-
def slugify(string)
|
95
|
-
string.downcase.strip.gsub(" ", "-").gsub(/[^\w-]/, "")
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "active_support/core_ext/string/filters"
|
4
|
-
require_relative "report"
|
5
|
-
|
6
|
-
module Decidim
|
7
|
-
module BackportsReporter
|
8
|
-
class CLIReport < Decidim::BackportsReporter::Report
|
9
|
-
private
|
10
|
-
|
11
|
-
def output_head
|
12
|
-
head = "| #{"ID".center(6)} | #{"Title".center(83)} | Backport v#{last_version_number} | Backport v#{penultimate_version_number} |\n"
|
13
|
-
head += "|#{"-" * 8}|#{"-" * 85}|#{"-" * 16}|#{"-" * 16}|\n"
|
14
|
-
head
|
15
|
-
end
|
16
|
-
|
17
|
-
def output_line(line)
|
18
|
-
output = "| ##{line[:id].to_s.center(5)} "
|
19
|
-
output += "| #{line[:title].truncate(83).ljust(84, " ")}"
|
20
|
-
output += "| #{format_backport(line[:related_issues], "v#{last_version_number}")}"
|
21
|
-
output += "| #{format_backport(line[:related_issues], "v#{penultimate_version_number}")}|\n"
|
22
|
-
output
|
23
|
-
end
|
24
|
-
|
25
|
-
def format_backport(related_issues, version)
|
26
|
-
none = "None".center(15, " ")
|
27
|
-
return none if related_issues.empty?
|
28
|
-
|
29
|
-
pull_request = extract_backport_pull_request_for_version(related_issues, version)
|
30
|
-
return none if pull_request.nil?
|
31
|
-
|
32
|
-
"\e[#{state_color(pull_request[:state])}m##{pull_request[:id]}\e[0m".center(24, " ")
|
33
|
-
end
|
34
|
-
|
35
|
-
def state_color(state)
|
36
|
-
{
|
37
|
-
closed: "35",
|
38
|
-
merged: "34",
|
39
|
-
open: "32"
|
40
|
-
}[state.to_sym]
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "report"
|
4
|
-
|
5
|
-
module Decidim
|
6
|
-
module BackportsReporter
|
7
|
-
class CSVReport < Decidim::BackportsReporter::Report
|
8
|
-
private
|
9
|
-
|
10
|
-
def output_head
|
11
|
-
"ID;Title;Backport v#{last_version_number};Backport v#{penultimate_version_number}\n"
|
12
|
-
end
|
13
|
-
|
14
|
-
def output_line(line)
|
15
|
-
output = "#{line[:id]};"
|
16
|
-
output += "#{line[:title]};"
|
17
|
-
output += "#{format_backport(line[:related_issues], "v#{last_version_number}")};"
|
18
|
-
output += "#{format_backport(line[:related_issues], "v#{penultimate_version_number}")}\n"
|
19
|
-
output
|
20
|
-
end
|
21
|
-
|
22
|
-
def format_backport(related_issues, version)
|
23
|
-
return if related_issues.empty?
|
24
|
-
|
25
|
-
pull_request = extract_backport_pull_request_for_version(related_issues, version)
|
26
|
-
return if pull_request.nil?
|
27
|
-
|
28
|
-
"#{pull_request[:state]}|#{pull_request[:id]}"
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Decidim
|
4
|
-
module BackportsReporter
|
5
|
-
# Abstract class for the different formats
|
6
|
-
class Report
|
7
|
-
attr_reader :report, :last_version_number
|
8
|
-
|
9
|
-
def initialize(report:, last_version_number:)
|
10
|
-
@report = report
|
11
|
-
@last_version_number = last_version_number
|
12
|
-
end
|
13
|
-
|
14
|
-
def call = output_report
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def penultimate_version_number
|
19
|
-
major, minor = last_version_number.split(".")
|
20
|
-
|
21
|
-
"#{major}.#{minor.to_i - 1}"
|
22
|
-
end
|
23
|
-
|
24
|
-
def output_report
|
25
|
-
output = output_head
|
26
|
-
report.each do |line|
|
27
|
-
output += output_line(line)
|
28
|
-
end
|
29
|
-
output
|
30
|
-
end
|
31
|
-
|
32
|
-
def output_head = raise "Called abstract method: output_head"
|
33
|
-
|
34
|
-
def output_line(_line) = raise "Called abstract method: output_line"
|
35
|
-
|
36
|
-
def extract_backport_pull_request_for_version(related_issues, version)
|
37
|
-
related_issues = related_issues.select do |pull_request|
|
38
|
-
pull_request[:title].start_with?("Backport") && pull_request[:title].include?(version)
|
39
|
-
end
|
40
|
-
return if related_issues.empty?
|
41
|
-
|
42
|
-
related_issues.first
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "github_manager/querier/by_label"
|
4
|
-
require_relative "github_manager/querier/related_issues"
|
5
|
-
require_relative "backports_reporter/csv_report"
|
6
|
-
require_relative "backports_reporter/cli_report"
|
7
|
-
|
8
|
-
module Decidim
|
9
|
-
# Extracts the status of the Pull Requests on the decidim repository
|
10
|
-
# with the label "type: fix" and shows the status of the related Pull Requests,
|
11
|
-
# so we can check which PRs have pending backports
|
12
|
-
class GitBackportChecker
|
13
|
-
# @param token [String] token for GitHub authentication
|
14
|
-
# @param days_to_check_from [Integer] the number of days since the pull requests were merged from when we will start the check
|
15
|
-
# @param last_version_number [String] the version number of the last release that we want to make the backport to
|
16
|
-
def initialize(token:, days_to_check_from:, last_version_number:)
|
17
|
-
@token = token
|
18
|
-
@days_to_check_from = days_to_check_from
|
19
|
-
@last_version_number = last_version_number
|
20
|
-
end
|
21
|
-
|
22
|
-
def call
|
23
|
-
@report = by_label(
|
24
|
-
label: "type: fix",
|
25
|
-
exclude_labels: ["backport", "no-backport"],
|
26
|
-
days_to_check_from: @days_to_check_from
|
27
|
-
).map do |pull_request|
|
28
|
-
{
|
29
|
-
id: pull_request[:id],
|
30
|
-
title: pull_request[:title],
|
31
|
-
related_issues: related_issues(pull_request[:id])
|
32
|
-
}
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
def csv_report
|
37
|
-
Decidim::BackportsReporter::CSVReport.new(
|
38
|
-
report: @report,
|
39
|
-
last_version_number: @last_version_number
|
40
|
-
).call
|
41
|
-
end
|
42
|
-
|
43
|
-
def cli_report
|
44
|
-
Decidim::BackportsReporter::CLIReport.new(
|
45
|
-
report: @report,
|
46
|
-
last_version_number: @last_version_number
|
47
|
-
).call
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
attr_reader :token
|
53
|
-
|
54
|
-
def by_label(label:, exclude_labels:, days_to_check_from:)
|
55
|
-
Decidim::GithubManager::Querier::ByLabel.new(
|
56
|
-
token:,
|
57
|
-
label:,
|
58
|
-
exclude_labels:,
|
59
|
-
days_to_check_from:
|
60
|
-
).call
|
61
|
-
end
|
62
|
-
|
63
|
-
def related_issues(issue_id)
|
64
|
-
Decidim::GithubManager::Querier::RelatedIssues.new(
|
65
|
-
token:,
|
66
|
-
issue_id:
|
67
|
-
).call
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,179 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "shellwords"
|
4
|
-
require "English"
|
5
|
-
|
6
|
-
module Decidim
|
7
|
-
# Handles the backport of a given pull request to a branch
|
8
|
-
# Uses the git commnad line client
|
9
|
-
class GitBackportManager
|
10
|
-
# @param pull_request_id [String] the ID of the pull request that we want to backport
|
11
|
-
# @param release_branch [String] the name of the branch that we want to backport to
|
12
|
-
# @param backport_branch [String] the name of the branch that we want to create
|
13
|
-
# @param working_dir [String] current working directory. Useful for testing purposes
|
14
|
-
# @param exit_with_unstaged_changes [Boolean] wheter we should exit cowardly if there is any unstaged change
|
15
|
-
def initialize(pull_request_id:, release_branch:, backport_branch:, working_dir: Dir.pwd, exit_with_unstaged_changes: false)
|
16
|
-
@pull_request_id = pull_request_id
|
17
|
-
@release_branch = release_branch
|
18
|
-
@backport_branch = sanitize_branch(backport_branch)
|
19
|
-
@working_dir = working_dir
|
20
|
-
@exit_with_unstaged_changes = exit_with_unstaged_changes
|
21
|
-
end
|
22
|
-
|
23
|
-
# Handles all the different tasks involved on a backport with the git command line utility
|
24
|
-
# It does the following tasks:
|
25
|
-
# * Creates a branch based on a release branch
|
26
|
-
# * Apply a commit to this branch
|
27
|
-
# * Push it to the remote repository
|
28
|
-
#
|
29
|
-
# @return [void]
|
30
|
-
def call
|
31
|
-
Dir.chdir(working_dir) do
|
32
|
-
exit_if_unstaged_changes if @exit_with_unstaged_changes
|
33
|
-
self.class.checkout_develop
|
34
|
-
sha_commit = sha_commit_to_backport
|
35
|
-
|
36
|
-
error_message = <<-EOERROR
|
37
|
-
Could not find commit for pull request #{pull_request_id}.
|
38
|
-
Please make sure you have pulled the latest changes.
|
39
|
-
EOERROR
|
40
|
-
exit_with_errors(error_message) unless sha_commit
|
41
|
-
|
42
|
-
create_backport_branch!
|
43
|
-
cherrypick_commit!(sha_commit)
|
44
|
-
clean_commit_message!
|
45
|
-
push_backport_branch!
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# Switch to the develop branch
|
50
|
-
# In case that it cannot do that, exits
|
51
|
-
#
|
52
|
-
# @return [void]
|
53
|
-
def self.checkout_develop
|
54
|
-
`git checkout develop`
|
55
|
-
|
56
|
-
error_message = <<-EOERROR
|
57
|
-
Could not checkout the develop branch.
|
58
|
-
Please make sure you do not have any uncommitted changes in the current branch.
|
59
|
-
EOERROR
|
60
|
-
exit_with_errors(error_message) unless $CHILD_STATUS.exitstatus.zero?
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
attr_reader :pull_request_id, :release_branch, :backport_branch, :working_dir
|
66
|
-
|
67
|
-
# Create the backport branch based on a release branch
|
68
|
-
# Checks that this branch does not exist already, if it does then exits
|
69
|
-
#
|
70
|
-
# @return [void]
|
71
|
-
def create_backport_branch!
|
72
|
-
`git checkout #{release_branch}`
|
73
|
-
|
74
|
-
diff_count = `git rev-list HEAD..#{remote}/#{release_branch} --count`.strip.to_i
|
75
|
-
`git pull #{remote} #{release_branch}` if diff_count.positive?
|
76
|
-
`git checkout -b #{backport_branch}`
|
77
|
-
|
78
|
-
error_message = <<-EOERROR
|
79
|
-
Branch already exists locally.
|
80
|
-
Delete it with 'git branch -D #{backport_branch}' and rerun the script.
|
81
|
-
EOERROR
|
82
|
-
exit_with_errors(error_message) unless $CHILD_STATUS.exitstatus.zero?
|
83
|
-
end
|
84
|
-
|
85
|
-
# Cherrypick a commit from another branch
|
86
|
-
# Apply the changes introduced by some existing commits
|
87
|
-
# Drops to a shell in case that it needs a manual conflict resolution
|
88
|
-
#
|
89
|
-
# @return [void]
|
90
|
-
def cherrypick_commit!(sha_commit)
|
91
|
-
return unless sha_commit
|
92
|
-
|
93
|
-
puts "Cherrypicking commit #{sha_commit}"
|
94
|
-
`git cherry-pick #{sha_commit}`
|
95
|
-
|
96
|
-
unless $CHILD_STATUS.exitstatus.zero?
|
97
|
-
puts "Resolve the cherrypick conflict manually and exit your shell to keep with the process."
|
98
|
-
system ENV.fetch("SHELL")
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
# Clean the commit message to remove the pull request ID of the last commit
|
103
|
-
# This is mostly cosmetic, but if we don´t do this, we will have the two IDs on the final commit:
|
104
|
-
# the ID of the original PR and the id of the backported PR.
|
105
|
-
#
|
106
|
-
# @return [void]
|
107
|
-
def clean_commit_message!
|
108
|
-
message = `git log --pretty=format:"%B" -1`
|
109
|
-
message = message.lines[0].gsub!(/ \(#[0-9]+\)$/, "").concat(*message.lines[1..-1])
|
110
|
-
message.gsub!('"', '"\""') # Escape the double quotes for bash as they are the message delimiters
|
111
|
-
|
112
|
-
`git commit --amend -m "#{message}"`
|
113
|
-
end
|
114
|
-
|
115
|
-
# Push the branch to a git remote repository
|
116
|
-
# Checks that there is actually something to push first, if not then it exits.
|
117
|
-
#
|
118
|
-
# @return [void]
|
119
|
-
def push_backport_branch!
|
120
|
-
if `git diff #{backport_branch}..#{release_branch}`.empty?
|
121
|
-
self.class.checkout_develop
|
122
|
-
|
123
|
-
error_message = <<-EOERROR
|
124
|
-
Nothing to push to remote server.
|
125
|
-
It was probably merged already or the cherry-pick was aborted.
|
126
|
-
EOERROR
|
127
|
-
exit_with_errors(error_message)
|
128
|
-
else
|
129
|
-
puts "Pushing branch #{backport_branch} to #{remote}"
|
130
|
-
`git push #{remote} #{backport_branch}`
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
# The name of the git remote repository in the local git repository configuration
|
135
|
-
# Most of the times this would be origin or upstream.
|
136
|
-
#
|
137
|
-
# @return [String] the name of the git repository
|
138
|
-
def remote
|
139
|
-
`git remote -v | grep -e 'decidim/decidim\\([^ ]*\\) (push)' | sed 's/\\s.*//'`.strip
|
140
|
-
end
|
141
|
-
|
142
|
-
# The SHA1 commit to backport
|
143
|
-
# It needs to have a pull_request_id associated in the commit message
|
144
|
-
#
|
145
|
-
# @return [String] the SHA1 commit
|
146
|
-
def sha_commit_to_backport
|
147
|
-
`git log --format=oneline | grep "(##{pull_request_id})"`.split.first
|
148
|
-
end
|
149
|
-
|
150
|
-
# Replace all the characters from the user supplied input that are uncontrolled
|
151
|
-
# and could generate a command line injection
|
152
|
-
#
|
153
|
-
# @return [String] the sanitized branch name
|
154
|
-
def sanitize_branch(branch_name)
|
155
|
-
Shellwords.escape(branch_name.gsub("`", ""))
|
156
|
-
end
|
157
|
-
|
158
|
-
# Exit the script execution if there are any unstaged changes
|
159
|
-
#
|
160
|
-
# @return [void]
|
161
|
-
def exit_if_unstaged_changes
|
162
|
-
return if `git diff`.empty?
|
163
|
-
|
164
|
-
error_message = <<-EOERROR
|
165
|
-
There are changes not staged in your project.
|
166
|
-
Please commit your changes or stash them.
|
167
|
-
EOERROR
|
168
|
-
exit_with_errors(error_message)
|
169
|
-
end
|
170
|
-
|
171
|
-
# Exit the script execution with a message
|
172
|
-
#
|
173
|
-
# @return [void]
|
174
|
-
def exit_with_errors(message)
|
175
|
-
puts message
|
176
|
-
exit 1
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "active_support/core_ext/hash/except"
|
4
|
-
require "faraday"
|
5
|
-
require "json"
|
6
|
-
|
7
|
-
module Decidim
|
8
|
-
module GithubManager
|
9
|
-
# Allows to make POST requests to GitHub Rest API about Pull Requests
|
10
|
-
# @see https://docs.github.com/en/rest
|
11
|
-
class Poster
|
12
|
-
# @param token [String] token for GitHub authentication
|
13
|
-
# @param params [Hash] Parameters accepted by the GitHub API
|
14
|
-
def initialize(token:, params:)
|
15
|
-
@token = token
|
16
|
-
@params = params
|
17
|
-
end
|
18
|
-
|
19
|
-
# Create the pull request or give error messages
|
20
|
-
#
|
21
|
-
# @return [Faraday::Response] An instance that represents an HTTP response from making an HTTP request
|
22
|
-
def call
|
23
|
-
response = create_pull_request!
|
24
|
-
pull_request_id = JSON.parse(response.body)["number"]
|
25
|
-
unless pull_request_id
|
26
|
-
puts "Pull request could not be created!"
|
27
|
-
puts "Please make sure you have enabled the 'public_repo' scope for the access token"
|
28
|
-
return
|
29
|
-
end
|
30
|
-
puts "Pull request created at https://github.com/decidim/decidim/pull/#{pull_request_id}"
|
31
|
-
|
32
|
-
add_labels_to_issue!(pull_request_id)
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
attr_reader :token, :params
|
38
|
-
|
39
|
-
# Make the POST request to GitHub API of the decidim repository
|
40
|
-
#
|
41
|
-
# @param path [String] The path to do the request to the GitHub API
|
42
|
-
# @param some_params [Hash] The parameters of the request
|
43
|
-
# @return [Faraday::Response] An instance that represents an HTTP response from making an HTTP request
|
44
|
-
def post!(path, some_params)
|
45
|
-
uri = "https://api.github.com/repos/decidim/decidim/#{path}"
|
46
|
-
Faraday.post(uri, some_params.to_json, { Authorization: "token #{token}" })
|
47
|
-
end
|
48
|
-
|
49
|
-
# Create a pull request using the GitHub API
|
50
|
-
#
|
51
|
-
# @see https://docs.github.com/en/rest/pulls/pulls#create-a-pull-request GitHub API documentation
|
52
|
-
# @return [Faraday::Response] An instance that represents an HTTP response from making an HTTP request
|
53
|
-
def create_pull_request!
|
54
|
-
puts "Creating the PR in GitHub"
|
55
|
-
post!("pulls", params.except(:labels))
|
56
|
-
end
|
57
|
-
|
58
|
-
# Add labels to an issue or a pull request
|
59
|
-
# GitHub does not support adding labels while creating the PR, so we need to do it afterwards
|
60
|
-
#
|
61
|
-
# @see https://docs.github.com/en/rest/issues/labels#add-labels-to-an-issue GitHub API documentation
|
62
|
-
# @param issue_id [String] String of the issue to add the labels to
|
63
|
-
# @return [Faraday::Response] An instance that represents an HTTP response from making an HTTP request
|
64
|
-
def add_labels_to_issue!(issue_id)
|
65
|
-
puts "Adding the labels to the PR"
|
66
|
-
post!("issues/#{issue_id}/labels", params.slice(:labels))
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "json"
|
4
|
-
require "faraday"
|
5
|
-
require "uri"
|
6
|
-
|
7
|
-
module Decidim
|
8
|
-
module GithubManager
|
9
|
-
module Querier
|
10
|
-
# Base class that allows making GET requests to GitHub Rest API about Issues and Pull Requests
|
11
|
-
# This must be inherited from other class with the following methods:
|
12
|
-
# - call
|
13
|
-
# - uri
|
14
|
-
# @see https://docs.github.com/en/rest
|
15
|
-
class Base
|
16
|
-
class InvalidMetadataError < StandardError; end
|
17
|
-
|
18
|
-
def initialize(token:)
|
19
|
-
@token = token
|
20
|
-
end
|
21
|
-
|
22
|
-
def call
|
23
|
-
raise "Not implemented"
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
attr_reader :token
|
29
|
-
|
30
|
-
def headers
|
31
|
-
nil
|
32
|
-
end
|
33
|
-
|
34
|
-
def authorization_header
|
35
|
-
{ Authorization: "token #{token}" }
|
36
|
-
end
|
37
|
-
|
38
|
-
def request(uri)
|
39
|
-
response = Faraday.get(uri, headers, authorization_header)
|
40
|
-
|
41
|
-
{ body: response.body, headers: response.headers }
|
42
|
-
end
|
43
|
-
|
44
|
-
# Get's the JSON response from a URI
|
45
|
-
# Supports pagination
|
46
|
-
#
|
47
|
-
# @param uri {String} - The URL that we want to get the JSON response from
|
48
|
-
# @param old_json {Array} - The Array with the old_json or an empty Array if it's the first time that we're calling this method
|
49
|
-
def json_response(uri, old_json = [])
|
50
|
-
body, headers = request(uri).values_at(:body, :headers)
|
51
|
-
json = JSON.parse(body)
|
52
|
-
json.concat(old_json) if json.is_a?(Array)
|
53
|
-
raise InvalidMetadataError if json.is_a?(Hash) && json["message"] == "Bad credentials"
|
54
|
-
|
55
|
-
# If there are more pages, then we call ourselves redundantly to fetch the next page
|
56
|
-
next_json = more_pages?(headers) ? json_response(next_page(headers), json) : []
|
57
|
-
|
58
|
-
if json.is_a?(Array)
|
59
|
-
# For some reason we have duplicated values, so we deduplicate them
|
60
|
-
json.concat(next_json).uniq { |issue| issue.has_key?("number") ? issue["number"] : issue }
|
61
|
-
else
|
62
|
-
json
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def more_pages?(headers)
|
67
|
-
return false if headers["link"].nil?
|
68
|
-
|
69
|
-
headers["link"].include?('rel="next"')
|
70
|
-
end
|
71
|
-
|
72
|
-
def next_page(headers)
|
73
|
-
URI.extract(headers["link"].split(",").select { |url| url.end_with?('rel="next"') }[0])[0]
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "base"
|
4
|
-
|
5
|
-
module Decidim
|
6
|
-
module GithubManager
|
7
|
-
module Querier
|
8
|
-
# Makes a GET request for the metadata of an Issue or Pull Request in GitHub
|
9
|
-
#
|
10
|
-
# @see https://docs.github.com/en/rest/issues/issues#get-an-issue GitHub API documentation
|
11
|
-
class ByIssueId < Decidim::GithubManager::Querier::Base
|
12
|
-
def initialize(issue_id:, token:)
|
13
|
-
@issue_id = issue_id
|
14
|
-
@token = token
|
15
|
-
end
|
16
|
-
|
17
|
-
# Makes the GET request and parses the response of an Issue or Pull Request in GitHub
|
18
|
-
#
|
19
|
-
# @return [Hash]
|
20
|
-
def call
|
21
|
-
data = json_response("https://api.github.com/repos/decidim/decidim/issues/#{@issue_id}")
|
22
|
-
return unless data["number"]
|
23
|
-
|
24
|
-
parse(data)
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
# Parses the response of an Issue or Pull Request in GitHub
|
30
|
-
#
|
31
|
-
# @return [Hash]
|
32
|
-
def parse(metadata)
|
33
|
-
labels = metadata["labels"].map { |l| l["name"] }.sort
|
34
|
-
|
35
|
-
{
|
36
|
-
id: metadata["number"],
|
37
|
-
title: metadata["title"],
|
38
|
-
labels:,
|
39
|
-
type: labels.select { |l| l.match(/^type: /) || l == "target: developer-experience" },
|
40
|
-
modules: labels.select { |l| l.match(/^module: /) }
|
41
|
-
}
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|