Compare commits

..

17 Commits

Author SHA1 Message Date
alexey
cbe4505d1e Fix for empty changelog 2026-03-16 20:19:59 +03:00
alexey
97b6db5b31 Fix version pasring for temporary build projects 2026-03-16 20:06:49 +03:00
alexey
46b2bc0d8e Fixed error on incorrect change log 2026-03-15 23:38:58 +03:00
Alexey Berezhok
77ee51c606 Update version 2025-12-27 16:36:04 +03:00
Alexey Berezhok
e0aedae6e0 Update documentation 2025-12-27 16:05:23 +03:00
Alexey Berezhok
4d0b237127 Added git info and docs updates 2025-12-26 23:01:25 +03:00
Alexey Berezhok
d098ffd3d0 Fixed typo in page templates 2025-12-25 23:39:27 +03:00
Alexey Berezhok
4eb58fc8ad Fixed project deletion errors 2025-12-25 23:32:53 +03:00
Alexey Berezhok
40f8a546f5 Added work with snapshots. Part 2 2025-12-25 15:10:24 +03:00
Alexey Berezhok
5dd481a81c Added snapshot. Part 2 2025-12-24 23:20:41 +03:00
Alexey Berezhok
8b4410eee7 Added snapshot 2025-12-24 23:01:50 +03:00
Alexey Berezhok
bacea404e2 Recreate repo on clean 2025-12-23 23:57:23 +03:00
Alexey Berezhok
5e59ea319f Added deleting of signed rpms on clean rpms 2025-12-23 23:45:33 +03:00
Alexey Berezhok
5f784270e2 Added deletion rpms 2025-12-23 23:33:01 +03:00
Alexey Berezhok
97ee27fe79 Fixed repoview generator 2025-12-05 00:06:26 +03:00
Alexey Berezhok
482a586b6e Added clean mock cache 2025-12-04 23:18:15 +03:00
Alexey Berezhok
f2136260c9 Added build time showing
Fixed package downloading 503 error
2025-12-03 23:47:03 +03:00
34 changed files with 890 additions and 24 deletions

10
VERSION
View File

@@ -1,3 +1,13 @@
0.4-3
* Исправлена ошибка при обнаружении некорректного Changelog
0.4-2
* Добавлена возможность создания снимков неподписанного репозитория
* Добавлена возможность управлять снимками репозитория
* Добавлена возможность очистки старых пакетов репозитория
* Добавленана возможность очищать закешированные билдруты
* Окружение сборке по умолчанию переключено на AlmaLinux
0.3-1 0.3-1
* Добавлена возможность добавлять сборки в состоянии ожидания * Добавлена возможность добавлять сборки в состоянии ожидания
* Изменена сортировка пакетов в repoview * Изменена сортировка пакетов в repoview

400
app.rb
View File

