This repository has no description
1package ssh
2
3import (
4 "fmt"
5
6 "github.com/bluesky-social/indigo/atproto/syntax"
7 indigoxrpc "github.com/bluesky-social/indigo/xrpc"
8 tea "github.com/charmbracelet/bubbletea"
9 "github.com/charmbracelet/ssh"
10 wishtea "github.com/charmbracelet/wish/bubbletea"
11 "tangled.org/core/api/tangled"
12 "tangled.org/core/appview/db"
13 "tangled.org/core/hostutil"
14 extlexutil "tangled.org/core/lexutil"
15 "tangled.org/core/orm"
16)
17
18func (s *Server) teaHandler(sess ssh.Session) (tea.Model, []tea.ProgramOption) {
19 remote := sess.RemoteAddr().String()
20 args := sess.Command()
21 l := s.logger.With("remote", remote)
22 l.Info("SSH connection", "args", args)
23 defer l.Info("SSH connection closed", "remote", remote)
24
25 renderer := wishtea.MakeRenderer(sess)
26
27 if len(args) != 2 {
28 l.Warn("bad invocation", "args", args)
29 return newErrorModel(renderer, "usage: ssh -t -p <port> <host> <repoDID> <sha>"), wishtea.MakeOptions(sess)
30 }
31
32 repoDID := args[0]
33 sha := args[1]
34
35 l = l.With("repoDID", repoDID, "sha", sha)
36
37 repo, err := db.GetRepo(s.db, orm.FilterEq("repo_did", repoDID))
38 if err != nil {
39 l.Warn("repo not found", "err", err)
40 return newErrorModel(renderer, fmt.Sprintf("repo %s not found", repoDID)), wishtea.MakeOptions(sess)
41 }
42 if repo.Spindle == "" {
43 l.Warn("no spindle configured")
44 return newErrorModel(renderer, "no spindle configured for this repo"), wishtea.MakeOptions(sess)
45 }
46
47 l = l.With("spindle", repo.Spindle)
48
49 host, err := hostutil.EnsureHttpScheme(repo.Spindle)
50 if err != nil {
51 l.Warn("invalid spindlie hostname", "err", err)
52 return newErrorModel(renderer, fmt.Sprintf("invalid spindle host %q", repo.Spindle)), wishtea.MakeOptions(sess)
53 }
54
55 xrpcc := extlexutil.Client{Client: indigoxrpc.Client{Host: host}}
56 out, err := tangled.CiQueryPipelines(sess.Context(), &xrpcc, []string{sha}, "", nil, 1, repoDID)
57 if err != nil || len(out.Pipelines) == 0 {
58 l.Warn("pipeline not found", "err", err)
59 return newErrorModel(renderer, fmt.Sprintf("pipeline not found for repo %s @ %s", repoDID, sha)), wishtea.MakeOptions(sess)
60 }
61
62 pipeline := out.Pipelines[0]
63 if _, err := syntax.ParseTID(pipeline.Id); err != nil {
64 l.Warn("invalid pipeline id", "id", pipeline.Id, "err", err)
65 return newErrorModel(renderer, fmt.Sprintf("invalid pipeline id %q", pipeline.Id)), wishtea.MakeOptions(sess)
66 }
67
68 l.Info("serving pipeline", "pipeline", pipeline.Id, "workflows", len(pipeline.Workflows))
69 pty, _, _ := sess.Pty()
70 opts := append(wishtea.MakeOptions(sess), tea.WithAltScreen())
71 return newPipelineModel(renderer, &xrpcc, pipeline, pty.Window.Width, pty.Window.Height), opts
72}