Skip to content

Commit

Permalink
Merge pull request #3 from Stex/master
Browse files Browse the repository at this point in the history
Comply to errbit_plugin v0.5
  • Loading branch information
stex committed Oct 9, 2015
2 parents c0caac2 + c490e1e commit 0e58135
Show file tree
Hide file tree
Showing 11 changed files with 207 additions and 107 deletions.
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# ErrbitGitlabPlugin

TODO: Write a gem description
This gem adds Gitlab issue tracker support to Errbit.

Version 1.0 is compatible with Errbit 0.4.

For (much) older versions of Errbit, try the 0.x gem versions or consider
updating your Errbit installation

## Installation

Expand All @@ -18,7 +23,20 @@ Or install it yourself as:

## Usage

TODO: Write usage instructions here
Simply add your Gitlab URL, private token and project name to your errbit app.

You can find your private token by clicking on "Account" in your Gitlab profile settings.

Upon saving the app, the gem will automatically test if your entered
credentials are valid and inform you otherwise.

## Troubleshoot

> I entered my Gitlab settings and the tracker was saved, but I cannot create issues
The Gitlab API (at least on gitlab.com) does not seem to accept POST requests when using
a non-encrypted connection. Therefore, please make sure to use `https://` when
using gitlab.com as URL.

## Contributing

Expand Down
43 changes: 43 additions & 0 deletions app/views/errbit_gitlab_plugin/issue.md.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
[See this exception on Errbit](<%= app_problem_url problem.app, problem %>)

<% if notice = problem.notices.first %>
# <%= notice.message.lines.map(&:strip).join(' ') %>

## Summary ##
<% if notice.request['url'].present? %>
### URL ###
<%= notice.request['url'] %>
<% end %>
### Where ###
<%= notice.where %>

### Occured ###
<%= notice.created_at.to_s(:precise) %>

### Similar ###
<%= [notice.problem.notices_count - 1, 1].max %>

## Params ##
```ruby
<%= pretty_hash(notice.params).html_safe %>
```

## Session ##
```ruby
<%= pretty_hash(notice.session).html_safe %>
```

## Backtrace ##
```
<% notice.backtrace.lines.each do |line| %><%= format '%4d:', line.number %> <%= line.file_relative %> -> **<%= line.method %>**
<% end %>
```

<% if notice.env_vars.present? %>
## Environment ##
| Key | Value |
|------------|------------|
<% notice.env_vars.each do |key, val| %>| <%= key %> | <%= val %> |
<% end %>
<% end %>
<% end %>
4 changes: 2 additions & 2 deletions errbit_gitlab_plugin.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ Gem::Specification.new do |spec|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]

spec.add_runtime_dependency 'errbit_plugin', '~> 0.4', '>= 0.4.0'
spec.add_runtime_dependency 'gitlab', '~> 3.0.0', '>= 3.0.0'
spec.add_runtime_dependency 'errbit_plugin', '~> 0.5', '>= 0.5.0'
spec.add_runtime_dependency 'gitlab', '~> 3.4', '>= 3.4.0'

spec.add_development_dependency 'bundler', '~> 1.3'
spec.add_development_dependency 'rake', '~> 0'
Expand Down
6 changes: 5 additions & 1 deletion lib/errbit_gitlab_plugin.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@

module ErrbitGitlabPlugin
def self.root
File.expand_path '../..', __FILE__
Pathname.new File.expand_path('../..', __FILE__)
end

def self.read_static_file(file)
File.read(root.join('static', file))
end
end

Expand Down
191 changes: 136 additions & 55 deletions lib/errbit_gitlab_plugin/issue_tracker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,24 @@ module ErrbitGitlabPlugin
class IssueTracker < ErrbitPlugin::IssueTracker
LABEL = 'gitlab'

NOTE = ''

FIELDS = [
[:account, {
:label => "Gitlab URL",
:placeholder => "e.g. https://example.net"
}],
[:api_token, {
:placeholder => "API Token for your account"
}],
[:project_id, {
:label => "Ticket Project ID (use Number)",
:placeholder => "Gitlab Project where issues will be created"
}],
[:alt_project_id, {
:label => "Project Name (namespace/project)",
:placeholder => "Gitlab Project where issues will be created"
}]
]
NOTE = "Creating issues may take some time as the actual project ID has to be looked up using the Gitlab API. <br/>
If you are using gitlab.com as installation, please make sure to use 'https://', otherwise, their API
will not accept some of the our commands."

FIELDS = {
endpoint: {
label: 'Gitlab URL',
placeholder: 'The URL to your gitlab installation or the public gitlab server, e.g. https://www.gitlab.com'
},
api_token: {
label: 'API Token',
placeholder: "Your account's API token (see Profile -> Account)"
},
path_with_namespace: {
label: 'Project name',
placeholder: 'E.g. your_username/your_project'
}
}

def self.label
LABEL
Expand All @@ -32,66 +31,148 @@ def self.note
NOTE
end

#
# Form fields that will be presented to the administrator when setting up
# or editing the errbit app. The values we collect will be available for use
# later when we have an instance of this class.
#
def self.fields
FIELDS
end

def self.body_template
@body_template ||= ERB.new(File.read(
File.join(
ErrbitGitlabPlugin.root, 'views', 'gitlab_issues_body.txt.erb'
)
))
#
# Icons to be displayed for this issue tracker
#
def self.icons
@icons ||= {
create: ['image/png', ErrbitGitlabPlugin.read_static_file('gitlab_create.png')],
goto: ['image/png', ErrbitGitlabPlugin.read_static_file('gitlab_goto.png')],
inactive: ['image/png', ErrbitGitlabPlugin.read_static_file('gitlab_inactive.png')]
}
end