@@ -419,6 +419,177 @@ get "/prjedit/:id" do
end end
end end
get "/prjclean/:id" do
prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil?
print_error_page(503, "Путь к проектам не существует")
else
prj_info = prj.get_project(params["id"])
if prj_info.nil?
print_error_page(503, "Путь к проектам не существует")
else
@page_name = prj_info[:projname]
@proj_name = prj_info[:projname]
@proj_descr = prj_info[:descr]
@proj_id = prj_info[:id]
@proj_public = prj_info[:public]
@proj_tmpbuild = prj_info[:tmpstpbuild]
erb :prjclean1
end
end
end
post "/prjclean/:id" do
prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil?
print_error_page(503, "Путь к проектам не существует")
else
prj_info = prj.get_project(params["id"])
if prj_info.nil?
print_error_page(503, "Путь к проектам не существует")
else
if params["cancel"].nil? && params["delete"] == "delete" && !params["isclean"].nil?
redirect "/prjclean_step2/#{params["id"]}"
end
redirect "/prjedit/#{params["id"]}"
end
end
end
get "/prjclean_step2/:id" do
prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil?
print_error_page(503, "Путь к проектам не существует")
else
prj_info = prj.get_project(params["id"])
@page_name = prj_info[:projname]
@proj_name = prj_info[:projname]
@proj_id = prj_info[:id]
filepath = ""
proj_path = prj.get_project_repo(params["id"])
f_path = File.join(proj_path, filepath)
if File.exist?(f_path)
erb :prjclean2
else
print_error_page(503, "Файл не существует")
end
end
end
post "/prjclean_step2/:id" do
prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil?
print_error_page(503, "Путь к проектам не существует")
else
prj_info = prj.get_project(params["id"])
if prj_info.nil?
print_error_page(503, "Путь к проектам не существует")
else
if params["cancel"].nil? && params["delete"] == "delete" && params["inputvernum"].to_i > 0
numb = params["inputvernum"]
redirect "/prjclean_step3/#{params["id"]}?numb=#{numb}"
end
redirect "/prjedit/#{params["id"]}"
end
end
end
get "/prjclean_step3/:id" do
prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil?
print_error_page(503, "Путь к проектам не существует")
else
if params["numb"].to_i > 0
prj_info = prj.get_project(params["id"])
@page_name = prj_info[:projname]
@proj_name = prj_info[:projname]
@proj_descr = prj_info[:descr]
@proj_id = prj_info[:id]
filepath = ""
proj_path = prj.get_project_repo(params["id"])
f_path = File.join(proj_path, filepath)
rpm_list_stay = []
if File.exist?(f_path)
rpm_list = get_rpms_list_full(f_path)
repo = RepoManager.new(f_path)
rpm_result_list = {}
numb = params["numb"].to_i
rpm_list.each do |item|
f_name = File.basename item
rpm_info = repo.get_rpm_info(item)
if rpm_info[:error].nil?
p_name = "#{rpm_info[:pkginfo].name}"
if f_name =~ /\.src\.rpm$/
p_name = "#{rpm_info[:pkginfo].name}_src"
end
if rpm_result_list[p_name].nil?
rpm_result_list[p_name] = [[rpm_info[:pkginfo], item, rpm_info[:pkginfo].version]]
else
rpm_result_list[p_name] << [rpm_info[:pkginfo], item, rpm_info[:pkginfo].version]
rpm_result_list[p_name].sort! do |a, b|
if a[2] < b[2]
1
elsif a[2] > b[2]
-1
else
a[2] <=> b[2]
end
end
if rpm_result_list[p_name].length > numb
rpm_result_list[p_name].pop
end
end
else
rpm_list_stay << item
end
end
rpm_result_list.each_pair do |k, v|
v.each do |item|
rpm_list_stay << item[1]
end
end
delete_rpm_list = rpm_list - rpm_list_stay
@del_list = delete_rpm_list
erb :prjclean3
else
print_error_page(503, "Файл не существует")
end
else
print_error_page(503, "Число оставшихся пакетов должно быть более 0")
end
end
end
post "/prjclean_step3/:id" do
prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil?
print_error_page(503, "Путь к проектам не существует")
else
prj_info = prj.get_project(params["id"])
if prj_info.nil?
print_error_page(503, "Путь к проектам не существует")
else
if params["cancel"].nil? && params["delete"] == "delete" && !params["prjrpmlst"].nil? && params["prjrpmlst"].length > 0
@page_name = prj_info[:projname]
@proj_name = prj_info[:projname]
@proj_descr = prj_info[:descr]
@proj_id = prj_info[:id]
params["prjrpmlst"].each do |item|
File.unlink(item)
end
prj.recreate_repo(@proj_id)
@rpm_list = params["prjrpmlst"]
erb :prjclean3_post
else
redirect "/prjedit/#{params["id"]}"
end
end
end
end
post "/prjagit/:id" do post "/prjagit/:id" do
prj = ProjectsActions.new(cfg.get_projects_path, db) prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil? if prj.path.nil?
@@ -613,7 +784,6 @@ post "/prjcfg/:id" do
if prj_info.nil? if prj_info.nil?
print_error_page(503, "Путь к проектам не существует") print_error_page(503, "Путь к проектам не существует")
else else
pp params
unless params["cancel"].nil? unless params["cancel"].nil?
redirect "/prjedit/#{params["id"]}" redirect "/prjedit/#{params["id"]}"
else else
@@ -981,7 +1151,8 @@ get "/buildinfofraw" do
print_error_page(503, "Файл не найден") print_error_page(503, "Файл не найден")
else else
if !File.binary?(params["file"]) && params["file"].start_with?(File.join(Dir.pwd(), cfg.get_projects_path)) if !File.binary?(params["file"]) && params["file"].start_with?(File.join(Dir.pwd(), cfg.get_projects_path))
send_file params["file"] f_name = File.basename(params["file"])
send_file(params["file"], :filename => f_name, :type => "application/octet-stream", :disposition => 'attachment')
else else
print_error_page(503, "Файл не может быть скачан") print_error_page(503, "Файл не может быть скачан")
end end
@@ -1060,10 +1231,15 @@ get "/prjrpm/:id" do
@file_content << "Версия пакета: #{rpm_info.version}" @file_content << "Версия пакета: #{rpm_info.version}"
@file_content << "" @file_content << ""
@file_content << "Changelog:" @file_content << "Changelog:"
rpm_info.changelog.first(10).each do |entry| begin
@file_content << "#{entry.time} #{entry.name}" rpm_info.changelog.first(10).each do |entry|
@file_content << "#{entry.text}" @file_content << "#{entry.time} #{entry.name}"
@file_content << "---------------" @file_content << "#{entry.text}"
@file_content << "---------------"
end
rescue
# Если есть ошибка с undefined local variable or method, пропускаем changelog
@file_content << "Changelog недоступен"
end end
@file_content << "---------------" @file_content << "---------------"
@file_content << "Файлы:" @file_content << "Файлы:"
@@ -1378,7 +1554,6 @@ end
get "/prjsignview/:id/*" do get "/prjsignview/:id/*" do
data_path = params[:splat] data_path = params[:splat]
pp data_path
if data_path.nil? || data_path.first.strip == "" if data_path.nil? || data_path.first.strip == ""
data_path = "index.html" data_path = "index.html"
end end
@@ -1407,6 +1582,209 @@ get "/prjsignview/:id/*" do
end end
end end
get "/prjshot/:id" do
prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil?
print_error_page(503, "Путь к проектам не существует")
else
prj_info = prj.get_project(params["id"])
@page_name = prj_info[:projname]
@proj_name = prj_info[:projname]
@proj_descr = prj_info[:descr]
@proj_id = prj_info[:id]
filepath = ""
proj_path = prj.get_project_repo(params["id"])
f_path = File.join(proj_path, filepath)
@rpms_list = []
if File.exist?(f_path)
@snap_list = prj.get_snap_list(prj_info[:id])
unless params["snap"].nil?
snap_shot = prj.get_project_snap(@proj_id, params["snap"])
if File.exist?(snap_shot)
@rpms_list = get_rpms_list(snap_shot)
end
end
@rpms_list = [ "Снимок не выбран" ] if @rpms_list.length == 0
erb :prjshot1
else
print_error_page(503, "Репозиторий не существует")
end
end
end
get "/prjsnap_add/:id" do
prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil?
print_error_page(503, "Путь к проектам не существует")
else
prj_info = prj.get_project(params["id"])
@page_name = prj_info[:projname]
@proj_name = prj_info[:projname]
@proj_descr = prj_info[:descr]
@proj_id = prj_info[:id]
filepath = ""
proj_path = prj.get_project_repo(params["id"])
f_path = File.join(proj_path, filepath)
if File.exist?(f_path)
erb :prjshot_add
else
print_error_page(503, "Репозиторий не существует")
end
end
end
post "/prjsnap_add/:id" do
prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil?
print_error_page(503, "Путь к проектам не существует")
else
prj_info = prj.get_project(params["id"])
if prj_info.nil?
print_error_page(503, "Путь к проектам не существует")
else
if params["cancel"].nil? && params["create"] == "create" && !params["yes"].nil?
prj.create_snapshot(prj_info[:id])
end
redirect "/prjshot/#{params["id"]}"
end
end
end
get "/prjsnap_delete/:id" do
prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil?
print_error_page(503, "Путь к проектам не существует")
else
prj_info = prj.get_project(params["id"])
@page_name = prj_info[:projname]
@proj_name = prj_info[:projname]
@proj_descr = prj_info[:descr]
@proj_id = prj_info[:id]
@snap_name = params["snap"]
if @snap_name.nil?
print_error_page(503, "Не указано имя снимка")
else
filepath = ""
proj_path = prj.get_project_snap(params["id"], params["snap"])
f_path = File.join(proj_path, filepath)
if File.exist?(f_path)
erb :prjshot_delete
else
print_error_page(503, "Снимок не существует")
end
end
end
end
post "/prjsnap_delete/:id" do
prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil?
print_error_page(503, "Путь к проектам не существует")
else
prj_info = prj.get_project(params["id"])
@page_name = prj_info[:projname]
@proj_name = prj_info[:projname]
@proj_descr = prj_info[:descr]
@proj_id = prj_info[:id]
@snap_name = params["snap"]
if @snap_name.nil?
print_error_page(503, "Не указано имя снимка")
else
filepath = ""
proj_path = prj.get_project_snap(params["id"], params["snap"])
f_path = File.join(proj_path, filepath)
if File.exist?(f_path)
if params["cancel"].nil? && params["delete"] == "delete" && !params["yes"].nil?
prj.delete_snapshot(prj_info[:id], @snap_name)
end
redirect "/prjshot/#{params["id"]}"
else
print_error_page(503, "Снимок не существует")
end
end
end
prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil?
print_error_page(503, "Путь к проектам не существует")
else
prj_info = prj.get_project(params["id"])
if prj_info.nil?
print_error_page(503, "Путь к проектам не существует")
else
end
end
end
get "/prjsnap_restore/:id" do
prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil?
print_error_page(503, "Путь к проектам не существует")
else
prj_info = prj.get_project(params["id"])
@page_name = prj_info[:projname]
@proj_name = prj_info[:projname]
@proj_descr = prj_info[:descr]
@proj_id = prj_info[:id]
@snap_name = params["snap"]
if @snap_name.nil?
print_error_page(503, "Не указано имя снимка")
else
filepath = ""
proj_path = prj.get_project_snap(params["id"], params["snap"])
f_path = File.join(proj_path, filepath)
if File.exist?(f_path)
erb :prjsnap_restore
else
print_error_page(503, "Снимок не существует")
end
end
end
end
post "/prjsnap_restore/:id" do
prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil?
print_error_page(503, "Путь к проектам не существует")
else
prj_info = prj.get_project(params["id"])
@page_name = prj_info[:projname]
@proj_name = prj_info[:projname]
@proj_descr = prj_info[:descr]
@proj_id = prj_info[:id]
@snap_name = params["snap"]
if @snap_name.nil?
print_error_page(503, "Не указано имя снимка")
else
filepath = ""
proj_path = prj.get_project_snap(params["id"], params["snap"])
f_path = File.join(proj_path, filepath)
if File.exist?(f_path)
if params["cancel"].nil? && params["restore"] == "restore" && !params["yes"].nil?
prj.restore_snapshot(prj_info[:id], @snap_name)
end
redirect "/prjshot/#{params["id"]}"
else
print_error_page(503, "Снимок не существует")
end
end
end
prj = ProjectsActions.new(cfg.get_projects_path, db)
if prj.path.nil?
print_error_page(503, "Путь к проектам не существует")
else
prj_info = prj.get_project(params["id"])
if prj_info.nil?
print_error_page(503, "Путь к проектам не существует")
else
end
end
end
get "/sanitize" do get "/sanitize" do
#Подчистим гит проекты, которые есть в базе, но нет в файловой системе #Подчистим гит проекты, которые есть в базе, но нет в файловой системе
all_gits = db.get_gits all_gits = db.get_gits
@@ -1437,6 +1815,14 @@ get "/sanitize" do
erb :sanitize erb :sanitize
end end
get "/buildsclean" do
@page_name = "Очистка окружений сборок"
mock_cache_path = "/var/cache/mock/"
@list_cleaned = get_dirs_in_mock_cache(mock_cache_path)
MockManager.clean_mock
erb :buildsclean
end
not_found do not_found do
status 404 status 404
@page_name = "Кто-то потерялся" @page_name = "Кто-то потерялся"

