Class: Match::Storage::GitLabSecureFiles

Inherits:
Interface
  • Object
show all
Defined in:
match/lib/match/storage/gitlab_secure_files.rb

Overview

Store the code signing identities in GitLab Secure Files

Constant Summary

Constants inherited from Interface

Interface::MATCH_VERSION_FILE_NAME

Instance Attribute Summary collapse

Attributes inherited from Interface

#working_directory

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Interface

#clear_changes, #configure, #save_changes!

Constructor Details

#initialize(api_v4_url: nil, project_id: nil, job_token: nil, private_token: nil, readonly: nil, username: nil, team_id: nil, team_name: nil, api_key_path: nil, api_key: nil, gitlab_host: nil) ⇒ GitLabSecureFiles

Returns a new instance of GitLabSecureFiles.



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
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 55

def initialize(api_v4_url: nil,
               project_id: nil,
               job_token: nil,
               private_token: nil,
               readonly: nil,
               username: nil,
               team_id: nil,
               team_name: nil,
               api_key_path: nil,
               api_key: nil,
               gitlab_host: nil)

  @readonly = readonly
  @username = username
  @team_id = team_id
  @team_name = team_name
  @api_key_path = api_key_path
  @api_key = api_key
  @gitlab_host = gitlab_host

  @job_token = job_token
  @private_token = private_token
  @api_v4_url = api_v4_url
  @project_id = project_id
  @gitlab_client = GitLab::Client.new(job_token: @job_token, private_token: @private_token, project_id: @project_id, api_v4_url: @api_v4_url)

  UI.message("Initializing match for GitLab project #{@project_id} on #{@gitlab_host}")
end

Instance Attribute Details

#api_keyObject (readonly)

Returns the value of attribute api_key.



24
25
26
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 24

def api_key
  @api_key
end

#api_key_pathObject (readonly)

Returns the value of attribute api_key_path.



23
24
25
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 23

def api_key_path
  @api_key_path
end

#api_v4_urlObject (readonly)

Returns the value of attribute api_v4_url.



25
26
27
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 25

def api_v4_url
  @api_v4_url
end

#gitlab_clientObject (readonly)

Returns the value of attribute gitlab_client.



17
18
19
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 17

def gitlab_client
  @gitlab_client
end

#project_idObject (readonly)

Returns the value of attribute project_id.



18
19
20
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 18

def project_id
  @project_id
end

#readonlyObject (readonly)

Returns the value of attribute readonly.



19
20
21
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 19

def readonly
  @readonly
end

#team_idObject (readonly)

Returns the value of attribute team_id.



21
22
23
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 21

def team_id
  @team_id
end

#team_nameObject (readonly)

Returns the value of attribute team_name.



22
23
24
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 22

def team_name
  @team_name
end

#usernameObject (readonly)

Returns the value of attribute username.



20
21
22
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 20

def username
  @username
end

Class Method Details

.configure(params) ⇒ Object



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
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 27

def self.configure(params)
  api_v4_url     = ENV['CI_API_V4_URL'] || "#{params[:gitlab_host]}/api/v4"
  project_id     = params[:gitlab_project] || ENV['GITLAB_PROJECT'] || ENV['CI_PROJECT_ID']
  job_token      = params[:job_token] || ENV['CI_JOB_TOKEN']
  private_token  = params[:private_token] || ENV['PRIVATE_TOKEN']

  if params[:git_url].to_s.length > 0
    UI.important("Looks like you still define a `git_url` somewhere, even though")
    UI.important("you use GitLab Secure Files. You can remove the `git_url`")
    UI.important("from your Matchfile and Fastfile")
    UI.message("The above is just a warning, fastlane will continue as usual now...")
  end

  return self.new(
    api_v4_url: api_v4_url,
    project_id: project_id,
    job_token: job_token,
    private_token: private_token,
    readonly: params[:readonly],
    username: params[:username],
    team_id: params[:team_id],
    team_name: params[:team_name],
    api_key_path: params[:api_key_path],
    api_key: params[:api_key],
    gitlab_host: params[:gitlab_host]
  )
end

Instance Method Details

#api_tokenObject



129
130
131
132
133
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 129

def api_token
  api_token = Spaceship::ConnectAPI::Token.from(hash: self.api_key, filepath: self.api_key_path)
  api_token ||= Spaceship::ConnectAPI.token
  return api_token
end

#currently_used_team_idObject



