1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
# frozen_string_literal: true
module Gitlab
module Ci
class Config
module External
module File
class Project < Base
extend ::Gitlab::Utils::Override
include Gitlab::Utils::StrongMemoize
attr_reader :project_name, :ref_name
def initialize(params, context)
@location = params[:file]
@project_name = get_project_name(params[:project])
@ref_name = params[:ref] || 'HEAD'
super
end
def matching?
super && project_name.present?
end
def content
strong_memoize(:content) { fetch_local_content }
end
def metadata
super.merge(
type: :file,
location: masked_location,
blob: masked_blob,
raw: masked_raw,
extra: { project: masked_project_name, ref: masked_ref_name }
)
end
private
def validate_context!
if !can_access_local_content?
errors.push("Project `#{masked_project_name}` not found or access denied! Make sure any includes in the pipeline configuration are correctly defined.")
elsif sha.nil?
errors.push("Project `#{masked_project_name}` reference `#{masked_ref_name}` does not exist!")
end
end
def validate_content!
if content.nil?
errors.push("Project `#{masked_project_name}` file `#{masked_location}` does not exist!")
elsif content.blank?
errors.push("Project `#{masked_project_name}` file `#{masked_location}` is empty!")
end
end
def project
strong_memoize(:project) do
::Project.find_by_full_path(project_name)
end
end
def can_access_local_content?
strong_memoize(:can_access_local_content) do
context.logger.instrument(:config_file_project_validate_access) do
Ability.allowed?(context.user, :download_code, project)
end
end
end
def fetch_local_content
return unless can_access_local_content?
return unless sha
context.logger.instrument(:config_file_fetch_project_content) do
project.repository.blob_data_at(sha, location)
end
rescue GRPC::NotFound, GRPC::Internal
nil
end
def sha
return unless project
strong_memoize(:sha) do
project.commit(ref_name).try(:sha)
end
end
override :expand_context_attrs
def expand_context_attrs
{
project: project,
sha: sha,
user: context.user,
parent_pipeline: context.parent_pipeline,
variables: context.variables
}
end
def masked_project_name
strong_memoize(:masked_project_name) do
context.mask_variables_from(project_name)
end
end
def masked_ref_name
strong_memoize(:masked_ref_name) do
context.mask_variables_from(ref_name)
end
end
def masked_blob
return unless project
strong_memoize(:masked_blob) do
context.mask_variables_from(
Gitlab::Routing.url_helpers.project_blob_url(project, ::File.join(sha, location))
)
end
end
def masked_raw
return unless project
strong_memoize(:masked_raw) do
context.mask_variables_from(
Gitlab::Routing.url_helpers.project_raw_url(project, ::File.join(sha, location))
)
end
end
# TODO: To be removed after we deprecate usage of array in `project` keyword.
# https://gitlab.com/gitlab-org/gitlab/-/issues/365975
def get_project_name(project_name)
if project_name.is_a?(Array)
project_name.first
else
project_name
end
end
end
end
end
end
end
end
|