#!/usr/bin/env ruby # coding: utf-8 # http://docs.gitlab.com/ee/workflow/repository_mirroring.html # https://gitlab.com/gitlab-org/gitlab-ee/issues/767 require 'net/http' require 'uri' require 'cgi' require 'json' class GitLabCE def initialize(api_uri, api_key, project_id) @api_uri = URI(api_uri) unless @api_uri.path.end_with?("/") @api_uri.path += "/" end @api_key = api_key.to_s @project_id = project_id.to_s @connections = {} @cache = {} # API docs suck, just look at `lib/api/projects.rb` @vars = [ :builds_enabled, # create | create-user | edit :container_registry_enabled, # create | | edit :default_branch # | create-user | edit :description, # create | create-user | edit :import_url, # create | create-user | :issues_enabled, # create | create-user | edit :lfs_enabled, # create | create-user | edit :merge_requests_enabled, # create | create-user | edit :name, # create | create-user | edit :namespace_id, # create | | :only_allow_merge_if_build_succeeds, # create | create-user | edit :path, # create | | edit :public, # create | create-user | edit :public_builds, # create | create-user | edit :request_access_enabled, # create | create-user | edit :shared_runners_enabled, # create | create-user | edit :snippets_enabled, # create | create-user | edit :visibility_level, # create | create-user | edit :wiki_enabled, # create | create-user | edit :only_allow_merge_if_all_discussions_are_resolved # create | create-user | edit ] @vars = [ "builds_enabled", "container_registry_enabled", "default_branch", "description", "issues_enabled", "lfs_enabled", "merge_requests_enabled", "name", "only_allow_merge_if_all_discussions_are_resolved", "only_allow_merge_if_build_succeeds", "path", "public", "public_builds", "request_access_enabled", "shared_runners_enabled", "snippets_enabled", "visibility_level", "wiki_enabled", ] end def _connection(uri) key=URI(uri.scheme+":") key.host = uri.host key.port = uri.port @connections[key] ||= Net::HTTP::start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') return @connections[key] end def _info unless @cache.has_key?(:info) req = Net::HTTP::Get.new(@api_uri + "projects/" + CGI::escape(@project_id)) req.add_field("PRIVATE-TOKEN", @api_key) con = _connection(req.uri) res = con.request(req) if res.code != "200" throw res end @cache[:info] = JSON::parse(res.body) end return @cache[:info] end def get_meta return _info.select{|k,v| @vars.include?(k)} end def set_meta(map) illegal = map.select{|k,v| not @vars.include?(k)} if illegal.count > 0 throw illegal end req = Net::HTTP::Put.new(@api_uri + "projects/" + CGI::escape(_info["id"].to_s)) req.add_field("PRIVATE-TOKEN", @api_key) req.add_field("Content-Type", "application/json") req.body = JSON::dump(map) con = _connection(req.uri) res = con.request(req) if res.code != "200" throw res end @cache[:info] = JSON::parse(res.body) return get_meta end def pushURL return _info["ssh_url_to_repo"] end def pullURL return _info["http_url_to_repo"] end def create(id, map) if map.has_key?("mirror") map["import_url"] = map["mirror"] map.delete("mirror") end req = Net::HTTP::Post.new(@api_uri + "projects") req.add_field("PRIVATE-TOKEN", @api_key) req.add_field("Content-Type", "application/json") req.body = JSON::dump(map) con = _connection(req.uri) res = con.request(req) end def capabilities return [ [ "get-meta", @vars ].flatten, [ "set-meta", @vars ].flatten, [ "push-url" ], [ "pull-url" ], ] end def finish @connections.each do |k,v| v.finish() end @connections = {} end end