teachers_pet 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +7 -0
- data/Guardfile +3 -1
- data/README.md +53 -28
- data/Rakefile +1 -1
- data/bin/teachers_pet +4 -0
- data/lib/teachers_pet.rb +4 -1
- data/lib/teachers_pet/actions/add_to_team.rb +31 -0
- data/lib/teachers_pet/actions/base.rb +36 -111
- data/lib/teachers_pet/actions/clone_repos.rb +9 -36
- data/lib/teachers_pet/actions/create_repos.rb +16 -39
- data/lib/teachers_pet/actions/create_student_teams.rb +35 -0
- data/lib/teachers_pet/actions/fork_collab.rb +4 -19
- data/lib/teachers_pet/actions/open_issue.rb +17 -32
- data/lib/teachers_pet/actions/push_files.rb +8 -22
- data/lib/teachers_pet/cli.rb +22 -0
- data/lib/teachers_pet/client_decorator.rb +59 -0
- data/lib/teachers_pet/commands/add_to_team.rb +12 -0
- data/lib/teachers_pet/commands/clone_repos.rb +15 -0
- data/lib/teachers_pet/commands/create_repos.rb +15 -0
- data/lib/teachers_pet/commands/create_student_teams.rb +13 -0
- data/lib/teachers_pet/commands/fork_collab.rb +12 -0
- data/lib/teachers_pet/commands/open_issue.rb +18 -0
- data/lib/teachers_pet/commands/push_files.rb +15 -0
- data/lib/teachers_pet/configuration.rb +0 -13
- data/lib/teachers_pet/version.rb +1 -1
- data/spec/actions/base_spec.rb +13 -0
- data/spec/cli_spec.rb +17 -0
- data/spec/commands/add_to_team_spec.rb +43 -0
- data/spec/commands/clone_repos_spec.rb +33 -0
- data/spec/commands/create_repos_spec.rb +55 -0
- data/spec/commands/create_student_teams_spec.rb +90 -0
- data/spec/commands/fork_collab_spec.rb +95 -0
- data/spec/commands/open_issue_spec.rb +63 -0
- data/spec/commands/push_files_spec.rb +33 -0
- data/spec/fixtures/empty +0 -0
- data/spec/fixtures/teams +1 -0
- data/spec/spec_helper.rb +13 -53
- data/spec/support/command_helpers.rb +11 -0
- data/spec/support/common_helpers.rb +52 -0
- data/teachers_pet.gemspec +6 -2
- metadata +89 -29
- data/bin/clone_repos +0 -6
- data/bin/create_repos +0 -6
- data/bin/create_teams +0 -6
- data/bin/fork_collab +0 -6
- data/bin/open_issue +0 -6
- data/bin/push_files +0 -6
- data/lib/teachers_pet/actions/create_teams.rb +0 -101
- data/spec/actions/clone_repos_spec.rb +0 -44
- data/spec/actions/create_repos_spec.rb +0 -65
- data/spec/actions/create_teams_spec.rb +0 -40
- data/spec/actions/open_issue_spec.rb +0 -71
@@ -0,0 +1,13 @@
|
|
1
|
+
module TeachersPet
|
2
|
+
class Cli
|
3
|
+
option :organization, required: true
|
4
|
+
|
5
|
+
students_option
|
6
|
+
common_options
|
7
|
+
|
8
|
+
desc 'create_student_teams', "Create teams for each student (or student group), and a team for all the instructors."
|
9
|
+
def create_student_teams
|
10
|
+
TeachersPet::Actions::CreateStudentTeams.new(options).run
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module TeachersPet
|
2
|
+
class Cli
|
3
|
+
option :repository, required: true, banner: 'OWNER/REPO'
|
4
|
+
option :dry_run, type: :boolean, default: false
|
5
|
+
common_options
|
6
|
+
|
7
|
+
desc "fork_collab", "Give collaborator access to everyone who has forked a particular repository."
|
8
|
+
def fork_collab
|
9
|
+
TeachersPet::Actions::ForkCollab.new(options).run
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module TeachersPet
|
2
|
+
class Cli
|
3
|
+
option :organization, required: true
|
4
|
+
option :repository, required: true
|
5
|
+
|
6
|
+
option :title, desc: "The title of the issue to be created"
|
7
|
+
option :body, banner: 'PATH', desc: "The path to the file containing the issue body (.txt or .md)"
|
8
|
+
option :labels, banner: 'LABEL1,LABEL2'
|
9
|
+
|
10
|
+
students_option
|
11
|
+
common_options
|
12
|
+
|
13
|
+
desc "open_issue", "Opens a single issue in each repository in the organization."
|
14
|
+
def open_issue
|
15
|
+
TeachersPet::Actions::OpenIssue.new(options).run
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module TeachersPet
|
2
|
+
class Cli
|
3
|
+
option :organization, required: true
|
4
|
+
option :repository, required: true
|
5
|
+
|
6
|
+
students_option
|
7
|
+
common_options
|
8
|
+
option :ssh, banner: 'HOST', default: TeachersPet::Configuration.sshEndpoint
|
9
|
+
|
10
|
+
desc 'push_files', "Run this command from a local Git repository to push the files up to the specified repository for each student. It will add a remote that is the name of each student team to your repository."
|
11
|
+
def push_files
|
12
|
+
TeachersPet::Actions::PushFiles.new(options).run
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -19,13 +19,6 @@ module TeachersPet
|
|
19
19
|
@@WEB_ENDPOINT
|
20
20
|
end
|
21
21
|
|
22
|
-
# The name of your organization
|
23
|
-
@@ORGANIZATION = 'edugit-test'
|
24
|
-
|
25
|
-
def self.organization
|
26
|
-
@@ORGANIZATION
|
27
|
-
end
|
28
|
-
|
29
22
|
# The name fo the file that contains the team definitions / students
|
30
23
|
@@STUDENTS_FILE = './students'
|
31
24
|
|
@@ -33,12 +26,6 @@ module TeachersPet
|
|
33
26
|
@@STUDENTS_FILE
|
34
27
|
end
|
35
28
|
|
36
|
-
# The name of the file that contains the GitHub usernames of the instructors
|
37
|
-
@@INSTRUCTORS_FILE = './instructors'
|
38
|
-
|
39
|
-
def self.instructorsFile
|
40
|
-
@@INSTRUCTORS_FILE
|
41
|
-
end
|
42
29
|
|
43
30
|
# github.com - set to 'github.com'
|
44
31
|
# GitHub Enterprise - 'yourserver.com'
|
data/lib/teachers_pet/version.rb
CHANGED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TeachersPet::Actions::Base do
|
4
|
+
describe '#read_file' do
|
5
|
+
it "returns a hash of usernames by team name" do
|
6
|
+
action = TeachersPet::Actions::Base.new
|
7
|
+
result = action.read_file(fixture_path('teams'))
|
8
|
+
expect(result).to eq(
|
9
|
+
'studentteam1' => %w(teststudent1 teststudent2)
|
10
|
+
)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe TeachersPet::Cli do
|
4
|
+
include CommandHelpers
|
5
|
+
|
6
|
+
it "throws an error for unsupported options" do
|
7
|
+
# ...using an arbirtrary command
|
8
|
+
|
9
|
+
# Make sure it short-circuits
|
10
|
+
expect(TeachersPet::Actions::CreateStudentTeams).to_not receive(:new)
|
11
|
+
|
12
|
+
output = capture(:stderr) {
|
13
|
+
TeachersPet::Cli.start(%w(create_student_teams --organization testorg --unsupported-option))
|
14
|
+
}
|
15
|
+
expect(output).to include('--unsupported-option')
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'add_to_team' do
|
4
|
+
include CommandHelpers
|
5
|
+
|
6
|
+
it "adds users to the team matching the filename" do
|
7
|
+
request_stubs = []
|
8
|
+
|
9
|
+
request_stubs << stub_get_json('https://testteacher:abc123@api.github.com/orgs/testorg/teams?per_page=100', [
|
10
|
+
{
|
11
|
+
id: 101,
|
12
|
+
name: 'instructors'
|
13
|
+
}
|
14
|
+
])
|
15
|
+
|
16
|
+
users = instructor_usernames
|
17
|
+
request_stubs << stub_get_json('https://testteacher:abc123@api.github.com/teams/101/members?per_page=100', [
|
18
|
+
{
|
19
|
+
login: users.first
|
20
|
+
}
|
21
|
+
])
|
22
|
+
|
23
|
+
users[1..-1].each do |instructor|
|
24
|
+
request_stubs << stub_request(:put, "https://testteacher:abc123@api.github.com/teams/101/members/#{instructor}")
|
25
|
+
end
|
26
|
+
|
27
|
+
teachers_pet(:add_to_team,
|
28
|
+
organization: 'testorg',
|
29
|
+
members: instructors_list_fixture_path,
|
30
|
+
|
31
|
+
username: 'testteacher',
|
32
|
+
password: 'abc123'
|
33
|
+
)
|
34
|
+
|
35
|
+
request_stubs.each do |request_stub|
|
36
|
+
expect(request_stub).to have_been_requested.once
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
it "creates the team if it doesn't already exist"
|
41
|
+
|
42
|
+
it "treats the team names case-insensitively"
|
43
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'clone_repos' do
|
4
|
+
include CommandHelpers
|
5
|
+
|
6
|
+
it "runs" do
|
7
|
+
request_stubs = []
|
8
|
+
|
9
|
+
request_stubs << stub_get_json('https://testteacher:abc123@api.github.com/orgs/testorg',
|
10
|
+
login: 'testorg',
|
11
|
+
url: 'https://api.github.com/orgs/testorg'
|
12
|
+
)
|
13
|
+
request_stubs << stub_get_json('https://testteacher:abc123@api.github.com/orgs/testorg/teams?per_page=100', student_teams)
|
14
|
+
student_usernames.each do |username|
|
15
|
+
request_stubs << stub_get_json("https://testteacher:abc123@api.github.com/repos/testorg/#{username}-testrepo", {})
|
16
|
+
expect_any_instance_of(TeachersPet::Actions::CloneRepos).to receive(:execute).with("git clone https://www.github.com/testorg/#{username}-testrepo.git").once
|
17
|
+
end
|
18
|
+
|
19
|
+
teachers_pet(:clone_repos,
|
20
|
+
repository: 'testrepo',
|
21
|
+
organization: 'testorg',
|
22
|
+
|
23
|
+
students: students_list_fixture_path,
|
24
|
+
|
25
|
+
username: 'testteacher',
|
26
|
+
password: 'abc123'
|
27
|
+
)
|
28
|
+
|
29
|
+
request_stubs.each do |request_stub|
|
30
|
+
expect(request_stub).to have_been_requested.once
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'create_repos' do
|
4
|
+
include CommandHelpers
|
5
|
+
|
6
|
+
def common_test(create_as_public)
|
7
|
+
request_stubs = []
|
8
|
+
|
9
|
+
request_stubs << stub_get_json('https://testteacher:abc123@api.github.com/orgs/testorg',
|
10
|
+
login: 'testorg',
|
11
|
+
url: 'https://api.github.com/orgs/testorg'
|
12
|
+
)
|
13
|
+
request_stubs << stub_get_json('https://testteacher:abc123@api.github.com/orgs/testorg/teams?per_page=100', student_teams)
|
14
|
+
student_usernames.each do |username|
|
15
|
+
# Check for the repos existing already
|
16
|
+
stub_request(:get, "https://testteacher:abc123@api.github.com/repos/testorg/#{username}-testrepo").
|
17
|
+
to_return(status: 404)
|
18
|
+
end
|
19
|
+
|
20
|
+
student_usernames.each do |username|
|
21
|
+
# actually create the repo
|
22
|
+
team_id = 0
|
23
|
+
student_teams.each do |st|
|
24
|
+
if st[:name].eql?(username)
|
25
|
+
team_id = st[:id]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
stub_request(:post, "https://testteacher:abc123@api.github.com/orgs/testorg/repos").
|
29
|
+
with(body: "{\"description\":\"testrepo created for #{username}\",\"private\":#{!create_as_public},\"has_issues\":true,\"has_wiki\":false,\"has_downloads\":false,\"team_id\":#{team_id},\"name\":\"#{username}-testrepo\"}")
|
30
|
+
end
|
31
|
+
|
32
|
+
teachers_pet(:create_repos,
|
33
|
+
repository: 'testrepo',
|
34
|
+
organization: 'testorg',
|
35
|
+
public: create_as_public,
|
36
|
+
|
37
|
+
students: students_list_fixture_path,
|
38
|
+
|
39
|
+
username: 'testteacher',
|
40
|
+
password: 'abc123'
|
41
|
+
)
|
42
|
+
|
43
|
+
request_stubs.each do |request_stub|
|
44
|
+
expect(request_stub).to have_been_requested.once
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "create repos public" do
|
49
|
+
common_test(true)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "create repos private" do
|
53
|
+
common_test(false)
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'create_student_teams' do
|
4
|
+
include CommandHelpers
|
5
|
+
|
6
|
+
def stub_owners_only
|
7
|
+
stub_get_json('https://testteacher:abc123@api.github.com/orgs/testorg/teams?per_page=100', [
|
8
|
+
{
|
9
|
+
id: 101,
|
10
|
+
name: 'Owners'
|
11
|
+
}
|
12
|
+
])
|
13
|
+
end
|
14
|
+
|
15
|
+
it "creates one team per student" do
|
16
|
+
request_stubs = []
|
17
|
+
request_stubs << stub_owners_only
|
18
|
+
|
19
|
+
student_usernames.each_with_index do |student, i|
|
20
|
+
# Creates team
|
21
|
+
request_stubs << stub_request(:post, 'https://testteacher:abc123@api.github.com/orgs/testorg/teams').
|
22
|
+
with(body: {
|
23
|
+
name: student,
|
24
|
+
permission: 'push'
|
25
|
+
}.to_json).to_return(body: {
|
26
|
+
id: i,
|
27
|
+
name: student
|
28
|
+
})
|
29
|
+
|
30
|
+
# Checks for existing team members
|
31
|
+
# TODO No need to retrieve members for a new team
|
32
|
+
request_stubs << stub_get_json("https://testteacher:abc123@api.github.com/teams/#{i}/members?per_page=100", [])
|
33
|
+
|
34
|
+
# Add student to their team
|
35
|
+
request_stubs << stub_request(:put, "https://testteacher:abc123@api.github.com/teams/#{i}/members/#{student}")
|
36
|
+
end
|
37
|
+
|
38
|
+
teachers_pet(:create_student_teams,
|
39
|
+
organization: 'testorg',
|
40
|
+
|
41
|
+
students: students_list_fixture_path,
|
42
|
+
instructors: empty_list_fixture_path,
|
43
|
+
|
44
|
+
username: 'testteacher',
|
45
|
+
password: 'abc123'
|
46
|
+
)
|
47
|
+
|
48
|
+
request_stubs.each do |request_stub|
|
49
|
+
expect(request_stub).to have_been_requested.once
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it "creates teams for groups of students" do
|
54
|
+
request_stubs = []
|
55
|
+
stub_owners_only
|
56
|
+
|
57
|
+
# Creates team
|
58
|
+
request_stubs << stub_request(:post, 'https://testteacher:abc123@api.github.com/orgs/testorg/teams').
|
59
|
+
with(body: {
|
60
|
+
name: 'studentteam1',
|
61
|
+
permission: 'push'
|
62
|
+
}.to_json).to_return(body: {
|
63
|
+
id: 1,
|
64
|
+
name: 'studentteam1'
|
65
|
+
})
|
66
|
+
|
67
|
+
# Checks for existing team members
|
68
|
+
# TODO No need to retrieve members for a new team
|
69
|
+
request_stubs << stub_get_json('https://testteacher:abc123@api.github.com/teams/1/members?per_page=100', [])
|
70
|
+
|
71
|
+
%w(teststudent1 teststudent2).each do |student|
|
72
|
+
# Add student to their team
|
73
|
+
request_stubs << stub_request(:put, "https://testteacher:abc123@api.github.com/teams/1/members/#{student}")
|
74
|
+
end
|
75
|
+
|
76
|
+
teachers_pet(:create_student_teams,
|
77
|
+
organization: 'testorg',
|
78
|
+
|
79
|
+
students: fixture_path('teams'),
|
80
|
+
instructors: empty_list_fixture_path,
|
81
|
+
|
82
|
+
username: 'testteacher',
|
83
|
+
password: 'abc123'
|
84
|
+
)
|
85
|
+
|
86
|
+
request_stubs.each do |request_stub|
|
87
|
+
expect(request_stub).to have_been_requested.once
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'fork_collab' do
|
4
|
+
include CommandHelpers
|
5
|
+
|
6
|
+
context 'through CLI' do
|
7
|
+
it "requires the repository be specified" do
|
8
|
+
expect {
|
9
|
+
teachers_pet(:fork_collab)
|
10
|
+
}.to raise_error(Thor::RequiredArgumentMissingError, /--repository/)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "passes the options to the action" do
|
14
|
+
expect_to_be_run_with(TeachersPet::Actions::ForkCollab,
|
15
|
+
'api' => 'https://api.github.com/',
|
16
|
+
'dry_run' => false,
|
17
|
+
'password' => 'abc123',
|
18
|
+
'repository' => 'testorg/testrepo',
|
19
|
+
'username' => ENV['USER'],
|
20
|
+
'web' => 'https://www.github.com/'
|
21
|
+
)
|
22
|
+
teachers_pet(:fork_collab, repository: 'testorg/testrepo', password: 'abc123')
|
23
|
+
end
|
24
|
+
|
25
|
+
it "succeeds for basic auth" do
|
26
|
+
request_stubs = []
|
27
|
+
request_stubs << stub_get_json('https://testteacher:abc123@api.github.com/repos/testorg/testrepo/forks?per_page=100', [
|
28
|
+
{
|
29
|
+
owner: {
|
30
|
+
login: 'teststudent',
|
31
|
+
type: 'User'
|
32
|
+
}
|
33
|
+
}
|
34
|
+
])
|
35
|
+
request_stubs << stub_request(:put, 'https://testteacher:abc123@api.github.com/repos/testorg/testrepo/collaborators/teststudent')
|
36
|
+
|
37
|
+
teachers_pet(:fork_collab,
|
38
|
+
repository: 'testorg/testrepo',
|
39
|
+
username: 'testteacher',
|
40
|
+
password: 'abc123'
|
41
|
+
)
|
42
|
+
|
43
|
+
request_stubs.each do |request_stub|
|
44
|
+
expect(request_stub).to have_been_requested.once
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "succeeds for OAuth" do
|
49
|
+
request_stubs = []
|
50
|
+
request_stubs << stub_get_json('https://api.github.com/repos/testorg/testrepo/forks?per_page=100', [
|
51
|
+
{
|
52
|
+
owner: {
|
53
|
+
login: 'teststudent',
|
54
|
+
type: 'User'
|
55
|
+
}
|
56
|
+
}
|
57
|
+
]).with(headers: {'Authorization' => 'token tokentokentoken'})
|
58
|
+
|
59
|
+
request_stubs << stub_request(:put, 'https://api.github.com/repos/testorg/testrepo/collaborators/teststudent').
|
60
|
+
with(headers: {'Authorization' => 'token tokentokentoken'})
|
61
|
+
|
62
|
+
teachers_pet(:fork_collab,
|
63
|
+
repository: 'testorg/testrepo',
|
64
|
+
token: 'tokentokentoken'
|
65
|
+
)
|
66
|
+
|
67
|
+
request_stubs.each do |request_stub|
|
68
|
+
expect(request_stub).to have_been_requested.once
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
it "prints the users on a dry run" do
|
73
|
+
request_stub = stub_get_json('https://testteacher:abc123@api.github.com/repos/testorg/testrepo/forks?per_page=100', [
|
74
|
+
{
|
75
|
+
owner: {
|
76
|
+
login: 'teststudent',
|
77
|
+
type: 'User'
|
78
|
+
}
|
79
|
+
}
|
80
|
+
])
|
81
|
+
|
82
|
+
output = capture(:stdout) do
|
83
|
+
teachers_pet(:fork_collab,
|
84
|
+
repository: 'testorg/testrepo',
|
85
|
+
username: 'testteacher',
|
86
|
+
password: 'abc123',
|
87
|
+
dry_run: true
|
88
|
+
)
|
89
|
+
end
|
90
|
+
|
91
|
+
expect(output).to include('teststudent')
|
92
|
+
expect(request_stub).to have_been_requested.once
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|