View File

@@ -320,7 +320,7 @@ class DBase
end end
def get_builds() def get_builds()
$DDB["select t1.id as buildid, t1.create_at as createat, t1.result as state, t2.reponame as reponame, t2.id as gitid, t3.id as projid, t3.projname as prjname, count(*) as pkgcnt from buildtask as t1 join repos as t2 on t1.repo_id = t2.id join projects as t3 on t1.proj_id = t3.id left join build_rpm as t4 on t4.build_id = t1.id group by buildid, createat, state, reponame, projid, prjname, gitid order by t1.id desc"].all $DDB["select t1.id as buildid, t1.create_at as createat, t1.result as state, case when buildstart is null then 0 when buildstop is null then 0 else Cast((JulianDay(buildstop) - JulianDay(buildstart))*24*60*60 As Integer) end as timeproc, t2.reponame as reponame, t2.id as gitid, t3.id as projid, t3.projname as prjname, count(*) as pkgcnt from buildtask as t1 join repos as t2 on t1.repo_id = t2.id join projects as t3 on t1.proj_id = t3.id left join build_rpm as t4 on t4.build_id = t1.id group by buildid, createat, state, reponame, projid, prjname, gitid order by t1.id desc"].all
end end
def get_build_info(build_id) def get_build_info(build_id)
@@ -341,11 +341,11 @@ class DBase
end end
def get_builds_for_project(prj_id) def get_builds_for_project(prj_id)
$DDB["select t1.id as buildid, t1.create_at as createat, t1.result as state, t2.reponame as reponame, t2.id as gitid, t3.id as projid, t3.projname as prjname, count(*) as pkgcnt from buildtask as t1 join repos as t2 on t1.repo_id = t2.id join projects as t3 on t1.proj_id = t3.id left join build_rpm as t4 on t4.build_id = t1.id where t1.proj_id = ? group by buildid, createat, state, reponame, projid, prjname, gitid order by t1.id desc", prj_id.to_i].all $DDB["select t1.id as buildid, t1.create_at as createat, t1.result as state, case when buildstart is null then 0 when buildstop is null then 0 else Cast((JulianDay(buildstop) - JulianDay(buildstart))*24*60*60 As Integer) end as timeproc,t2.reponame as reponame, t2.id as gitid, t3.id as projid, t3.projname as prjname, count(*) as pkgcnt from buildtask as t1 join repos as t2 on t1.repo_id = t2.id join projects as t3 on t1.proj_id = t3.id left join build_rpm as t4 on t4.build_id = t1.id where t1.proj_id = ? group by buildid, createat, state, reponame, projid, prjname, gitid order by t1.id desc", prj_id.to_i].all
end end
def get_builds_for_project_git(prj_id, git_id) def get_builds_for_project_git(prj_id, git_id)
$DDB["select t1.id as buildid, t1.create_at as createat, t1.result as state, t2.reponame as reponame, t2.id as gitid, t3.id as projid, t3.projname as prjname, count(*) as pkgcnt from buildtask as t1 join repos as t2 on t1.repo_id = t2.id join projects as t3 on t1.proj_id = t3.id left join build_rpm as t4 on t4.build_id = t1.id where t1.proj_id = ? and t1.repo_id = ? group by buildid, createat, state, reponame, projid, prjname, gitid order by t1.id desc", prj_id.to_i, git_id.to_i].all $DDB["select t1.id as buildid, t1.create_at as createat, t1.result as state, case when buildstart is null then 0 when buildstop is null then 0 else Cast((JulianDay(buildstop) - JulianDay(buildstart))*24*60*60 As Integer) end as timeproc ,t2.reponame as reponame, t2.id as gitid, t3.id as projid, t3.projname as prjname, count(*) as pkgcnt from buildtask as t1 join repos as t2 on t1.repo_id = t2.id join projects as t3 on t1.proj_id = t3.id left join build_rpm as t4 on t4.build_id = t1.id where t1.proj_id = ? and t1.repo_id = ? group by buildid, createat, state, reponame, projid, prjname, gitid order by t1.id desc", prj_id.to_i, git_id.to_i].all
end end
def delete_git_from_project(prj_id, git_id) def delete_git_from_project(prj_id, git_id)
@@ -354,15 +354,27 @@ class DBase
end end
def delete_project(prj_id) def delete_project(prj_id)
result = ProjectsProjects.where(proj_id_repository: prj_id.to_i)
count = 0
result.each do |item|
count = count + 1
end
return 1 if count > 0
ReposProjects.where(proj_id: prj_id.to_i).delete ReposProjects.where(proj_id: prj_id.to_i).delete
ProjectsReposSpec.where(proj_id: prj_id.to_i).delete ProjectsReposSpec.where(proj_id: prj_id.to_i).delete
builds = BuildTask.where(proj_id: prj_id.to_i) builds = BuildTask.where(proj_id: prj_id.to_i)
builds.each do |item| builds.each do |item|
rpms = BuildRpms.where(build_id: item[:id]) rpms = BuildRpms.where(build_id: item[:id])
Rpms.where(id: rpms[:rpm_id]).delete rpms.each do |rpm|
rpm_id_t = rpm[:rpm_id]
BuildRpms.where(build_id: item[:id], rpm_id: rpm_id_t).delete
Rpms.where(id: rpm_id_t).delete
end
end end
BuildTask.where(proj_id: prj_id.to_i).delete BuildTask.where(proj_id: prj_id.to_i).delete
ProjectsProjects.where(proj_id: prj_id.to_i).delete
Projects.where(id: prj_id.to_i).delete Projects.where(id: prj_id.to_i).delete
0
end end
def projects_with_current_as_link(prj_id) def projects_with_current_as_link(prj_id)
@@ -392,4 +404,12 @@ class DBase
def cancel_hang_builds() def cancel_hang_builds()
BuildTask.where(result: [0, 3]).update(result: 4) BuildTask.where(result: [0, 3]).update(result: 4)
end end
def update_build_task_begin_time(build_id)
BuildTask.where(id: build_id.to_i).update(buildstart: DateTime.now)
end
def update_build_task_end_time(build_id)
BuildTask.where(id: build_id.to_i).update(buildstop: DateTime.now)
end
end end

View File

