knotserver: refactor replyCompare, and minor bugfix #746

merged
opened by oppi.li targeting master from push-uwppnnwrsyxn

knotservers do not respond with the compare link when pushing a tag.

Signed-off-by: oppiliappan me@oppi.li

Changed files
+84 -48
knotserver
+84 -48
knotserver/internal.go
··· 27 ) 28 29 type InternalHandle struct { 30 - db *db.DB 31 - c *config.Config 32 - e *rbac.Enforcer 33 - l *slog.Logger 34 - n *notifier.Notifier 35 } 36 37 func (h *InternalHandle) PushAllowed(w http.ResponseWriter, r *http.Request) { ··· 121 // non-fatal 122 } 123 124 - if (line.NewSha.String() != line.OldSha.String()) && line.OldSha.IsZero() { 125 - msg, err := h.replyCompare(line, repoDid, gitRelativeDir, repoName, r.Context()) 126 - if err != nil { 127 - l.Error("failed to reply with compare link", "err", err, "line", line, "did", gitUserDid, "repo", gitRelativeDir) 128 - // non-fatal 129 - } else { 130 - for msgLine := range msg { 131 - resp.Messages = append(resp.Messages, msg[msgLine]) 132 - } 133 - } 134 } 135 136 err = h.triggerPipeline(&resp.Messages, line, gitUserDid, repoDid, repoName, pushOptions) ··· 143 writeJSON(w, resp) 144 } 145 146 - func (h *InternalHandle) replyCompare(line git.PostReceiveLine, repoOwner string, gitRelativeDir string, repoName string, ctx context.Context) ([]string, error) { 147 - l := h.l.With("handler", "replyCompare") 148 - userIdent, err := idresolver.DefaultResolver().ResolveIdent(ctx, repoOwner) 149 - user := repoOwner 150 - if err != nil { 151 - l.Error("Failed to fetch user identity", "err", err) 152 - // non-fatal 153 - } else { 154 - user = userIdent.Handle.String() 155 - } 156 - gr, err := git.PlainOpen(gitRelativeDir) 157 - if err != nil { 158 - l.Error("Failed to open git repository", "err", err) 159 - return []string{}, err 160 - } 161 - defaultBranch, err := gr.FindMainBranch() 162 - if err != nil { 163 - l.Error("Failed to fetch default branch", "err", err) 164 - return []string{}, err 165 - } 166 - if line.Ref == plumbing.NewBranchReferenceName(defaultBranch).String() { 167 - return []string{}, nil 168 - } 169 - ZWS := "\u200B" 170 - var msg []string 171 - msg = append(msg, ZWS) 172 - msg = append(msg, fmt.Sprintf("Create a PR pointing to %s", defaultBranch)) 173 - msg = append(msg, fmt.Sprintf("\t%s/%s/%s/compare/%s...%s", h.c.AppViewEndpoint, user, repoName, defaultBranch, strings.TrimPrefix(line.Ref, "refs/heads/"))) 174 - msg = append(msg, ZWS) 175 - return msg, nil 176 - } 177 - 178 func (h *InternalHandle) insertRefUpdate(line git.PostReceiveLine, gitUserDid, repoDid, repoName string) error { 179 didSlashRepo, err := securejoin.SecureJoin(repoDid, repoName) 180 if err != nil { ··· 220 return errors.Join(errs, h.db.InsertEvent(event, h.n)) 221 } 222 223 - func (h *InternalHandle) triggerPipeline(clientMsgs *[]string, line git.PostReceiveLine, gitUserDid, repoDid, repoName string, pushOptions PushOptions) error { 224 if pushOptions.skipCi { 225 return nil 226 } ··· 315 return h.db.InsertEvent(event, h.n) 316 } 317 318 func Internal(ctx context.Context, c *config.Config, db *db.DB, e *rbac.Enforcer, n *notifier.Notifier) http.Handler { 319 r := chi.NewRouter() 320 l := log.FromContext(ctx) 321 l = log.SubLogger(l, "internal") 322 323 h := InternalHandle{ 324 db, ··· 326 e, 327 l, 328 n, 329 } 330 331 r.Get("/push-allowed", h.PushAllowed)
··· 27 ) 28 29 type InternalHandle struct { 30 + db *db.DB 31 + c *config.Config 32 + e *rbac.Enforcer 33 + l *slog.Logger 34 + n *notifier.Notifier 35 + res *idresolver.Resolver 36 } 37 38 func (h *InternalHandle) PushAllowed(w http.ResponseWriter, r *http.Request) { ··· 122 // non-fatal 123 } 124 125 + err = h.emitCompareLink(&resp.Messages, line, repoDid, repoName) 126 + if err != nil { 127 + l.Error("failed to reply with compare link", "err", err, "line", line, "did", gitUserDid, "repo", gitRelativeDir) 128 + // non-fatal 129 } 130 131 err = h.triggerPipeline(&resp.Messages, line, gitUserDid, repoDid, repoName, pushOptions) ··· 138 writeJSON(w, resp) 139 } 140 141 func (h *InternalHandle) insertRefUpdate(line git.PostReceiveLine, gitUserDid, repoDid, repoName string) error { 142 didSlashRepo, err := securejoin.SecureJoin(repoDid, repoName) 143 if err != nil { ··· 183 return errors.Join(errs, h.db.InsertEvent(event, h.n)) 184 } 185 186 + func (h *InternalHandle) triggerPipeline( 187 + clientMsgs *[]string, 188 + line git.PostReceiveLine, 189 + gitUserDid string, 190 + repoDid string, 191 + repoName string, 192 + pushOptions PushOptions, 193 + ) error { 194 if pushOptions.skipCi { 195 return nil 196 } ··· 285 return h.db.InsertEvent(event, h.n) 286 } 287 288 + func (h *InternalHandle) emitCompareLink( 289 + clientMsgs *[]string, 290 + line git.PostReceiveLine, 291 + repoDid string, 292 + repoName string, 293 + ) error { 294 + // this is a second push to a branch, don't reply with the link again 295 + if !line.OldSha.IsZero() { 296 + return nil 297 + } 298 + 299 + // the ref was not updated to a new hash, don't reply with the link 300 + // 301 + // NOTE: do we need this? 302 + if line.NewSha.String() == line.OldSha.String() { 303 + return nil 304 + } 305 + 306 + pushedRef := plumbing.ReferenceName(line.Ref) 307 + 308 + userIdent, err := h.res.ResolveIdent(context.Background(), repoDid) 309 + user := repoDid 310 + if err == nil { 311 + user = userIdent.Handle.String() 312 + } 313 + 314 + didSlashRepo, err := securejoin.SecureJoin(repoDid, repoName) 315 + if err != nil { 316 + return err 317 + } 318 + 319 + repoPath, err := securejoin.SecureJoin(h.c.Repo.ScanPath, didSlashRepo) 320 + if err != nil { 321 + return err 322 + } 323 + 324 + gr, err := git.PlainOpen(repoPath) 325 + if err != nil { 326 + return err 327 + } 328 + 329 + defaultBranch, err := gr.FindMainBranch() 330 + if err != nil { 331 + return err 332 + } 333 + 334 + // pushing to default branch 335 + if pushedRef == plumbing.NewBranchReferenceName(defaultBranch) { 336 + return nil 337 + } 338 + 339 + // pushing a tag, don't prompt the user the open a PR 340 + if pushedRef.IsTag() { 341 + return nil 342 + } 343 + 344 + ZWS := "\u200B" 345 + *clientMsgs = append(*clientMsgs, ZWS) 346 + *clientMsgs = append(*clientMsgs, fmt.Sprintf("Create a PR pointing to %s", defaultBranch)) 347 + *clientMsgs = append(*clientMsgs, fmt.Sprintf("\t%s/%s/%s/compare/%s...%s", h.c.AppViewEndpoint, user, repoName, defaultBranch, strings.TrimPrefix(line.Ref, "refs/heads/"))) 348 + *clientMsgs = append(*clientMsgs, ZWS) 349 + return nil 350 + } 351 + 352 func Internal(ctx context.Context, c *config.Config, db *db.DB, e *rbac.Enforcer, n *notifier.Notifier) http.Handler { 353 r := chi.NewRouter() 354 l := log.FromContext(ctx) 355 l = log.SubLogger(l, "internal") 356 + res := idresolver.DefaultResolver() 357 358 h := InternalHandle{ 359 db, ··· 361 e, 362 l, 363 n, 364 + res, 365 } 366 367 r.Get("/push-allowed", h.PushAllowed)