Class: ReleaseManager::VCSManager::GitlabAdapter

Inherits:
VcsAdapter
  • Object
show all
Defined in:
lib/release_manager/vcs_manager/gitlab_adapter.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from VcsAdapter

#add_known_hosts_keys, #rebase_mr

Methods included from Logger

#color, #log_level, #logger

Constructor Details

#initializeGitlabAdapter

Returns a new instance of GitlabAdapter.



8
9
10
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 8

def initialize
  @client = Gitlab.client
end

Instance Attribute Details

#clientObject (readonly)

Returns the value of attribute client.



6
7
8
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 6

def client
  @client
end

Class Method Details

.createObject

creates an instance of the gitlab adapter



13
14
15
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 13

def self.create
  new
end

Instance Method Details

#add_permission(username, project_id, access_level = 20) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 48

def add_permission(username, project_id, access_level = 20)
  begin
    project_name = client.project(project_id).path_with_namespace
    user = client.user_search(username).find{|u| u.username == username}
    unless user
      logger.warn("No user found for #{username}")
      return
    end
    unless check_access?(username, project_id, access_level)
      logger.info("Adding member #{username} to project #{project_name}")
      client.add_team_member(project_id, user.id, access_level)
    end
  rescue Gitlab::Error::BadRequest => e
    # if the key is already added no need to do anything else
    logger.warn(e.message)
  end
end

#add_permissions(project_id, user_ids = [], access_level = 20) ⇒ Object



71
72
73
74
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 71

def add_permissions(project_id, user_ids = [], access_level = 20)
  user_ids ||= []  # default to empty if nil
  user_ids.map {|id| add_permission(id, project_id, access_level)}
end

#add_ssh_key(public_key_filename = nil) ⇒ Object

adds the ssh key to the user of the token

Raises:



18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 18

def add_ssh_key(public_key_filename = nil)
  public_key_filename ||= File.expand_path(File.join(ENV['HOME'], '.ssh', 'id_rsa.pub'))
  title = "#{ENV['USER']}@#{ENV['HOST']}"
  raise InvalidSshkey.new("Ssh key does not exist #{public_key_filename}") unless File.exist?(public_key_filename)
  begin
    client.create_ssh_key(title, File.read(public_key_filename))
    logger.info("Adding ssh key #{public_key_filename} to gitlab")
  rescue Gitlab::Error::BadRequest => e
    # if the key is already added no need to do anything else
    return unless e.response_status == 400
  end
end

#check_access?(username, project_id, access_level) ⇒ Boolean

Returns:

  • (Boolean)


66
67
68
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 66

def check_access?(username, project_id, access_level)
  client.team_members(project_id).find { |user| user.username == username && user.access_level == access_level}
end

#clone_repo(branch_name, mod_name, url, repos_dir) ⇒ Object



81
82
83
84
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 81

def clone_repo(branch_name, mod_name, url, repos_dir)
  path = File.join(repos_dir, mod_name)
  Rugged::Repository.clone_at(url, path, checkout_branch: branch_name)
end

#create_merge_request(url, title, options = {}) ⇒ Gitlab::ObjectifiedHash

Creates a merge request.

Examples:

create_merge_request(5, 'New merge request',
  { source_branch: 'source_branch', target_branch: 'target_branch' })
create_merge_request(5, 'New merge request',
  { source_branch: 'source_branch', target_branch: 'target_branch', assignee_id: 42 })

Parameters:

  • url (String)
    • a git url

  • title (String)

    The title of a merge request.

  • options (Hash) (defaults to: {})

    A customizable set of options.

Options Hash (options):

  • :source_branch (String) — default: required

    The source branch name.

  • :target_branch (String) — default: required

    The target branch name.

  • :assignee_id (Integer) — default: optional

    The ID of a user to assign merge request.

  • :target_project_url (Integer) — default: optional

    The target project url.

Returns:

  • (Gitlab::ObjectifiedHash)

    Information about created merge request.

Raises:

  • (ArgumentError)


160
161
162
163
164
165
166
167
168
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 160

def create_merge_request(url, title, options={})
  logger.debug("Creating merge request at #{url}")
  project = name_to_id(repo_id(url))
  options[:target_project_id] = name_to_id(repo_id(options.delete(:target_project_url))) if options[:target_project_url]
  raise ArgumentError unless options[:source_branch] and options[:target_branch]
  output = client.create_merge_request(project, title, options)
  logger.info("Merge request created: #{output.web_url}")
  output
end

#create_repo_branch(repo_id, branch_name) ⇒ Object

Returns String - the branch name that was created.

Returns:

  • String - the branch name that was created



77
78
79
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 77

def create_repo_branch(repo_id, branch_name)
  client.repo_create_branch(repo_id, branch_name)
end

#create_repo_fork(url, options = {}) ⇒ Gitlab::ObjectifiedHash

TODO verify the proposed fork does not match the upstream

Parameters:

Returns:

  • (Gitlab::ObjectifiedHash)

    Information about the forked project



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 89