@@ -72,6 +72,24 @@ class GitRepo
repos_data repos_data
end end
def git_walker(repo, tree, dir_name, result)
tree.each_tree do |entry|
new_tree = repo.lookup(entry[:oid])
result = git_walker(repo, new_tree, "#{dir_name}/#{entry[:name]}", result)
end
tree.each_blob { |entry| result << "#{dir_name}/#{entry[:name]}" }
result
end
def get_git_tree(repo, ref, result)
tree = ref.target.tree
result = git_walker(repo, tree, "", result)
end
def repo_info(reponame, branch = nil) def repo_info(reponame, branch = nil)
info = {} info = {}
result = "" result = ""
@@ -97,6 +115,7 @@ class GitRepo
info[:commits] = [] info[:commits] = []
info[:branches] = [] info[:branches] = []
info[:tags] = [] info[:tags] = []
info[:files] = []
else else
ref = repo.head ref = repo.head
unless branch.nil? unless branch.nil?
@@ -104,6 +123,7 @@ class GitRepo
ref = repo.references[ref_name] ref = repo.references[ref_name]
end end
commits = [] commits = []
files = []
unless ref.nil? unless ref.nil?
walker = Rugged::Walker.new(repo) walker = Rugged::Walker.new(repo)
walker.sorting(Rugged::SORT_DATE) walker.sorting(Rugged::SORT_DATE)
@@ -111,10 +131,15 @@ class GitRepo
commits = walker.map do |commit| commits = walker.map do |commit|
{ :message => commit.message, :author => commit.author, :time => commit.time, :sha => commit.oid } { :message => commit.message, :author => commit.author, :time => commit.time, :sha => commit.oid }
end.first(10) end.first(10)
unless ref.target.nil? && ref.target.tree.nil?
files = get_git_tree(repo, ref, files)
end
end end
info[:commits] = commits info[:commits] = commits
info[:branches] = repo.branches.each_name(:local).sort info[:branches] = repo.branches.each_name(:local).sort
info[:tags] = repo.tags.map { |tag| tag.name } info[:tags] = repo.tags.map { |tag| tag.name }
info[:files] = files
end end
else else
@error = result @error = result

View File

@@ -117,12 +117,20 @@ class MockManager
bld_id = @build_id.to_i bld_id = @build_id.to_i
bld_str = "%010d" % bld_id bld_str = "%010d" % bld_id
dt_str = dt.strftime("%Y%m%d_#{bld_str}") dt_str = dt.strftime("%Y%m%d_#{bld_str}")
cmd_args = %Q(/usr/bin/rpm -q --specfile #{spec_file} --queryformat "%{RELEASE}") cmd_args = %Q(/usr/bin/rpm -q --specfile #{spec_file} --queryformat "%{RELEASE}\n" 2>/dev/null)
@log.debug(cmd_args) @log.debug(cmd_args)
cmd = Runner.new(cmd_args, @log) cmd = Runner.new(cmd_args, @log)
cmd.run cmd.run
if cmd.exit_status == 0 if cmd.exit_status == 0
res = "#{cmd.stdout}.#{dt_str}" res = "#{cmd.stdout}.#{dt_str}"
versions = "#{cmd.stdout}".split("\n")
if versions.length()>0
res = versions[0].strip
res = "#{res}.#{dt_str}"
else
res = cmd.stdout.strip
res = "#{res}.#{dt_str}"
end
line_array = [] line_array = []
File.readlines(spec_file).each do |line| File.readlines(spec_file).each do |line|
if line =~ /^[\t ]*[Rr]elease:/ if line =~ /^[\t ]*[Rr]elease:/
@@ -281,11 +289,12 @@ class MockManager
global_lock.rewind global_lock.rewind
build_info = @db.get_build_task_status(build_id) build_info = @db.get_build_task_status(build_id)
unless build_info.nil? unless build_info.nil?
if build_info[:result].to_i == 4 if build_info[:result].to_i == 4
return return
end end
end end
@db.update_build_task_status(@build_id, 0) @db.update_build_task_status(@build_id, 0)
@db.update_build_task_begin_time(@build_id)
if @spec == "" if @spec == ""
@error = true @error = true
@@ -312,11 +321,18 @@ class MockManager
else else
@db.update_build_task_status(@build_id, 2) @db.update_build_task_status(@build_id, 2)
end end
@db.update_build_task_end_time(@build_id)
global_lock.flock(File::LOCK_UN) global_lock.flock(File::LOCK_UN)
end end
end end
@db.after_fork @db.after_fork
end
def self.clean_mock
cmd_args = %Q(/usr/bin/mock --scrub-all-chroots)
cmd = Runner.new(cmd_args)
cmd.run_clean
end end
end end

View File

@@ -12,6 +12,7 @@ PROJECTS_STRUCTURE = {
:SRCPRP => "srcprp", :SRCPRP => "srcprp",
:SIGNED => "signed", :SIGNED => "signed",
:SRC => "src", :SRC => "src",
:SNAP => "snapshot",
} }
class ProjectsActions class ProjectsActions
@@ -71,6 +72,11 @@ class ProjectsActions
File.join(proj_path, PROJECTS_STRUCTURE[:REPO]) File.join(proj_path, PROJECTS_STRUCTURE[:REPO])
end end
def get_project_snap(id, snap)
proj_path = get_project_path(id)
File.join(proj_path, PROJECTS_STRUCTURE[:SNAP], snap)
end
def get_project_path_git(id, gitname) def get_project_path_git(id, gitname)
proj_path = get_project_path(id) proj_path = get_project_path(id)
File.join(proj_path, PROJECTS_STRUCTURE[:SRC], gitname) File.join(proj_path, PROJECTS_STRUCTURE[:SRC], gitname)
@@ -367,7 +373,9 @@ class ProjectsActions
if linked.nil? || linked.length == 0 if linked.nil? || linked.length == 0
proj_path = get_project_path(prj_id) proj_path = get_project_path(prj_id)
FileUtils.rm_rf(proj_path, secure: true) FileUtils.rm_rf(proj_path, secure: true)
@db.delete_project(prj_id) if @db.delete_project(prj_id) != 0
@error = "На текущий проект ссылаются другие проекты. Удаление запрещено"
end
else else
@error = "На текущий проект ссылаются другие проекты. Удаление запрещено" @error = "На текущий проект ссылаются другие проекты. Удаление запрещено"
end end
@@ -405,6 +413,12 @@ class ProjectsActions
end end
end end
rpm_signed_list = get_rpms_list(sign_repo_path) rpm_signed_list = get_rpms_list(sign_repo_path)
if rpm_signed_list.length > rpm_list.length
rpms_for_delete = get_rpms_list_full(sign_repo_path)
rpms_for_delete.each do |item|
File.unlink(item)
end
end
rpm_list = rpm_list.select do |item| rpm_list = rpm_list.select do |item|
sign_repo_path_rpm = File.join(sign_repo_path, item) sign_repo_path_rpm = File.join(sign_repo_path, item)
unless File.exist?(sign_repo_path_rpm) unless File.exist?(sign_repo_path_rpm)
@@ -461,4 +475,67 @@ class ProjectsActions
path = get_project_path(id) path = get_project_path(id)
File.join(path, PROJECTS_STRUCTURE[:SIGNED]) File.join(path, PROJECTS_STRUCTURE[:SIGNED])
end end
def recreate_repo(id)
proj_path = get_project_path(id)
repo_path = File.join(proj_path, PROJECTS_STRUCTURE[:REPO])
repoman = RepoManager.new(repo_path)
repoman.create_repo
end
def get_snap_list(id)
proj_path = get_project_path(id)
snap_path = File.join(proj_path, PROJECTS_STRUCTURE[:SNAP])
unless Dir.exist?(snap_path)
FileUtils.mkdir_p(snap_path)
end
snap_list = Dir.glob(File.join(snap_path, "*")).select { |path| File.directory?(path) }.map { |dir| File.basename(dir) }
return snap_list
end
def create_snapshot(id)
proj_path = get_project_path(id)
snap_path = File.join(proj_path, PROJECTS_STRUCTURE[:SNAP])
repo_path = File.join(proj_path, PROJECTS_STRUCTURE[:REPO])
unless Dir.exist?(snap_path)
FileUtils.mkdir_p(snap_path)
end
date_str = Time.now.strftime("%Y-%m-%d")
snapshot_dir = "#{date_str}_0"
while Dir.exist?(File.join(snap_path, snapshot_dir))
num = snapshot_dir.split("_").last.to_i
num += 1
snapshot_dir = "#{date_str}_#{num}"
end
snapshot_full_path = File.join(snap_path, snapshot_dir)
FileUtils.cp_r(repo_path, snapshot_full_path)
end
def delete_snapshot(id, snap)
proj_path = get_project_path(id)
snap_path = get_project_snap(id, snap)
snap_path_base = File.join(proj_path, PROJECTS_STRUCTURE[:SNAP])
unless snap_path == snap_path_base || "#{snap_path}/" == snap_path_base || snap_path == "#{snap_path_base}/"
if File.exist?(snap_path)
FileUtils.rm_rf(snap_path)
end
end
end
def restore_snapshot(id, snap)
repo_path = get_project_repo(id)
snap_path = get_project_snap(id, snap)
if Dir.exist?(repo_path) && Dir.exist?(snap_path)
Dir.glob(File.join(repo_path, '*')).each { |file| File.unlink(file) if File.file?(file) || FileUtils.rm_rf(file) }
FileUtils.cp_r(Dir.glob(File.join(snap_path, '*')), repo_path)
end
end
end end

