feat: добавлена пометка типа операции (Build/Push) в истории сборок Dockerfile

- Добавлена колонка 'Тип' во все таблицы истории сборок
- Для push операций отображается registry вместо платформ
- Сохранение пользователя при создании push лога
- Исправлена ошибка с logger в push_docker_image endpoint
- Улучшено отображение истории сборок с визуальными индикаторами
This commit is contained in:
Сергей Антропов
2026-02-15 22:59:02 +03:00
parent 23e1a6037b
commit 1fbf9185a2
232 changed files with 38075 additions and 5 deletions

View File

@@ -0,0 +1,307 @@
{% extends "base.html" %}
{% block title %}Создать роль - DevOpsLab{% endblock %}
{% block page_title %}Создание новой роли{% endblock %}
{% block header_actions %}
<a href="/roles" class="btn btn-secondary btn-sm">
<i class="fas fa-arrow-left me-2"></i>
Назад к списку
</a>
{% endblock %}
{% block content %}
<div x-data="roleCreator()">
<form
hx-post="/api/v1/roles/create"
hx-target="#result"
hx-swap="innerHTML"
@submit.prevent="submitForm"
class="card"
>
<div class="card-header">
<h5 class="mb-0">Шаг 1: Базовая информация</h5>
</div>
<div class="card-body">
<div class="mb-3">
<label class="form-label">Имя роли *</label>
<input
type="text"
name="role_name"
x-model="formData.role_name"
required
pattern="[a-z0-9_-]+"
class="form-control"
placeholder="nginx, docker, python"
>
<div class="form-text">
Только строчные буквы, цифры, дефисы и подчеркивания
</div>
</div>
<div class="mb-3">
<label class="form-label">Описание</label>
<textarea
name="description"
x-model="formData.description"
rows="3"
class="form-control"
placeholder="Краткое описание роли..."
></textarea>
</div>
<div class="mb-3">
<label class="form-label">Тип роли (шаблон)</label>
<select
name="template"
x-model="formData.template"
class="form-select"
>
<option value="default">По умолчанию</option>
<option value="service">Сервис (service)</option>
<option value="package">Пакеты (package)</option>
<option value="config">Конфигурация (config)</option>
</select>
</div>
</div>
</form>
<form
hx-post="/api/v1/roles/create"
hx-target="#result"
hx-swap="innerHTML"
@submit.prevent="submitForm"
class="card mt-3"
>
<div class="card-header">
<h5 class="mb-0">Шаг 2: Поддерживаемые ОС</h5>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-12 col-md-6 col-lg-4">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
value="ubuntu"
x-model="formData.platforms"
id="platform-ubuntu"
>
<label class="form-check-label" for="platform-ubuntu">
Ubuntu
</label>
</div>
</div>
<div class="col-12 col-md-6 col-lg-4">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
value="debian"
x-model="formData.platforms"
id="platform-debian"
>
<label class="form-check-label" for="platform-debian">
Debian
</label>
</div>
</div>
<div class="col-12 col-md-6 col-lg-4">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
value="centos"
x-model="formData.platforms"
id="platform-centos"
>
<label class="form-check-label" for="platform-centos">
CentOS
</label>
</div>
</div>
<div class="col-12 col-md-6 col-lg-4">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
value="rhel"
x-model="formData.platforms"
id="platform-rhel"
>
<label class="form-check-label" for="platform-rhel">
RHEL
</label>
</div>
</div>
<div class="col-12 col-md-6 col-lg-4">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
value="almalinux"
x-model="formData.platforms"
id="platform-almalinux"
>
<label class="form-check-label" for="platform-almalinux">
AlmaLinux
</label>
</div>
</div>
<div class="col-12 col-md-6 col-lg-4">
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
value="rocky"
x-model="formData.platforms"
id="platform-rocky"
>
<label class="form-check-label" for="platform-rocky">
Rocky Linux
</label>
</div>
</div>
</div>
</div>
</form>
<form
hx-post="/api/v1/roles/create"
hx-target="#result"
hx-swap="innerHTML"
@submit.prevent="submitForm"
class="card mt-3"
>
<div class="card-header">
<h5 class="mb-0">Шаг 3: Переменные (опционально)</h5>
</div>
<div class="card-body">
<div class="space-y-2 mb-3" x-ref="variablesContainer">
<template x-for="(variable, index) in formData.variables" :key="index">
<div class="row g-2 mb-2 align-items-end">
<div class="col-12 col-md-4">
<input
type="text"
x-model="variable.name"
placeholder="Имя переменной"
class="form-control"
>
</div>
<div class="col-12 col-md-4">
<input
type="text"
x-model="variable.value"
placeholder="Значение по умолчанию"
class="form-control"
>
</div>
<div class="col-12 col-md-3">
<select
x-model="variable.type"
class="form-select"
>
<option value="string">String</option>
<option value="int">Integer</option>
<option value="bool">Boolean</option>
<option value="list">List</option>
<option value="dict">Dict</option>
</select>
</div>
<div class="col-12 col-md-1">
<button
type="button"
@click="removeVariable(index)"
class="btn btn-danger btn-sm w-100"
title="Удалить"
>
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</template>
</div>
<button
type="button"
@click="addVariable"
class="btn btn-outline-secondary"
>
<i class="fas fa-plus me-2"></i>
Добавить переменную
</button>
</div>
<!-- Скрытые поля для отправки -->
<input
type="hidden"
name="role_name"
:value="formData.role_name"
>
<input
type="hidden"
name="description"
:value="formData.description"
>
<input
type="hidden"
name="template"
:value="formData.template"
>
<input
type="hidden"
name="platforms"
:value="JSON.stringify(formData.platforms)"
>
<input
type="hidden"
name="variables"
:value="JSON.stringify(formData.variables)"
>
<!-- Результат -->
<div id="result" class="card-body border-top"></div>
<!-- Кнопки -->
<div class="card-footer">
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary">
<i class="fas fa-check me-2"></i>
Создать роль
</button>
<a href="/roles" class="btn btn-secondary">
<i class="fas fa-times me-2"></i>
Отмена
</a>
</div>
</div>
</form>
</div>
<script>
function roleCreator() {
return {
formData: {
role_name: '',
description: '',
template: 'default',
platforms: [],
variables: []
},
addVariable() {
this.formData.variables.push({
name: '',
value: '',
type: 'string'
});
},
removeVariable(index) {
this.formData.variables.splice(index, 1);
},
submitForm(event) {
// HTMX обработает отправку
}
}
}
</script>
{% endblock %}