kin: KIN-049 Кнопка Deploy на странице задачи после approve. Для каждого проекта настраивается deploy-команда (git push, scp, ssh restart). В Settings проекта.

This commit is contained in:
Gros Frumos 2026-03-16 08:21:13 +02:00
parent 860ef3f6c9
commit d50bd703ae
11 changed files with 517 additions and 61 deletions

View file

@ -1,7 +1,7 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { api, type TaskFull, type PipelineStep, type PendingAction } from '../api'
import { api, type TaskFull, type PipelineStep, type PendingAction, type DeployResult } from '../api'
import Badge from '../components/Badge.vue'
import Modal from '../components/Modal.vue'
@ -262,6 +262,23 @@ async function changeStatus(newStatus: string) {
}
}
// Deploy
const deploying = ref(false)
const deployResult = ref<DeployResult | null>(null)
async function runDeploy() {
if (!task.value) return
deploying.value = true
deployResult.value = null
try {
deployResult.value = await api.deployProject(task.value.project_id)
} catch (e: any) {
error.value = e.message
} finally {
deploying.value = false
}
}
// Edit modal (pending tasks only)
const showEdit = ref(false)
const editForm = ref({ title: '', briefText: '', priority: 5 })
@ -488,6 +505,27 @@ async function saveEdit() {
<span v-if="resolvingManually" class="inline-block w-3 h-3 border-2 border-orange-400 border-t-transparent rounded-full animate-spin mr-1"></span>
{{ resolvingManually ? 'Сохраняем...' : '&#10003; Решить вручную' }}
</button>
<button v-if="task.status === 'done' && task.project_deploy_command"
@click.stop="runDeploy"
:disabled="deploying"
class="px-4 py-2 text-sm bg-teal-900/50 text-teal-400 border border-teal-800 rounded hover:bg-teal-900 disabled:opacity-50">
<span v-if="deploying" class="inline-block w-3 h-3 border-2 border-teal-400 border-t-transparent rounded-full animate-spin mr-1"></span>
{{ deploying ? 'Deploying...' : '&#x1F680; Deploy' }}
</button>
</div>
<!-- Deploy result inline block -->
<div v-if="deployResult" class="mx-0 mt-2 p-3 rounded border text-xs font-mono"
:class="deployResult.success ? 'border-teal-800 bg-teal-950/30 text-teal-300' : 'border-red-800 bg-red-950/30 text-red-300'">
<div class="flex items-center gap-2 mb-1">
<span :class="deployResult.success ? 'text-teal-400' : 'text-red-400'" class="font-semibold">
{{ deployResult.success ? '✓ Deploy succeeded' : '✗ Deploy failed' }}
</span>
<span class="text-gray-500">exit {{ deployResult.exit_code }} · {{ deployResult.duration_seconds }}s</span>
<button @click.stop="deployResult = null" class="ml-auto text-gray-600 hover:text-gray-400 bg-transparent border-none cursor-pointer text-xs"></button>
</div>
<pre v-if="deployResult.stdout" class="whitespace-pre-wrap text-gray-300 max-h-40 overflow-y-auto">{{ deployResult.stdout }}</pre>
<pre v-if="deployResult.stderr" class="whitespace-pre-wrap text-red-400/80 max-h-40 overflow-y-auto mt-1">{{ deployResult.stderr }}</pre>
</div>
<!-- Approve Modal -->