diff options
Diffstat (limited to 'lib/gitlab/ci/components/instance_path.rb')
-rw-r--r-- | lib/gitlab/ci/components/instance_path.rb | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/lib/gitlab/ci/components/instance_path.rb b/lib/gitlab/ci/components/instance_path.rb new file mode 100644 index 00000000000..010ce57d2a0 --- /dev/null +++ b/lib/gitlab/ci/components/instance_path.rb @@ -0,0 +1,75 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + module Components + class InstancePath + include Gitlab::Utils::StrongMemoize + + def self.match?(address) + address.include?('@') && address.start_with?(Settings.gitlab_ci['component_fqdn']) + end + + attr_reader :host + + def initialize(address:, content_filename:) + @full_path, @version = address.to_s.split('@', 2) + @content_filename = content_filename + @host = Settings.gitlab_ci['component_fqdn'] + end + + def fetch_content!(current_user:) + return unless project + return unless sha + + raise Gitlab::Access::AccessDeniedError unless Ability.allowed?(current_user, :download_code, project) + + project.repository.blob_data_at(sha, project_file_path) + end + + def project + find_project_by_component_path(instance_path) + end + strong_memoize_attr :project + + def project_file_path + return unless project + + component_dir = instance_path.delete_prefix(project.full_path) + File.join(component_dir, @content_filename).delete_prefix('/') + end + + # TODO: Add support when version is a released tag and "~latest" moving target + def sha + return unless project + + project.commit(version)&.id + end + strong_memoize_attr :sha + + private + + attr_reader :version, :path + + def instance_path + @full_path.delete_prefix(host) + end + + # Given a path like "my-org/sub-group/the-project/path/to/component" + # find the project "my-org/sub-group/the-project" by looking at all possible paths. + def find_project_by_component_path(path) + possible_paths = [path] + + while index = path.rindex('/') # find index of last `/` in a path + possible_paths << (path = path[0..index - 1]) + end + + # remove shortest path as it is group + possible_paths.pop + + ::Project.where_full_path_in(possible_paths).take # rubocop: disable CodeReuse/ActiveRecord + end + end + end + end +end |