Repository: go
Issue: x/build/maintner: occasional unexpected updates for specific issues/PRs
Labels: Builders,NeedsInvestigation

I created a [`NewNetworkMutationSource`](https://godoc.org/golang.org/x/build/maintner#NewNetworkMutationSource) and let it stream events for the last hour or so. Most of the events that came in was legitimate current activity.

However, I also noticed a few suspect events. They refer to issues/PRs that as far as I can tell have had no recent activity, so I can't explain why they came up (quite regularly). Filing this here so I can investigate later (unless someone gets to it first).

```
2018/04/14 19:21:11 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"crypto" number:32 pull_request:true > )
2018/04/14 19:23:18 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"tour" number:428 > )
2018/04/14 19:36:11 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"crypto" number:32 pull_request:true > )
2018/04/14 19:38:20 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"tour" number:428 > )
2018/04/14 19:51:12 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"crypto" number:32 pull_request:true > )
2018/04/14 19:53:22 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"tour" number:428 > )
2018/04/14 20:06:13 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"crypto" number:32 pull_request:true > )
2018/04/14 20:08:24 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"tour" number:428 > )
2018/04/14 20:21:13 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"crypto" number:32 pull_request:true > )
2018/04/14 20:23:26 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"tour" number:428 > )
2018/04/14 20:36:14 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"crypto" number:32 pull_request:true > )
2018/04/14 20:38:27 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"tour" number:428 > )
2018/04/14 20:51:15 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"crypto" number:32 pull_request:true > )
2018/04/14 20:53:29 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"tour" number:428 > )
2018/04/14 21:06:16 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"crypto" number:32 pull_request:true > )
2018/04/14 21:08:31 (*maintpb.Mutation)(github_issue:<owner:"golang" repo:"tour" number:428 > )
```

(I've removed all the normal events from the log, so it only includes the unexpected ones.)

I'm avoiding linking to those issues/PRs because that might create legitimate events there. But you can infer them from the log. The issue is number 428 at https://github.com/golang/tour/issues?page=2, and the PR is number 32 at https://github.com/golang/crypto/pulls?q=is%3Aclosed. Both have no recent activity, definitely not anything in the last hour (as far as I can tell).

/cc @bradfitz @andybons

For reference, this is the code I ran:

<details><br>

```Go
// Play with streaming mutations from maintner.NewNetworkMutationSource.
package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"os/signal"

	"github.com/davecgh/go-spew/spew"
	"golang.org/x/build/maintner"
	"golang.org/x/build/maintner/godata"
	"golang.org/x/build/maintner/maintpb"
)

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	go func() {
		sigint := make(chan os.Signal, 1)
		signal.Notify(sigint, os.Interrupt)
		<-sigint
		cancel()
	}()

	err := run(ctx)
	if err != nil {
		log.Fatalln(err)
	}
}

var s struct {
	didInit bool
}

func run(ctx context.Context) error {
	src := maintner.NewNetworkMutationSource("https://maintner.golang.org/logs", godata.Dir())
	done := ctx.Done()
Outer:
	for {
		ch := src.GetMutations(ctx)
		for {
			select {
			case <-done:
				log.Printf("Context expired while loading data from log %T: %v", src, ctx.Err())
				return nil
			case e := <-ch:
				if e.Err != nil {
					log.Printf("Corpus GetMutations: %v", e.Err)
					return e.Err
				}
				if e.End {
					log.Printf("Reloaded data from log %T.", src)
					s.didInit = true
					continue Outer
				}
				processMutation(e.Mutation)
			}
		}
	}
}

func processMutation(m *maintpb.Mutation) {
	if !s.didInit {
		fmt.Print(".")
		return
	}

	spew.Dump(m)
}
```

</details>