DEV: Support new discourse-compatibility format on old core (#186)

This introduces a fallback compatibility parser, identical to the one introduced in https://github.com/discourse/discourse/pull/22714

This will allow Docker Manager to parse new compatibility files, even when running on older Discourse instances. This is only intended as a temporary solution, and will be removed before the Discourse 3.2 release.
This commit is contained in:
David Taylor 2023-07-25 14:31:27 +01:00 committed by GitHub
parent 8edc1df602
commit 4a493543de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 110 additions and 4 deletions

View File

@ -1,4 +1,3 @@
# Do you need to make fixes for Discourse v3.1.0.beta1 and below?
# Push to the `old-version-up-to-v3.1.0.beta1` branch, update the commit hash for "3.1.0.beta1"
# in the line below and push this file to the `main` branch.
3.1.0.beta1: 1b2d7eb0369155b6442b09adfb17b8942c04b093
# Make a PR to the `old-version-up-to-v3.1.0.beta1` branch
3.1.0.beta1: old-version-up-to-v3.1.0.beta1

View File

@ -0,0 +1,72 @@
# frozen_string_literal: true
# This is the compatibility parser introduced in https://github.com/discourse/discourse/pull/22714
# It's copied here to be used as a fallback when docker_manager is running on an older Discourse version.
# Should be removed just before the Discourse 3.2 release.
module DockerManager::FallbackCompatibilityParser
def self.find_compatible_resource(version_list, target_version = ::Discourse::VERSION::STRING)
return unless version_list.present?
begin
version_list = YAML.safe_load(version_list)
rescue Psych::SyntaxError, Psych::DisallowedClass => e
end
raise Discourse::InvalidVersionListError unless version_list.is_a?(Hash)
version_list =
version_list
.transform_keys do |v|
Gem::Requirement.parse(v)
rescue Gem::Requirement::BadRequirementError => e
raise Discourse::InvalidVersionListError, "Invalid version specifier: #{v}"
end
.sort_by do |parsed_requirement, _|
operator, version = parsed_requirement
[version, operator == "<" ? 0 : 1]
end
parsed_target_version = Gem::Version.new(target_version)
lowest_matching_entry =
version_list.find do |parsed_requirement, target|
req_operator, req_version = parsed_requirement
req_operator = "<=" if req_operator == "="
if !%w[<= <].include?(req_operator)
raise Discourse::InvalidVersionListError,
"Invalid version specifier operator for '#{req_operator} #{req_version}'. Operator must be one of <= or <"
end
resolved_requirement = Gem::Requirement.new("#{req_operator} #{req_version.to_s}")
resolved_requirement.satisfied_by?(parsed_target_version)
end
return if lowest_matching_entry.nil?
checkout_version = lowest_matching_entry[1]
begin
Discourse::Utils.execute_command "git",
"check-ref-format",
"--allow-onelevel",
checkout_version
rescue RuntimeError
raise Discourse::InvalidVersionListError, "Invalid ref name: #{checkout_version}"
end
checkout_version
end
# Find a compatible resource from a git repo
def self.find_compatible_git_resource(path)
return unless File.directory?("#{path}/.git")
compat_resource, std_error, s =
Open3.capture3(
"git -C '#{path}' show HEAD@{upstream}:#{Discourse::VERSION_COMPATIBILITY_FILENAME}",
)
self.find_compatible_resource(compat_resource) if s.success?
rescue Discourse::InvalidVersionListError => e
$stderr.puts "Invalid version list in #{path}"
end
end

View File

@ -1,5 +1,7 @@
# frozen_string_literal: true
require_relative "fallback_compatibility_parser"
class DockerManager::GitRepo
attr_reader :path, :name
@ -150,7 +152,13 @@ class DockerManager::GitRepo
end
def tracking_branch
branch = Discourse.find_compatible_git_resource(path)
branch =
begin
Discourse.find_compatible_git_resource(path)
rescue ArgumentError
DockerManager::FallbackCompatibilityParser.find_compatible_git_resource(path)
end
return branch if branch.present?
head = upstream_branch

View File

@ -651,5 +651,32 @@ RSpec.describe DockerManager::GitRepo do
include_examples "common tests"
end
context "with modern discourse-compatibility file" do
let!(:clone_method) { GitHelpers::CLONE_SHALLOW }
before do
@before_local_repo_clone << -> {
@remote_git_repo.commit(
filename: ".discourse-compatibility",
commits: [{ content: "<= 1000.0.0: twoPointFiveBranch", date: "2023-03-06T20:31:17Z" }],
)
}
end
it "works" do
DockerManager::FallbackCompatibilityParser.expects(:find_compatible_resource).never
expect(subject.tracking_ref).to eq("twoPointFiveBranch")
end
it "works even in old core" do
Discourse
.stubs(:find_compatible_resource)
.with { |version_list| version_list.include?("<=") }
.raises(ArgumentError)
expect(subject.tracking_ref).to eq("twoPointFiveBranch")
end
end
end
end