yanapiri 0.2.4 → 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/lib/yanapiri/bot.rb +89 -84
- data/lib/yanapiri/cli.rb +189 -0
- data/lib/yanapiri/entrega.rb +42 -45
- data/lib/yanapiri/transformacion_wollok.rb +15 -13
- data/lib/yanapiri/version.rb +1 -1
- data/lib/yanapiri.rb +1 -182
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0693d55c2926d49f024324e341b2a72b7e7bf7b726e220152aaf862ab3eaa52d'
|
4
|
+
data.tar.gz: b8d9156cc3de8c17a3d6c47afd6fe94c92e0c32855e7d30e29d58c4053a7d973
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 88efae31854130a2cdb26f769a0f8a12c4104bd34a9a87498307bad9ef9c946a068f609e8bdc5e023e98e236777f6fcbf93184b4bbad18bf86265f25447bff3a
|
7
|
+
data.tar.gz: 7a9e3f178ad6ba469f3f18397e9743f9a75c9937620e35e50cf1a5bdaab75970fe0117c01177e5ca1e9e371876d4a1969ad48d86587378c20864162e3ae86091
|
data/lib/yanapiri/bot.rb
CHANGED
@@ -1,108 +1,113 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
1
|
+
module Yanapiri
|
2
|
+
class Bot
|
3
|
+
attr_reader :organization
|
4
|
+
|
5
|
+
def initialize(organization, gh_client)
|
6
|
+
@organization = organization
|
7
|
+
@gh_client = gh_client
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
10
|
+
def clonar_entrega!(nombre)
|
11
|
+
result = @gh_client.search_repositories "org:#{@organization} #{nombre}\\-", {per_page: 200}
|
12
|
+
puts "Encontrados #{result.total_count} repositorios."
|
13
|
+
FileUtils.mkdir_p nombre
|
14
|
+
Dir.chdir(nombre) do
|
15
|
+
result.items.each do |repo|
|
16
|
+
if File.exist? repo.name
|
17
|
+
puts "Actualizando #{repo.name}..."
|
18
|
+
actualizar! repo.name
|
19
|
+
else
|
20
|
+
puts "Clonando #{repo.name}..."
|
21
|
+
clonar! repo.full_name
|
22
|
+
end
|
21
23
|
end
|
22
24
|
end
|
23
25
|
end
|
24
|
-
end
|
25
26
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
27
|
+
def preparar_correccion!(entrega, transformaciones = [])
|
28
|
+
if not entrega.hay_cambios?
|
29
|
+
crear_issue_advertencia! entrega
|
30
|
+
else
|
31
|
+
entrega.crear_branch! 'base', entrega.commit_base
|
32
|
+
entrega.crear_branch! 'entrega', 'master'
|
33
|
+
transformaciones.select {|t| t.aplica? entrega}.each {|t| t.transformar! entrega, self}
|
34
|
+
publicar_cambios! entrega
|
35
|
+
crear_pull_request! entrega
|
36
|
+
end
|
35
37
|
end
|
36
|
-
end
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
def preparar_entrega!(nombre, repo_base)
|
40
|
+
repo = clonar! repo_base
|
41
|
+
aplanar_commits! repo
|
42
|
+
publicar_repo! nombre, repo
|
43
|
+
end
|
43
44
|
|
44
|
-
|
45
|
-
|
46
|
-
|
45
|
+
def nombre
|
46
|
+
'Yanapiri Bot'
|
47
|
+
end
|
47
48
|
|
48
|
-
|
49
|
-
|
50
|
-
|
49
|
+
def email
|
50
|
+
'bot@yanapiri.org'
|
51
|
+
end
|
51
52
|
|
52
|
-
|
53
|
-
|
54
|
-
|
53
|
+
def git_author
|
54
|
+
"#{nombre} <#{email}>"
|
55
|
+
end
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
57
|
+
def github_user
|
58
|
+
@gh_client.user
|
59
|
+
end
|
59
60
|
|
60
|
-
|
61
|
-
|
62
|
-
|
61
|
+
def commit!(repo, mensaje)
|
62
|
+
repo.add
|
63
|
+
repo.commit mensaje, author: git_author
|
64
|
+
end
|
63
65
|
|
64
|
-
|
66
|
+
def aplanar_commits!(repo)
|
67
|
+
repo.chdir do
|
68
|
+
`git checkout --orphan new-master master`
|
69
|
+
commit! repo, 'Enunciado preparado por Yanapiri'
|
70
|
+
`git branch -M new-master master`
|
71
|
+
end
|
65
72
|
|
66
|
-
|
67
|
-
repo.chdir do
|
68
|
-
`git checkout --orphan new-master master`
|
69
|
-
commit! repo, 'Enunciado preparado por Yanapiri'
|
70
|
-
`git branch -M new-master master`
|
73
|
+
repo.branches.reject {|b| b.name == 'master'}.each(&:delete)
|
71
74
|
end
|
72
|
-
end
|
73
75
|
|
74
|
-
|
75
|
-
Git.open(repo_path).pull
|
76
|
-
end
|
76
|
+
private
|
77
77
|
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
def actualizar!(repo_path)
|
79
|
+
Git.open(repo_path).pull
|
80
|
+
end
|
81
81
|
|
82
|
-
|
83
|
-
|
84
|
-
|
82
|
+
def clonar!(repo_slug)
|
83
|
+
Git.clone "git@github.com:#{repo_slug}.git", repo_slug.split('/').last
|
84
|
+
end
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
|
86
|
+
def crear_pull_request!(entrega)
|
87
|
+
@gh_client.create_pull_request(gh_repo_para(entrega), "base", "entrega", "Corrección", entrega.mensaje_pull_request) rescue nil
|
88
|
+
end
|
89
89
|
|
90
|
-
|
91
|
-
|
92
|
-
|
90
|
+
def crear_issue_advertencia!(entrega)
|
91
|
+
@gh_client.create_issue(gh_repo_para(entrega), "Corrección", "¡Hola! Te estamos cargando esta _issue_ porque no subiste ningún cambio al repositorio y ya pasó la fecha de entrega. :pensive:\n\nPor favor, si tuviste algún problema acercate a hablar con tus docentes." )
|
92
|
+
end
|
93
93
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
repo.add_remote 'origin', repo_nuevo.ssh_url
|
98
|
-
repo.push
|
99
|
-
end
|
94
|
+
def gh_repo_para(entrega)
|
95
|
+
"#{@organization}/#{entrega.id}"
|
96
|
+
end
|
100
97
|
|
101
|
-
|
102
|
-
|
103
|
-
|
98
|
+
def publicar_repo!(nombre, repo)
|
99
|
+
repo_nuevo = crear_repo!(nombre)
|
100
|
+
repo.remote('origin').remove
|
101
|
+
repo.add_remote 'origin', repo_nuevo.ssh_url
|
102
|
+
repo.push
|
103
|
+
end
|
104
|
+
|
105
|
+
def crear_repo!(nombre)
|
106
|
+
@gh_client.create_repository nombre, organization: @organization
|
107
|
+
end
|
104
108
|
|
105
|
-
|
106
|
-
|
109
|
+
def publicar_cambios!(entrega)
|
110
|
+
entrega.repo.push 'origin', '--all'
|
111
|
+
end
|
107
112
|
end
|
108
|
-
end
|
113
|
+
end
|
data/lib/yanapiri/cli.rb
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
module Yanapiri
|
2
|
+
class CLI < Thor
|
3
|
+
include Thor::Actions
|
4
|
+
include ActionView::Helpers::DateHelper
|
5
|
+
|
6
|
+
class_option :orga, {aliases: :o}
|
7
|
+
class_option :github_token
|
8
|
+
|
9
|
+
def initialize(args = [], local_options = {}, config = {})
|
10
|
+
super(args, local_options, config)
|
11
|
+
@bot = crear_bot options
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.exit_on_failure?
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
map %w(--version -v) => :version
|
19
|
+
desc "--version, -v", "Muestra la versión actual de Yanapiri"
|
20
|
+
def version
|
21
|
+
say "yanapiri version #{VERSION}"
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'setup', 'Configura a Yanapiri para el primer uso'
|
25
|
+
def setup
|
26
|
+
say '¡Kamisaraki! Yo soy Yanapiri, tu ayudante, y necesito algunos datos antes de empezar:', :bold
|
27
|
+
|
28
|
+
config = OpenStruct.new
|
29
|
+
config.github_token = ask 'Token de GitHub (lo necesito para armar los pull requests):'
|
30
|
+
config.orga = ask 'Organización por defecto:'
|
31
|
+
|
32
|
+
begin
|
33
|
+
bot = crear_bot config
|
34
|
+
success "Los pull requests serán creados por @#{bot.github_user.login}, asegurate de que tenga los permisos necesarios en las organizaciones que uses."
|
35
|
+
dump_global_config! config
|
36
|
+
rescue Octokit::Unauthorized
|
37
|
+
raise 'El access token de GitHub no es correcto, revisalo por favor.'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
desc 'init', 'Inicializa una carpeta para contener entregas'
|
42
|
+
def init
|
43
|
+
config = OpenStruct.new
|
44
|
+
config.orga = ask 'Nombre de la organización:', default: File.basename(Dir.pwd)
|
45
|
+
success "De ahora en más, trabajaré con la organización #{config.orga} siempre que estés dentro de esta carpeta."
|
46
|
+
dump_local_config! config
|
47
|
+
end
|
48
|
+
|
49
|
+
desc 'whoami', 'Muestra organización y usuario con el que se está trabajando'
|
50
|
+
def whoami
|
51
|
+
say "Estoy trabajando en la organización #{@bot.organization}, commiteando con el usuario #{@bot.git_author}."
|
52
|
+
end
|
53
|
+
|
54
|
+
desc 'clonar [ENTREGA]', 'Clona todos los repositorios de la entrega dentro de una subcarpeta'
|
55
|
+
def clonar(nombre)
|
56
|
+
@bot.clonar_entrega!(nombre)
|
57
|
+
end
|
58
|
+
|
59
|
+
option :repo_base, {required: true, aliases: :b}
|
60
|
+
desc 'actualizar [ENTREGA]', 'Actualiza cada repositorio con el contenido que haya en el repositorio base'
|
61
|
+
def actualizar(nombre)
|
62
|
+
path_repo_base = "#{nombre}-base"
|
63
|
+
`git clone git@github.com:#{options.repo_base}.git #{path_repo_base}`
|
64
|
+
|
65
|
+
foreach_repo(nombre) do
|
66
|
+
`git remote rm base`
|
67
|
+
`git remote add base ../../#{path_repo_base}`
|
68
|
+
`git pull base master`
|
69
|
+
`git push origin master`
|
70
|
+
end
|
71
|
+
|
72
|
+
`rm -rf #{path_repo_base}`
|
73
|
+
end
|
74
|
+
|
75
|
+
option :repo_base, {required: true, aliases: :b}
|
76
|
+
desc 'preparar [ENTREGA]', 'Crea el repositorio que va a servir de base para la entrega, con un solo commit en la rama master'
|
77
|
+
def preparar(nombre)
|
78
|
+
@bot.preparar_entrega! nombre, options.repo_base
|
79
|
+
end
|
80
|
+
|
81
|
+
desc 'corregir [ENTREGA]', 'Prepara la entrega para la corrección, creando los archivos y el pull request'
|
82
|
+
option :commit_base, {required: true, aliases: :b}
|
83
|
+
option :fecha_limite, {default: Time.now.to_s, aliases: :l}
|
84
|
+
option :renombrar_proyecto_wollok, {type: :boolean, default: true}
|
85
|
+
def corregir(nombre)
|
86
|
+
foreach_entrega(nombre) do |entrega|
|
87
|
+
@bot.preparar_correccion! entrega, options.renombrar_proyecto_wollok ? [TransformacionWollok] : []
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
desc 'ultimo_commit [ENTREGA]', 'Muestra la fecha del último commit de cada repositorio e indica si se pasó de la fecha límite'
|
92
|
+
option :fecha_limite, {default: Time.now.to_s, aliases: :l}
|
93
|
+
option :commit_base, {aliases: :b}
|
94
|
+
option :solo_excedidos, {type: :boolean}
|
95
|
+
def ultimo_commit(nombre)
|
96
|
+
print_table entregas(nombre)
|
97
|
+
.select {|e| not options.solo_excedidos or e.fuera_de_termino?}
|
98
|
+
.sort_by(&:fecha)
|
99
|
+
.reverse!
|
100
|
+
.map(&method(:fila_ultimo_commit))
|
101
|
+
end
|
102
|
+
|
103
|
+
no_commands do
|
104
|
+
def crear_bot(config)
|
105
|
+
Bot.new config.orga, Octokit::Client.new(access_token: config.github_token)
|
106
|
+
end
|
107
|
+
|
108
|
+
def fila_ultimo_commit(entrega)
|
109
|
+
fecha = if entrega.hay_cambios?
|
110
|
+
"hace #{time_ago_in_words entrega.fecha} (#{entrega.fecha.strftime "%d/%m/%Y %H:%M"})"
|
111
|
+
else
|
112
|
+
'(no hay cambios)'
|
113
|
+
end
|
114
|
+
|
115
|
+
fila = [entrega.autor, fecha, if entrega.fuera_de_termino? then '---> Fuera de término' else '' end]
|
116
|
+
color = if entrega.fuera_de_termino? then :red else :white end
|
117
|
+
fila.map {|s| set_color s, color }
|
118
|
+
end
|
119
|
+
|
120
|
+
def foreach_repo(dir_base)
|
121
|
+
Dir.chdir(dir_base) do
|
122
|
+
working_dir = Dir.pwd
|
123
|
+
repos = Dir.glob('*').select {|f| File.directory? f}.sort
|
124
|
+
|
125
|
+
for repo in repos
|
126
|
+
Dir.chdir "#{working_dir}/#{repo}" do
|
127
|
+
yield repo, working_dir
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def foreach_entrega(nombre)
|
134
|
+
foreach_repo(nombre) do |repo, base_path|
|
135
|
+
yield Entrega.new "#{base_path}/#{repo}", options.commit_base, Time.parse(options.fecha_limite)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def entregas(nombre)
|
140
|
+
resultado = []
|
141
|
+
foreach_entrega(nombre) { |e| resultado << e }
|
142
|
+
resultado
|
143
|
+
end
|
144
|
+
|
145
|
+
def global_config_file
|
146
|
+
File.expand_path "~/#{config_file_name}"
|
147
|
+
end
|
148
|
+
|
149
|
+
def local_config_file
|
150
|
+
File.expand_path config_file_name
|
151
|
+
end
|
152
|
+
|
153
|
+
def config_file_name
|
154
|
+
'.yanapiri'
|
155
|
+
end
|
156
|
+
|
157
|
+
def dump_global_config!(config)
|
158
|
+
dump_config! global_config_file, config
|
159
|
+
end
|
160
|
+
|
161
|
+
def dump_local_config!(config)
|
162
|
+
dump_config! local_config_file, config
|
163
|
+
end
|
164
|
+
|
165
|
+
def dump_config!(destination, config)
|
166
|
+
File.write destination, config.to_h.stringify_keys.to_yaml
|
167
|
+
end
|
168
|
+
|
169
|
+
def load_config(source)
|
170
|
+
if File.exist? source then YAML.load_file source else {} end
|
171
|
+
end
|
172
|
+
|
173
|
+
def options
|
174
|
+
original_options = super
|
175
|
+
defaults_global = load_config global_config_file
|
176
|
+
defaults_local = load_config local_config_file
|
177
|
+
Thor::CoreExt::HashWithIndifferentAccess.new defaults_global.merge(defaults_local).merge(original_options)
|
178
|
+
end
|
179
|
+
|
180
|
+
def raise(message)
|
181
|
+
super Thor::Error, set_color(message, :red)
|
182
|
+
end
|
183
|
+
|
184
|
+
def success(message)
|
185
|
+
say "Yuspagara. #{message}", :green
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
data/lib/yanapiri/entrega.rb
CHANGED
@@ -1,56 +1,53 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
def crear_pull_request!(bot)
|
13
|
-
bot.crear_pull_request!(@id, mensaje_pull_request)
|
14
|
-
end
|
1
|
+
module Yanapiri
|
2
|
+
class Entrega
|
3
|
+
attr_reader :id, :fecha_limite, :repo, :commit_base
|
4
|
+
|
5
|
+
def initialize(repo_path, commit_base = nil, fecha_limite = nil)
|
6
|
+
@id = File.basename repo_path
|
7
|
+
@fecha_limite = fecha_limite || Time.now + 1.second
|
8
|
+
@commit_base = commit_base || '--max-parents=0 HEAD'
|
9
|
+
@repo = Git.open repo_path
|
10
|
+
end
|
15
11
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
12
|
+
def fuera_de_termino?
|
13
|
+
@repo.checkout 'master'
|
14
|
+
@repo.log.since(@fecha_limite.iso8601).any?
|
15
|
+
end
|
20
16
|
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
def autor
|
18
|
+
@id.split('-').last
|
19
|
+
end
|
24
20
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
21
|
+
def fecha
|
22
|
+
@repo.checkout 'master'
|
23
|
+
@repo.log.first.author_date
|
24
|
+
end
|
29
25
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
26
|
+
def mensaje_pull_request
|
27
|
+
if fuera_de_termino?
|
28
|
+
"**Ojo:** tu último commit fue el #{formato_humano fecha}, pero la fecha límite era el #{formato_humano fecha_limite}.\n\n¡Tenés que respetar la fecha de entrega establecida! :point_up:"
|
29
|
+
else
|
30
|
+
''
|
31
|
+
end
|
35
32
|
end
|
36
|
-
end
|
37
33
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
34
|
+
def crear_branch!(nombre, head)
|
35
|
+
@repo.checkout head
|
36
|
+
@repo.branch(nombre).checkout
|
37
|
+
end
|
42
38
|
|
43
|
-
|
44
|
-
|
45
|
-
|
39
|
+
def contiene_archivo?(nombre)
|
40
|
+
@repo.chdir { File.exist? nombre }
|
41
|
+
end
|
46
42
|
|
47
|
-
|
48
|
-
|
49
|
-
|
43
|
+
def hay_cambios?
|
44
|
+
@repo.log.between(@commit_base, 'master').any?
|
45
|
+
end
|
50
46
|
|
51
|
-
|
47
|
+
private
|
52
48
|
|
53
|
-
|
54
|
-
|
49
|
+
def formato_humano(fecha)
|
50
|
+
fecha.strftime("%d/%m/%Y a las %H:%M")
|
51
|
+
end
|
55
52
|
end
|
56
|
-
end
|
53
|
+
end
|
@@ -1,18 +1,20 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
def self.transformar!(entrega, bot)
|
7
|
-
entrega.repo.chdir do
|
8
|
-
xml = File.read proyecto_wollok
|
9
|
-
File.open(proyecto_wollok, "w") {|file| file.puts xml.sub(/<name>.*<\/name>/, "<name>#{entrega.id}</name>") }
|
1
|
+
module Yanapiri
|
2
|
+
module TransformacionWollok
|
3
|
+
def self.aplica?(entrega)
|
4
|
+
entrega.contiene_archivo? proyecto_wollok
|
10
5
|
end
|
11
6
|
|
12
|
-
|
13
|
-
|
7
|
+
def self.transformar!(entrega, bot)
|
8
|
+
entrega.repo.chdir do
|
9
|
+
xml = File.read proyecto_wollok
|
10
|
+
File.open(proyecto_wollok, "w") {|file| file.puts xml.sub(/<name>.*<\/name>/, "<name>#{entrega.id}</name>") }
|
11
|
+
end
|
14
12
|
|
15
|
-
|
16
|
-
|
13
|
+
bot.commit! entrega.repo, 'Renombrado proyecto Wollok'
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.proyecto_wollok
|
17
|
+
'.project'
|
18
|
+
end
|
17
19
|
end
|
18
20
|
end
|
data/lib/yanapiri/version.rb
CHANGED
data/lib/yanapiri.rb
CHANGED
@@ -11,190 +11,9 @@ require_relative './yanapiri/version'
|
|
11
11
|
require_relative './yanapiri/entrega'
|
12
12
|
require_relative './yanapiri/bot'
|
13
13
|
require_relative './yanapiri/transformacion_wollok'
|
14
|
+
require_relative './yanapiri/cli'
|
14
15
|
|
15
16
|
module Yanapiri
|
16
|
-
class CLI < Thor
|
17
|
-
include Thor::Actions
|
18
|
-
include ActionView::Helpers::DateHelper
|
19
|
-
|
20
|
-
class_option :orga, {aliases: :o}
|
21
|
-
class_option :github_token
|
22
|
-
|
23
|
-
def initialize(args = [], local_options = {}, config = {})
|
24
|
-
super(args, local_options, config)
|
25
|
-
@bot = Bot.new(options.orga, options.github_token)
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.exit_on_failure?
|
29
|
-
true
|
30
|
-
end
|
31
|
-
|
32
|
-
map %w(--version -v) => :version
|
33
|
-
desc "--version, -v", "Muestra la versión actual de Yanapiri"
|
34
|
-
def version
|
35
|
-
say "yanapiri version #{VERSION}"
|
36
|
-
end
|
37
|
-
|
38
|
-
desc 'setup', 'Configura a Yanapiri para el primer uso'
|
39
|
-
def setup
|
40
|
-
say '¡Kamisaraki! Yo soy Yanapiri, tu ayudante, y necesito algunos datos antes de empezar:', :bold
|
41
|
-
|
42
|
-
config = OpenStruct.new
|
43
|
-
config.github_token = ask 'Token de GitHub (lo necesito para armar los pull requests):'
|
44
|
-
config.orga = ask 'Organización por defecto:'
|
45
|
-
|
46
|
-
begin
|
47
|
-
bot = Bot.new(config.orga, config.github_token)
|
48
|
-
success "Los pull requests serán creados por @#{bot.github_user.login}, asegurate de que tenga los permisos necesarios en las organizaciones que uses."
|
49
|
-
dump_global_config! config
|
50
|
-
rescue Octokit::Unauthorized
|
51
|
-
raise 'El access token de GitHub no es correcto, revisalo por favor.'
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
desc 'init', 'Inicializa una carpeta para contener entregas'
|
56
|
-
def init
|
57
|
-
config = OpenStruct.new
|
58
|
-
config.orga = ask 'Nombre de la organización:', default: File.basename(Dir.pwd)
|
59
|
-
success "De ahora en más, trabajaré con la organización #{config.orga} siempre que estés dentro de esta carpeta."
|
60
|
-
dump_local_config! config
|
61
|
-
end
|
62
|
-
|
63
|
-
desc 'whoami', 'Muestra organización y usuario con el que se está trabajando'
|
64
|
-
def whoami
|
65
|
-
say "Estoy trabajando en la organización #{@bot.organization}, commiteando con el usuario #{@bot.git_author}."
|
66
|
-
end
|
67
|
-
|
68
|
-
desc 'clonar [ENTREGA]', 'Clona todos los repositorios de la entrega dentro de una subcarpeta'
|
69
|
-
def clonar(nombre)
|
70
|
-
@bot.clonar_entrega!(nombre)
|
71
|
-
end
|
72
|
-
|
73
|
-
option :repo_base, {required: true, aliases: :b}
|
74
|
-
desc 'actualizar [ENTREGA]', 'Actualiza cada repositorio con el contenido que haya en el repositorio base'
|
75
|
-
def actualizar(nombre)
|
76
|
-
path_repo_base = "#{nombre}-base"
|
77
|
-
`git clone git@github.com:#{options.repo_base}.git #{path_repo_base}`
|
78
|
-
|
79
|
-
foreach_repo(nombre) do
|
80
|
-
`git remote rm base`
|
81
|
-
`git remote add base ../../#{path_repo_base}`
|
82
|
-
`git pull base master`
|
83
|
-
`git push origin master`
|
84
|
-
end
|
85
|
-
|
86
|
-
`rm -rf #{path_repo_base}`
|
87
|
-
end
|
88
|
-
|
89
|
-
option :repo_base, {required: true, aliases: :b}
|
90
|
-
desc 'preparar [ENTREGA]', 'Crea el repositorio que va a servir de base para la entrega, con un solo commit en la rama master'
|
91
|
-
def preparar(nombre)
|
92
|
-
@bot.preparar_entrega! nombre, options.repo_base
|
93
|
-
end
|
94
|
-
|
95
|
-
desc 'corregir [ENTREGA]', 'Prepara la entrega para la corrección, creando los archivos y el pull request'
|
96
|
-
option :commit_base, {required: true, aliases: :b}
|
97
|
-
option :fecha_limite, {default: Time.now.to_s, aliases: :l}
|
98
|
-
def corregir(nombre)
|
99
|
-
foreach_entrega(nombre) do |entrega|
|
100
|
-
@bot.preparar_correccion! entrega
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
desc 'ultimo_commit [ENTREGA]', 'Muestra la fecha del último commit de cada repositorio e indica si se pasó de la fecha límite'
|
105
|
-
option :fecha_limite, {default: Time.now.to_s, aliases: :l}
|
106
|
-
option :commit_base, {aliases: :b}
|
107
|
-
option :solo_excedidos, {type: :boolean}
|
108
|
-
def ultimo_commit(nombre)
|
109
|
-
print_table entregas(nombre)
|
110
|
-
.select {|e| not options.solo_excedidos or e.fuera_de_termino?}
|
111
|
-
.sort_by(&:fecha)
|
112
|
-
.reverse!
|
113
|
-
.map(&method(:fila_ultimo_commit))
|
114
|
-
end
|
115
|
-
|
116
|
-
no_commands do
|
117
|
-
def fila_ultimo_commit(entrega)
|
118
|
-
fecha = if entrega.hay_cambios?
|
119
|
-
"hace #{time_ago_in_words entrega.fecha} (#{entrega.fecha.strftime "%d/%m/%Y %H:%M"})"
|
120
|
-
else
|
121
|
-
'(no hay cambios)'
|
122
|
-
end
|
123
|
-
|
124
|
-
fila = [entrega.autor, fecha, if entrega.fuera_de_termino? then '---> Fuera de término' else '' end]
|
125
|
-
color = if entrega.fuera_de_termino? then :red else :white end
|
126
|
-
fila.map {|s| set_color s, color }
|
127
|
-
end
|
128
|
-
|
129
|
-
def foreach_repo(dir_base)
|
130
|
-
Dir.chdir(dir_base) do
|
131
|
-
working_dir = Dir.pwd
|
132
|
-
repos = Dir.glob('*').select {|f| File.directory? f}.sort
|
133
|
-
|
134
|
-
for repo in repos
|
135
|
-
Dir.chdir "#{working_dir}/#{repo}" do
|
136
|
-
yield repo, working_dir
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def foreach_entrega(nombre)
|
143
|
-
foreach_repo(nombre) do |repo, base_path|
|
144
|
-
yield Entrega.new base_path, repo, options.commit_base, Time.parse(options.fecha_limite)
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
def entregas(nombre)
|
149
|
-
resultado = []
|
150
|
-
foreach_entrega(nombre) { |e| resultado << e }
|
151
|
-
resultado
|
152
|
-
end
|
153
|
-
|
154
|
-
def global_config_file
|
155
|
-
File.expand_path "~/#{config_file_name}"
|
156
|
-
end
|
157
|
-
|
158
|
-
def local_config_file
|
159
|
-
File.expand_path config_file_name
|
160
|
-
end
|
161
|
-
|
162
|
-
def config_file_name
|
163
|
-
'.yanapiri'
|
164
|
-
end
|
165
|
-
|
166
|
-
def dump_global_config!(config)
|
167
|
-
dump_config! global_config_file, config
|
168
|
-
end
|
169
|
-
|
170
|
-
def dump_local_config!(config)
|
171
|
-
dump_config! local_config_file, config
|
172
|
-
end
|
173
|
-
|
174
|
-
def dump_config!(destination, config)
|
175
|
-
File.write destination, config.to_h.stringify_keys.to_yaml
|
176
|
-
end
|
177
|
-
|
178
|
-
def load_config(source)
|
179
|
-
if File.exist? source then YAML.load_file source else {} end
|
180
|
-
end
|
181
|
-
|
182
|
-
def options
|
183
|
-
original_options = super
|
184
|
-
defaults_global = load_config global_config_file
|
185
|
-
defaults_local = load_config local_config_file
|
186
|
-
Thor::CoreExt::HashWithIndifferentAccess.new defaults_global.merge(defaults_local).merge(original_options)
|
187
|
-
end
|
188
|
-
|
189
|
-
def raise(message)
|
190
|
-
super Thor::Error, set_color(message, :red)
|
191
|
-
end
|
192
|
-
|
193
|
-
def success(message)
|
194
|
-
say "Yuspagara. #{message}", :green
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|
198
17
|
end
|
199
18
|
|
200
19
|
I18n.load_path << Dir[File.join(File.dirname(__FILE__), '/locales') + '/*.yml']
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yanapiri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Federico Aloi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-05-
|
11
|
+
date: 2019-05-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -174,6 +174,7 @@ files:
|
|
174
174
|
- lib/locales/es-AR.yml
|
175
175
|
- lib/yanapiri.rb
|
176
176
|
- lib/yanapiri/bot.rb
|
177
|
+
- lib/yanapiri/cli.rb
|
177
178
|
- lib/yanapiri/entrega.rb
|
178
179
|
- lib/yanapiri/transformacion_wollok.rb
|
179
180
|
- lib/yanapiri/version.rb
|