Name the cause when a watch stops on an auth failure
A 401/403 was handled as one thing, so watchpr re-minted on every rejection and reported "token expired" for a permission boundary or an anonymous run that had no token to expire, sending the reader after the wrong problem. Classify a 401/403 as a rejected credential, a permission denial, or a request that carried no token, and re-mint only the first. Reject a re-minted empty token instead of replaying anonymously. Report the classified cause from --once as well as from the watch loop. Document watchpr's exit behaviour per cause.
This commit is contained in:
+20
-8
@@ -105,7 +105,7 @@ func runOnce(c *agent.GiteaClient, refs []agent.PRRef, jsonMode bool) error {
|
||||
for _, ref := range refs {
|
||||
st, err := agent.FetchState(c, ref, login)
|
||||
if err != nil {
|
||||
return err
|
||||
return describeFailure(err)
|
||||
}
|
||||
states = append(states, st)
|
||||
}
|
||||
@@ -137,18 +137,30 @@ func runWatch(c *agent.GiteaClient, refs []agent.PRRef, interval time.Duration,
|
||||
|
||||
res, err := agent.Watch(c, refs, login, ticker.C, onBaseline, onError)
|
||||
if err != nil {
|
||||
if agent.IsAuthError(err) {
|
||||
return fmt.Errorf("gitea authentication failed after re-minting the token, watch aborted: %w", err)
|
||||
}
|
||||
if agent.IsPRGone(err) {
|
||||
return fmt.Errorf("PR no longer visible (repo deleted, renamed, or made private), watch aborted: %w", err)
|
||||
}
|
||||
return err
|
||||
return describeFailure(err)
|
||||
}
|
||||
report(res.Ref.String(), res.Reason, res.State, jsonMode)
|
||||
return nil
|
||||
}
|
||||
|
||||
// describeFailure names the cause of a terminal failure so a watcher that stops
|
||||
// says why. An anonymous rejection, a permission boundary and a token that
|
||||
// outlived its Vault lease are three different problems and only the last is
|
||||
// fixed by a fresh token.
|
||||
func describeFailure(err error) error {
|
||||
switch {
|
||||
case agent.IsNoCredential(err):
|
||||
return fmt.Errorf("gitea requires authentication and no token could be minted, aborted: %w", err)
|
||||
case agent.IsPermissionDenied(err):
|
||||
return fmt.Errorf("gitea denied access to %s (a fresh token will not help), aborted: %w", agent.AgentLogin(), err)
|
||||
case agent.IsAuthError(err):
|
||||
return fmt.Errorf("gitea rejected the token and re-minting did not recover it, aborted: %w", err)
|
||||
case agent.IsPRGone(err):
|
||||
return fmt.Errorf("PR no longer visible (repo deleted, renamed, or made private), aborted: %w", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// report emits the change that ended the watch.
|
||||
func report(key, reason string, st agent.PRState, jsonMode bool) {
|
||||
if jsonMode {
|
||||
|
||||
Reference in New Issue
Block a user