View File

@@ -103,7 +103,11 @@ class RepoManager
pkg_info[:stat] = File.stat(full_rpm_path).ctime pkg_info[:stat] = File.stat(full_rpm_path).ctime
pkg_info[:pname] = "noname" pkg_info[:pname] = "noname"
if info[:error].nil? if info[:error].nil?
pkg_info[:chlog] = info[:pkginfo].changelog.first(5) pkg_info[:chlog] = []
begin
pkg_info[:chlog] << info[:pkginfo].changelog.first
rescue
end
pkg_info[:pname] = info[:pkginfo].name pkg_info[:pname] = info[:pkginfo].name
else else
pkg_info[:chlog] = [] pkg_info[:chlog] = []
@@ -132,7 +136,7 @@ class RepoManager
data_keys << key.to_s data_keys << key.to_s
end end
data_keys.sort! data_keys.sort!
data_keys.each do |item| data_keys.each do |item|
repo_data << [lresult[item], item] repo_data << [lresult[item], item]
@@ -144,7 +148,7 @@ class RepoManager
{ fname: record[:fname], stat: record[:stat] } { fname: record[:fname], stat: record[:stat] }
end.sort_by do |item| end.sort_by do |item|
[item[:stat], item[:fname].downcase.ord] [item[:stat], item[:fname].downcase.ord]
end.reverse.map do |record| end.reverse.map do |record|
if record[:stat].nil? if record[:stat].nil?
["нет даты", record[:fname]] ["нет даты", record[:fname]]
else else
@@ -153,8 +157,6 @@ class RepoManager
end end
end end
pp repo_data
tpl_file = File.join(template_dir, "template.erb") tpl_file = File.join(template_dir, "template.erb")
template = File.read(tpl_file) template = File.read(tpl_file)
renderer = ERB.new(template) renderer = ERB.new(template)

View File

