yanapiri 0.2.4 → 0.3.0
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 +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
|