tokite 0.4.1 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: e2fe3544c3670e931721a0ce647c8b09db335835
4
- data.tar.gz: 6ac94d96a79fa5fdaa76d81dedcdeb1c9bfb5e84
2
+ SHA256:
3
+ metadata.gz: df86e7d4a9d7b0f255b606554fc0d39e2cdbb7f949ba586c824c3137ad5342e8
4
+ data.tar.gz: e3cadbe47f0ebd104eb4dc7809061c759b47867414771f13d6c21d5a8810948a
5
5
  SHA512:
6
- metadata.gz: 46491fa456724eb6a327a35b5aca39cabca50975df29f892e390a39b13f2f749aa7d750e220801bfce026f0a63ac0de021b6fefce5e37e424bbf91d6d8a5348a
7
- data.tar.gz: 492a5efb83efa8139efc8740250ac4f21c9a603df4bbfb845425b041cc592cbb7141268b775da0c008965efd3b6326ba1262cb0bcc791b29896685eb4af87b51
6
+ metadata.gz: fc465032bf4171b089fffef510ecad969418839242197c10409fa0902a4628b6ad94d1008446d63110fef169bad18d1b6797190403d1aa6ac77921cc99f26787
7
+ data.tar.gz: 14d7fc592455556266150de2a22d6f6f8323268db806e36d34d9bef381efb35ed57f3b0196d640a2da50afe3e7cb4dfd0808bee964b9327c9375e4559702e770
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Tokite [![CircleCI](https://circleci.com/gh/cookpad/tokite.svg?style=svg)](https://circleci.com/gh/cookpad/tokite) [![Gem Version](https://badge.fury.io/rb/tokite.svg)](https://badge.fury.io/rb/tokite)
1
+ # Tokite [![Gem Version](https://badge.fury.io/rb/tokite.svg)](https://badge.fury.io/rb/tokite)
2
2
 
3
3
  Tokite send GitHub event (pull-request, issue and comment) to Slack.
4
4
 
@@ -35,8 +35,8 @@ $ ./bin/rails tokite:yarn:install
35
35
 
36
36
  ## Configuration
37
37
  <table>
38
- <tr><th>GITHUB_CLIENT_ID</th><td>Google+ OAuth2 client ID</td></tr>
39
- <tr><th>GITHUB_CLIENT_SECRET</th><td>Google+ OAuth2 client secret</td></tr>
38
+ <tr><th>GITHUB_CLIENT_ID</th><td>GitHub OAuth2 client ID</td></tr>
39
+ <tr><th>GITHUB_CLIENT_SECRET</th><td>GitHub OAuth2 client secret</td></tr>
40
40
  <tr><th>GITHUB_HOST (optional)</th><td>GitHub Enterprise host</td></tr>
41
41
  <tr><th>SECRET_KEY_BASE</th><td><code>rails secret</code> key</td></tr>
42
42
  <tr><th>SLACK_WEBHOOK_URL</th><td>Slack incoming webhook url</td></tr>
@@ -73,6 +73,9 @@ Tokite support only below events now.
73
73
  <tr><td>event:</td><td>Match event type pull_request, issues, issue_comment, pull_request_review, pull_request_review_comment.</td><td>event:/pull_request|issues|pull_request_review|pull_request_review_comment/</td></tr>
74
74
  <tr><td>body:</td><td>Match body text.</td><td>body:"review please"</td></tr>
75
75
  <tr><td>user:</td><td>Match user name.</td><td>user:hogelog</td></tr>
76
+ <tr><td>label:</td><td>Match pull_request or issue label.</td><td>label:Feature</td></tr>
76
77
  <tr><td>review_state:</td><td>Match pull_request_review state.</td><td>review_state:/commented|approved|changes_requested/</td></tr>
78
+ <tr><td>requested_reviewer:</td><td>Match user name of review requested reviewer</td><td>requested_reviewer:hogelog</td></tr>
79
+ <tr><td>requested_team:</td><td>Match team name of review requested team</td><td>requested_team:cookpad/chef</td></tr>
77
80
  <tr><td>unspecified</td><td>Match title or body field.</td><td>review please</td></tr>
78
81
  </table>
@@ -1,6 +1,6 @@
1
1
  @import "bulma/sass/utilities/initial-variables";
2
2
 
3
- // Bootstrap like colors
3
+ // Bootstrap-like colors
4
4
  $white: #fff;
5
5
  $black: #000;
6
6
  $red: #d9534f;
@@ -21,7 +21,3 @@ $dark: $grey-darker;
21
21
  $text: $grey-dark;
22
22
 
23
23
  @import "bulma/bulma";
24
-
25
- .vspace-40 {
26
- margin: 40px 0;
27
- }
@@ -7,9 +7,12 @@ module Tokite
7
7
  end
8
8
 
9
9
  def new
10
- github_repos = octokit_client.repositories.select{|r| r.permissions.admin }.delete_if(&:fork)
10
+ github_repos = octokit_client.repositories.
11
+ select{|r| r.permissions.admin }.
12
+ delete_if(&:fork).
13
+ delete_if(&:archived)
11
14
  @repositories = github_repos.map do |repo|
12
- Repository.new(name: repo.full_name, url: repo.html_url)
15
+ Repository.new(name: repo.full_name, url: repo.html_url, private: repo.private)
13
16
  end
14
17
  Repository.all.pluck(:name).each do |existing_name|
15
18
  @repositories.delete_if {|repo| repo.name == existing_name }
@@ -17,11 +20,22 @@ module Tokite
17
20
  end
18
21
 
19
22
  def create
20
- params[:names].each do |name|
21
- github_repo = octokit_client.repository(name)
22
- Repository.hook!(octokit_client, github_repo)
23
+ if params[:names].nil?
24
+ flash[:error] = "Error: No repository was selected"
25
+ else
26
+ github_repos = params[:names].map do |name|
27
+ octokit_client.repository(name)
28
+ end
29
+ errors = github_repos.select(&:archived).map(&:full_name)
30
+ if errors != []
31
+ flash[:error] = %(Error: The following repositories have been archived: #{errors.join(", ")})
32
+ else
33
+ github_repos.each do |repo|
34
+ Repository.hook!(octokit_client, repo)
35
+ end
36
+ flash[:info] = "Import repositories."
37
+ end
23
38
  end
24
- flash[:info] = "Import repositories."
25
39
  redirect_to repositories_path
26
40
  end
27
41
 
@@ -46,7 +46,7 @@ module Tokite
46
46
  private
47
47
 
48
48
  def rule_params
49
- params.require(:rule).permit(:user_id, :name, :query, :channel, :icon_emoji, :additional_text)
49
+ params.require(:rule).permit(:user_id, :name, :query, :channel, :icon_emoji, :additional_text, :display_name)
50
50
  end
51
51
  end
52
52
  end
@@ -2,9 +2,9 @@ module Tokite
2
2
  module ApplicationHelper
3
3
  def nav_list_item(name, path, controllers)
4
4
  if controllers.include?(params[:controller])
5
- link_to(name, path, class: "nav-item is-tab is-active")
5
+ link_to(name, path, class: "navbar-item is-tab is-active")
6
6
  else
7
- link_to(name, path, class: "nav-item is-tab")
7
+ link_to(name, path, class: "navbar-item is-tab")
8
8
  end
9
9
  end
10
10
 
@@ -32,6 +32,7 @@ module Tokite
32
32
  if payloads.none? {|payload| payload[:channel] == rule.channel && payload[:emoji] == emoji && payload[:additional_text] == additional_text }
33
33
  payloads << {
34
34
  channel: rule.channel,
35
+ username: rule.display_name.presence || "tokite",
35
36
  text: event.slack_text,
36
37
  emoji: emoji,
37
38
  additional_text: additional_text,
@@ -40,8 +41,22 @@ module Tokite
40
41
  end
41
42
  end
42
43
  payloads.each do |payload|
43
- notify!(channel: payload[:channel], text: payload[:text], icon_emoji: payload[:emoji], attachments: payload[:attachments])
44
- notify!(channel: payload[:channel], text: payload[:additional_text], icon_emoji: payload[:emoji], parse: "full") if payload[:additional_text].present?
44
+ notify!(
45
+ channel: payload[:channel],
46
+ text: payload[:text],
47
+ icon_emoji: payload[:emoji],
48
+ attachments: payload[:attachments],
49
+ username: payload[:username]
50
+ )
51
+ if payload[:additional_text].present?
52
+ notify!(
53
+ channel: payload[:channel],
54
+ text: payload[:additional_text],
55
+ icon_emoji: payload[:emoji],
56
+ parse: "full",
57
+ username: payload[:username]
58
+ )
59
+ end
45
60
  end
46
61
  end
47
62
 
@@ -7,17 +7,18 @@ module Tokite
7
7
  repo: hook_params[:repository][:full_name],
8
8
  body: hook_params[:comment][:body],
9
9
  user: hook_params[:comment][:user][:login],
10
+ label: hook_params[:issue][:labels].map { |label| label[:name] },
10
11
  }
11
12
  end
12
-
13
+
13
14
  def notify?
14
15
  %w(created).include?(hook_params[:action])
15
16
  end
16
-
17
+
17
18
  def slack_text
18
19
  "[#{hook_params[:repository][:full_name]}] New comment by #{hook_params[:comment][:user][:login]} on issue <#{hook_params[:comment][:html_url]}|##{hook_params[:issue][:number]}: #{hook_params[:issue][:title]}>"
19
20
  end
20
-
21
+
21
22
  def slack_attachment
22
23
  {
23
24
  fallback: hook_params[:comment][:body],
@@ -6,8 +6,9 @@ module Tokite
6
6
  event: "issues",
7
7
  repo: hook_params[:repository][:full_name],
8
8
  title: hook_params[:issue][:title],
9
- body: hook_params[:issue][:body],
9
+ body: hook_params[:issue][:body] || "",
10
10
  user: hook_params[:issue][:user][:login],
11
+ label: hook_params[:issue][:labels].map { |label| label[:name] },
11
12
  }
12
13
  end
13
14
 
@@ -24,7 +25,7 @@ module Tokite
24
25
  title: "##{hook_params[:issue][:number]} #{hook_params[:issue][:title]}",
25
26
  title_link: hook_params[:issue][:html_url],
26
27
  fallback: "#{hook_params[:issue][:title]}\n#{hook_params[:issue][:body]}",
27
- text: hook_params[:issue][:body],
28
+ text: hook_params[:issue][:body] || "",
28
29
  color: "good",
29
30
  }
30
31
  end
@@ -8,15 +8,32 @@ module Tokite
8
8
  title: hook_params[:pull_request][:title],
9
9
  body: hook_params[:pull_request][:body],
10
10
  user: hook_params[:pull_request][:user][:login],
11
+ label: hook_params[:pull_request][:labels].map { |label| label[:name] },
12
+ requested_reviewer: hook_params[:requested_reviewer]&.[](:login) || hook_params[:pull_request][:requested_reviewers].map { |reviewer| reviewer[:login] },
13
+ requested_team: hook_params[:pull_request][:requested_teams].map { |team| parse_team_name(team) },
11
14
  }
12
15
  end
13
16
 
17
+ def parse_team_name(team)
18
+ html_url = team[:html_url]
19
+ if /\/orgs\/(?<org_name>[^\s\/]+)\/teams\/(?<team_name>[^\s\/]+)\z/ =~ html_url
20
+ org_name + "/" + team_name
21
+ else
22
+ team[:slug] || team[:name]
23
+ end
24
+ end
25
+
14
26
  def notify?
15
- %w(opened).include?(hook_params[:action])
27
+ %w(opened review_requested).include?(hook_params[:action])
16
28
  end
17
29
 
18
30
  def slack_text
19
- "[#{hook_params[:repository][:full_name]}] Pull request submitted by <#{hook_params[:pull_request][:user][:html_url]}|#{hook_params[:pull_request][:user][:login]}>"
31
+ case hook_params[:action]
32
+ when 'opened'
33
+ "[#{hook_params[:repository][:full_name]}] Pull request submitted by <#{hook_params[:pull_request][:user][:html_url]}|#{hook_params[:pull_request][:user][:login]}>"
34
+ when 'review_requested'
35
+ "[#{hook_params[:repository][:full_name]}] Pull request review requested by <#{hook_params[:pull_request][:user][:html_url]}|#{hook_params[:pull_request][:user][:login]}>"
36
+ end
20
37
  end
21
38
 
22
39
  def slack_attachment
@@ -5,16 +5,17 @@ module Tokite
5
5
  {
6
6
  event: "pull_request_review",
7
7
  repo: hook_params[:repository][:full_name],
8
- body: hook_params[:review][:body],
8
+ body: hook_params[:review][:body] || "",
9
9
  user: hook_params[:review][:user][:login],
10
10
  review_state: hook_params[:review][:state],
11
11
  }
12
12
  end
13
13
 
14
14
  def notify?
15
- return false unless hook_params[:action] == "submitted"
16
- if hook_params[:review][:state] == "commented"
17
- hook_params[:review][:body]
15
+ if hook_params[:action] != "submitted"
16
+ false
17
+ elsif hook_params[:review][:state] == "commented"
18
+ hook_params[:review][:body] != nil
18
19
  else
19
20
  true
20
21
  end
@@ -35,7 +36,6 @@ module Tokite
35
36
  end
36
37
 
37
38
  def slack_attachment
38
- return unless hook_params[:review][:body]
39
39
  case hook_params[:review][:state]
40
40
  when "commented"
41
41
  when "approved"
@@ -44,8 +44,8 @@ module Tokite
44
44
  color = "warning"
45
45
  end
46
46
  {
47
- fallback: hook_params[:review][:body],
48
- text: hook_params[:review][:body],
47
+ fallback: hook_params[:review][:body] || "",
48
+ text: hook_params[:review][:body] || "",
49
49
  color: color,
50
50
  }
51
51
  end
@@ -47,8 +47,8 @@ module Tokite
47
47
  private
48
48
 
49
49
  def validate_query
50
- SearchQuery.parse(query)
51
- rescue SearchQuery::ParseError => e
50
+ SearchQuery.validate(query)
51
+ rescue SearchQuery::QueryError => e
52
52
  errors.add(:query, e.message)
53
53
  end
54
54
 
@@ -6,7 +6,11 @@ module Tokite
6
6
 
7
7
  DEFAULT_FIELDS = %i(title body)
8
8
 
9
- class ParseError < StandardError
9
+ class QueryError < StandardError
10
+ end
11
+ class QueryParseError < QueryError
12
+ end
13
+ class QueryRegexpError < QueryError
10
14
  end
11
15
 
12
16
  class Parser < Parslet::Parser
@@ -37,7 +41,16 @@ module Tokite
37
41
  def self.parse(query)
38
42
  Array.wrap(parser.parse(query))
39
43
  rescue Parslet::ParseFailed => e
40
- raise ParseError, e
44
+ raise QueryParseError, e
45
+ end
46
+
47
+ def self.validate(query)
48
+ tree = SearchQuery.parse(query)
49
+ tree.each do |word|
50
+ Regexp.compile(word[:regexp_word].to_s, Regexp::IGNORECASE) if word[:regexp_word]
51
+ end
52
+ rescue RegexpError => e
53
+ raise QueryRegexpError, e
41
54
  end
42
55
 
43
56
  def initialize(query)
@@ -49,13 +62,25 @@ module Tokite
49
62
  tree.all? do |word|
50
63
  field = word[:field]
51
64
  if field
52
- targets = doc[field.to_sym] ? [doc[field.to_sym].downcase] : []
65
+ targets =
66
+ case doc[field.to_sym]
67
+ when Array
68
+ doc[field.to_sym].map(&:downcase)
69
+ when nil
70
+ []
71
+ else
72
+ [doc[field.to_sym].downcase]
73
+ end
53
74
  else
54
75
  targets = DEFAULT_FIELDS.map{|field| doc[field]&.downcase }.compact
55
76
  end
56
77
  if word[:regexp_word]
57
- regexp = Regexp.compile(word[:regexp_word].to_s, Regexp::IGNORECASE)
58
- matched = targets.any?{|text| regexp.match?(text) }
78
+ begin
79
+ regexp = Regexp.compile(word[:regexp_word].to_s, Regexp::IGNORECASE)
80
+ matched = targets.any?{|text| regexp.match?(text) }
81
+ rescue RegexpError
82
+ matched = false
83
+ end
59
84
  else
60
85
  value = word[:word].to_s.downcase
61
86
  matched = targets.any?{|text| text.index(value) }
@@ -9,17 +9,19 @@
9
9
 
10
10
  %body
11
11
  - if current_user
12
- %nav.nav.has-shadow
13
- .container
14
- .nav-left
12
+ %nav.navbar.has-shadow
13
+ .navbar-menu.is-active
14
+ .navbar-start
15
15
  = nav_list_item "Top", root_path, ["top"]
16
16
  = nav_list_item "Users", users_path, ["users"]
17
17
  = nav_list_item "Rules", rules_path, ["rules"]
18
18
  = nav_list_item "Repositories", repositories_path, ["repositories"]
19
- .nav-right
20
- %span.nav-item.is-tab= current_user.name_with_provider
19
+ .navbar-end
20
+ %span.navbar-item= current_user.name_with_provider
21
21
 
22
22
  %section.section
23
+ - if flash[:error]
24
+ .notification.is-danger= flash[:error]
23
25
  - if flash[:info]
24
26
  .notification.is-success= flash[:info]
25
27
 
@@ -1,11 +1,11 @@
1
1
  - if current_user_token
2
2
  = link_to "Watch new repositories", new_repository_path, class: "button is-primary"
3
3
 
4
- .vspace-40
4
+ .my-6
5
5
 
6
6
  %h1.title Watching repositories
7
7
 
8
- %table.table.is-bordered
8
+ %table.table.is-bordered.is-hoverable
9
9
  - @repositories.each do |repo|
10
10
  %tr
11
11
  %td= link_to repo.name, repo.url
@@ -7,9 +7,11 @@
7
7
  %label.checkbox
8
8
  = check_box_tag "names[]", repo.name, false, id: "names_#{sanitize_to_id(repo.name)}", multiple: true
9
9
  = repo.name
10
+ - if repo.private?
11
+ %span.tag.is-danger{style: "height: 1.5em"} private
10
12
  = link_to "@", repo.url
11
13
 
12
- .vspace-40
14
+ .my-6
13
15
 
14
16
  .field
15
17
  .control
@@ -4,13 +4,14 @@
4
4
  = form_text_field f, :channel, size: 40, class: "input"
5
5
  = form_text_field f, :icon_emoji, size: 40, class: "input"
6
6
  = form_text_field f, :additional_text, size: 40, class: "input"
7
+ = form_text_field f, :display_name, size: 40, class: "input"
7
8
  .field.columns
8
9
  .column.is-8= f.submit "Update", class: "button is-primary"
9
10
  - if @rule.persisted?
10
11
  .column.is-2= link_to "Transfer", new_rule_transfers_path(@rule), class: "button is-primary"
11
12
  .column.is-2= link_to "Delete", rule_path(@rule), method: :delete, data: { confirm: %(Delete "#{@rule.name}"?) }, class: "button is-danger"
12
13
 
13
- .message.vspace-40
14
+ .message.my-6
14
15
  .message-header
15
16
  Query description
16
17
  .message-body
@@ -58,10 +59,22 @@
58
59
  %td user:
59
60
  %td Match user name.
60
61
  %td user:hogelog
62
+ %tr
63
+ %td label:
64
+ %td Match pull_request or issue label.
65
+ %td label:Feature
61
66
  %tr
62
67
  %td review_state:
63
68
  %td Match pull_request_review state.
64
69
  %td review_state:/commented|approved|changes_requested/
70
+ %tr
71
+ %td requested_reviewer:
72
+ %td Match user name of review requested reviewer.
73
+ %td requested_reviewer:hogelog
74
+ %tr
75
+ %td requested_team:
76
+ %td Match team name of review requested team.
77
+ %td requested_team:cookpad/chef
65
78
  %tr
66
79
  %td unspecified
67
80
  %td Match title or body field.
@@ -1,3 +1,3 @@
1
1
  module Tokite
2
- VERSION = '0.4.1'
2
+ VERSION = '0.5.1'
3
3
  end
@@ -2,6 +2,7 @@ create_table "tokite_repositories", force: :cascade do |t|
2
2
  t.string "name", limit: 200, null: false
3
3
  t.string "url", limit: 200, null: false
4
4
  t.datetime "created_at", null: false
5
+ t.boolean "private", null: false, default: false
5
6
  end
6
7
 
7
8
  add_index "tokite_repositories", ["name"], name: "tokite_repositories_uniq_name", unique: true, using: :btree
@@ -3,10 +3,11 @@ create_table "tokite_rules", force: :cascade do |t|
3
3
  t.string "name", limit: 50, null: false
4
4
  t.string "query", limit: 2000, null: false
5
5
  t.string "channel", limit: 100, null: false
6
- t.string "icon_emoji", limit: 20, null: false, default: ""
6
+ t.string "icon_emoji", limit: 30, null: false, default: ""
7
7
  t.string "additional_text", limit: 200, null: false, default: ""
8
8
  t.datetime "created_at", null: false
9
9
  t.datetime "updated_at", null: false
10
+ t.string "display_name", limit: 60, null: false, default: ""
10
11
  end
11
12
 
12
13
  add_index "tokite_rules", ["user_id", "name"], name: "tokite_rule_uniq_name", unique: true, using: :btree
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tokite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - hogelog
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-12 00:00:00.000000000 Z
11
+ date: 2023-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,14 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 5.1.1
19
+ version: '5.2'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 5.2.8.1
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
- version: 5.1.1
29
+ version: '5.2'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 5.2.8.1
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: pg
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -44,14 +50,14 @@ dependencies:
44
50
  requirements:
45
51
  - - "~>"
46
52
  - !ruby/object:Gem::Version
47
- version: '5.0'
53
+ version: '5.1'
48
54
  type: :runtime
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
51
57
  requirements:
52
58
  - - "~>"
53
59
  - !ruby/object:Gem::Version
54
- version: '5.0'
60
+ version: '5.1'
55
61
  - !ruby/object:Gem::Dependency
56
62
  name: haml
57
63
  requirement: !ruby/object:Gem::Requirement
@@ -156,14 +162,14 @@ dependencies:
156
162
  requirements:
157
163
  - - ">="
158
164
  - !ruby/object:Gem::Version
159
- version: '0'
165
+ version: 3.9.0
160
166
  type: :development
161
167
  prerelease: false
162
168
  version_requirements: !ruby/object:Gem::Requirement
163
169
  requirements:
164
170
  - - ">="
165
171
  - !ruby/object:Gem::Version
166
- version: '0'
172
+ version: 3.9.0
167
173
  - !ruby/object:Gem::Dependency
168
174
  name: factory_bot_rails
169
175
  requirement: !ruby/object:Gem::Requirement
@@ -255,7 +261,7 @@ homepage: https://github.com/cookpad/tokite/
255
261
  licenses:
256
262
  - MIT
257
263
  metadata: {}
258
- post_install_message:
264
+ post_install_message:
259
265
  rdoc_options: []
260
266
  require_paths:
261
267
  - lib
@@ -270,9 +276,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
270
276
  - !ruby/object:Gem::Version
271
277
  version: '0'
272
278
  requirements: []
273
- rubyforge_project:
274
- rubygems_version: 2.6.11
275
- signing_key:
279
+ rubygems_version: 3.1.6
280
+ signing_key:
276
281
  specification_version: 4
277
282
  summary: Customizable Slack notification from GitHub
278
283
  test_files: []