Gitfed
bastien-mrq/gitfed / cmd / gitfed-ctl / screens_updates.go
package main

import "strings"

func (m model) viewUpdatesCheck() string {
	var b strings.Builder

	if !m.checked {
		b.WriteString(m.spin.View() + " " + styleBody.Render("Vérification des nouvelles versions…"))
		return stylePanel.Render(b.String())
	}

	if m.checkErr != nil {
		b.WriteString(styleDanger.Render("Erreur : " + m.checkErr.Error()))
		return stylePanelDanger.Render(b.String())
	}

	b.WriteString(row("", "Version actuelle", m.currentVersion) + "\n")

	if m.upToDate {
		b.WriteString("\n" + styleOK.Render("✓ instance à jour"))
		return stylePanel.Render(b.String())
	}

	b.WriteString(row(glyph(statusWarn), "Version disponible", m.targetVersion) + "\n")

	if m.fetchingVersions {
		b.WriteString("\n" + m.spin.View() + " " + styleBody.Render("Lecture du changelog…"))
	} else if m.versionsErr != nil {
		b.WriteString("\n" + styleDanger.Render("Erreur en lisant le changelog : "+m.versionsErr.Error()))
	}

	return stylePanel.Render(b.String())
}

func (m model) viewAckBreaking() string {
	var b strings.Builder
	b.WriteString(styleBody.Render("Cette mise à jour contient des changements cassants — coche chacun pour continuer.") + "\n\n")

	for i, bl := range m.breaking {
		box := "[ ]"
		if m.ackChecklist[i] {
			box = styleOK.Render("[x]")
		}
		cursor := "  "
		if i == m.ackCursor {
			cursor = styleAccent.Render("> ")
		}
		b.WriteString(cursor + box + " " + styleBody.Render(bl.Text) + "\n")
	}

	return stylePanelDanger.Render(b.String())
}

func (m model) viewConfirm() string {
	var b strings.Builder
	b.WriteString(row("", "Mise à jour", m.currentVersion+" → "+m.targetVersion) + "\n\n")

	for _, v := range m.versions {
		heading := styleBold.Render(v.Version)
		if v.TagMissing {
			heading += " " + styleMuted.Render("(tag introuvable)")
		}
		b.WriteString(heading + "\n")
		for _, bl := range v.Bullets {
			if bl.Breaking {
				continue
			}
			b.WriteString("  · " + styleBody.Render(bl.Text) + "\n")
		}
	}

	backupBox := "[ ]"
	if m.backupToggle {
		backupBox = styleOK.Render("[x]")
	}
	b.WriteString("\n" + backupBox + " " + styleBody.Render("Sauvegarder la base avant de déployer") + "\n")

	return stylePanel.Render(b.String())
}

func (m model) viewRunning() string {
	var b strings.Builder

	type namedStep struct {
		label  string
		stream string
		s      pipelineStepStatus
	}
	var steps []namedStep
	if m.backupToggle {
		steps = append(steps, namedStep{"Sauvegarde", "backup", m.backupStep})
	}
	steps = append(steps,
		namedStep{"Récupération du code", "pull", m.pullStep},
		namedStep{"Build de l'image", "build", m.buildStep},
		namedStep{"Import dans containerd", "import", m.importStep},
		namedStep{"Application du déploiement", "apply", m.applyStep},
		namedStep{"Déploiement du pod", "rollout", m.rolloutStep},
	)

	current := -1
	failed := -1
	for i, st := range steps {
		if st.s.Err != nil {
			failed = i
		}
		if current == -1 && m.pipelineErr == nil && !st.s.Done && st.s.Err == nil {
			current = i
		}
	}

	for i, st := range steps {
		switch {
		case st.s.Err != nil:
			b.WriteString(row(glyph(statusWarn), st.label, "") + "\n")
		case st.s.Done:
			b.WriteString(row(glyph(statusOK), st.label, "prêt") + "\n")
		case i == current:
			b.WriteString(row(m.spin.View(), st.label, "") + "\n")
		default:
			b.WriteString(row(glyph(statusMissing), st.label, "") + "\n")
		}
	}

	if m.pipelineErr != nil {
		b.WriteString("\n" + styleDanger.Render("Erreur : "+m.pipelineErr.Error()))
	}

	// Show the live/failed step's own captured output — this is what
	// actually explains a bare "exit status 1" (e.g. git's real refusal
	// reason, docker's real build failure, kubectl's real rejection).
	logStep := current
	if failed != -1 {
		logStep = failed
	}
	if logStep != -1 {
		if lines := m.stepLogs[steps[logStep].stream]; len(lines) > 0 {
			b.WriteString("\n\n" + styleLog.Render(tailLines(lines, 10)))
		}
	}

	return stylePanel.Render(b.String())
}

func (m model) viewSuccess() string {
	var b strings.Builder
	version := m.resolvedVersion
	if version == "" {
		version = m.targetVersion
	}
	b.WriteString(styleOK.Render("✓ v" + version + " est en ligne"))
	return stylePanel.Render(b.String())
}

func tailLines(lines []string, n int) string {
	if len(lines) == 0 {
		return styleMuted.Render("(pas encore de sortie)")
	}
	if len(lines) > n {
		lines = lines[len(lines)-n:]
	}
	return strings.Join(lines, "\n")
}