ruboty-qiita-github 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/dependabot.yml +11 -0
- data/.github/workflows/test.yml +37 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +9 -0
- data/.rubocop_todo.yml +84 -0
- data/CHANGELOG.md +15 -0
- data/Gemfile +2 -0
- data/README.md +3 -0
- data/Rakefile +2 -1
- data/lib/ruboty/github/actions/base.rb +10 -9
- data/lib/ruboty/github/actions/close_issue.rb +10 -9
- data/lib/ruboty/github/actions/create_deploy_pull_request.rb +28 -20
- data/lib/ruboty/github/actions/create_issue.rb +6 -4
- data/lib/ruboty/github/actions/create_pull_request.rb +20 -11
- data/lib/ruboty/github/actions/merge_pull_request.rb +2 -0
- data/lib/ruboty/github/actions/remember.rb +2 -0
- data/lib/ruboty/github/actions/search_issues.rb +43 -0
- data/lib/ruboty/github/version.rb +3 -1
- data/lib/ruboty/github.rb +15 -12
- data/lib/ruboty/handlers/github.rb +28 -16
- data/ruboty-github.gemspec +23 -17
- data/spec/ruboty/handlers/github_spec.rb +82 -46
- data/spec/spec_helper.rb +5 -4
- metadata +81 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: caf076de8647564c4cf76b70a6e79068e26a1cf64a9d317c0ff2954db458aca6
|
4
|
+
data.tar.gz: 13e155d2450644cd6277502e9b8024e4a0521573cc21655a22ad289b60575071
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dacf9494aa6a174e25a6ce677016d8d38462a23b92b7636f92aa8b5a6763fb6cd9729de624e7234a0c1b7969534d6c0e49c5c04b5bbda8c821658b4e6e5014a5
|
7
|
+
data.tar.gz: 74ea9024b5403dbba94ab085145b50dfadf4a439800884c6539cfc33e2f7d7afadf84c8d5787316917f2d9ff72d59c600dc568b52101858bb1d15cbfe77438ba
|
@@ -0,0 +1,37 @@
|
|
1
|
+
name: Test
|
2
|
+
|
3
|
+
on:
|
4
|
+
pull_request:
|
5
|
+
push:
|
6
|
+
branches:
|
7
|
+
- master
|
8
|
+
workflow_dispatch:
|
9
|
+
|
10
|
+
permissions:
|
11
|
+
contents: read
|
12
|
+
|
13
|
+
jobs:
|
14
|
+
rspec:
|
15
|
+
strategy:
|
16
|
+
fail-fast: false
|
17
|
+
matrix:
|
18
|
+
ruby: ["2.7", "3.0", "3.1"]
|
19
|
+
runs-on: "ubuntu-latest"
|
20
|
+
continue-on-error: false
|
21
|
+
steps:
|
22
|
+
- uses: actions/checkout@v3
|
23
|
+
- uses: ruby/setup-ruby@v1
|
24
|
+
with:
|
25
|
+
ruby-version: ${{ matrix.ruby }}
|
26
|
+
bundler-cache: true
|
27
|
+
- run: bundle exec rspec
|
28
|
+
|
29
|
+
rubocop:
|
30
|
+
runs-on: "ubuntu-latest"
|
31
|
+
steps:
|
32
|
+
- uses: actions/checkout@v3
|
33
|
+
- uses: ruby/setup-ruby@v1
|
34
|
+
with:
|
35
|
+
ruby-version: "3.1"
|
36
|
+
bundler-cache: true
|
37
|
+
- run: bundle exec rubocop
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config --exclude-limit 99999`
|
3
|
+
# on 2022-10-12 04:57:08 UTC using RuboCop version 1.36.0.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 1
|
10
|
+
# Configuration parameters: Include.
|
11
|
+
# Include: **/*.gemspec
|
12
|
+
Gemspec/RequiredRubyVersion:
|
13
|
+
Exclude:
|
14
|
+
- 'ruboty-github.gemspec'
|
15
|
+
|
16
|
+
# Offense count: 1
|
17
|
+
Lint/UnreachableCode:
|
18
|
+
Exclude:
|
19
|
+
- 'lib/ruboty/github/actions/close_issue.rb'
|
20
|
+
|
21
|
+
# Offense count: 1
|
22
|
+
# Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods, CountRepeatedAttributes.
|
23
|
+
Metrics/AbcSize:
|
24
|
+
Max: 24
|
25
|
+
|
26
|
+
# Offense count: 2
|
27
|
+
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, AllowedMethods, AllowedPatterns, IgnoredMethods.
|
28
|
+
Metrics/MethodLength:
|
29
|
+
Max: 14
|
30
|
+
|
31
|
+
# Offense count: 2
|
32
|
+
# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros.
|
33
|
+
# NamePrefix: is_, has_, have_
|
34
|
+
# ForbiddenPrefixes: is_, has_, have_
|
35
|
+
# AllowedMethods: is_a?
|
36
|
+
# MethodDefinitionMacros: define_method, define_singleton_method
|
37
|
+
Naming/PredicateName:
|
38
|
+
Exclude:
|
39
|
+
- 'spec/**/*'
|
40
|
+
- 'lib/ruboty/github/actions/base.rb'
|
41
|
+
- 'lib/ruboty/github/actions/close_issue.rb'
|
42
|
+
|
43
|
+
# Offense count: 3
|
44
|
+
# Configuration parameters: .
|
45
|
+
# SupportedStyles: have_received, receive
|
46
|
+
RSpec/MessageSpies:
|
47
|
+
EnforcedStyle: receive
|
48
|
+
|
49
|
+
# Offense count: 2
|
50
|
+
RSpec/MultipleExpectations:
|
51
|
+
Max: 2
|
52
|
+
|
53
|
+
# Offense count: 11
|
54
|
+
# Configuration parameters: AllowSubject.
|
55
|
+
RSpec/MultipleMemoizedHelpers:
|
56
|
+
Max: 13
|
57
|
+
|
58
|
+
# Offense count: 1
|
59
|
+
RSpec/NoExpectationExample:
|
60
|
+
Exclude:
|
61
|
+
- 'spec/ruboty/handlers/github_spec.rb'
|
62
|
+
|
63
|
+
# Offense count: 9
|
64
|
+
# Configuration parameters: AllowedConstants.
|
65
|
+
Style/Documentation:
|
66
|
+
Exclude:
|
67
|
+
- 'spec/**/*'
|
68
|
+
- 'test/**/*'
|
69
|
+
- 'lib/ruboty/github/actions/base.rb'
|
70
|
+
- 'lib/ruboty/github/actions/close_issue.rb'
|
71
|
+
- 'lib/ruboty/github/actions/create_deploy_pull_request.rb'
|
72
|
+
- 'lib/ruboty/github/actions/create_issue.rb'
|
73
|
+
- 'lib/ruboty/github/actions/create_pull_request.rb'
|
74
|
+
- 'lib/ruboty/github/actions/merge_pull_request.rb'
|
75
|
+
- 'lib/ruboty/github/actions/remember.rb'
|
76
|
+
- 'lib/ruboty/github/actions/search_issues.rb'
|
77
|
+
- 'lib/ruboty/handlers/github.rb'
|
78
|
+
|
79
|
+
# Offense count: 1
|
80
|
+
# This cop supports safe autocorrection (--autocorrect).
|
81
|
+
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, IgnoredPatterns.
|
82
|
+
# URISchemes: http, https
|
83
|
+
Layout/LineLength:
|
84
|
+
Max: 148
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,18 @@
|
|
1
|
+
## Unreleased
|
2
|
+
|
3
|
+
## 0.3.0
|
4
|
+
- Fix a bug that deploy pr messages trigger other actions also
|
5
|
+
- Warn when deployment pull request includes database migration
|
6
|
+
- Refactor CreateDeployPullRequest
|
7
|
+
- Add `search issues` command
|
8
|
+
- Support test on GitHub Actions
|
9
|
+
- Add rubocop, rubocop-rake, rubocop-performance, rubocop-rspec gems
|
10
|
+
- Use rubocop autocorrect and modify the code
|
11
|
+
- Added "search issues" description and status badge to README.md
|
12
|
+
|
13
|
+
## 0.2.3
|
14
|
+
- Fix typo
|
15
|
+
|
1
16
|
## 0.2.2
|
2
17
|
- Fix a bug about pull request user
|
3
18
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
# Ruboty::Github
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/ruboty-qiita-github.svg)](https://badge.fury.io/rb/ruboty-qiita-github) [![Test](https://github.com/increments/ruboty-qiita-github/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/increments/ruboty-qiita-github/actions/workflows/test.yml) [![Maintainability](https://api.codeclimate.com/v1/badges/764bf9dc5796f0d3bef3/maintainability)](https://codeclimate.com/github/increments/ruboty-qiita-github/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/764bf9dc5796f0d3bef3/test_coverage)](https://codeclimate.com/github/increments/ruboty-qiita-github/test_coverage)
|
3
|
+
|
2
4
|
Manage GitHub via Ruboty.
|
3
5
|
This gem adds `deploy pull request` command to original ruboty-github plugin.
|
4
6
|
|
@@ -16,6 +18,7 @@ gem "ruboty-github"
|
|
16
18
|
@ruboty pull request "<title>" from <from> to <to> - Create a new Pull Request
|
17
19
|
@ruboty deploy pull request "<title>" from <from> to <to> - Create a new Pull Request for Deploy
|
18
20
|
@ruboty remember my github token <token> - Remember sender's GitHub access token
|
21
|
+
@ruboty search issues "<query>" - Search an Issues/Pull Requests
|
19
22
|
```
|
20
23
|
|
21
24
|
## ENV
|
data/Rakefile
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Ruboty
|
2
4
|
module Github
|
3
5
|
module Actions
|
4
6
|
class Base
|
5
|
-
NAMESPACE =
|
7
|
+
NAMESPACE = 'github'
|
6
8
|
|
7
9
|
attr_reader :message
|
8
10
|
|
@@ -17,7 +19,7 @@ module Ruboty
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def body
|
20
|
-
message[:description] ||
|
22
|
+
message[:description] || ''
|
21
23
|
end
|
22
24
|
|
23
25
|
def sender_name
|
@@ -45,14 +47,14 @@ module Ruboty
|
|
45
47
|
end
|
46
48
|
|
47
49
|
def client_options
|
48
|
-
client_options_with_nil_value.
|
50
|
+
client_options_with_nil_value.compact
|
49
51
|
end
|
50
52
|
|
51
53
|
def client_options_with_nil_value
|
52
54
|
{
|
53
55
|
access_token: access_token,
|
54
56
|
api_endpoint: api_endpoint,
|
55
|
-
web_endpoint: web_endpoint
|
57
|
+
web_endpoint: web_endpoint
|
56
58
|
}
|
57
59
|
end
|
58
60
|
|
@@ -66,11 +68,10 @@ module Ruboty
|
|
66
68
|
|
67
69
|
# @note GITHUB_HOST will be deprecated on the next major version
|
68
70
|
def github_base_url
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
"https://#{ENV['GITHUB_HOST']}"
|
71
|
+
if ENV.fetch('GITHUB_BASE_URL', nil)
|
72
|
+
ENV.fetch('GITHUB_BASE_URL', nil)
|
73
|
+
elsif ENV.fetch('GITHUB_HOST', nil)
|
74
|
+
"https://#{ENV.fetch('GITHUB_HOST', nil)}"
|
74
75
|
end
|
75
76
|
end
|
76
77
|
end
|
@@ -1,23 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Ruboty
|
2
4
|
module Github
|
3
5
|
module Actions
|
4
6
|
class CloseIssue < Base
|
5
7
|
def call
|
6
|
-
|
7
|
-
when !has_access_token?
|
8
|
+
if !has_access_token?
|
8
9
|
require_access_token
|
9
|
-
|
10
|
+
elsif has_closed_issue_number?
|
10
11
|
reply_already_closed
|
11
12
|
else
|
12
13
|
close
|
13
14
|
end
|
14
15
|
rescue Octokit::Unauthorized
|
15
|
-
message.reply(
|
16
|
+
message.reply('Failed in authentication (401)')
|
16
17
|
rescue Octokit::NotFound
|
17
|
-
message.reply(
|
18
|
-
rescue =>
|
19
|
-
raise
|
20
|
-
message.reply("Failed by #{
|
18
|
+
message.reply('Could not find that issue')
|
19
|
+
rescue StandardError => e
|
20
|
+
raise e
|
21
|
+
message.reply("Failed by #{e.class}")
|
21
22
|
end
|
22
23
|
|
23
24
|
private
|
@@ -32,7 +33,7 @@ module Ruboty
|
|
32
33
|
end
|
33
34
|
|
34
35
|
def has_closed_issue_number?
|
35
|
-
issue.state ==
|
36
|
+
issue.state == 'closed'
|
36
37
|
end
|
37
38
|
|
38
39
|
def reply_already_closed
|
@@ -1,40 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Ruboty
|
2
4
|
module Github
|
3
5
|
module Actions
|
4
6
|
class CreateDeployPullRequest < CreatePullRequest
|
5
7
|
private
|
6
8
|
|
9
|
+
def create
|
10
|
+
super
|
11
|
+
|
12
|
+
message.reply('@here :warning: This deployment includes some database migrations') if database_schema_changed?
|
13
|
+
end
|
14
|
+
|
7
15
|
# e.g. master
|
8
16
|
def to_branch
|
9
|
-
to.split(
|
17
|
+
to.split(':').last
|
10
18
|
end
|
11
19
|
|
12
20
|
def body
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
pr[:title],
|
19
|
-
"by",
|
20
|
-
"@#{pr[:user][:login]}\n",
|
21
|
-
].join(' ')
|
22
|
-
end
|
23
|
-
body
|
21
|
+
lines = included_pull_requests.map do |pr|
|
22
|
+
"- [##{pr[:number]}](#{pr[:html_url]}): #{pr[:title]} by @#{pr[:user][:login]}"
|
23
|
+
end
|
24
|
+
lines.unshift('## Pull Requests to deploy', '')
|
25
|
+
lines.join("\n")
|
24
26
|
end
|
25
27
|
|
26
|
-
def
|
27
|
-
numbers =
|
28
|
+
def included_pull_requests
|
29
|
+
numbers = comparison.commits.map do |commit|
|
28
30
|
/^Merge pull request #(\d+) from/ =~ commit[:commit][:message]
|
29
|
-
|
31
|
+
::Regexp.last_match(1)
|
30
32
|
end
|
31
|
-
numbers.compact.map { |
|
33
|
+
numbers.compact.map { |number| client.pull_request(repository, number.to_i) }
|
34
|
+
end
|
35
|
+
|
36
|
+
def database_schema_changed?
|
37
|
+
comparison.files.any? { |file| file.filename == 'db/schema.rb' }
|
32
38
|
end
|
33
39
|
|
34
|
-
def
|
35
|
-
|
36
|
-
|
37
|
-
|
40
|
+
def comparison
|
41
|
+
@comparison ||= begin
|
42
|
+
start = client.branch(repository, to_branch)[:commit][:sha]
|
43
|
+
endd = client.branch(repository, from_branch)[:commit][:sha]
|
44
|
+
client.compare(repository, start, endd)
|
45
|
+
end
|
38
46
|
end
|
39
47
|
end
|
40
48
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Ruboty
|
2
4
|
module Github
|
3
5
|
module Actions
|
@@ -15,11 +17,11 @@ module Ruboty
|
|
15
17
|
def create
|
16
18
|
message.reply("Created #{issue.html_url}")
|
17
19
|
rescue Octokit::Unauthorized
|
18
|
-
message.reply(
|
20
|
+
message.reply('Failed in authentication (401)')
|
19
21
|
rescue Octokit::NotFound
|
20
|
-
message.reply(
|
21
|
-
rescue =>
|
22
|
-
message.reply("Failed by #{
|
22
|
+
message.reply('Could not find that repository')
|
23
|
+
rescue StandardError => e
|
24
|
+
message.reply("Failed by #{e.class}")
|
23
25
|
end
|
24
26
|
|
25
27
|
def issue
|
@@ -1,25 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Ruboty
|
2
4
|
module Github
|
3
5
|
module Actions
|
4
6
|
class CreatePullRequest < Base
|
5
7
|
def call
|
6
8
|
if has_access_token?
|
7
|
-
|
9
|
+
create_with_error_handling
|
8
10
|
else
|
9
11
|
require_access_token
|
10
12
|
end
|
13
|
+
# Action handlers should return truthy value to tell ruboty that the given message has been handled.
|
14
|
+
# Otherwise, ruboty tries to execute other handlers.
|
15
|
+
true
|
11
16
|
end
|
12
17
|
|
13
18
|
private
|
14
19
|
|
15
|
-
def
|
16
|
-
|
20
|
+
def create_with_error_handling
|
21
|
+
create
|
17
22
|
rescue Octokit::Unauthorized
|
18
|
-
message.reply(
|
23
|
+
message.reply('Failed in authentication (401)')
|
19
24
|
rescue Octokit::NotFound
|
20
|
-
message.reply(
|
21
|
-
rescue =>
|
22
|
-
message.reply("Failed by #{
|
25
|
+
message.reply('Could not find that repository')
|
26
|
+
rescue StandardError => e
|
27
|
+
message.reply("Failed by #{e.class} #{e}")
|
28
|
+
end
|
29
|
+
|
30
|
+
def create
|
31
|
+
message.reply("Created #{pull_request.html_url}")
|
23
32
|
end
|
24
33
|
|
25
34
|
def pull_request
|
@@ -37,12 +46,12 @@ module Ruboty
|
|
37
46
|
|
38
47
|
# e.g. alice
|
39
48
|
def from_user
|
40
|
-
from.split(
|
49
|
+
from.split('/').first
|
41
50
|
end
|
42
51
|
|
43
52
|
# e.g. test
|
44
53
|
def from_branch
|
45
|
-
from.split(
|
54
|
+
from.split(':').last
|
46
55
|
end
|
47
56
|
|
48
57
|
# e.g. bob/foo:master
|
@@ -52,7 +61,7 @@ module Ruboty
|
|
52
61
|
|
53
62
|
# e.g. bob/foo
|
54
63
|
def repository
|
55
|
-
to.split(
|
64
|
+
to.split(':').first
|
56
65
|
end
|
57
66
|
|
58
67
|
# e.g. alice:test
|
@@ -62,7 +71,7 @@ module Ruboty
|
|
62
71
|
|
63
72
|
# e.g. master
|
64
73
|
def base
|
65
|
-
to.split(
|
74
|
+
to.split(':').last
|
66
75
|
end
|
67
76
|
end
|
68
77
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Ruboty
|
4
|
+
module Github
|
5
|
+
module Actions
|
6
|
+
class SearchIssues < Base
|
7
|
+
def call
|
8
|
+
if has_access_token?
|
9
|
+
search
|
10
|
+
else
|
11
|
+
require_access_token
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def search
|
18
|
+
results = search_issues.items.each_with_object(["Searched: '#{query}'"]) do |item, object|
|
19
|
+
repository_url = item[:repository_url].delete_prefix('https://api.github.com/repos/')
|
20
|
+
|
21
|
+
object << "[#{repository_url}##{item[:number]}] #{item[:title]} (#{item[:user][:login]})\n#{item[:html_url]}"
|
22
|
+
end
|
23
|
+
|
24
|
+
message.reply(results.join("\n"))
|
25
|
+
rescue Octokit::Unauthorized
|
26
|
+
message.reply('Failed in authentication (401)')
|
27
|
+
rescue Octokit::NotFound
|
28
|
+
message.reply('Could not find that repository')
|
29
|
+
rescue StandardError => e
|
30
|
+
message.reply("Failed by #{e.class}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def query
|
34
|
+
message[:query]
|
35
|
+
end
|
36
|
+
|
37
|
+
def search_issues
|
38
|
+
client.search_issues(query)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/ruboty/github.rb
CHANGED
@@ -1,13 +1,16 @@
|
|
1
|
-
|
2
|
-
require "octokit"
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
require
|
5
|
-
require
|
6
|
-
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
3
|
+
require 'active_support/core_ext/string/strip'
|
4
|
+
require 'octokit'
|
5
|
+
|
6
|
+
require 'ruboty'
|
7
|
+
require 'ruboty/github/actions/base'
|
8
|
+
require 'ruboty/github/actions/close_issue'
|
9
|
+
require 'ruboty/github/actions/create_issue'
|
10
|
+
require 'ruboty/github/actions/create_pull_request'
|
11
|
+
require 'ruboty/github/actions/create_deploy_pull_request'
|
12
|
+
require 'ruboty/github/actions/merge_pull_request'
|
13
|
+
require 'ruboty/github/actions/remember'
|
14
|
+
require 'ruboty/github/actions/search_issues'
|
15
|
+
require 'ruboty/github/version'
|
16
|
+
require 'ruboty/handlers/github'
|
@@ -1,50 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Ruboty
|
2
4
|
module Handlers
|
3
5
|
class Github < Base
|
4
|
-
ISSUE_PATTERN = %r
|
6
|
+
ISSUE_PATTERN = %r{(?:https?://[^/]+/)?(?<repo>.+)(?:#|/pull/|/issues/)(?<number>\d+) ?}.freeze
|
5
7
|
|
6
|
-
env :GITHUB_BASE_URL,
|
8
|
+
env :GITHUB_BASE_URL, 'Pass GitHub URL if needed (e.g. https://github.example.com)', optional: true
|
7
9
|
|
8
10
|
on(
|
9
11
|
/create issue "(?<title>.+)" on (?<repo>.+)(?:\n(?<description>[\s\S]+))?\z/,
|
10
|
-
name:
|
11
|
-
description:
|
12
|
+
name: 'create_issue',
|
13
|
+
description: 'Create a new issue'
|
14
|
+
)
|
15
|
+
|
16
|
+
on(
|
17
|
+
/search issues "(?<query>.+)"/,
|
18
|
+
name: 'search_issues',
|
19
|
+
description: 'Search an issue'
|
12
20
|
)
|
13
21
|
|
14
22
|
on(
|
15
23
|
/remember my github token (?<token>.+)\z/,
|
16
|
-
name:
|
17
|
-
description: "Remember sender's GitHub access token"
|
24
|
+
name: 'remember',
|
25
|
+
description: "Remember sender's GitHub access token"
|
18
26
|
)
|
19
27
|
|
20
28
|
on(
|
21
|
-
/close(?: issue)? #{ISSUE_PATTERN}\z
|
22
|
-
name:
|
23
|
-
description:
|
29
|
+
/close(?: issue)? #{ISSUE_PATTERN}\z/o,
|
30
|
+
name: 'close_issue',
|
31
|
+
description: 'Close an issue'
|
24
32
|
)
|
25
33
|
|
26
34
|
on(
|
27
35
|
/pull request "(?<title>.+)" from (?<from>.+) to (?<to>.+)(?:\n(?<description>[\s\S]+))?\z/,
|
28
|
-
name:
|
29
|
-
description:
|
36
|
+
name: 'create_pull_request',
|
37
|
+
description: 'Create a pull request'
|
30
38
|
)
|
31
39
|
|
32
40
|
on(
|
33
41
|
/deploy pull request "(?<title>.+)" from (?<from>.+) to (?<to>.+)(?:\n(?<description>[\s\S]+))?\z/,
|
34
|
-
name:
|
35
|
-
description:
|
42
|
+
name: 'create_deploy_pull_request',
|
43
|
+
description: 'Create a pull request to deploy'
|
36
44
|
)
|
37
45
|
|
38
46
|
on(
|
39
|
-
/merge #{ISSUE_PATTERN}\z
|
40
|
-
name:
|
41
|
-
description:
|
47
|
+
/merge #{ISSUE_PATTERN}\z/o,
|
48
|
+
name: 'merge_pull_request',
|
49
|
+
description: 'Merge pull request'
|
42
50
|
)
|
43
51
|
|
44
52
|
def create_issue(message)
|
45
53
|
Ruboty::Github::Actions::CreateIssue.new(message).call
|
46
54
|
end
|
47
55
|
|
56
|
+
def search_issues(message)
|
57
|
+
Ruboty::Github::Actions::SearchIssues.new(message).call
|
58
|
+
end
|
59
|
+
|
48
60
|
def close_issue(message)
|
49
61
|
Ruboty::Github::Actions::CloseIssue.new(message).call
|
50
62
|
end
|
data/ruboty-github.gemspec
CHANGED
@@ -1,27 +1,33 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
2
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
5
|
require 'ruboty/github/version'
|
4
6
|
|
5
7
|
Gem::Specification.new do |spec|
|
6
|
-
spec.name =
|
8
|
+
spec.name = 'ruboty-qiita-github'
|
7
9
|
spec.version = Ruboty::Github::VERSION
|
8
|
-
spec.authors = [
|
9
|
-
spec.email = [
|
10
|
-
spec.summary =
|
11
|
-
spec.homepage =
|
12
|
-
spec.license =
|
10
|
+
spec.authors = ['Ryo Nakamura', 'Seigo Uchida']
|
11
|
+
spec.email = ['r7kamura@gmail.com', 'spesnova@gmail.com']
|
12
|
+
spec.summary = 'Manage GitHub via Ruboty.'
|
13
|
+
spec.homepage = 'https://github.com/increments/ruboty-qiita-github'
|
14
|
+
spec.license = 'MIT'
|
13
15
|
|
14
16
|
spec.files = `git ls-files -z`.split("\x0")
|
15
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
16
|
-
spec.
|
17
|
-
spec.require_paths = ["lib"]
|
18
|
+
spec.require_paths = ['lib']
|
18
19
|
|
19
|
-
spec.add_dependency
|
20
|
-
spec.add_dependency
|
21
|
-
spec.add_dependency
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
20
|
+
spec.add_dependency 'activesupport'
|
21
|
+
spec.add_dependency 'octokit'
|
22
|
+
spec.add_dependency 'ruboty'
|
23
|
+
spec.add_development_dependency 'bundler'
|
24
|
+
spec.add_development_dependency 'rake'
|
25
|
+
spec.add_development_dependency 'rspec'
|
26
|
+
spec.add_development_dependency 'rubocop'
|
27
|
+
spec.add_development_dependency 'rubocop-performance'
|
28
|
+
spec.add_development_dependency 'rubocop-rake'
|
29
|
+
spec.add_development_dependency 'rubocop-rspec'
|
30
|
+
spec.add_development_dependency 'simplecov'
|
31
|
+
spec.add_development_dependency 'webmock'
|
32
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
27
33
|
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'json'
|
3
5
|
|
4
6
|
describe Ruboty::Handlers::Github do
|
5
7
|
before do
|
@@ -15,23 +17,23 @@ describe Ruboty::Handlers::Github do
|
|
15
17
|
end
|
16
18
|
|
17
19
|
let(:github_access_token) do
|
18
|
-
|
20
|
+
'dummy'
|
19
21
|
end
|
20
22
|
|
21
23
|
let(:sender) do
|
22
|
-
|
24
|
+
'bob'
|
23
25
|
end
|
24
26
|
|
25
27
|
let(:channel) do
|
26
|
-
|
28
|
+
'#general'
|
27
29
|
end
|
28
30
|
|
29
31
|
let(:user) do
|
30
|
-
|
32
|
+
'alice'
|
31
33
|
end
|
32
34
|
|
33
35
|
let(:repository) do
|
34
|
-
|
36
|
+
'test'
|
35
37
|
end
|
36
38
|
|
37
39
|
let(:access_tokens) do
|
@@ -42,78 +44,112 @@ describe Ruboty::Handlers::Github do
|
|
42
44
|
robot.receive(body: body, from: sender, to: channel)
|
43
45
|
end
|
44
46
|
|
45
|
-
shared_examples_for
|
46
|
-
context
|
47
|
+
shared_examples_for 'requires access token without access token' do
|
48
|
+
context 'without access token' do
|
47
49
|
let(:stored_access_token) do
|
48
50
|
nil
|
49
51
|
end
|
50
52
|
|
51
|
-
it
|
52
|
-
|
53
|
+
it 'requires access token' do
|
54
|
+
expect(robot).to receive(:say).with(hash_including(body: "I don't know your github access token"))
|
53
55
|
call
|
54
|
-
a_request(:any, //).
|
56
|
+
expect(a_request(:any, //)).not_to have_been_made
|
55
57
|
end
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
59
|
-
describe
|
61
|
+
describe '#create_issue' do
|
60
62
|
before do
|
61
|
-
stub_request(:post, "https://api.github.com/repos/#{user}/#{repository}/issues")
|
62
|
-
with(
|
63
|
+
stub_request(:post, "https://api.github.com/repos/#{user}/#{repository}/issues")
|
64
|
+
.with(
|
63
65
|
body: {
|
64
66
|
labels: [],
|
65
67
|
title: title,
|
66
|
-
body:
|
68
|
+
body: ''
|
67
69
|
}.to_json,
|
68
70
|
headers: {
|
69
71
|
Authorization: "token #{github_access_token}"
|
70
|
-
}
|
72
|
+
}
|
71
73
|
)
|
72
74
|
end
|
73
75
|
|
74
76
|
let(:title) do
|
75
|
-
|
77
|
+
'This is a test issue'
|
76
78
|
end
|
77
79
|
|
78
80
|
let(:body) do
|
79
|
-
|
81
|
+
%(ruboty create issue "#{title}" on #{user}/#{repository})
|
80
82
|
end
|
81
83
|
|
82
|
-
include_examples
|
84
|
+
include_examples 'requires access token without access token'
|
83
85
|
|
84
|
-
context
|
85
|
-
it
|
86
|
+
context 'with access token' do
|
87
|
+
it 'creates a new issue with given title on given repository' do
|
86
88
|
call
|
87
|
-
a_request(:any, //).
|
89
|
+
expect(a_request(:any, //)).to have_been_made
|
88
90
|
end
|
89
91
|
end
|
90
92
|
end
|
91
93
|
|
92
|
-
describe
|
94
|
+
describe '#search_issues' do
|
93
95
|
before do
|
94
|
-
stub_request(:get, "https://api.github.com/
|
95
|
-
with(
|
96
|
+
stub_request(:get, "https://api.github.com/search/issues?q=#{query}")
|
97
|
+
.with(
|
96
98
|
headers: {
|
97
99
|
Authorization: "token #{github_access_token}"
|
98
|
-
}
|
99
|
-
)
|
100
|
-
to_return(
|
100
|
+
}
|
101
|
+
)
|
102
|
+
.to_return(
|
103
|
+
body: '',
|
104
|
+
headers: {
|
105
|
+
'Content-Type' => 'application/json'
|
106
|
+
}
|
107
|
+
)
|
108
|
+
end
|
109
|
+
|
110
|
+
let(:query) do
|
111
|
+
'org:increments is:open is:public is:pr'
|
112
|
+
end
|
113
|
+
|
114
|
+
let(:body) do
|
115
|
+
%(ruboty search issues "#{query}")
|
116
|
+
end
|
117
|
+
|
118
|
+
include_examples 'requires access token without access token'
|
119
|
+
|
120
|
+
context 'with access token' do
|
121
|
+
it 'search an issue with given query' do
|
122
|
+
call
|
123
|
+
expect(a_request(:any, //)).to have_been_made
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe '#close_issue' do
|
129
|
+
before do
|
130
|
+
stub_request(:get, "https://api.github.com/repos/#{user}/#{repository}/issues/#{issue_number}")
|
131
|
+
.with(
|
132
|
+
headers: {
|
133
|
+
Authorization: "token #{github_access_token}"
|
134
|
+
}
|
135
|
+
)
|
136
|
+
.to_return(
|
101
137
|
body: {
|
102
138
|
state: issue_status,
|
103
|
-
html_url: html_url
|
139
|
+
html_url: html_url
|
104
140
|
}.to_json,
|
105
141
|
headers: {
|
106
|
-
|
107
|
-
}
|
142
|
+
'Content-Type' => 'application/json'
|
143
|
+
}
|
108
144
|
)
|
109
|
-
stub_request(:patch, "https://api.github.com/repos/#{user}/#{repository}/issues/#{issue_number}")
|
110
|
-
with(
|
145
|
+
stub_request(:patch, "https://api.github.com/repos/#{user}/#{repository}/issues/#{issue_number}")
|
146
|
+
.with(
|
111
147
|
body: {
|
112
|
-
state:
|
148
|
+
state: 'closed'
|
113
149
|
}.to_json,
|
114
150
|
headers: {
|
115
151
|
Authorization: "token #{github_access_token}"
|
116
|
-
}
|
152
|
+
}
|
117
153
|
)
|
118
154
|
end
|
119
155
|
|
@@ -122,7 +158,7 @@ describe Ruboty::Handlers::Github do
|
|
122
158
|
end
|
123
159
|
|
124
160
|
let(:issue_status) do
|
125
|
-
|
161
|
+
'open'
|
126
162
|
end
|
127
163
|
|
128
164
|
let(:body) do
|
@@ -133,31 +169,31 @@ describe Ruboty::Handlers::Github do
|
|
133
169
|
1
|
134
170
|
end
|
135
171
|
|
136
|
-
include_examples
|
172
|
+
include_examples 'requires access token without access token'
|
137
173
|
|
138
|
-
context
|
139
|
-
it
|
140
|
-
|
174
|
+
context 'with closed issue' do
|
175
|
+
it 'replies so' do
|
176
|
+
expect(robot).to receive(:say).with(hash_including(body: "Closed #{html_url}"))
|
141
177
|
call
|
142
178
|
end
|
143
179
|
end
|
144
180
|
|
145
|
-
context
|
146
|
-
it
|
181
|
+
context 'with access token' do
|
182
|
+
it 'closes specified issue' do
|
147
183
|
call
|
148
184
|
end
|
149
185
|
end
|
150
186
|
end
|
151
187
|
|
152
|
-
describe
|
188
|
+
describe '#remember' do
|
153
189
|
let(:body) do
|
154
190
|
"@ruboty remember my github token #{github_access_token}"
|
155
191
|
end
|
156
192
|
|
157
193
|
it "remembers sender's access token in its brain" do
|
158
|
-
|
194
|
+
expect(robot).to receive(:say).with(hash_including(body: "Remembered #{sender}'s github access token"))
|
159
195
|
call
|
160
|
-
access_tokens[sender].
|
196
|
+
expect(access_tokens[sender]).to eq(github_access_token)
|
161
197
|
end
|
162
198
|
end
|
163
199
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'simplecov'
|
2
4
|
SimpleCov.start
|
3
5
|
|
4
|
-
require
|
5
|
-
require
|
6
|
+
require 'ruboty/github'
|
7
|
+
require 'webmock/rspec'
|
6
8
|
|
7
9
|
RSpec.configure do |config|
|
8
|
-
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
10
|
config.run_all_when_everything_filtered = true
|
10
11
|
config.filter_run :focus
|
11
12
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruboty-qiita-github
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryo Nakamura
|
8
8
|
- Seigo Uchida
|
9
|
-
autorequire:
|
9
|
+
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2022-10-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '0'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
|
-
name:
|
29
|
+
name: octokit
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
32
|
- - ">="
|
@@ -40,7 +40,7 @@ dependencies:
|
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '0'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
|
-
name:
|
43
|
+
name: ruboty
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
46
|
- - ">="
|
@@ -57,16 +57,16 @@ dependencies:
|
|
57
57
|
name: bundler
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
|
-
- - "
|
60
|
+
- - ">="
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: '
|
62
|
+
version: '0'
|
63
63
|
type: :development
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
|
-
- - "
|
67
|
+
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '
|
69
|
+
version: '0'
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: rake
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
@@ -85,16 +85,72 @@ dependencies:
|
|
85
85
|
name: rspec
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
|
-
- -
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: rubocop
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: rubocop-performance
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
89
117
|
- !ruby/object:Gem::Version
|
90
|
-
version:
|
118
|
+
version: '0'
|
91
119
|
type: :development
|
92
120
|
prerelease: false
|
93
121
|
version_requirements: !ruby/object:Gem::Requirement
|
94
122
|
requirements:
|
95
|
-
- -
|
123
|
+
- - ">="
|
96
124
|
- !ruby/object:Gem::Version
|
97
|
-
version:
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: rubocop-rake
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: rubocop-rspec
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '0'
|
147
|
+
type: :development
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
98
154
|
- !ruby/object:Gem::Dependency
|
99
155
|
name: simplecov
|
100
156
|
requirement: !ruby/object:Gem::Requirement
|
@@ -123,7 +179,7 @@ dependencies:
|
|
123
179
|
- - ">="
|
124
180
|
- !ruby/object:Gem::Version
|
125
181
|
version: '0'
|
126
|
-
description:
|
182
|
+
description:
|
127
183
|
email:
|
128
184
|
- r7kamura@gmail.com
|
129
185
|
- spesnova@gmail.com
|
@@ -131,7 +187,11 @@ executables: []
|
|
131
187
|
extensions: []
|
132
188
|
extra_rdoc_files: []
|
133
189
|
files:
|
190
|
+
- ".github/dependabot.yml"
|
191
|
+
- ".github/workflows/test.yml"
|
134
192
|
- ".gitignore"
|
193
|
+
- ".rubocop.yml"
|
194
|
+
- ".rubocop_todo.yml"
|
135
195
|
- CHANGELOG.md
|
136
196
|
- Gemfile
|
137
197
|
- LICENSE.txt
|
@@ -146,6 +206,7 @@ files:
|
|
146
206
|
- lib/ruboty/github/actions/create_pull_request.rb
|
147
207
|
- lib/ruboty/github/actions/merge_pull_request.rb
|
148
208
|
- lib/ruboty/github/actions/remember.rb
|
209
|
+
- lib/ruboty/github/actions/search_issues.rb
|
149
210
|
- lib/ruboty/github/version.rb
|
150
211
|
- lib/ruboty/handlers/github.rb
|
151
212
|
- ruboty-github.gemspec
|
@@ -154,8 +215,9 @@ files:
|
|
154
215
|
homepage: https://github.com/increments/ruboty-qiita-github
|
155
216
|
licenses:
|
156
217
|
- MIT
|
157
|
-
metadata:
|
158
|
-
|
218
|
+
metadata:
|
219
|
+
rubygems_mfa_required: 'true'
|
220
|
+
post_install_message:
|
159
221
|
rdoc_options: []
|
160
222
|
require_paths:
|
161
223
|
- lib
|
@@ -170,11 +232,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
170
232
|
- !ruby/object:Gem::Version
|
171
233
|
version: '0'
|
172
234
|
requirements: []
|
173
|
-
|
174
|
-
|
175
|
-
signing_key:
|
235
|
+
rubygems_version: 3.1.4
|
236
|
+
signing_key:
|
176
237
|
specification_version: 4
|
177
238
|
summary: Manage GitHub via Ruboty.
|
178
|
-
test_files:
|
179
|
-
- spec/ruboty/handlers/github_spec.rb
|
180
|
-
- spec/spec_helper.rb
|
239
|
+
test_files: []
|