def self.summary_template
@summary_template ||= ERB.new(File.read(
File.join(
ErrbitGitlabPlugin.root, 'views', 'gitlab_issues_summary.txt.erb'
)
))
#
# Used to pass an own template to errbit's issue rendering.
# The rendered template is then passed to any #create_issue call.
#
def render_body_args
['errbit_gitlab_plugin/issue', :formats => [:md]]
end

#
# @return [String] the URL to the given project's issues section
#
def url
sprintf('%s/%s/issues', params['account'], params['alt_project_id'])
format '%s/%s/issues', options[:endpoint], options[:path_with_namespace]
end

def configured?
params['project_id'].present? && params['api_token'].present?
self.class.fields.keys.all? { |field_name| options[field_name].present? }
end

def comments_allowed?; false; end
def comments_allowed?
true
end

# Called to validate user input. Just return a hash of errors if there are any
def errors
errors = []
if self.class.fields.detect {|f| params[f[0]].blank? }
errors << [:base, 'You must specify your Gitlab URL, API token, Project ID and Project Name']
errs = []

# Make sure that every field is filled out
self.class.fields.except(:project_id).each_with_object({}) do |(field_name, field_options), h|
if options[field_name].blank?
errs << "#{field_options[:label]} must be present"
end
end

# We can only perform the other tests if the necessary values are at least present
return {:base => errs.to_sentence} unless errs.size.zero?

# Check if the given endpoint actually exists
unless gitlab_endpoint_exists?(options[:endpoint])
errs << 'No Gitlab installation was found under the given URL'
return {:base => errs.to_sentence}
end

# Check if a user by the given token exists
unless gitlab_user_exists?(options[:endpoint], options[:api_token])
errs << 'No user with the given API token was found'
return {:base => errs.to_sentence}
end

# Check if there is a project with the given name on the server
unless gitlab_project_id(options[:endpoint], options[:api_token], options[:path_with_namespace])
errs << "A project named '#{options[:path_with_namespace]}' could not be found on the server.
Please make sure to enter it exactly as it appears in your address bar in Gitlab (case sensitive)"
return {:base => errs.to_sentence}
end

{}
end

def create_issue(title, body, reported_by = nil)
ticket = with_gitlab do |g|
g.create_issue(gitlab_project_id, title, description: body, labels: 'errbit')
end
errors

format('%s/%s', url, ticket.id)
end

def create_issue(problem, reported_by = nil)
Gitlab.configure do |config|
config.endpoint = sprintf('%s/api/v3', params['account'])
config.private_token = params['api_token']
config.user_agent = 'Errbit User Agent'
private

#
# Tries to find a project with the given name in the given Gitlab installation
# and returns its ID (if any)
#
def gitlab_project_id(gitlab_url = options[:endpoint], token = options[:api_token], project = options[:path_with_namespace])
@project_id ||= with_gitlab(gitlab_url, token) do |g|
g.projects.detect { |p| p.path_with_namespace == project }.try(:id)
end
end

title = "[#{ problem.environment }][#{ problem.where }] #{problem.message.to_s.truncate(100)}"
description_summary = self.class.summary_template.result(binding)
description_body = self.class.body_template.result(binding)
#
# @return [String] a formatted APIv3 URL for the given +gitlab_url+
#
def gitlab_endpoint(gitlab_url)
format '%s/api/v3', gitlab_url
end

ticket = Gitlab.create_issue(params['project_id'], title, {
:description => description_summary,
:labels => "errbit"
})
#
# Checks whether there is a gitlab installation
# at the given +gitlab_url+
#
def gitlab_endpoint_exists?(gitlab_url)
with_gitlab(gitlab_url, 'Iamsecret') do |g|
g.user
end
rescue Gitlab::Error::Unauthorized
true
rescue Exception
false
end

Gitlab.create_issue_note(params['project_id'], ticket.id, description_body)
#
# Checks whether a user with the given +token+ exists
# in the gitlab installation located at +gitlab_url+
#
def gitlab_user_exists?(gitlab_url, private_token)
with_gitlab(gitlab_url, private_token) do |g|
g.user
end

true
rescue Gitlab::Error::Unauthorized
false
end

problem.update_attributes(
:issue_link => sprintf("%s/%s", url, ticket.id),
:issue_type => self.class.label
)
#
# Connects to the gitlab installation at +gitlab_url+
# using the given +private_token+ and executes the given block
#
def with_gitlab(gitlab_url = options[:endpoint], private_token = options[:api_token])
yield Gitlab.client(endpoint: gitlab_endpoint(gitlab_url),
private_token: private_token,
user_agent: 'Errbit User Agent')
end
end
end
2 changes: 1 addition & 1 deletion lib/errbit_gitlab_plugin/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module ErrbitGitlabPlugin
VERSION = "0.1.0"
VERSION = '1.0.0'
end
File renamed without changes
File renamed without changes
File renamed without changes
29 changes: 0 additions & 29 deletions views/gitlab_issues_body.txt.erb

This file was deleted.

17 changes: 0 additions & 17 deletions views/gitlab_issues_summary.txt.erb

This file was deleted.

0 comments on commit 0e58135

Please sign in to comment.