116
117
118
119
120
121
122
123
124
125
126
127
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 116

def currently_used_team_id
  if self.readonly
    # In readonly mode, we still want to see if the user provided a team_id
    # see `prefixed_working_directory` comments for more details
    return self.team_id
  else
    UI.user_error!("The `team_id` option is required. fastlane cannot automatically determine portal team id via the App Store Connect API (yet)") if self.team_id.to_s.empty?

    spaceship = SpaceshipEnsure.new(self.username, self.team_id, self.team_name, api_token)
    return spaceship.team_id
  end
end

#delete_files(files_to_delete: [], custom_message: nil) ⇒ Object



160
161
162
163
164
165
166
167
168
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 160

def delete_files(files_to_delete: [], custom_message: nil)
  files_to_delete.each do |current_file|
    target_path = current_file.gsub(self.working_directory + "/", "")

    secure_file = @gitlab_client.find_file_by_name(target_path)
    UI.message("Deleting '#{target_path}' from GitLab Secure Files...")
    secure_file.delete
  end
end

#downloadObject



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 100

def download
  gitlab_client.prompt_for_access_token

  # Check if we already have a functional working_directory
  return if @working_directory

  # No existing working directory, creating a new one now
  self.working_directory = Dir.mktmpdir

  @gitlab_client.files.each do |secure_file|
    secure_file.download(self.working_directory)
  end

  UI.verbose("Successfully downloaded all Secure Files from GitLab to #{self.working_directory}")
end

#generate_matchfile_content(template: nil) ⇒ Object

Implement this for the ‘fastlane match init` command This method must return the content of the Matchfile that should be generated



181
182
183
184
185
186
187
188
189
190
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 181

def generate_matchfile_content(template: nil)
  project = UI.input("What is your GitLab Project (i.e. gitlab-org/gitlab): ")
  host = UI.input("What is your GitLab Host (i.e. https://gitlab.example.com, skip to default to https://gitlab.com): ")

  content = "gitlab_project(\"#{project}\")"

  content += "\ngitlab_host(\"#{host}\")" if host

  return content
end

#human_readable_descriptionObject

Returns a short string describing + identifing the current storage backend. This will be printed when nuking a storage



137
138
139
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 137

def human_readable_description
  "GitLab Secure Files Storage [#{self.project_id}]"
end

#list_files(file_name: "", file_ext: "") ⇒ Object



174
175
176
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 174

def list_files(file_name: "", file_ext: "")
  Dir[File.join(working_directory, self.team_id, "**", file_name, "*.#{file_ext}")]
end

#prefixed_working_directoryObject

To make debugging easier, we have a custom exception here



85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 85

def prefixed_working_directory
  # We fall back to "*", which means certificates and profiles
  # from all teams that use this bucket would be installed. This is not ideal, but
  # unless the user provides a `team_id`, we can't know which one to use
  # This only happens if `readonly` is activated, and no `team_id` was provided
  @_folder_prefix ||= currently_used_team_id
  if @_folder_prefix.nil?
    # We use a `@_folder_prefix` variable, to keep state between multiple calls of this
    # method, as the value won't change. This way the warning is only printed once
    UI.important("Looks like you run `match` in `readonly` mode, and didn't provide a `team_id`. This will still work, however it is recommended to provide a `team_id` in your Appfile or Matchfile")
    @_folder_prefix = "*"
  end
  return File.join(working_directory, @_folder_prefix)
end

#skip_docsObject



170
171
172
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 170

def skip_docs
  true
end

#upload_files(files_to_upload: [], custom_message: nil) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'match/lib/match/storage/gitlab_secure_files.rb', line 141

def upload_files(files_to_upload: [], custom_message: nil)
  # `files_to_upload` is an array of files that need to be uploaded to GitLab Secure Files
  # Those doesn't mean they're new, it might just be they're changed
  # Either way, we'll upload them using the same technique

  files_to_upload.each do |current_file|
    # Go from
    #   "/var/folders/px/bz2kts9n69g8crgv4jpjh6b40000gn/T/d20181026-96528-1av4gge/profiles/development/Development_me.mobileprovision"
    # to
    #   "profiles/development/Development_me.mobileprovision"
    #

    # We also remove the trailing `/`
    target_file = current_file.gsub(self.working_directory + "/", "")
    UI.verbose("Uploading '#{target_file}' to GitLab Secure Files...")
    @gitlab_client.upload_file(current_file, target_file)
  end
end