From 0dea0f6a7673865b16e71f1998c3b0db33a54514 Mon Sep 17 00:00:00 2001 From: Amine Hilaly Date: Sun, 23 Jun 2019 13:50:45 +0200 Subject: [bridge/github] simplify export operation hashs [bridge/github] exporter tests: add more test cases and global tests [bridge/github] rename export_query to export_mutation [bridge/github] exporter: Log number of exported issues and labels [bridge/github] Improve comments --- bridge/github/export.go | 38 +++---- bridge/github/export_mutation.go | 74 ++++++++++++++ bridge/github/export_query.go | 74 -------------- bridge/github/export_test.go | 213 +++++++++++++++++++++++++++++++-------- 4 files changed, 259 insertions(+), 140 deletions(-) create mode 100644 bridge/github/export_mutation.go delete mode 100644 bridge/github/export_query.go (limited to 'bridge') diff --git a/bridge/github/export.go b/bridge/github/export.go index 947d5aca..1ab6ebca 100644 --- a/bridge/github/export.go +++ b/bridge/github/export.go @@ -29,6 +29,9 @@ type githubExporter struct { // number of exported bugs exportedBugs int + // number of exported labels + exportedLabels int + // export only bugs taged with one of these origins onlyOrigins []string @@ -146,6 +149,7 @@ bugLoop: } } + fmt.Printf("Successfully exported %d issues and %d labels to Github\n", ge.exportedBugs, ge.exportedLabels) return nil } @@ -272,10 +276,8 @@ func (ge *githubExporter) exportBug(b *cache.BugCache, since time.Time) error { return errors.Wrap(err, "adding comment") } - hash, err = opr.Hash() - if err != nil { - return errors.Wrap(err, "comment hash") - } + // cache comment id + ge.cachedIDs[hash.String()] = id case *bug.EditCommentOperation: @@ -311,22 +313,12 @@ func (ge *githubExporter) exportBug(b *cache.BugCache, since time.Time) error { url = eurl } - hash, err = opr.Hash() - if err != nil { - return errors.Wrap(err, "comment hash") - } - case *bug.SetStatusOperation: opr := op.(*bug.SetStatusOperation) if err := updateGithubIssueStatus(client, bugGithubID, opr.Status); err != nil { return errors.Wrap(err, "editing status") } - hash, err = opr.Hash() - if err != nil { - return errors.Wrap(err, "set status operation hash") - } - id = bugGithubID url = bugGithubURL @@ -336,11 +328,6 @@ func (ge *githubExporter) exportBug(b *cache.BugCache, since time.Time) error { return errors.Wrap(err, "editing title") } - hash, err = opr.Hash() - if err != nil { - return errors.Wrap(err, "set title operation hash") - } - id = bugGithubID url = bugGithubURL @@ -350,11 +337,6 @@ func (ge *githubExporter) exportBug(b *cache.BugCache, since time.Time) error { return errors.Wrap(err, "updating labels") } - hash, err = opr.Hash() - if err != nil { - return errors.Wrap(err, "label change operation hash") - } - id = bugGithubID url = bugGithubURL @@ -367,6 +349,7 @@ func (ge *githubExporter) exportBug(b *cache.BugCache, since time.Time) error { return errors.Wrap(err, "marking operation as exported") } + // commit at each operation export to avoid exporting same events multiple times if err := b.CommitAsNeeded(); err != nil { return errors.Wrap(err, "bug commit") } @@ -451,7 +434,7 @@ func (ge *githubExporter) getGithubLabelID(gc *githubv4.Client, label string) (s return q.Repository.Label.ID, nil } -func (ge *githubExporter) createGithubLabel(gc *githubv4.Client, label, labelColor string) (string, error) { +func (ge *githubExporter) createGithubLabel(label, labelColor string) (string, error) { url := fmt.Sprintf("%s/repos/%s/%s/labels", githubV3Url, ge.conf[keyOwner], ge.conf[keyProject]) client := &http.Client{ @@ -538,11 +521,14 @@ func (ge *githubExporter) getOrCreateGithubLabelID(gc *githubv4.Client, reposito hexColor := fmt.Sprintf("%.2x%.2x%.2x", rgba.R, rgba.G, rgba.B) // create label and return id - labelID, err = ge.createGithubLabel(gc, string(label), hexColor) + // NOTE: since createLabel mutation is still in preview mode we use github api v4 to create labels + // see https://developer.github.com/v4/mutation/createlabel/ and https://developer.github.com/v4/previews/#labels-preview + labelID, err = ge.createGithubLabel(string(label), hexColor) if err != nil { return "", err } + ge.exportedLabels++ return labelID, nil } diff --git a/bridge/github/export_mutation.go b/bridge/github/export_mutation.go new file mode 100644 index 00000000..95d4e6a9 --- /dev/null +++ b/bridge/github/export_mutation.go @@ -0,0 +1,74 @@ +package github + +import "github.com/shurcooL/githubv4" + +type createIssueMutation struct { + CreateIssue struct { + Issue struct { + ID string `graphql:"id"` + URL string `graphql:"url"` + } + } `graphql:"createIssue(input:$input)"` +} + +type updateIssueMutation struct { + UpdateIssue struct { + Issue struct { + ID string `graphql:"id"` + URL string `graphql:"url"` + } + } `graphql:"updateIssue(input:$input)"` +} + +type addCommentToIssueMutation struct { + AddComment struct { + CommentEdge struct { + Node struct { + ID string `graphql:"id"` + URL string `graphql:"url"` + } + } + } `graphql:"addComment(input:$input)"` +} + +type updateIssueCommentMutation struct { + UpdateIssueComment struct { + IssueComment struct { + ID string `graphql:"id"` + URL string `graphql:"url"` + } `graphql:"issueComment"` + } `graphql:"updateIssueComment(input:$input)"` +} + +type removeLabelsFromLabelableMutation struct { + AddLabels struct { + Labelable struct { + Typename string `graphql:"__typename"` + } + } `graphql:"removeLabelsFromLabelable(input:$input)"` +} + +type addLabelsToLabelableMutation struct { + RemoveLabels struct { + Labelable struct { + Typename string `graphql:"__typename"` + } + } `graphql:"addLabelsToLabelable(input:$input)"` +} + +type createLabelMutation struct { + CreateLabel struct { + Label struct { + ID string `graphql:"id"` + } `graphql:"label"` + } `graphql:"createLabel(input: $input)"` +} + +type createLabelInput struct { + Color githubv4.String `json:"color"` + Description *githubv4.String `json:"description,omitempty"` + Name githubv4.String `json:"name"` + RepositoryID githubv4.ID `json:"repositoryId"` + + ClientMutationID *githubv4.String `json:"clientMutationId,omitempty"` +} diff --git a/bridge/github/export_query.go b/bridge/github/export_query.go deleted file mode 100644 index 95d4e6a9..00000000 --- a/bridge/github/export_query.go +++ /dev/null @@ -1,74 +0,0 @@ -package github - -import "github.com/shurcooL/githubv4" - -type createIssueMutation struct { - CreateIssue struct { - Issue struct { - ID string `graphql:"id"` - URL string `graphql:"url"` - } - } `graphql:"createIssue(input:$input)"` -} - -type updateIssueMutation struct { - UpdateIssue struct { - Issue struct { - ID string `graphql:"id"` - URL string `graphql:"url"` - } - } `graphql:"updateIssue(input:$input)"` -} - -type addCommentToIssueMutation struct { - AddComment struct { - CommentEdge struct { - Node struct { - ID string `graphql:"id"` - URL string `graphql:"url"` - } - } - } `graphql:"addComment(input:$input)"` -} - -type updateIssueCommentMutation struct { - UpdateIssueComment struct { - IssueComment struct { - ID string `graphql:"id"` - URL string `graphql:"url"` - } `graphql:"issueComment"` - } `graphql:"updateIssueComment(input:$input)"` -} - -type removeLabelsFromLabelableMutation struct { - AddLabels struct { - Labelable struct { - Typename string `graphql:"__typename"` - } - } `graphql:"removeLabelsFromLabelable(input:$input)"` -} - -type addLabelsToLabelableMutation struct { - RemoveLabels struct { - Labelable struct { - Typename string `graphql:"__typename"` - } - } `graphql:"addLabelsToLabelable(input:$input)"` -} - -type createLabelMutation struct { - CreateLabel struct { - Label struct { - ID string `graphql:"id"` - } `graphql:"label"` - } `graphql:"createLabel(input: $input)"` -} - -type createLabelInput struct { - Color githubv4.String `json:"color"` - Description *githubv4.String `json:"description,omitempty"` - Name githubv4.String `json:"name"` - RepositoryID githubv4.ID `json:"repositoryId"` - - ClientMutationID *githubv4.String `json:"clientMutationId,omitempty"` -} diff --git a/bridge/github/export_test.go b/bridge/github/export_test.go index b60b86d8..0a0c6d95 100644 --- a/bridge/github/export_test.go +++ b/bridge/github/export_test.go @@ -22,48 +22,142 @@ const ( testRepoBaseName = "git-bug-test-github-exporter" ) -// testCases creates bugs in repo cache -func testCases(repo *cache.RepoCache, identity *cache.IdentityCache) (map[string]*cache.BugCache, error) { - bugs := make(map[string]*cache.BugCache) +type testCase struct { + name string + bug *cache.BugCache + numOrOp int // number of original operations +} +func testCases(repo *cache.RepoCache, identity *cache.IdentityCache) ([]*testCase, error) { // simple bug - simpleBug, err := repo.NewBugRaw(identity, time.Now().Unix(), "simple bug", "new bug", nil, nil) + simpleBug, err := repo.NewBug("simple bug", "new bug") if err != nil { return nil, err } - bugs["simple bug"] = simpleBug - /* - // bug with comments - bugWithComments, err := repo.NewBugRaw(author, time.Now().Unix(), "bug with comments", "new bug", nil, nil) - if err != nil { - return nil, err - } + // bug with comments + bugWithComments, err := repo.NewBug("bug with comments", "new bug") + if err != nil { + return nil, err + } - _, err = bugWithComments.AddCommentRaw(author, time.Now().Unix(), "new comment", nil, nil) - if err != nil { - return nil, err - } - bugs["bug with comments"] = bugWithComments + _, err = bugWithComments.AddComment("new comment") + if err != nil { + return nil, err + } - // bug with label changes - bugLabelChange, err := repo.NewBugRaw(author, time.Now().Unix(), "bug label change", "new bug", nil, nil) - if err != nil { - return nil, err - } + // bug with label changes + bugLabelChange, err := repo.NewBug("bug label change", "new bug") + if err != nil { + return nil, err + } - _, _, err = bugLabelChange.ChangeLabelsRaw(author, time.Now().Unix(), []string{"bug", "core"}, nil, nil) - if err != nil { - return nil, err - } + _, _, err = bugLabelChange.ChangeLabels([]string{"bug"}, nil) + if err != nil { + return nil, err + } + + _, _, err = bugLabelChange.ChangeLabels([]string{"core"}, nil) + if err != nil { + return nil, err + } + + _, _, err = bugLabelChange.ChangeLabels(nil, []string{"bug"}) + if err != nil { + return nil, err + } + + // bug with comments editions + bugWithCommentEditions, err := repo.NewBug("bug with comments editions", "new bug") + if err != nil { + return nil, err + } + + createOpHash, err := bugWithCommentEditions.Snapshot().Operations[0].Hash() + if err != nil { + return nil, err + } + + _, err = bugWithCommentEditions.EditComment(createOpHash, "first comment edited") + if err != nil { + return nil, err + } + + commentOp, err := bugWithCommentEditions.AddComment("first comment") + if err != nil { + return nil, err + } + + commentOpHash, err := commentOp.Hash() + if err != nil { + return nil, err + } + + _, err = bugWithCommentEditions.EditComment(commentOpHash, "first comment edited") + if err != nil { + return nil, err + } + + // bug status changed + bugStatusChanged, err := repo.NewBug("bug status changed", "new bug") + if err != nil { + return nil, err + } + + _, err = bugStatusChanged.Close() + if err != nil { + return nil, err + } + + _, err = bugStatusChanged.Open() + if err != nil { + return nil, err + } + + // bug title changed + bugTitleEdited, err := repo.NewBug("bug title edited", "new bug") + if err != nil { + return nil, err + } + + _, err = bugTitleEdited.SetTitle("bug title edited again") + if err != nil { + return nil, err + } + + return []*testCase{ + &testCase{ + name: "simple bug", + bug: simpleBug, + numOrOp: 1, + }, + &testCase{ + name: "bug with comments", + bug: bugWithComments, + numOrOp: 2, + }, + &testCase{ + name: "bug label change", + bug: bugLabelChange, + numOrOp: 4, + }, + &testCase{ + name: "bug with comment editions", + bug: bugWithCommentEditions, + numOrOp: 4, + }, + &testCase{ + name: "bug changed status", + bug: bugStatusChanged, + numOrOp: 3, + }, + &testCase{ + name: "bug title edited", + bug: bugTitleEdited, + numOrOp: 2, + }, + }, nil - _, _, err = bugLabelChange.ChangeLabelsRaw(author, time.Now().Unix(), nil, []string{"bug"}, nil) - if err != nil { - return nil, err - } - bugs["bug change label"] = bugWithComments - */ - return nil, err } func TestExporter(t *testing.T) { @@ -79,7 +173,7 @@ func TestExporter(t *testing.T) { backend, err := cache.NewRepoCache(repo) require.NoError(t, err) - author, err := backend.NewIdentity("test identity", "hello@testidentity.org") + author, err := backend.NewIdentity("test identity", "test@test.org") if err != nil { t.Fatal(err) } @@ -99,20 +193,22 @@ func TestExporter(t *testing.T) { // generate project name projectName := generateRepoName() - fmt.Println("creating repo", projectName) + + // create repository if err := createRepository(projectName, token); err != nil { t.Fatal(err) } + fmt.Println("created repository", projectName) - // - // + // delete repository before ending tests defer func(t *testing.T) { - fmt.Println("deleting repo", projectName) if err := deleteRepository(projectName, user, token); err != nil { t.Fatal(err) } + fmt.Println("deleted repository:", projectName) }(t) + // initialize exporter exporter := &githubExporter{} err = exporter.Init(core.Configuration{ keyOwner: user, @@ -123,13 +219,50 @@ func TestExporter(t *testing.T) { start := time.Now() + // export all bugs err = exporter.ExportAll(backend, time.Time{}) require.NoError(t, err) fmt.Printf("test repository exported in %f seconds\n", time.Since(start).Seconds()) - for name, tt := range tests { - t.Run(name, func(t *testing.T) { - fmt.Println(tt.Snapshot()) + + repoTwo := repository.CreateTestRepo(false) + defer repository.CleanupTestRepos(t, repoTwo) + + // create a second backend + backendTwo, err := cache.NewRepoCache(repoTwo) + require.NoError(t, err) + + importer := &githubImporter{} + err = importer.Init(core.Configuration{ + keyOwner: user, + keyProject: projectName, + keyToken: token, + }) + require.NoError(t, err) + + // import all exported bugs to the second backend + err = importer.ImportAll(backendTwo, time.Time{}) + require.NoError(t, err) + + require.Len(t, backendTwo.AllBugsIds(), len(tests)) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // for each operation a SetMetadataOperation will be added + // so number of operations should double + require.Len(t, tt.bug.Snapshot().Operations, tt.numOrOp*2) + + bugGithubID, ok := tt.bug.Snapshot().Operations[0].GetMetadata(keyGithubId) + require.True(t, ok) + + importedBug, err := backendTwo.ResolveBugCreateMetadata(keyGithubId, bugGithubID) + require.NoError(t, err) + + require.Len(t, importedBug.Snapshot().Operations, tt.numOrOp) + + for _, _ = range importedBug.Snapshot().Operations { + // test operations or last bug state ? + } }) } } -- cgit