gitfed-install now bootstraps gitfed-ctl for future updates
Installs it straight into /usr/local/bin via a throwaway golang container right after the pod comes up, so a fresh instance is ready for sudo gitfed-ctl without a manual step. Best-effort — falls back to deploy/update.sh in the success screen's suggestions if it fails. Also fixes the gitfed-ctl install instructions in INSTALL.md, verified live: go install run directly on the VPS fails since nothing puts a system Go there.
4 files changed
+60 −2
M
CHANGELOG.md
+5 −0
M
cmd/gitfed-install/actions.go
+16 −0
M
cmd/gitfed-install/model.go
+23 −1
M
cmd/gitfed-install/screens_finish.go
+16 −1
CHANGELOG.md
@@ -2,6 +2,11 @@
A bullet starting with `**BREAKING:**` flags a change gitfed-ctl's update wizard makes you acknowledge individually before it will let you upgrade past that version.
+## 1.2.9
+
+- `gitfed-install` now installs `gitfed-ctl` into `/usr/local/bin` itself (via a throwaway `golang` container, no system Go needed on the host — same trick the fix below uses) right after the pod comes up, so a fresh instance is ready for `sudo gitfed-ctl` updates without a separate manual step. Best-effort: a failure here doesn't block the install, it just falls back to `deploy/update.sh` in the final screen's suggestions.
+- Fixed `INSTALL.md`'s `gitfed-ctl` install instructions from 1.2.8: `go install` run directly on the VPS fails, since nothing in the install flow puts a system Go there (the main image build compiles inside Docker). Verified fix: run it inside a throwaway `golang:1.25-bookworm` container instead, writing straight into `/usr/local/bin`.
+
## 1.2.8
- New `gitfed-ctl`: an update utility for instances that follow someone else's releases rather than cutting their own. Runs locally on the VPS (no SSH-to-self, no repeated password prompt — the problem with `deploy/update.sh current` observed live), checks for new versions, makes any `**BREAKING:**` CHANGELOG.md entry something you have to individually acknowledge before continuing, optionally backs up the data volume, then rebuilds and redeploys. `GOPRIVATE=git.neuromancer.ovh/* go install git.neuromancer.ovh/bastien-mrq/gitfed/cmd/gitfed-ctl@latest`, then `sudo gitfed-ctl` from inside a checkout. Account and federation-trust management stay on the web admin UI, which already covers both.
cmd/gitfed-install/actions.go
@@ -190,6 +190,22 @@ func diagnoseStuckPod(ctx context.Context, sourceDir string) tagDiagnosis {
return diagnoseImageTag(string(deployYAML), imagesOut)
}
+// installGitfedCtl installs gitfed-ctl (see cmd/gitfed-ctl) straight into
+// /usr/local/bin via a throwaway golang container — no system Go needed on
+// the host (nothing else in this flow puts one there; the main image build
+// compiles inside Docker too). The golang:1.25-bookworm base is already
+// cached locally from runBuildImage a moment ago, so this is fast, not a
+// second cold pull.
+func installGitfedCtl(ctx context.Context) error {
+ _, err := runQuiet(ctx, "", "docker", "run", "--rm",
+ "-e", "GOPRIVATE=git.neuromancer.ovh/*",
+ "-e", "GOBIN=/out",
+ "-v", "/usr/local/bin:/out",
+ "golang:1.25-bookworm",
+ "go", "install", "git.neuromancer.ovh/bastien-mrq/gitfed/cmd/gitfed-ctl@latest")
+ return err
+}
+
func runVerify(ctx context.Context, domain string) []verifyResult {
client := &http.Client{Timeout: 8 * time.Second}
check := func(label, url string) verifyResult {
cmd/gitfed-install/model.go
@@ -93,6 +93,9 @@ type model struct {
verify []verifyResult
verifyDone bool
+ ctlInstallDone bool
+ ctlInstallErr error
+
spin spinner.Model
}
@@ -198,7 +201,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.podPolling = false
if msg.err == nil && msg.status.Phase == podReady {
m.step = stepVerify
- return m, tea.Batch(m.cmdVerify(), listen(m.msgCh))
+ return m, tea.Batch(m.cmdVerify(), m.cmdInstallCtl(), listen(m.msgCh))
}
if msg.err == nil && msg.status.Phase == podErrImageNeverPull {
m.step = stepPodStuck
@@ -218,6 +221,11 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
m.verifyDone = true
return m, listen(m.msgCh)
+ case ctlInstallMsg:
+ m.ctlInstallDone = true
+ m.ctlInstallErr = msg.err
+ return m, listen(m.msgCh)
+
case accountHandoffDoneMsg:
m.step = stepSuccess
return m, listen(m.msgCh)
@@ -301,6 +309,7 @@ type podPollMsg struct {
err error
}
type verifyResultMsg struct{ results []verifyResult }
+type ctlInstallMsg struct{ err error }
type stuckDiagMsg struct{ diag tagDiagnosis }
type accountHandoffDoneMsg struct{}
type fatalErrMsg struct{ err error }
@@ -407,6 +416,19 @@ func (m model) cmdVerify() tea.Cmd {
}
}
+// cmdInstallCtl installs gitfed-ctl (the update utility, see cmd/gitfed-ctl)
+// straight into /usr/local/bin so it's ready for future updates without a
+// separate manual step — best-effort, never blocks the wizard from
+// finishing (see viewVerify/viewSuccess for how a failure here is shown).
+func (m model) cmdInstallCtl() tea.Cmd {
+ ch := m.msgCh
+ ctx := m.ctx
+ return func() tea.Msg {
+ go func() { ch <- ctlInstallMsg{err: installGitfedCtl(ctx)} }()
+ return nil
+ }
+}
+
// launchAccountTUI suspends gitfed-install and hands the terminal to a
// real, unmodified, interactive `kubectl exec -it ... gitfed-tui` session
// — see screens_finish.go for why this is a handoff rather than gitfed-
cmd/gitfed-install/screens_finish.go
@@ -14,6 +14,16 @@ func (m model) viewVerify() string {
}
b.WriteString(row(g, v.Label, v.Detail) + "\n")
}
+
+ switch {
+ case !m.ctlInstallDone:
+ b.WriteString(row(m.spin.View(), "gitfed-ctl (mises à jour futures)", "installation…") + "\n")
+ case m.ctlInstallErr != nil:
+ b.WriteString(row(glyph(statusWarn), "gitfed-ctl (mises à jour futures)", "échec — voir INSTALL.md") + "\n")
+ default:
+ b.WriteString(row(glyph(statusOK), "gitfed-ctl (mises à jour futures)", "installé") + "\n")
+ }
+
return stylePanel.Render(b.String())
}
@@ -41,9 +51,14 @@ func (m model) viewSuccess() string {
b.WriteString(row("", "Interface web", "https://"+domain) + "\n")
b.WriteString(row("", "Connexion", "https://"+domain+"/login") + "\n")
b.WriteString(row("", "Clone SSH", "git clone ssh://git@"+domain+":2222/<utilisateur>/<dépôt>") + "\n\n")
+
+ updateHint := "sudo gitfed-ctl depuis ce checkout"
+ if m.ctlInstallErr != nil {
+ updateHint = "deploy/update.sh (l'installation de gitfed-ctl a échoué — voir INSTALL.md)"
+ }
b.WriteString(styleMuted.Render(
"Suggéré pour la suite : sauvegardes régulières (deploy/backup.sh), mises à jour\n" +
- "(deploy/update.sh), et la page /security de ta propre instance pour le détail\n" +
+ "(" + updateHint + "), et la page /security de ta propre instance pour le détail\n" +
"du modèle de confiance."))
return stylePanel.Render(b.String())
}