@@ -54,3 +54,11 @@ end
def get_rpms_list(directory) def get_rpms_list(directory)
Dir.glob(File.join(directory, "**", "*.rpm")).reject { |f| File.directory?(f) || f =~ /repodata\// }.map { |f| f.delete_prefix(directory + "/") } Dir.glob(File.join(directory, "**", "*.rpm")).reject { |f| File.directory?(f) || f =~ /repodata\// }.map { |f| f.delete_prefix(directory + "/") }
end end
def get_dirs_in_mock_cache(dir_path)
Dir.glob(File.join(dir_path, "*")).select { |f| File.directory?(f) }.map{ |f| File.basename(f) }
end
def get_rpms_list_full(directory)
Dir.glob(File.join(directory, "**", "*.rpm")).reject { |f| File.directory?(f) || f =~ /repodata\// }
end

View File

@@ -16,8 +16,8 @@ path = "locks/counter"
path = "locks/build" path = "locks/build"
[configs] [configs]
hide=open,amazon,anolis,circle,custom,euro,fedora,mageia,navy,alma,rocky hide=open,amazon,anolis,circle,custom,euro,fedora,mageia,navy,rocky
selected=msvsphere selected=alma
[pages] [pages]
items_per_page = 30 items_per_page = 30

View File

@@ -0,0 +1,6 @@
require "sequel"
Sequel.migration do
change do
end
end

View File

@@ -0,0 +1,12 @@
require "sequel"
Sequel.migration do
change do
alter_table(:buildtask) do
add_column :buildstart, DateTime
add_column :buildstop, DateTime
set_column_allow_null :buildstart
set_column_allow_null :buildstop
end
end
end

View File

@@ -8,4 +8,12 @@
* Одновременно может запускаться только одна сборка. * Одновременно может запускаться только одна сборка.
* Сборка потребляет все доступные ядра процессора * Сборка потребляет все доступные ядра процессора
* На текущий момент система является alpha сборкой, поэтому подавление ошибок не включено, для детального отслеживания ошибок * На текущий момент система является alpha сборкой, поэтому подавление ошибок не включено, для детального отслеживания ошибок
## Особые указания
Внизу страницы веб интерфейса есть нижняя панель управления. Там имеется два сервисных пункта меню:
`Сбросить buildroots` - со временем, при большом количестве сборок, кэш mock-билдера может разрастаться, для освобождения кэшей рекомендуется периодически запускать сброс с помощью данного пункта меню.
`Подчистка` - проводится инвентаризация гит-проектов и если в базе данных нет записи, то она добавляется. Этот пункт дает возможность подложить гит-проекты и одним нажатием добавить их в веб-интерфейс.

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 74 KiB

View File

@@ -25,6 +25,7 @@
* Списка тегов * Списка тегов
* Строки для клонирования репозитория * Строки для клонирования репозитория
* Описание репозитория * Описание репозитория
* Списка файлов указанной ветки репозитория
Список тегов и коммитов даст информацию о том, что исходные коды в ветке master находятся в нужно состоянии ис нужными коммитами. Список тегов и коммитов даст информацию о том, что исходные коды в ветке master находятся в нужно состоянии ис нужными коммитами.
Сборочница производит выборку исходных кодов из master ветки git репозитория. Сборочница производит выборку исходных кодов из master ветки git репозитория.
@@ -37,6 +38,10 @@
Для успешного клонирования и наполнения git репозитория, необходимо либо установить публичный ключ для доступа пользователя по ssh или знать пароль к mockgui пользователю по ssh. Вот почему в [инсталляционном руководстве](../install.md) рекомендуется установить пароль для mockgui пользователя. Для успешного клонирования и наполнения git репозитория, необходимо либо установить публичный ключ для доступа пользователя по ssh или знать пароль к mockgui пользователю по ssh. Вот почему в [инсталляционном руководстве](../install.md) рекомендуется установить пароль для mockgui пользователя.
Вкладка отображения списка файлов репозитория и указанной ветки или HEAD:
![Информация о git репозитории](../img/mockgui_creategit5_1.png)
## Удаление git репозитория ## Удаление git репозитория
Удаление возможно только в том случае, если данный git репозиторий не имеет ни рецептов сборки, а так же не подключен ни к одному проекту и соответственно, не имеет сборок, указывающих на данный git репозиторий. Удаление возможно только в том случае, если данный git репозиторий не имеет ни рецептов сборки, а так же не подключен ни к одному проекту и соответственно, не имеет сборок, указывающих на данный git репозиторий.

View File

@@ -56,6 +56,34 @@
Отображается структура репозитория, где можно перемещаться по папкам и нажимать на rpm пакеты, получая о них информацию. Отображается структура репозитория, где можно перемещаться по папкам и нажимать на rpm пакеты, получая о них информацию.
`Управление снимками репозитория` - это ссылка настраницу, где можно создать снимок `неопубликоанного` репозитория, восстановить пакеты из сохраненного писка или удалить ранее созданные снимки или посмотреть содержимое снимков.
Данная опция полезна при деструктивных изменениях в проекте, например собирается пакет с сомнительным функционалом и лучше перед сборкой создать снимок, чтоб можно было потом откатить изменения обратно.
Пример создания и управления снимками.
Так выглядит страница управления снимками:
![Снимки репозитория](../img/mockgui_projects20_1.png)
Слева список снимков, справа - содержимое выбранного снимка.
Пример отображения содержимого:
![Снимки репозитория](../img/mockgui_projects20_2.png)
Напротив каждого снимка есть занчок "Корзина" и "Стрелочка". Нажимая на корзинку - можно удалить снимок, а на жимая на стрелочку - восстановить пакеты из снимка. При восстановлении, пакеты из неподписанного репозитория удаляются и заменяются пакетами из снимка. Далее их можно переподписать и они переместятся в репозиторий с подписанными пакетами.
Для создания снимка необхоимо нажать на знак "+".
Важно отметить, что для создания, удаления или восстановления снимка открывается дополнительный экран:
![Снимки репозитория](../img/mockgui_projects20_3.png)
Для подтвержения действия недостаточно только нажать на кнопку "Создать", "Удалить", "Восстановить". Важно еще сделать активным флажок.
Этот флажок подтверждает действие окончательно. Если его не установить, то ничего не произойдет и операция не будет выполнена.
`Список сборок проектов` - отображается список сборок, принадлежащих проекту. `Список сборок проектов` - отображается список сборок, принадлежащих проекту.
В данном списке можно получить информацию о каждой сборке. Детальнее о [сборках](builds.md) В данном списке можно получить информацию о каждой сборке. Детальнее о [сборках](builds.md)
@@ -101,6 +129,12 @@ gpgcheck=1" > /etc/yum.repos.d/project_test1.repo
т.е устанавливается корректный url будущего удаленного репозитория. т.е устанавливается корректный url будущего удаленного репозитория.
`Удалить старые версии пакетов` - позволяет подчистить накопившиеся старые версии пакетов, остаются только заданное число самых свежив версий.
При нажатии, так же нужно подтвердить намерение удаления и указать, число версий пакета, которые должны быть оставлены. Но нужно быть аккуратным, например некоторые пакеты требуют наличие более старых версий при сборке.
Именно для этого, перед удалением выдается сисок всех пакетов, которые планируются к удалению. И в данном списке можно отменить удаление отдельных пакетов.
`Удалить проект` - удаляется весь проект, подписанные и неподписанные репозитории, сборки. `Удалить проект` - удаляется весь проект, подписанные и неподписанные репозитории, сборки.
Но если проект залинкован в другом проекте, то удаление будет невозможным, пока не будет снят линк. Но если проект залинкован в другом проекте, то удаление будет невозможным, пока не будет снят линк.

23
views/buildsclean.erb Normal file
View File

@@ -0,0 +1,23 @@
<%= erb :header %>
<div class="container">
<div class="row">
<div class="col-md-4"></div>
<div class="col-md-4">
<div class="card">
<div class="card-header">
<h5 class="mb-0">Подчистка окружений сборок произошла успешно</h5>
</div>
<div class="card-body">
<p class="card-text">Ни один проект не был очищен, очищены только окружения сборок. Это значит, что следующая сборка будет длится дольше, но некоторые ошибки накопившиеся в кэше сборки будут устранены</p>
<ul class="list-group">
<% @list_cleaned.each do |item| %>
<li class="list-group-item"><%= item %></li>
<% end %>
</ul>
</div>
</div>
</div>
<div class="col-md-4"></div>
</div>
</div>
<%= erb :footer %>

View File

@@ -8,6 +8,7 @@
<th scope="col" class="text-center">git репозиторий</th> <th scope="col" class="text-center">git репозиторий</th>
<th scope="col" class="text-center">Дата сборки</th> <th scope="col" class="text-center">Дата сборки</th>
<th scope="col" class="text-center">Число собранных пакетов</th> <th scope="col" class="text-center">Число собранных пакетов</th>
<th scope="col" class="text-center">Время сборки</th>
<th scope="col" class="text-center">Состояние</th> <th scope="col" class="text-center">Состояние</th>
<th scope="col" class="text-center">Перейти к сборке</th> <th scope="col" class="text-center">Перейти к сборке</th>
</tr> </tr>
@@ -42,6 +43,7 @@
<td class="text-center"><a href="/prjgitf/<%= ERB::Util.url_encode(item[:projid]) %>/<%= ERB::Util.url_encode(item[:gitid]) %>"><%= item[:reponame] %></a></td> <td class="text-center"><a href="/prjgitf/<%= ERB::Util.url_encode(item[:projid]) %>/<%= ERB::Util.url_encode(item[:gitid]) %>"><%= item[:reponame] %></a></td>
<td class="text-center"><%= item[:createat] %></td> <td class="text-center"><%= item[:createat] %></td>
<td class="text-center"><%= item[:pkgcnt] %></td> <td class="text-center"><%= item[:pkgcnt] %></td>
<td class="text-center"><%= item[:timeproc] %> сек</td>
<td class="text-center <%= cl %>"> <td class="text-center <%= cl %>">
<%= st %> <%= st %>
</td> </td>

View File

@@ -7,6 +7,7 @@
<li class="list-inline-item me-4"><a class="link-light" href="https://brepo.ru">Документация</a></li> <li class="list-inline-item me-4"><a class="link-light" href="https://brepo.ru">Документация</a></li>
<li class="list-inline-item me-4"><a class="link-light" href="https://dev.brepo.ru">Разработка</a></li> <li class="list-inline-item me-4"><a class="link-light" href="https://dev.brepo.ru">Разработка</a></li>
<li class="list-inline-item"><a class="link-light" href="/sanitize">Подчистка</a></li> <li class="list-inline-item"><a class="link-light" href="/sanitize">Подчистка</a></li>
<li class="list-inline-item"><a class="link-light" href="/buildsclean">Сбросить buildroots</a></li>
</ul> </ul>
<ul class="list-inline"> <ul class="list-inline">
<li class="list-inline-item me-4"><a href="https://dev.brepo.ru"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16" class="bi bi-github text-light"> <li class="list-inline-item me-4"><a href="https://dev.brepo.ru"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" fill="currentColor" viewBox="0 0 16 16" class="bi bi-github text-light">

View File

@@ -6,6 +6,7 @@
<li class="nav-item" role="presentation"><a class="nav-link" role="tab" data-bs-toggle="tab" href="#tab-2">Список коммитов</a></li> <li class="nav-item" role="presentation"><a class="nav-link" role="tab" data-bs-toggle="tab" href="#tab-2">Список коммитов</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" role="tab" data-bs-toggle="tab" href="#tab-3">Список тэгов</a></li> <li class="nav-item" role="presentation"><a class="nav-link" role="tab" data-bs-toggle="tab" href="#tab-3">Список тэгов</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" role="tab" data-bs-toggle="tab" href="#tab-4">Клонировать</a></li> <li class="nav-item" role="presentation"><a class="nav-link" role="tab" data-bs-toggle="tab" href="#tab-4">Клонировать</a></li>
<li class="nav-item" role="presentation"><a class="nav-link" role="tab" data-bs-toggle="tab" href="#tab-5">Список файлов</a></li>
</ul> </ul>
<div class="tab-content"> <div class="tab-content">
<div class="tab-pane active" role="tabpanel" id="tab-1"> <div class="tab-pane active" role="tabpanel" id="tab-1">
@@ -123,6 +124,34 @@
</div> </div>
</div> </div>
</div> </div>
<div class="tab-pane" role="tabpanel" id="tab-5">
<div class="container">
<div class="row align-items-start">
<div class="col-10">
<p style="font-weight: bold;"><%= @repo_data[:info][:reponame] %></p>
</div>
</div>
<div class="row align-items-start">
<div class="col-4" style="background: #d3e2ff;border-radius: 15px;padding-top: 20px;padding-bottom: 20px;">
<p>
<% if @repo_data[:info][:descr].nil? || @repo_data[:info][:descr] == "" %>
"Нет описания"
<% else %>
<%= @repo_data[:info][:descr] %>
<% end %>
</p>
</div>
<div class="col-6">
<p style="color: var(--bs-red);">Список файлов</p>
<ul>
<% @repo_data[:files].each do |tags| %>
<li><%= tags %></li>
<% end %>
</ul>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -9,6 +9,7 @@
<th scope="col" class="text-center">git репозиторий</th> <th scope="col" class="text-center">git репозиторий</th>
<th scope="col" class="text-center">Дата сборки</th> <th scope="col" class="text-center">Дата сборки</th>
<th scope="col" class="text-center">Число собранных пакетов</th> <th scope="col" class="text-center">Число собранных пакетов</th>
<th scope="col" class="text-center">Время сборки</th>
<th scope="col" class="text-center">Состояние</th> <th scope="col" class="text-center">Состояние</th>
<th scope="col" class="text-center">Перейти к сборке</th> <th scope="col" class="text-center">Перейти к сборке</th>
</tr> </tr>
@@ -43,6 +44,7 @@
<td class="text-center"><a href="/prjgitf/<%= ERB::Util.url_encode(item[:projid]) %>/<%= ERB::Util.url_encode(item[:gitid]) %>"><%= item[:reponame] %></a></td> <td class="text-center"><a href="/prjgitf/<%= ERB::Util.url_encode(item[:projid]) %>/<%= ERB::Util.url_encode(item[:gitid]) %>"><%= item[:reponame] %></a></td>
<td class="text-center"><%= item[:createat] %></td> <td class="text-center"><%= item[:createat] %></td>
<td class="text-center"><%= item[:pkgcnt] %></td> <td class="text-center"><%= item[:pkgcnt] %></td>
<td class="text-center"><%= item[:timeproc] %> сек</td>
<td class="text-center <%= cl %>"> <td class="text-center <%= cl %>">
<%= st %> <%= st %>
</td> </td>

View File

@@ -9,6 +9,7 @@
<th scope="col" class="text-center">git репозиторий</th> <th scope="col" class="text-center">git репозиторий</th>
<th scope="col" class="text-center">Дата сборки</th> <th scope="col" class="text-center">Дата сборки</th>
<th scope="col" class="text-center">Число собранных пакетов</th> <th scope="col" class="text-center">Число собранных пакетов</th>
<th scope="col" class="text-center">Время сборки</th>
<th scope="col" class="text-center">Состояние</th> <th scope="col" class="text-center">Состояние</th>
<th scope="col" class="text-center">Перейти к сборке</th> <th scope="col" class="text-center">Перейти к сборке</th>
</tr> </tr>
@@ -43,6 +44,7 @@
<td class="text-center"><a href="/prjgitf/<%= ERB::Util.url_encode(item[:projid]) %>/<%= ERB::Util.url_encode(item[:gitid]) %>"><%= item[:reponame] %></a></td> <td class="text-center"><a href="/prjgitf/<%= ERB::Util.url_encode(item[:projid]) %>/<%= ERB::Util.url_encode(item[:gitid]) %>"><%= item[:reponame] %></a></td>
<td class="text-center"><%= item[:createat] %></td> <td class="text-center"><%= item[:createat] %></td>
<td class="text-center"><%= item[:pkgcnt] %></td> <td class="text-center"><%= item[:pkgcnt] %></td>
<td class="text-center"><%= item[:timeproc] %> сек</td>
<td class="text-center <%= cl %>"> <td class="text-center <%= cl %>">
<%= st %> <%= st %>
</td> </td>

18
views/prjclean1.erb Normal file
View File

@@ -0,0 +1,18 @@
<%= erb :header %>
<div class="container">
<h2 class="text-center">Удаление сатрых версий пакетов проекта <%= @proj_name %></h2>
<form action="/prjclean/<%= ERB::Util.url_encode(@proj_id) %>" method="post">
<div class="form-check form-switch text-center pb-3">
<input class="form-check-input" type="checkbox" role="switch" id="isclean" name="isclean">
<label class="form-check-label" for="isclean">
Вы уверены, что хотите удалить старые версии пакетов?<br />
Все старые версии пакетов проекта будут удалены, действие не подлежит отмене.
</label>
</div>
<div class="mb-3 text-center">
<button type="submit" class="btn btn-primary" name="cancel" value="cancel">Отменить</button>
<button type="submit" class="btn btn-danger" name="delete" value="delete">Удалить</button>
</div>
</form>
</div>
<%= erb :footer %>

18
views/prjclean2.erb Normal file
View File

@@ -0,0 +1,18 @@
<%= erb :header %>
<div class="container">
<h2 class="text-center">Удаление сатрых версий пакетов проекта <%= @proj_name %></h2>
<form action="/prjclean_step2/<%= ERB::Util.url_encode(@proj_id) %>" method="post">
<div class="form-check form-switch text-center pb-3">
<label for="inputvernum" class="form-label">Число версий</label>
<input type="text" id="inputvernum" name="inputvernum" class="form-control" aria-describedby="vernumHelpBlock">
<div id="vernumHelpBlock" class="form-text">
Укажите число версий каждого пакета, которые должны остаться
</div>
</div>
<div class="mb-3 text-center">
<button type="submit" class="btn btn-primary" name="cancel" value="cancel">Отменить</button>
<button type="submit" class="btn btn-danger" name="delete" value="delete">Удалить</button>
</div>
</form>
</div>
<%= erb :footer %>

41
views/prjclean3.erb Normal file
View File

@@ -0,0 +1,41 @@
<%= erb :header %>
<script src="/js/jquery.dropdown.min.js"></script>
<div class="container">
<div class="row">
<div class="col-4">
<h3 class="bg-secondary-subtle text-center border-bottom border-primary-subtle rounded-1 pb-1 mb-2">
<a href="/prjedit/<%= ERB::Util.url_encode(@proj_id) %>"><%= @proj_name %></a>
</h3>
<div class="pb-2"><%= @proj_descr %></div>
</div>
<div class="col-8">
<div class="vstack gap-3">
<form action="/prjclean_step3/<%= ERB::Util.url_encode(@proj_id) %>" method="post">
<div class="mb-3">
<label for="prjrpmlst" class="form-label">Пакеты для удаления (могут быть удалены из списка)</label>
<div class="prjrpmlist">
<select class="form-control" id="prjrpmlst" name="prjrpmlst[]" multiple>
<% @del_list.each do |item| %>
<option value="<%= item %>" selected><%= File.basename(item) %></option>
<% end %>
</select>
</div>
</div>
<div class="container">
<div style="padding-top: 45px;"></div>
</div>
<div class="mb-3 text-center">
<button type="submit" class="btn btn-primary" name="cancel" value="cancel">Отменить</button>
<button type="submit" class="btn btn-danger" name="delete" value="delete">Удалить</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script>
$('.prjrpmlist').dropdown({
searchNoData: '<li style="color:#ddd">Нет данных</li>',
});
</script>
<%= erb :footer %>

22
views/prjclean3_post.erb Normal file
View File

@@ -0,0 +1,22 @@
<%= erb :header %>
<div class="container">
<div class="row">
<div class="col-4">
<h3 class="bg-secondary-subtle text-center border-bottom border-primary-subtle rounded-1 pb-1 mb-2">
<a href="/prjedit/<%= ERB::Util.url_encode(@proj_id) %>"><%= @proj_name %></a>
</h3>
<div class="pb-2"><%= @proj_descr %></div>
</div>
<div class="col-8">
<div class="vstack gap-3">
<ul class="list-group">
<li class="list-group-item active" aria-current="true">Список удаленных пакетов (не забудьте пересоздать repoview)</li>
<% @rpm_list.each do |item| %>
<li class="list-group-item"><%= item %></li>
<% end %>
</ul>
</div>
</div>
</div>
</div>
<%= erb :footer %>

View File

@@ -49,6 +49,8 @@
<a href="/prjrpm/<%= ERB::Util.url_encode(@proj_id) %>" class="list-group-item list-group-item-action list-group-item-dark icon-link"><i <a href="/prjrpm/<%= ERB::Util.url_encode(@proj_id) %>" class="list-group-item list-group-item-action list-group-item-dark icon-link"><i
class="bi bi-box"></i><span class="ms-2">Список всех class="bi bi-box"></i><span class="ms-2">Список всех
пакетов</span></a> пакетов</span></a>
<a href="/prjshot/<%= ERB::Util.url_encode(@proj_id) %>" class="list-group-item list-group-item-action list-group-item-dark icon-link"><i
class="bi bi-camera-fill"></i><span class="ms-2">Управление снимками репозитория</span></a>
<a href="/prjbuilds/<%= ERB::Util.url_encode(@proj_id) %>" class="list-group-item list-group-item-action list-group-item-dark icon-link"><i <a href="/prjbuilds/<%= ERB::Util.url_encode(@proj_id) %>" class="list-group-item list-group-item-action list-group-item-dark icon-link"><i
class="bi bi-list"></i><span class="ms-2">Список сборок проекта</span></a> class="bi bi-list"></i><span class="ms-2">Список сборок проекта</span></a>
<a href="/prjsign/<%= ERB::Util.url_encode(@proj_id) %>" class="list-group-item list-group-item-action list-group-item-dark icon-link"><i <a href="/prjsign/<%= ERB::Util.url_encode(@proj_id) %>" class="list-group-item list-group-item-action list-group-item-dark icon-link"><i
@@ -57,6 +59,8 @@
class="bi bi-file-earmark-diff"></i><span class="ms-2">Просмотр подписанного репозитория</span></a> class="bi bi-file-earmark-diff"></i><span class="ms-2">Просмотр подписанного репозитория</span></a>
<a href="/prjremoteaddr/<%= ERB::Util.url_encode(@proj_id) %>" class="list-group-item list-group-item-action list-group-item-dark icon-link"><i <a href="/prjremoteaddr/<%= ERB::Util.url_encode(@proj_id) %>" class="list-group-item list-group-item-action list-group-item-dark icon-link"><i
class="bi bi-pin-map-fill"></i><span class="ms-2">Установить адрес подписаннго репозитория</span></a> class="bi bi-pin-map-fill"></i><span class="ms-2">Установить адрес подписаннго репозитория</span></a>
<a href="/prjclean/<%= ERB::Util.url_encode(@proj_id) %>" class="list-group-item list-group-item-action list-group-item-dark icon-link"><i
class="bi bi-suitcase"></i><span class="ms-2">Удалить старые версии пакетов</span></a>
<a href="/prjdelete/<%= ERB::Util.url_encode(@proj_id) %>" class="list-group-item list-group-item-action list-group-item-dark icon-link"><i <a href="/prjdelete/<%= ERB::Util.url_encode(@proj_id) %>" class="list-group-item list-group-item-action list-group-item-dark icon-link"><i
class="bi bi-trash"></i><span class="ms-2">Удалить проект</span></a> class="bi bi-trash"></i><span class="ms-2">Удалить проект</span></a>
</div> </div>

42
views/prjshot1.erb Normal file
View File

@@ -0,0 +1,42 @@
<%= erb :header %>
<div class="container">
<div class="row">
<div class="col-4">
<h3 class="bg-secondary-subtle text-center border-bottom border-primary-subtle rounded-1 pb-1 mb-2">
<%= @proj_name %>
</h3>
<div class="pb-2"><%= @proj_descr %></div>
<div>
<table class="table">
<tbody>
<% @snap_list.each do |item| %>
<tr>
<td><a href="/prjshot/<%= ERB::Util.url_encode(@proj_id) %>?snap=<%= ERB::Util.url_encode(item) %>"><%= item %></a></td>
<td><a href="/prjsnap_delete/<%= ERB::Util.url_encode(@proj_id) %>?snap=<%= ERB::Util.url_encode(item) %>" class="icon-link"><i
class="bi bi-trash3"></i></a></td>
<td><a href="/prjsnap_restore/<%= ERB::Util.url_encode(@proj_id) %>?snap=<%= ERB::Util.url_encode(item) %>" class="icon-link"><i
class="bi bi-capslock"></i></a></td>
</tr>
<% end %>
</tbody>
</table>
</div>
</div>
<div class="col-8">
<div class="vstack gap-3">
<div class="p-2">
<a href="/prjsnap_add/<%= ERB::Util.url_encode(@proj_id) %>" class="icon-link"><i
class="bi bi-plus-circle"></i><span class="ms-2">Создать снимок текущего репозитория</span></a>
</div>
<div class="p-2">
<ul class="list-group">
<% @rpms_list.each do |rpm| %>
<li class="list-group-item"><%= rpm %></li>
<% end %>
</ul>
</div>
</div>
</div>
</div>
</div>
<%= erb :footer %>

17
views/prjshot_add.erb Normal file
View File

@@ -0,0 +1,17 @@
<%= erb :header %>
<div class="container">
<h2 class="text-center">Создание снимка репозитория проекта <%= @proj_name %></h2>
<form action="/prjsnap_add/<%= ERB::Util.url_encode(@proj_id) %>" method="post">
<div class="form-check form-switch text-center pb-3">
<input class="form-check-input" type="checkbox" role="switch" id="yes" name="yes">
<label class="form-check-label" for="yes">
Вы уверены, что хотите создать копию текущего репозитория?
</label>
</div>
<div class="mb-3 text-center">
<button type="submit" class="btn btn-primary" name="cancel" value="cancel">Отменить</button>
<button type="submit" class="btn btn-success" name="create" value="create">Создать</button>
</div>
</form>
</div>
<%= erb :footer %>

18
views/prjshot_delete.erb Normal file
View File

@@ -0,0 +1,18 @@
<%= erb :header %>
<div class="container">
<h2 class="text-center">Удаление снимка проекта <%= @proj_name %></h2>
<form action="/prjsnap_delete/<%= ERB::Util.url_encode(@proj_id) %>?snap=<%= ERB::Util.url_encode(@snap_name) %>" method="post">
<div class="form-check form-switch text-center pb-3">
<input class="form-check-input" type="checkbox" role="switch" id="yes" name="yes">
<label class="form-check-label" for="yes">
Вы уверены, что хотите удалить снимок <%= @snap_name %>?<br />
Все пакеты из снимка будут удалены, действие не подлежит отмене.
</label>
</div>
<div class="mb-3 text-center">
<button type="submit" class="btn btn-primary" name="cancel" value="cancel">Отменить</button>
<button type="submit" class="btn btn-danger" name="delete" value="delete">Удалить</button>
</div>
</form>
</div>
<%= erb :footer %>

18
views/prjsnap_restore.erb Normal file
View File

@@ -0,0 +1,18 @@
<%= erb :header %>
<div class="container">
<h2 class="text-center">Восстановить пакеты репозитория <%= @proj_name %> из снимка</h2>
<form action="/prjsnap_restore/<%= ERB::Util.url_encode(@proj_id) %>?snap=<%= ERB::Util.url_encode(@snap_name) %>" method="post">
<div class="form-check form-switch text-center pb-3">
<input class="form-check-input" type="checkbox" role="switch" id="yes" name="yes">
<label class="form-check-label" for="yes">
Вы уверены, что хотите восстановить пакеты из снимка <%= @snap_name %>?<br />
Все пакеты в текущем репозитории будут перезаписаны, действие не подлежит отмене.
</label>
</div>
<div class="mb-3 text-center">
<button type="submit" class="btn btn-primary" name="cancel" value="cancel">Отменить</button>
<button type="submit" class="btn btn-danger" name="restore" value="restore">Восстановить</button>
</div>
</form>
</div>
<%= erb :footer %>