|
4 | 4 | "context" |
5 | 5 | "encoding/base64" |
6 | 6 | "fmt" |
7 | | - "math/rand" |
8 | 7 | "net/http" |
9 | 8 | "net/url" |
10 | 9 | "regexp" |
@@ -42,6 +41,8 @@ const ( |
42 | 41 |
|
43 | 42 | var _ provider.Interface = (*Provider)(nil) |
44 | 43 |
|
| 44 | +var syncMap = sync.Map{} |
| 45 | + |
45 | 46 | type Provider struct { |
46 | 47 | ghClient *github.Client |
47 | 48 | Logger *zap.SugaredLogger |
@@ -803,39 +804,27 @@ func (v *Provider) CreateComment(ctx context.Context, event *info.Event, commit, |
803 | 804 | } |
804 | 805 | return nil |
805 | 806 | } |
| 807 | + } |
806 | 808 |
|
807 | | - // HACK: Workaround for duplicate comment creation issue. |
808 | | - // In E2E tests, we occasionally see two identical comments created on a PR when |
809 | | - // there should only be one. The root cause is unclear, despite only one |
810 | | - // create_comment API call being logged, two comments appear on the PR. |
811 | | - // |
812 | | - // This workaround adds a random sleep (0-500ms) before re-checking for existing |
813 | | - // comments. This reduces the window where parallel processes might both |
814 | | - // see no existing comment and both decide to create one. |
815 | | - //nolint:gosec // No need for crypto/rand here, just reducing timing window |
816 | | - jitter := time.Duration(rand.Intn(500)) * time.Millisecond |
817 | | - timer := time.NewTimer(jitter) |
818 | | - defer timer.Stop() |
819 | | - |
820 | | - select { |
821 | | - case <-ctx.Done(): |
822 | | - return ctx.Err() |
823 | | - case <-timer.C: |
824 | | - } |
825 | | - |
826 | | - // Re-check if a comment exists now |
827 | | - existingComment, err = v.listAndFindComment(ctx, event, updateMarker) |
828 | | - if err != nil { |
829 | | - return err |
830 | | - } |
831 | | - if existingComment != nil { |
832 | | - return nil |
| 809 | + var once *sync.Once |
| 810 | + var err error |
| 811 | + if event.TriggerTarget == triggertype.PullRequest { |
| 812 | + key := fmt.Sprintf("%s/%s/%d", event.Organization, event.Repository, event.PullRequestNumber) |
| 813 | + value, _ := syncMap.LoadOrStore(key, &sync.Once{}) |
| 814 | + var ok bool |
| 815 | + once, ok = value.(*sync.Once) |
| 816 | + if !ok { |
| 817 | + return fmt.Errorf("unexpected type in sync map for key %s", key) |
833 | 818 | } |
| 819 | + } else { |
| 820 | + once = &sync.Once{} |
834 | 821 | } |
835 | 822 |
|
836 | | - _, _, err := wrapAPI(v, "create_comment", func() (*github.IssueComment, *github.Response, error) { |
837 | | - return v.Client().Issues.CreateComment(ctx, event.Organization, event.Repository, event.PullRequestNumber, &github.IssueComment{ |
838 | | - Body: github.Ptr(commit), |
| 823 | + once.Do(func() { |
| 824 | + _, _, err = wrapAPI(v, "create_comment", func() (*github.IssueComment, *github.Response, error) { |
| 825 | + return v.Client().Issues.CreateComment(ctx, event.Organization, event.Repository, event.PullRequestNumber, &github.IssueComment{ |
| 826 | + Body: github.Ptr(commit), |
| 827 | + }) |
839 | 828 | }) |
840 | 829 | }) |
841 | 830 | return err |
|
0 commit comments