def create_repo_fork(url, options = {} )
  namespace = options[:namespace] || client.user.username
  new_url = swap_namespace(url, namespace)
  repo = repo_exists?(new_url)
  unless repo or url == new_url
    upstream_repo_id = name_to_id(repo_id(url))
    logger.info("Forking project from #{url} to #{new_url}")
    repo = client.create_fork(upstream_repo_id)
    # gitlab lies about having completed the forking process, so lets sleep until it is actually done
    loop do
      sleep(1)
      break if repo_exists?(repo.ssh_url_to_repo)
    end
  end
  add_permissions(repo.id, options[:default_members])
  repo
end

#create_tag(url, tag_name, ref, message = nil, description = nil) ⇒ Gitlab::ObjectifiedHash

Parameters:

  • url (String)
    • a git url

  • tag_name (String)

    The name of the new tag.

  • ref (String)

    The ref (commit sha, branch name, or another tag) the tag will point to.

  • message (String) (defaults to: nil)

    Optional message for tag, creates annotated tag if specified.

  • description (String) (defaults to: nil)

    Optional release notes for tag.

Returns:

  • (Gitlab::ObjectifiedHash)


113
114
115
116
117
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 113

def create_tag(url, tag_name, ref, message = nil, description = nil)
  id = repo_id(url)
  logger.info("Creating tag #{tag_name} which points to #{ref}")
  client.create_tag(id, tag_name, ref, message, description)
end

#diff_2_commit(diff_obj) ⇒ Object

Parameters:

  • Array (Hash)

    the changed files in the commit or all the commits in the diff between src and dst



172
173
174
175
176
177
178
179
180
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 172

def diff_2_commit(diff_obj)
  diff_obj.map do |obj|
    {
        action: convert_status(obj[:status]),
        file_path: obj[:new_path],
        content: obj[:content]
    }
  end
end

#project_name(project_id) ⇒ Object



31
32
33
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 31

def project_name(project_id)
  client.projects(project_id)
end

#remote_tag_exists?(url, tag) ⇒ Boolean

Returns:

  • (Boolean)


200
201
202
203
204
205
206
207
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 200

def remote_tag_exists?(url, tag)
  begin
    project = name_to_id(repo_id(url))
    client.tag(project, tag)
  rescue Gitlab::Error::NotFound
    false
  end
end

#remote_tag_names(url) ⇒ Object



196
197
198
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 196

def remote_tag_names(url)
  remote_tags(url)
end

#remote_tags(url) ⇒ Object



191
192
193
194
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 191

def remote_tags(url)
  project = name_to_id(repo_id(url))
  client.tags(project).map(&:name)
end

#validate_authorizationObject

Parameters:

  • - (Boolean)

    returns true if the user has valid access by trying to access the api



36
37
38
39
40
41
42
43
44
45
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 36

def validate_authorization
  begin
    client.todos
    true
  rescue Gitlab::Error::Unauthorized
    logger.fatal "Please set the GITLAB_API_PRIVATE_TOKEN environment variable with a valid token"
    logger.fatal "Example: export GITLAB_API_PRIVATE_TOKEN=kdii2ljljijsldjfoa"
    raise InvalidToken, "The gitlab token is invalid or expired"
  end
end

#vcs_create_branch(url, name, ref) ⇒ Object

Parameters:

  • url (String)
    • a git url

  • name (String)

    The name of the new branch.

  • ref (String)

    The ref (commit sha, branch name, or another tag) the tag will point to.



185
186
187
188
189
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 185

def vcs_create_branch(url, name, ref)
  project = name_to_id(repo_id(url))
  logger.info("Creating remote branch #{name} from #{ref}")
  client.create_branch(project, name, ref)
end

#vcs_create_commit(url, branch, message, actions, options = {}) ⇒ Gitlab::ObjectifiedHash

Creates a single commit with one or more changes

create_commit(2726132, ‘master’, ‘refactors everything’, [‘create’, file_path: ‘/foo.txt’, content: ‘bar’]) create_commit(2726132, ‘master’, ‘refactors everything’, [‘delete’, file_path: ‘/foo.txt’])

Parameters:

  • url (String)
    • a git url

  • branch (String)

    the branch name you wish to commit to

  • message (String)

    the commit message

  • An (Array[Hash])

    array of action hashes to commit as a batch. See the next table for what attributes it can take.

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :author_email (String)

    the email address of the author

  • :author_name (String)

    the name of the author

Returns:

  • (Gitlab::ObjectifiedHash)

    hash of commit related data



133
134
135
136
137
138
139
140
141
142
# File 'lib/release_manager/vcs_manager/gitlab_adapter.rb', line 133

def vcs_create_commit(url, branch, message, actions, options={})
  if actions.empty?
    logger.info("Nothing to commit, no changes")
    return false
  end
  project = name_to_id(repo_id(url))
  logger.debug("Creating commit for #{url} on branch #{branch} with project id: #{project}")
  logger.info("Creating commit #{message}")
  client.create_commit(project, branch, message, actions, options)
end