feat(mr): store auto-merge state and allow_auto_merge setting
- commit
- 4bb6db7919afdadd47a988c5ec165937b4bf960c
- author
- brice · · 2026-10-20 15:44 UTC
- parent
- 3ed7469
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
8 files · +319 -37
M gen/ermite/storage/merge_request.pb.go +163 -35
| @@ -352,9 +352,10 @@ type RepoSettings struct { | |||
| 352 | 352 | // choice of the owner. When false (settings stored before), exactly | |
| 353 | 353 | // {fast-forward, squash} was the old default and gains MERGE_MODE_MERGE on | |
| 354 | 354 | // read. | |
| 355 | - | MergeModesV2 bool `protobuf:"varint,4,opt,name=merge_modes_v2,json=mergeModesV2,proto3" json:"merge_modes_v2,omitempty"` | |
| 356 | - | unknownFields protoimpl.UnknownFields | |
| 357 | - | sizeCache protoimpl.SizeCache | |
| 355 | + | MergeModesV2 bool `protobuf:"varint,4,opt,name=merge_modes_v2,json=mergeModesV2,proto3" json:"merge_modes_v2,omitempty"` | |
| 356 | + | AllowAutoMerge bool `protobuf:"varint,5,opt,name=allow_auto_merge,json=allowAutoMerge,proto3" json:"allow_auto_merge,omitempty"` | |
| 357 | + | unknownFields protoimpl.UnknownFields | |
| 358 | + | sizeCache protoimpl.SizeCache | |
| 358 | 359 | } | |
| 359 | 360 | ||
| 360 | 361 | func (x *RepoSettings) Reset() { | |
| @@ -415,6 +416,13 @@ func (x *RepoSettings) GetMergeModesV2() bool { | |||
| 415 | 416 | return false | |
| 416 | 417 | } | |
| 417 | 418 | ||
| 419 | + | func (x *RepoSettings) GetAllowAutoMerge() bool { | |
| 420 | + | if x != nil { | |
| 421 | + | return x.AllowAutoMerge | |
| 422 | + | } | |
| 423 | + | return false | |
| 424 | + | } | |
| 425 | + | ||
| 418 | 426 | // MergeRequest is stored under the key "mr/<repo>/<number:010d>". | |
| 419 | 427 | type MergeRequest struct { | |
| 420 | 428 | state protoimpl.MessageState `protogen:"open.v1"` | |
| @@ -437,7 +445,10 @@ type MergeRequest struct { | |||
| 437 | 445 | MergedCommitId string `protobuf:"bytes,12,opt,name=merged_commit_id,json=mergedCommitId,proto3" json:"merged_commit_id,omitempty"` | |
| 438 | 446 | MergeMode MergeMode `protobuf:"varint,13,opt,name=merge_mode,json=mergeMode,proto3,enum=ermite.storage.MergeMode" json:"merge_mode,omitempty"` | |
| 439 | 447 | // Last comment id handed out for this request. | |
| 440 | - | CommentSeq int64 `protobuf:"varint,14,opt,name=comment_seq,json=commentSeq,proto3" json:"comment_seq,omitempty"` | |
| 448 | + | CommentSeq int64 `protobuf:"varint,14,opt,name=comment_seq,json=commentSeq,proto3" json:"comment_seq,omitempty"` | |
| 449 | + | // Pending auto-merge; unset when off. | |
| 450 | + | AutoMerge *AutoMerge `protobuf:"bytes,15,opt,name=auto_merge,json=autoMerge,proto3" json:"auto_merge,omitempty"` | |
| 451 | + | AutoMerged bool `protobuf:"varint,16,opt,name=auto_merged,json=autoMerged,proto3" json:"auto_merged,omitempty"` | |
| 441 | 452 | unknownFields protoimpl.UnknownFields | |
| 442 | 453 | sizeCache protoimpl.SizeCache | |
| 443 | 454 | } | |
| @@ -570,6 +581,106 @@ func (x *MergeRequest) GetCommentSeq() int64 { | |||
| 570 | 581 | return 0 | |
| 571 | 582 | } | |
| 572 | 583 | ||
| 584 | + | func (x *MergeRequest) GetAutoMerge() *AutoMerge { | |
| 585 | + | if x != nil { | |
| 586 | + | return x.AutoMerge | |
| 587 | + | } | |
| 588 | + | return nil | |
| 589 | + | } | |
| 590 | + | ||
| 591 | + | func (x *MergeRequest) GetAutoMerged() bool { | |
| 592 | + | if x != nil { | |
| 593 | + | return x.AutoMerged | |
| 594 | + | } | |
| 595 | + | return false | |
| 596 | + | } | |
| 597 | + | ||
| 598 | + | // AutoMerge is the pending auto-merge of an open merge request. | |
| 599 | + | type AutoMerge struct { | |
| 600 | + | state protoimpl.MessageState `protogen:"open.v1"` | |
| 601 | + | Mode MergeMode `protobuf:"varint,1,opt,name=mode,proto3,enum=ermite.storage.MergeMode" json:"mode,omitempty"` | |
| 602 | + | HeadId string `protobuf:"bytes,2,opt,name=head_id,json=headId,proto3" json:"head_id,omitempty"` | |
| 603 | + | // Kind and token id of the CIPusher that enabled it. | |
| 604 | + | EnablerKind string `protobuf:"bytes,3,opt,name=enabler_kind,json=enablerKind,proto3" json:"enabler_kind,omitempty"` | |
| 605 | + | EnablerTokenId string `protobuf:"bytes,4,opt,name=enabler_token_id,json=enablerTokenId,proto3" json:"enabler_token_id,omitempty"` | |
| 606 | + | EnablerLabel string `protobuf:"bytes,5,opt,name=enabler_label,json=enablerLabel,proto3" json:"enabler_label,omitempty"` | |
| 607 | + | EnabledAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=enabled_at,json=enabledAt,proto3" json:"enabled_at,omitempty"` | |
| 608 | + | unknownFields protoimpl.UnknownFields | |
| 609 | + | sizeCache protoimpl.SizeCache | |
| 610 | + | } | |
| 611 | + | ||
| 612 | + | func (x *AutoMerge) Reset() { | |
| 613 | + | *x = AutoMerge{} | |
| 614 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[2] | |
| 615 | + | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |
| 616 | + | ms.StoreMessageInfo(mi) | |
| 617 | + | } | |
| 618 | + | ||
| 619 | + | func (x *AutoMerge) String() string { | |
| 620 | + | return protoimpl.X.MessageStringOf(x) | |
| 621 | + | } | |
| 622 | + | ||
| 623 | + | func (*AutoMerge) ProtoMessage() {} | |
| 624 | + | ||
| 625 | + | func (x *AutoMerge) ProtoReflect() protoreflect.Message { | |
| 626 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[2] | |
| 627 | + | if x != nil { | |
| 628 | + | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |
| 629 | + | if ms.LoadMessageInfo() == nil { | |
| 630 | + | ms.StoreMessageInfo(mi) | |
| 631 | + | } | |
| 632 | + | return ms | |
| 633 | + | } | |
| 634 | + | return mi.MessageOf(x) | |
| 635 | + | } | |
| 636 | + | ||
| 637 | + | // Deprecated: Use AutoMerge.ProtoReflect.Descriptor instead. | |
| 638 | + | func (*AutoMerge) Descriptor() ([]byte, []int) { | |
| 639 | + | return file_ermite_storage_merge_request_proto_rawDescGZIP(), []int{2} | |
| 640 | + | } | |
| 641 | + | ||
| 642 | + | func (x *AutoMerge) GetMode() MergeMode { | |
| 643 | + | if x != nil { | |
| 644 | + | return x.Mode | |
| 645 | + | } | |
| 646 | + | return MergeMode_MERGE_MODE_UNSPECIFIED | |
| 647 | + | } | |
| 648 | + | ||
| 649 | + | func (x *AutoMerge) GetHeadId() string { | |
| 650 | + | if x != nil { | |
| 651 | + | return x.HeadId | |
| 652 | + | } | |
| 653 | + | return "" | |
| 654 | + | } | |
| 655 | + | ||
| 656 | + | func (x *AutoMerge) GetEnablerKind() string { | |
| 657 | + | if x != nil { | |
| 658 | + | return x.EnablerKind | |
| 659 | + | } | |
| 660 | + | return "" | |
| 661 | + | } | |
| 662 | + | ||
| 663 | + | func (x *AutoMerge) GetEnablerTokenId() string { | |
| 664 | + | if x != nil { | |
| 665 | + | return x.EnablerTokenId | |
| 666 | + | } | |
| 667 | + | return "" | |
| 668 | + | } | |
| 669 | + | ||
| 670 | + | func (x *AutoMerge) GetEnablerLabel() string { | |
| 671 | + | if x != nil { | |
| 672 | + | return x.EnablerLabel | |
| 673 | + | } | |
| 674 | + | return "" | |
| 675 | + | } | |
| 676 | + | ||
| 677 | + | func (x *AutoMerge) GetEnabledAt() *timestamppb.Timestamp { | |
| 678 | + | if x != nil { | |
| 679 | + | return x.EnabledAt | |
| 680 | + | } | |
| 681 | + | return nil | |
| 682 | + | } | |
| 683 | + | ||
| 573 | 684 | // Comment is stored under the key "mrc/<repo>/<number:010d>/<id:010d>". | |
| 574 | 685 | type Comment struct { | |
| 575 | 686 | state protoimpl.MessageState `protogen:"open.v1"` | |
| @@ -593,7 +704,7 @@ type Comment struct { | |||
| 593 | 704 | ||
| 594 | 705 | func (x *Comment) Reset() { | |
| 595 | 706 | *x = Comment{} | |
| 596 | - | mi := &file_ermite_storage_merge_request_proto_msgTypes[2] | |
| 707 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[3] | |
| 597 | 708 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |
| 598 | 709 | ms.StoreMessageInfo(mi) | |
| 599 | 710 | } | |
| @@ -605,7 +716,7 @@ func (x *Comment) String() string { | |||
| 605 | 716 | func (*Comment) ProtoMessage() {} | |
| 606 | 717 | ||
| 607 | 718 | func (x *Comment) ProtoReflect() protoreflect.Message { | |
| 608 | - | mi := &file_ermite_storage_merge_request_proto_msgTypes[2] | |
| 719 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[3] | |
| 609 | 720 | if x != nil { | |
| 610 | 721 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |
| 611 | 722 | if ms.LoadMessageInfo() == nil { | |
| @@ -618,7 +729,7 @@ func (x *Comment) ProtoReflect() protoreflect.Message { | |||
| 618 | 729 | ||
| 619 | 730 | // Deprecated: Use Comment.ProtoReflect.Descriptor instead. | |
| 620 | 731 | func (*Comment) Descriptor() ([]byte, []int) { | |
| 621 | - | return file_ermite_storage_merge_request_proto_rawDescGZIP(), []int{2} | |
| 732 | + | return file_ermite_storage_merge_request_proto_rawDescGZIP(), []int{3} | |
| 622 | 733 | } | |
| 623 | 734 | ||
| 624 | 735 | func (x *Comment) GetId() int64 { | |
| @@ -730,7 +841,7 @@ type Sequence struct { | |||
| 730 | 841 | ||
| 731 | 842 | func (x *Sequence) Reset() { | |
| 732 | 843 | *x = Sequence{} | |
| 733 | - | mi := &file_ermite_storage_merge_request_proto_msgTypes[3] | |
| 844 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[4] | |
| 734 | 845 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |
| 735 | 846 | ms.StoreMessageInfo(mi) | |
| 736 | 847 | } | |
| @@ -742,7 +853,7 @@ func (x *Sequence) String() string { | |||
| 742 | 853 | func (*Sequence) ProtoMessage() {} | |
| 743 | 854 | ||
| 744 | 855 | func (x *Sequence) ProtoReflect() protoreflect.Message { | |
| 745 | - | mi := &file_ermite_storage_merge_request_proto_msgTypes[3] | |
| 856 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[4] | |
| 746 | 857 | if x != nil { | |
| 747 | 858 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |
| 748 | 859 | if ms.LoadMessageInfo() == nil { | |
| @@ -755,7 +866,7 @@ func (x *Sequence) ProtoReflect() protoreflect.Message { | |||
| 755 | 866 | ||
| 756 | 867 | // Deprecated: Use Sequence.ProtoReflect.Descriptor instead. | |
| 757 | 868 | func (*Sequence) Descriptor() ([]byte, []int) { | |
| 758 | - | return file_ermite_storage_merge_request_proto_rawDescGZIP(), []int{3} | |
| 869 | + | return file_ermite_storage_merge_request_proto_rawDescGZIP(), []int{4} | |
| 759 | 870 | } | |
| 760 | 871 | ||
| 761 | 872 | func (x *Sequence) GetLast() int64 { | |
| @@ -783,7 +894,7 @@ type Mergeability struct { | |||
| 783 | 894 | ||
| 784 | 895 | func (x *Mergeability) Reset() { | |
| 785 | 896 | *x = Mergeability{} | |
| 786 | - | mi := &file_ermite_storage_merge_request_proto_msgTypes[4] | |
| 897 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[5] | |
| 787 | 898 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |
| 788 | 899 | ms.StoreMessageInfo(mi) | |
| 789 | 900 | } | |
| @@ -795,7 +906,7 @@ func (x *Mergeability) String() string { | |||
| 795 | 906 | func (*Mergeability) ProtoMessage() {} | |
| 796 | 907 | ||
| 797 | 908 | func (x *Mergeability) ProtoReflect() protoreflect.Message { | |
| 798 | - | mi := &file_ermite_storage_merge_request_proto_msgTypes[4] | |
| 909 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[5] | |
| 799 | 910 | if x != nil { | |
| 800 | 911 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |
| 801 | 912 | if ms.LoadMessageInfo() == nil { | |
| @@ -808,7 +919,7 @@ func (x *Mergeability) ProtoReflect() protoreflect.Message { | |||
| 808 | 919 | ||
| 809 | 920 | // Deprecated: Use Mergeability.ProtoReflect.Descriptor instead. | |
| 810 | 921 | func (*Mergeability) Descriptor() ([]byte, []int) { | |
| 811 | - | return file_ermite_storage_merge_request_proto_rawDescGZIP(), []int{4} | |
| 922 | + | return file_ermite_storage_merge_request_proto_rawDescGZIP(), []int{5} | |
| 812 | 923 | } | |
| 813 | 924 | ||
| 814 | 925 | func (x *Mergeability) GetState() MergeabilityState { | |
| @@ -871,12 +982,13 @@ var File_ermite_storage_merge_request_proto protoreflect.FileDescriptor | |||
| 871 | 982 | ||
| 872 | 983 | const file_ermite_storage_merge_request_proto_rawDesc = "" + | |
| 873 | 984 | "\n" + | |
| 874 | - | "\"ermite/storage/merge_request.proto\x12\x0eermite.storage\x1a\x1fgoogle/protobuf/timestamp.proto\"\xe5\x01\n" + | |
| 985 | + | "\"ermite/storage/merge_request.proto\x12\x0eermite.storage\x1a\x1fgoogle/protobuf/timestamp.proto\"\x8f\x02\n" + | |
| 875 | 986 | "\fRepoSettings\x12I\n" + | |
| 876 | 987 | "\x13allowed_merge_modes\x18\x01 \x03(\x0e2\x19.ermite.storage.MergeModeR\x11allowedMergeModes\x120\n" + | |
| 877 | 988 | "\x14failing_checks_block\x18\x02 \x01(\bR\x12failingChecksBlock\x122\n" + | |
| 878 | 989 | "\x06issues\x18\x03 \x01(\x0e2\x1a.ermite.storage.IssuesModeR\x06issues\x12$\n" + | |
| 879 | - | "\x0emerge_modes_v2\x18\x04 \x01(\bR\fmergeModesV2\"\xa6\x04\n" + | |
| 990 | + | "\x0emerge_modes_v2\x18\x04 \x01(\bR\fmergeModesV2\x12(\n" + | |
| 991 | + | "\x10allow_auto_merge\x18\x05 \x01(\bR\x0eallowAutoMerge\"\x81\x05\n" + | |
| 880 | 992 | "\fMergeRequest\x12\x16\n" + | |
| 881 | 993 | "\x06number\x18\x01 \x01(\x03R\x06number\x12\x14\n" + | |
| 882 | 994 | "\x05title\x18\x02 \x01(\tR\x05title\x12 \n" + | |
| @@ -896,7 +1008,19 @@ const file_ermite_storage_merge_request_proto_rawDesc = "" + | |||
| 896 | 1008 | "\n" + | |
| 897 | 1009 | "merge_mode\x18\r \x01(\x0e2\x19.ermite.storage.MergeModeR\tmergeMode\x12\x1f\n" + | |
| 898 | 1010 | "\vcomment_seq\x18\x0e \x01(\x03R\n" + | |
| 899 | - | "commentSeq\"\xcf\x03\n" + | |
| 1011 | + | "commentSeq\x128\n" + | |
| 1012 | + | "\n" + | |
| 1013 | + | "auto_merge\x18\x0f \x01(\v2\x19.ermite.storage.AutoMergeR\tautoMerge\x12\x1f\n" + | |
| 1014 | + | "\vauto_merged\x18\x10 \x01(\bR\n" + | |
| 1015 | + | "autoMerged\"\x80\x02\n" + | |
| 1016 | + | "\tAutoMerge\x12-\n" + | |
| 1017 | + | "\x04mode\x18\x01 \x01(\x0e2\x19.ermite.storage.MergeModeR\x04mode\x12\x17\n" + | |
| 1018 | + | "\ahead_id\x18\x02 \x01(\tR\x06headId\x12!\n" + | |
| 1019 | + | "\fenabler_kind\x18\x03 \x01(\tR\venablerKind\x12(\n" + | |
| 1020 | + | "\x10enabler_token_id\x18\x04 \x01(\tR\x0eenablerTokenId\x12#\n" + | |
| 1021 | + | "\renabler_label\x18\x05 \x01(\tR\fenablerLabel\x129\n" + | |
| 1022 | + | "\n" + | |
| 1023 | + | "enabled_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\tenabledAt\"\xcf\x03\n" + | |
| 900 | 1024 | "\aComment\x12\x0e\n" + | |
| 901 | 1025 | "\x02id\x18\x01 \x01(\x03R\x02id\x12\x16\n" + | |
| 902 | 1026 | "\x06author\x18\x02 \x01(\tR\x06author\x12\x12\n" + | |
| @@ -970,7 +1094,7 @@ func file_ermite_storage_merge_request_proto_rawDescGZIP() []byte { | |||
| 970 | 1094 | } | |
| 971 | 1095 | ||
| 972 | 1096 | var file_ermite_storage_merge_request_proto_enumTypes = make([]protoimpl.EnumInfo, 6) | |
| 973 | - | var file_ermite_storage_merge_request_proto_msgTypes = make([]protoimpl.MessageInfo, 5) | |
| 1097 | + | var file_ermite_storage_merge_request_proto_msgTypes = make([]protoimpl.MessageInfo, 6) | |
| 974 | 1098 | var file_ermite_storage_merge_request_proto_goTypes = []any{ | |
| 975 | 1099 | (MergeMode)(0), // 0: ermite.storage.MergeMode | |
| 976 | 1100 | (IssuesMode)(0), // 1: ermite.storage.IssuesMode | |
| @@ -980,29 +1104,33 @@ var file_ermite_storage_merge_request_proto_goTypes = []any{ | |||
| 980 | 1104 | (MergeabilityState)(0), // 5: ermite.storage.MergeabilityState | |
| 981 | 1105 | (*RepoSettings)(nil), // 6: ermite.storage.RepoSettings | |
| 982 | 1106 | (*MergeRequest)(nil), // 7: ermite.storage.MergeRequest | |
| 983 | - | (*Comment)(nil), // 8: ermite.storage.Comment | |
| 984 | - | (*Sequence)(nil), // 9: ermite.storage.Sequence | |
| 985 | - | (*Mergeability)(nil), // 10: ermite.storage.Mergeability | |
| 986 | - | (*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp | |
| 1107 | + | (*AutoMerge)(nil), // 8: ermite.storage.AutoMerge | |
| 1108 | + | (*Comment)(nil), // 9: ermite.storage.Comment | |
| 1109 | + | (*Sequence)(nil), // 10: ermite.storage.Sequence | |
| 1110 | + | (*Mergeability)(nil), // 11: ermite.storage.Mergeability | |
| 1111 | + | (*timestamppb.Timestamp)(nil), // 12: google.protobuf.Timestamp | |
| 987 | 1112 | } | |
| 988 | 1113 | var file_ermite_storage_merge_request_proto_depIdxs = []int32{ | |
| 989 | 1114 | 0, // 0: ermite.storage.RepoSettings.allowed_merge_modes:type_name -> ermite.storage.MergeMode | |
| 990 | 1115 | 1, // 1: ermite.storage.RepoSettings.issues:type_name -> ermite.storage.IssuesMode | |
| 991 | 1116 | 2, // 2: ermite.storage.MergeRequest.state:type_name -> ermite.storage.MergeRequestState | |
| 992 | - | 11, // 3: ermite.storage.MergeRequest.created_at:type_name -> google.protobuf.Timestamp | |
| 993 | - | 11, // 4: ermite.storage.MergeRequest.updated_at:type_name -> google.protobuf.Timestamp | |
| 1117 | + | 12, // 3: ermite.storage.MergeRequest.created_at:type_name -> google.protobuf.Timestamp | |
| 1118 | + | 12, // 4: ermite.storage.MergeRequest.updated_at:type_name -> google.protobuf.Timestamp | |
| 994 | 1119 | 0, // 5: ermite.storage.MergeRequest.merge_mode:type_name -> ermite.storage.MergeMode | |
| 995 | - | 3, // 6: ermite.storage.Comment.side:type_name -> ermite.storage.DiffSide | |
| 996 | - | 11, // 7: ermite.storage.Comment.created_at:type_name -> google.protobuf.Timestamp | |
| 997 | - | 4, // 8: ermite.storage.Comment.verdict:type_name -> ermite.storage.Verdict | |
| 998 | - | 11, // 9: ermite.storage.Comment.edited_at:type_name -> google.protobuf.Timestamp | |
| 999 | - | 5, // 10: ermite.storage.Mergeability.state:type_name -> ermite.storage.MergeabilityState | |
| 1000 | - | 11, // 11: ermite.storage.Mergeability.checked_at:type_name -> google.protobuf.Timestamp | |
| 1001 | - | 12, // [12:12] is the sub-list for method output_type | |
| 1002 | - | 12, // [12:12] is the sub-list for method input_type | |
| 1003 | - | 12, // [12:12] is the sub-list for extension type_name | |
| 1004 | - | 12, // [12:12] is the sub-list for extension extendee | |
| 1005 | - | 0, // [0:12] is the sub-list for field type_name | |
| 1120 | + | 8, // 6: ermite.storage.MergeRequest.auto_merge:type_name -> ermite.storage.AutoMerge | |
| 1121 | + | 0, // 7: ermite.storage.AutoMerge.mode:type_name -> ermite.storage.MergeMode | |
| 1122 | + | 12, // 8: ermite.storage.AutoMerge.enabled_at:type_name -> google.protobuf.Timestamp | |
| 1123 | + | 3, // 9: ermite.storage.Comment.side:type_name -> ermite.storage.DiffSide | |
| 1124 | + | 12, // 10: ermite.storage.Comment.created_at:type_name -> google.protobuf.Timestamp | |
| 1125 | + | 4, // 11: ermite.storage.Comment.verdict:type_name -> ermite.storage.Verdict | |
| 1126 | + | 12, // 12: ermite.storage.Comment.edited_at:type_name -> google.protobuf.Timestamp | |
| 1127 | + | 5, // 13: ermite.storage.Mergeability.state:type_name -> ermite.storage.MergeabilityState | |
| 1128 | + | 12, // 14: ermite.storage.Mergeability.checked_at:type_name -> google.protobuf.Timestamp | |
| 1129 | + | 15, // [15:15] is the sub-list for method output_type | |
| 1130 | + | 15, // [15:15] is the sub-list for method input_type | |
| 1131 | + | 15, // [15:15] is the sub-list for extension type_name | |
| 1132 | + | 15, // [15:15] is the sub-list for extension extendee | |
| 1133 | + | 0, // [0:15] is the sub-list for field type_name | |
| 1006 | 1134 | } | |
| 1007 | 1135 | ||
| 1008 | 1136 | func init() { file_ermite_storage_merge_request_proto_init() } | |
| @@ -1016,7 +1144,7 @@ func file_ermite_storage_merge_request_proto_init() { | |||
| 1016 | 1144 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | |
| 1017 | 1145 | RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_storage_merge_request_proto_rawDesc), len(file_ermite_storage_merge_request_proto_rawDesc)), | |
| 1018 | 1146 | NumEnums: 6, | |
| 1019 | - | NumMessages: 5, | |
| 1147 | + | NumMessages: 6, | |
| 1020 | 1148 | NumExtensions: 0, | |
| 1021 | 1149 | NumServices: 0, | |
| 1022 | 1150 | }, | |
| @@ -352,9 +352,10 @@ type RepoSettings struct { | |||||
| 352 | // choice of the owner. When false (settings stored before), exactly | 352 | // choice of the owner. When false (settings stored before), exactly | ||
| 353 | // {fast-forward, squash} was the old default and gains MERGE_MODE_MERGE on | 353 | // {fast-forward, squash} was the old default and gains MERGE_MODE_MERGE on | ||
| 354 | // read. | 354 | // read. | ||
| 355 | - | MergeModesV2 bool `protobuf:"varint,4,opt,name=merge_modes_v2,json=mergeModesV2,proto3" json:"merge_modes_v2,omitempty"` | 355 | + | MergeModesV2 bool `protobuf:"varint,4,opt,name=merge_modes_v2,json=mergeModesV2,proto3" json:"merge_modes_v2,omitempty"` |
| 356 | - | unknownFields protoimpl.UnknownFields | 356 | + | AllowAutoMerge bool `protobuf:"varint,5,opt,name=allow_auto_merge,json=allowAutoMerge,proto3" json:"allow_auto_merge,omitempty"` |
| 357 | - | sizeCache protoimpl.SizeCache | 357 | + | unknownFields protoimpl.UnknownFields |
| 358 | + | sizeCache protoimpl.SizeCache | |||
| 358 | } | 359 | } | ||
| 359 | 360 | ||||
| 360 | func (x *RepoSettings) Reset() { | 361 | func (x *RepoSettings) Reset() { | ||
| @@ -415,6 +416,13 @@ func (x *RepoSettings) GetMergeModesV2() bool { | |||||
| 415 | return false | 416 | return false | ||
| 416 | } | 417 | } | ||
| 417 | 418 | ||||
| 419 | + | func (x *RepoSettings) GetAllowAutoMerge() bool { | |||
| 420 | + | if x != nil { | |||
| 421 | + | return x.AllowAutoMerge | |||
| 422 | + | } | |||
| 423 | + | return false | |||
| 424 | + | } | |||
| 425 | + | ||||
| 418 | // MergeRequest is stored under the key "mr/<repo>/<number:010d>". | 426 | // MergeRequest is stored under the key "mr/<repo>/<number:010d>". | ||
| 419 | type MergeRequest struct { | 427 | type MergeRequest struct { | ||
| 420 | state protoimpl.MessageState `protogen:"open.v1"` | 428 | state protoimpl.MessageState `protogen:"open.v1"` | ||
| @@ -437,7 +445,10 @@ type MergeRequest struct { | |||||
| 437 | MergedCommitId string `protobuf:"bytes,12,opt,name=merged_commit_id,json=mergedCommitId,proto3" json:"merged_commit_id,omitempty"` | 445 | MergedCommitId string `protobuf:"bytes,12,opt,name=merged_commit_id,json=mergedCommitId,proto3" json:"merged_commit_id,omitempty"` | ||
| 438 | MergeMode MergeMode `protobuf:"varint,13,opt,name=merge_mode,json=mergeMode,proto3,enum=ermite.storage.MergeMode" json:"merge_mode,omitempty"` | 446 | MergeMode MergeMode `protobuf:"varint,13,opt,name=merge_mode,json=mergeMode,proto3,enum=ermite.storage.MergeMode" json:"merge_mode,omitempty"` | ||
| 439 | // Last comment id handed out for this request. | 447 | // Last comment id handed out for this request. | ||
| 440 | - | CommentSeq int64 `protobuf:"varint,14,opt,name=comment_seq,json=commentSeq,proto3" json:"comment_seq,omitempty"` | 448 | + | CommentSeq int64 `protobuf:"varint,14,opt,name=comment_seq,json=commentSeq,proto3" json:"comment_seq,omitempty"` |
| 449 | + | // Pending auto-merge; unset when off. | |||
| 450 | + | AutoMerge *AutoMerge `protobuf:"bytes,15,opt,name=auto_merge,json=autoMerge,proto3" json:"auto_merge,omitempty"` | |||
| 451 | + | AutoMerged bool `protobuf:"varint,16,opt,name=auto_merged,json=autoMerged,proto3" json:"auto_merged,omitempty"` | |||
| 441 | unknownFields protoimpl.UnknownFields | 452 | unknownFields protoimpl.UnknownFields | ||
| 442 | sizeCache protoimpl.SizeCache | 453 | sizeCache protoimpl.SizeCache | ||
| 443 | } | 454 | } | ||
| @@ -570,6 +581,106 @@ func (x *MergeRequest) GetCommentSeq() int64 { | |||||
| 570 | return 0 | 581 | return 0 | ||
| 571 | } | 582 | } | ||
| 572 | 583 | ||||
| 584 | + | func (x *MergeRequest) GetAutoMerge() *AutoMerge { | |||
| 585 | + | if x != nil { | |||
| 586 | + | return x.AutoMerge | |||
| 587 | + | } | |||
| 588 | + | return nil | |||
| 589 | + | } | |||
| 590 | + | ||||
| 591 | + | func (x *MergeRequest) GetAutoMerged() bool { | |||
| 592 | + | if x != nil { | |||
| 593 | + | return x.AutoMerged | |||
| 594 | + | } | |||
| 595 | + | return false | |||
| 596 | + | } | |||
| 597 | + | ||||
| 598 | + | // AutoMerge is the pending auto-merge of an open merge request. | |||
| 599 | + | type AutoMerge struct { | |||
| 600 | + | state protoimpl.MessageState `protogen:"open.v1"` | |||
| 601 | + | Mode MergeMode `protobuf:"varint,1,opt,name=mode,proto3,enum=ermite.storage.MergeMode" json:"mode,omitempty"` | |||
| 602 | + | HeadId string `protobuf:"bytes,2,opt,name=head_id,json=headId,proto3" json:"head_id,omitempty"` | |||
| 603 | + | // Kind and token id of the CIPusher that enabled it. | |||
| 604 | + | EnablerKind string `protobuf:"bytes,3,opt,name=enabler_kind,json=enablerKind,proto3" json:"enabler_kind,omitempty"` | |||
| 605 | + | EnablerTokenId string `protobuf:"bytes,4,opt,name=enabler_token_id,json=enablerTokenId,proto3" json:"enabler_token_id,omitempty"` | |||
| 606 | + | EnablerLabel string `protobuf:"bytes,5,opt,name=enabler_label,json=enablerLabel,proto3" json:"enabler_label,omitempty"` | |||
| 607 | + | EnabledAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=enabled_at,json=enabledAt,proto3" json:"enabled_at,omitempty"` | |||
| 608 | + | unknownFields protoimpl.UnknownFields | |||
| 609 | + | sizeCache protoimpl.SizeCache | |||
| 610 | + | } | |||
| 611 | + | ||||
| 612 | + | func (x *AutoMerge) Reset() { | |||
| 613 | + | *x = AutoMerge{} | |||
| 614 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[2] | |||
| 615 | + | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |||
| 616 | + | ms.StoreMessageInfo(mi) | |||
| 617 | + | } | |||
| 618 | + | ||||
| 619 | + | func (x *AutoMerge) String() string { | |||
| 620 | + | return protoimpl.X.MessageStringOf(x) | |||
| 621 | + | } | |||
| 622 | + | ||||
| 623 | + | func (*AutoMerge) ProtoMessage() {} | |||
| 624 | + | ||||
| 625 | + | func (x *AutoMerge) ProtoReflect() protoreflect.Message { | |||
| 626 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[2] | |||
| 627 | + | if x != nil { | |||
| 628 | + | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | |||
| 629 | + | if ms.LoadMessageInfo() == nil { | |||
| 630 | + | ms.StoreMessageInfo(mi) | |||
| 631 | + | } | |||
| 632 | + | return ms | |||
| 633 | + | } | |||
| 634 | + | return mi.MessageOf(x) | |||
| 635 | + | } | |||
| 636 | + | ||||
| 637 | + | // Deprecated: Use AutoMerge.ProtoReflect.Descriptor instead. | |||
| 638 | + | func (*AutoMerge) Descriptor() ([]byte, []int) { | |||
| 639 | + | return file_ermite_storage_merge_request_proto_rawDescGZIP(), []int{2} | |||
| 640 | + | } | |||
| 641 | + | ||||
| 642 | + | func (x *AutoMerge) GetMode() MergeMode { | |||
| 643 | + | if x != nil { | |||
| 644 | + | return x.Mode | |||
| 645 | + | } | |||
| 646 | + | return MergeMode_MERGE_MODE_UNSPECIFIED | |||
| 647 | + | } | |||
| 648 | + | ||||
| 649 | + | func (x *AutoMerge) GetHeadId() string { | |||
| 650 | + | if x != nil { | |||
| 651 | + | return x.HeadId | |||
| 652 | + | } | |||
| 653 | + | return "" | |||
| 654 | + | } | |||
| 655 | + | ||||
| 656 | + | func (x *AutoMerge) GetEnablerKind() string { | |||
| 657 | + | if x != nil { | |||
| 658 | + | return x.EnablerKind | |||
| 659 | + | } | |||
| 660 | + | return "" | |||
| 661 | + | } | |||
| 662 | + | ||||
| 663 | + | func (x *AutoMerge) GetEnablerTokenId() string { | |||
| 664 | + | if x != nil { | |||
| 665 | + | return x.EnablerTokenId | |||
| 666 | + | } | |||
| 667 | + | return "" | |||
| 668 | + | } | |||
| 669 | + | ||||
| 670 | + | func (x *AutoMerge) GetEnablerLabel() string { | |||
| 671 | + | if x != nil { | |||
| 672 | + | return x.EnablerLabel | |||
| 673 | + | } | |||
| 674 | + | return "" | |||
| 675 | + | } | |||
| 676 | + | ||||
| 677 | + | func (x *AutoMerge) GetEnabledAt() *timestamppb.Timestamp { | |||
| 678 | + | if x != nil { | |||
| 679 | + | return x.EnabledAt | |||
| 680 | + | } | |||
| 681 | + | return nil | |||
| 682 | + | } | |||
| 683 | + | ||||
| 573 | // Comment is stored under the key "mrc/<repo>/<number:010d>/<id:010d>". | 684 | // Comment is stored under the key "mrc/<repo>/<number:010d>/<id:010d>". | ||
| 574 | type Comment struct { | 685 | type Comment struct { | ||
| 575 | state protoimpl.MessageState `protogen:"open.v1"` | 686 | state protoimpl.MessageState `protogen:"open.v1"` | ||
| @@ -593,7 +704,7 @@ type Comment struct { | |||||
| 593 | 704 | ||||
| 594 | func (x *Comment) Reset() { | 705 | func (x *Comment) Reset() { | ||
| 595 | *x = Comment{} | 706 | *x = Comment{} | ||
| 596 | - | mi := &file_ermite_storage_merge_request_proto_msgTypes[2] | 707 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[3] |
| 597 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | 708 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||
| 598 | ms.StoreMessageInfo(mi) | 709 | ms.StoreMessageInfo(mi) | ||
| 599 | } | 710 | } | ||
| @@ -605,7 +716,7 @@ func (x *Comment) String() string { | |||||
| 605 | func (*Comment) ProtoMessage() {} | 716 | func (*Comment) ProtoMessage() {} | ||
| 606 | 717 | ||||
| 607 | func (x *Comment) ProtoReflect() protoreflect.Message { | 718 | func (x *Comment) ProtoReflect() protoreflect.Message { | ||
| 608 | - | mi := &file_ermite_storage_merge_request_proto_msgTypes[2] | 719 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[3] |
| 609 | if x != nil { | 720 | if x != nil { | ||
| 610 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | 721 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||
| 611 | if ms.LoadMessageInfo() == nil { | 722 | if ms.LoadMessageInfo() == nil { | ||
| @@ -618,7 +729,7 @@ func (x *Comment) ProtoReflect() protoreflect.Message { | |||||
| 618 | 729 | ||||
| 619 | // Deprecated: Use Comment.ProtoReflect.Descriptor instead. | 730 | // Deprecated: Use Comment.ProtoReflect.Descriptor instead. | ||
| 620 | func (*Comment) Descriptor() ([]byte, []int) { | 731 | func (*Comment) Descriptor() ([]byte, []int) { | ||
| 621 | - | return file_ermite_storage_merge_request_proto_rawDescGZIP(), []int{2} | 732 | + | return file_ermite_storage_merge_request_proto_rawDescGZIP(), []int{3} |
| 622 | } | 733 | } | ||
| 623 | 734 | ||||
| 624 | func (x *Comment) GetId() int64 { | 735 | func (x *Comment) GetId() int64 { | ||
| @@ -730,7 +841,7 @@ type Sequence struct { | |||||
| 730 | 841 | ||||
| 731 | func (x *Sequence) Reset() { | 842 | func (x *Sequence) Reset() { | ||
| 732 | *x = Sequence{} | 843 | *x = Sequence{} | ||
| 733 | - | mi := &file_ermite_storage_merge_request_proto_msgTypes[3] | 844 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[4] |
| 734 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | 845 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||
| 735 | ms.StoreMessageInfo(mi) | 846 | ms.StoreMessageInfo(mi) | ||
| 736 | } | 847 | } | ||
| @@ -742,7 +853,7 @@ func (x *Sequence) String() string { | |||||
| 742 | func (*Sequence) ProtoMessage() {} | 853 | func (*Sequence) ProtoMessage() {} | ||
| 743 | 854 | ||||
| 744 | func (x *Sequence) ProtoReflect() protoreflect.Message { | 855 | func (x *Sequence) ProtoReflect() protoreflect.Message { | ||
| 745 | - | mi := &file_ermite_storage_merge_request_proto_msgTypes[3] | 856 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[4] |
| 746 | if x != nil { | 857 | if x != nil { | ||
| 747 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | 858 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||
| 748 | if ms.LoadMessageInfo() == nil { | 859 | if ms.LoadMessageInfo() == nil { | ||
| @@ -755,7 +866,7 @@ func (x *Sequence) ProtoReflect() protoreflect.Message { | |||||
| 755 | 866 | ||||
| 756 | // Deprecated: Use Sequence.ProtoReflect.Descriptor instead. | 867 | // Deprecated: Use Sequence.ProtoReflect.Descriptor instead. | ||
| 757 | func (*Sequence) Descriptor() ([]byte, []int) { | 868 | func (*Sequence) Descriptor() ([]byte, []int) { | ||
| 758 | - | return file_ermite_storage_merge_request_proto_rawDescGZIP(), []int{3} | 869 | + | return file_ermite_storage_merge_request_proto_rawDescGZIP(), []int{4} |
| 759 | } | 870 | } | ||
| 760 | 871 | ||||
| 761 | func (x *Sequence) GetLast() int64 { | 872 | func (x *Sequence) GetLast() int64 { | ||
| @@ -783,7 +894,7 @@ type Mergeability struct { | |||||
| 783 | 894 | ||||
| 784 | func (x *Mergeability) Reset() { | 895 | func (x *Mergeability) Reset() { | ||
| 785 | *x = Mergeability{} | 896 | *x = Mergeability{} | ||
| 786 | - | mi := &file_ermite_storage_merge_request_proto_msgTypes[4] | 897 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[5] |
| 787 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | 898 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||
| 788 | ms.StoreMessageInfo(mi) | 899 | ms.StoreMessageInfo(mi) | ||
| 789 | } | 900 | } | ||
| @@ -795,7 +906,7 @@ func (x *Mergeability) String() string { | |||||
| 795 | func (*Mergeability) ProtoMessage() {} | 906 | func (*Mergeability) ProtoMessage() {} | ||
| 796 | 907 | ||||
| 797 | func (x *Mergeability) ProtoReflect() protoreflect.Message { | 908 | func (x *Mergeability) ProtoReflect() protoreflect.Message { | ||
| 798 | - | mi := &file_ermite_storage_merge_request_proto_msgTypes[4] | 909 | + | mi := &file_ermite_storage_merge_request_proto_msgTypes[5] |
| 799 | if x != nil { | 910 | if x != nil { | ||
| 800 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | 911 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) | ||
| 801 | if ms.LoadMessageInfo() == nil { | 912 | if ms.LoadMessageInfo() == nil { | ||
| @@ -808,7 +919,7 @@ func (x *Mergeability) ProtoReflect() protoreflect.Message { | |||||
| 808 | 919 | ||||
| 809 | // Deprecated: Use Mergeability.ProtoReflect.Descriptor instead. | 920 | // Deprecated: Use Mergeability.ProtoReflect.Descriptor instead. | ||
| 810 | func (*Mergeability) Descriptor() ([]byte, []int) { | 921 | func (*Mergeability) Descriptor() ([]byte, []int) { | ||
| 811 | - | return file_ermite_storage_merge_request_proto_rawDescGZIP(), []int{4} | 922 | + | return file_ermite_storage_merge_request_proto_rawDescGZIP(), []int{5} |
| 812 | } | 923 | } | ||
| 813 | 924 | ||||
| 814 | func (x *Mergeability) GetState() MergeabilityState { | 925 | func (x *Mergeability) GetState() MergeabilityState { | ||
| @@ -871,12 +982,13 @@ var File_ermite_storage_merge_request_proto protoreflect.FileDescriptor | |||||
| 871 | 982 | ||||
| 872 | const file_ermite_storage_merge_request_proto_rawDesc = "" + | 983 | const file_ermite_storage_merge_request_proto_rawDesc = "" + | ||
| 873 | "\n" + | 984 | "\n" + | ||
| 874 | - | "\"ermite/storage/merge_request.proto\x12\x0eermite.storage\x1a\x1fgoogle/protobuf/timestamp.proto\"\xe5\x01\n" + | 985 | + | "\"ermite/storage/merge_request.proto\x12\x0eermite.storage\x1a\x1fgoogle/protobuf/timestamp.proto\"\x8f\x02\n" + |
| 875 | "\fRepoSettings\x12I\n" + | 986 | "\fRepoSettings\x12I\n" + | ||
| 876 | "\x13allowed_merge_modes\x18\x01 \x03(\x0e2\x19.ermite.storage.MergeModeR\x11allowedMergeModes\x120\n" + | 987 | "\x13allowed_merge_modes\x18\x01 \x03(\x0e2\x19.ermite.storage.MergeModeR\x11allowedMergeModes\x120\n" + | ||
| 877 | "\x14failing_checks_block\x18\x02 \x01(\bR\x12failingChecksBlock\x122\n" + | 988 | "\x14failing_checks_block\x18\x02 \x01(\bR\x12failingChecksBlock\x122\n" + | ||
| 878 | "\x06issues\x18\x03 \x01(\x0e2\x1a.ermite.storage.IssuesModeR\x06issues\x12$\n" + | 989 | "\x06issues\x18\x03 \x01(\x0e2\x1a.ermite.storage.IssuesModeR\x06issues\x12$\n" + | ||
| 879 | - | "\x0emerge_modes_v2\x18\x04 \x01(\bR\fmergeModesV2\"\xa6\x04\n" + | 990 | + | "\x0emerge_modes_v2\x18\x04 \x01(\bR\fmergeModesV2\x12(\n" + |
| 991 | + | "\x10allow_auto_merge\x18\x05 \x01(\bR\x0eallowAutoMerge\"\x81\x05\n" + | |||
| 880 | "\fMergeRequest\x12\x16\n" + | 992 | "\fMergeRequest\x12\x16\n" + | ||
| 881 | "\x06number\x18\x01 \x01(\x03R\x06number\x12\x14\n" + | 993 | "\x06number\x18\x01 \x01(\x03R\x06number\x12\x14\n" + | ||
| 882 | "\x05title\x18\x02 \x01(\tR\x05title\x12 \n" + | 994 | "\x05title\x18\x02 \x01(\tR\x05title\x12 \n" + | ||
| @@ -896,7 +1008,19 @@ const file_ermite_storage_merge_request_proto_rawDesc = "" + | |||||
| 896 | "\n" + | 1008 | "\n" + | ||
| 897 | "merge_mode\x18\r \x01(\x0e2\x19.ermite.storage.MergeModeR\tmergeMode\x12\x1f\n" + | 1009 | "merge_mode\x18\r \x01(\x0e2\x19.ermite.storage.MergeModeR\tmergeMode\x12\x1f\n" + | ||
| 898 | "\vcomment_seq\x18\x0e \x01(\x03R\n" + | 1010 | "\vcomment_seq\x18\x0e \x01(\x03R\n" + | ||
| 899 | - | "commentSeq\"\xcf\x03\n" + | 1011 | + | "commentSeq\x128\n" + |
| 1012 | + | "\n" + | |||
| 1013 | + | "auto_merge\x18\x0f \x01(\v2\x19.ermite.storage.AutoMergeR\tautoMerge\x12\x1f\n" + | |||
| 1014 | + | "\vauto_merged\x18\x10 \x01(\bR\n" + | |||
| 1015 | + | "autoMerged\"\x80\x02\n" + | |||
| 1016 | + | "\tAutoMerge\x12-\n" + | |||
| 1017 | + | "\x04mode\x18\x01 \x01(\x0e2\x19.ermite.storage.MergeModeR\x04mode\x12\x17\n" + | |||
| 1018 | + | "\ahead_id\x18\x02 \x01(\tR\x06headId\x12!\n" + | |||
| 1019 | + | "\fenabler_kind\x18\x03 \x01(\tR\venablerKind\x12(\n" + | |||
| 1020 | + | "\x10enabler_token_id\x18\x04 \x01(\tR\x0eenablerTokenId\x12#\n" + | |||
| 1021 | + | "\renabler_label\x18\x05 \x01(\tR\fenablerLabel\x129\n" + | |||
| 1022 | + | "\n" + | |||
| 1023 | + | "enabled_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\tenabledAt\"\xcf\x03\n" + | |||
| 900 | "\aComment\x12\x0e\n" + | 1024 | "\aComment\x12\x0e\n" + | ||
| 901 | "\x02id\x18\x01 \x01(\x03R\x02id\x12\x16\n" + | 1025 | "\x02id\x18\x01 \x01(\x03R\x02id\x12\x16\n" + | ||
| 902 | "\x06author\x18\x02 \x01(\tR\x06author\x12\x12\n" + | 1026 | "\x06author\x18\x02 \x01(\tR\x06author\x12\x12\n" + | ||
| @@ -970,7 +1094,7 @@ func file_ermite_storage_merge_request_proto_rawDescGZIP() []byte { | |||||
| 970 | } | 1094 | } | ||
| 971 | 1095 | ||||
| 972 | var file_ermite_storage_merge_request_proto_enumTypes = make([]protoimpl.EnumInfo, 6) | 1096 | var file_ermite_storage_merge_request_proto_enumTypes = make([]protoimpl.EnumInfo, 6) | ||
| 973 | - | var file_ermite_storage_merge_request_proto_msgTypes = make([]protoimpl.MessageInfo, 5) | 1097 | + | var file_ermite_storage_merge_request_proto_msgTypes = make([]protoimpl.MessageInfo, 6) |
| 974 | var file_ermite_storage_merge_request_proto_goTypes = []any{ | 1098 | var file_ermite_storage_merge_request_proto_goTypes = []any{ | ||
| 975 | (MergeMode)(0), // 0: ermite.storage.MergeMode | 1099 | (MergeMode)(0), // 0: ermite.storage.MergeMode | ||
| 976 | (IssuesMode)(0), // 1: ermite.storage.IssuesMode | 1100 | (IssuesMode)(0), // 1: ermite.storage.IssuesMode | ||
| @@ -980,29 +1104,33 @@ var file_ermite_storage_merge_request_proto_goTypes = []any{ | |||||
| 980 | (MergeabilityState)(0), // 5: ermite.storage.MergeabilityState | 1104 | (MergeabilityState)(0), // 5: ermite.storage.MergeabilityState | ||
| 981 | (*RepoSettings)(nil), // 6: ermite.storage.RepoSettings | 1105 | (*RepoSettings)(nil), // 6: ermite.storage.RepoSettings | ||
| 982 | (*MergeRequest)(nil), // 7: ermite.storage.MergeRequest | 1106 | (*MergeRequest)(nil), // 7: ermite.storage.MergeRequest | ||
| 983 | - | (*Comment)(nil), // 8: ermite.storage.Comment | 1107 | + | (*AutoMerge)(nil), // 8: ermite.storage.AutoMerge |
| 984 | - | (*Sequence)(nil), // 9: ermite.storage.Sequence | 1108 | + | (*Comment)(nil), // 9: ermite.storage.Comment |
| 985 | - | (*Mergeability)(nil), // 10: ermite.storage.Mergeability | 1109 | + | (*Sequence)(nil), // 10: ermite.storage.Sequence |
| 986 | - | (*timestamppb.Timestamp)(nil), // 11: google.protobuf.Timestamp | 1110 | + | (*Mergeability)(nil), // 11: ermite.storage.Mergeability |
| 1111 | + | (*timestamppb.Timestamp)(nil), // 12: google.protobuf.Timestamp | |||
| 987 | } | 1112 | } | ||
| 988 | var file_ermite_storage_merge_request_proto_depIdxs = []int32{ | 1113 | var file_ermite_storage_merge_request_proto_depIdxs = []int32{ | ||
| 989 | 0, // 0: ermite.storage.RepoSettings.allowed_merge_modes:type_name -> ermite.storage.MergeMode | 1114 | 0, // 0: ermite.storage.RepoSettings.allowed_merge_modes:type_name -> ermite.storage.MergeMode | ||
| 990 | 1, // 1: ermite.storage.RepoSettings.issues:type_name -> ermite.storage.IssuesMode | 1115 | 1, // 1: ermite.storage.RepoSettings.issues:type_name -> ermite.storage.IssuesMode | ||
| 991 | 2, // 2: ermite.storage.MergeRequest.state:type_name -> ermite.storage.MergeRequestState | 1116 | 2, // 2: ermite.storage.MergeRequest.state:type_name -> ermite.storage.MergeRequestState | ||
| 992 | - | 11, // 3: ermite.storage.MergeRequest.created_at:type_name -> google.protobuf.Timestamp | 1117 | + | 12, // 3: ermite.storage.MergeRequest.created_at:type_name -> google.protobuf.Timestamp |
| 993 | - | 11, // 4: ermite.storage.MergeRequest.updated_at:type_name -> google.protobuf.Timestamp | 1118 | + | 12, // 4: ermite.storage.MergeRequest.updated_at:type_name -> google.protobuf.Timestamp |
| 994 | 0, // 5: ermite.storage.MergeRequest.merge_mode:type_name -> ermite.storage.MergeMode | 1119 | 0, // 5: ermite.storage.MergeRequest.merge_mode:type_name -> ermite.storage.MergeMode | ||
| 995 | - | 3, // 6: ermite.storage.Comment.side:type_name -> ermite.storage.DiffSide | 1120 | + | 8, // 6: ermite.storage.MergeRequest.auto_merge:type_name -> ermite.storage.AutoMerge |
| 996 | - | 11, // 7: ermite.storage.Comment.created_at:type_name -> google.protobuf.Timestamp | 1121 | + | 0, // 7: ermite.storage.AutoMerge.mode:type_name -> ermite.storage.MergeMode |
| 997 | - | 4, // 8: ermite.storage.Comment.verdict:type_name -> ermite.storage.Verdict | 1122 | + | 12, // 8: ermite.storage.AutoMerge.enabled_at:type_name -> google.protobuf.Timestamp |
| 998 | - | 11, // 9: ermite.storage.Comment.edited_at:type_name -> google.protobuf.Timestamp | 1123 | + | 3, // 9: ermite.storage.Comment.side:type_name -> ermite.storage.DiffSide |
| 999 | - | 5, // 10: ermite.storage.Mergeability.state:type_name -> ermite.storage.MergeabilityState | 1124 | + | 12, // 10: ermite.storage.Comment.created_at:type_name -> google.protobuf.Timestamp |
| 1000 | - | 11, // 11: ermite.storage.Mergeability.checked_at:type_name -> google.protobuf.Timestamp | 1125 | + | 4, // 11: ermite.storage.Comment.verdict:type_name -> ermite.storage.Verdict |
| 1001 | - | 12, // [12:12] is the sub-list for method output_type | 1126 | + | 12, // 12: ermite.storage.Comment.edited_at:type_name -> google.protobuf.Timestamp |
| 1002 | - | 12, // [12:12] is the sub-list for method input_type | 1127 | + | 5, // 13: ermite.storage.Mergeability.state:type_name -> ermite.storage.MergeabilityState |
| 1003 | - | 12, // [12:12] is the sub-list for extension type_name | 1128 | + | 12, // 14: ermite.storage.Mergeability.checked_at:type_name -> google.protobuf.Timestamp |
| 1004 | - | 12, // [12:12] is the sub-list for extension extendee | 1129 | + | 15, // [15:15] is the sub-list for method output_type |
| 1005 | - | 0, // [0:12] is the sub-list for field type_name | 1130 | + | 15, // [15:15] is the sub-list for method input_type |
| 1131 | + | 15, // [15:15] is the sub-list for extension type_name | |||
| 1132 | + | 15, // [15:15] is the sub-list for extension extendee | |||
| 1133 | + | 0, // [0:15] is the sub-list for field type_name | |||
| 1006 | } | 1134 | } | ||
| 1007 | 1135 | ||||
| 1008 | func init() { file_ermite_storage_merge_request_proto_init() } | 1136 | func init() { file_ermite_storage_merge_request_proto_init() } | ||
| @@ -1016,7 +1144,7 @@ func file_ermite_storage_merge_request_proto_init() { | |||||
| 1016 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | 1144 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), | ||
| 1017 | RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_storage_merge_request_proto_rawDesc), len(file_ermite_storage_merge_request_proto_rawDesc)), | 1145 | RawDescriptor: unsafe.Slice(unsafe.StringData(file_ermite_storage_merge_request_proto_rawDesc), len(file_ermite_storage_merge_request_proto_rawDesc)), | ||
| 1018 | NumEnums: 6, | 1146 | NumEnums: 6, | ||
| 1019 | - | NumMessages: 5, | 1147 | + | NumMessages: 6, |
| 1020 | NumExtensions: 0, | 1148 | NumExtensions: 0, | ||
| 1021 | NumServices: 0, | 1149 | NumServices: 0, | ||
| 1022 | }, | 1150 | }, | ||
M internal/adapters/kvstore/mergerequests.go +32 -2
| @@ -728,6 +728,18 @@ func encodeMergeRequest(mr domain.MergeRequest) ([]byte, error) { | |||
| 728 | 728 | if err != nil { | |
| 729 | 729 | return nil, err | |
| 730 | 730 | } | |
| 731 | + | var autoMerge *storagepb.AutoMerge | |
| 732 | + | if am := mr.AutoMerge; am != nil { | |
| 733 | + | amMode, err := encodeMode(am.Mode) | |
| 734 | + | if err != nil || amMode == storagepb.MergeMode_MERGE_MODE_UNSPECIFIED { | |
| 735 | + | return nil, fmt.Errorf("%w: merge mode %q in the auto-merge", domain.ErrInvalid, am.Mode) | |
| 736 | + | } | |
| 737 | + | autoMerge = &storagepb.AutoMerge{ | |
| 738 | + | Mode: amMode, HeadId: am.HeadID.String(), | |
| 739 | + | EnablerKind: string(am.EnabledBy.Kind), EnablerTokenId: am.EnabledBy.TokenID, | |
| 740 | + | EnablerLabel: am.EnablerLabel, EnabledAt: encodeTime(am.EnabledAt), | |
| 741 | + | } | |
| 742 | + | } | |
| 731 | 743 | return mustMarshal(&storagepb.MergeRequest{ | |
| 732 | 744 | Number: mr.Number, | |
| 733 | 745 | Title: mr.Title.String(), | |
| @@ -743,6 +755,8 @@ func encodeMergeRequest(mr domain.MergeRequest) ([]byte, error) { | |||
| 743 | 755 | MergedCommitId: mr.MergedCommitID.String(), | |
| 744 | 756 | MergeMode: mode, | |
| 745 | 757 | CommentSeq: mr.CommentSeq, | |
| 758 | + | AutoMerge: autoMerge, | |
| 759 | + | AutoMerged: mr.AutoMerged, | |
| 746 | 760 | }), nil | |
| 747 | 761 | } | |
| 748 | 762 | ||
| @@ -773,8 +787,24 @@ func decodeMergeRequest(repo domain.RepoName, item kv.Item) (domain.MergeRequest | |||
| 773 | 787 | CreatedAt: decodeTime(pb.GetCreatedAt()), UpdatedAt: decodeTime(pb.GetUpdatedAt()), | |
| 774 | 788 | MergeMode: decodeMode(pb.GetMergeMode()), | |
| 775 | 789 | CommentSeq: pb.GetCommentSeq(), | |
| 790 | + | AutoMerged: pb.GetAutoMerged(), | |
| 776 | 791 | Version: item.Version, | |
| 777 | 792 | } | |
| 793 | + | if am := pb.GetAutoMerge(); am != nil { | |
| 794 | + | head, err := domain.ParseObjectID(am.GetHeadId()) | |
| 795 | + | if err != nil { | |
| 796 | + | return fail(err) | |
| 797 | + | } | |
| 798 | + | mode := decodeMode(am.GetMode()) | |
| 799 | + | if mode == "" { | |
| 800 | + | return fail(fmt.Errorf("unknown auto-merge mode %d", am.GetMode())) | |
| 801 | + | } | |
| 802 | + | mr.AutoMerge = &domain.AutoMerge{ | |
| 803 | + | Mode: mode, HeadID: head, | |
| 804 | + | EnabledBy: domain.CIPusher{Kind: domain.CIPusherKind(am.GetEnablerKind()), TokenID: am.GetEnablerTokenId()}, | |
| 805 | + | EnablerLabel: am.GetEnablerLabel(), EnabledAt: decodeTime(am.GetEnabledAt()), | |
| 806 | + | } | |
| 807 | + | } | |
| 778 | 808 | for _, f := range []struct { | |
| 779 | 809 | dst *domain.ObjectID | |
| 780 | 810 | src string | |
| @@ -909,7 +939,7 @@ func decodeSide(s storagepb.DiffSide) domain.DiffSide { | |||
| 909 | 939 | } | |
| 910 | 940 | ||
| 911 | 941 | func encodeSettings(s domain.RepoSettings) (*storagepb.RepoSettings, error) { | |
| 912 | - | pb := &storagepb.RepoSettings{FailingChecksBlock: s.FailingChecksBlock, MergeModesV2: true} | |
| 942 | + | pb := &storagepb.RepoSettings{FailingChecksBlock: s.FailingChecksBlock, MergeModesV2: true, AllowAutoMerge: s.AllowAutoMerge} | |
| 913 | 943 | for _, m := range s.AllowedMergeModes { | |
| 914 | 944 | mode, err := encodeMode(m) | |
| 915 | 945 | if err != nil || mode == storagepb.MergeMode_MERGE_MODE_UNSPECIFIED { | |
| @@ -949,5 +979,5 @@ func decodeSettings(pb *storagepb.RepoSettings) domain.RepoSettings { | |||
| 949 | 979 | if !pb.GetMergeModesV2() && slices.Equal(normalized, []domain.MergeMode{domain.MergeModeFastForward, domain.MergeModeSquash}) { | |
| 950 | 980 | normalized = domain.MergeModes() | |
| 951 | 981 | } | |
| 952 | - | return domain.RepoSettings{AllowedMergeModes: normalized, FailingChecksBlock: pb.GetFailingChecksBlock(), Issues: decodeIssuesMode(pb.GetIssues())} | |
| 982 | + | return domain.RepoSettings{AllowedMergeModes: normalized, FailingChecksBlock: pb.GetFailingChecksBlock(), Issues: decodeIssuesMode(pb.GetIssues()), AllowAutoMerge: pb.GetAllowAutoMerge()} | |
| 953 | 983 | } | |
| @@ -728,6 +728,18 @@ func encodeMergeRequest(mr domain.MergeRequest) ([]byte, error) { | |||||
| 728 | if err != nil { | 728 | if err != nil { | ||
| 729 | return nil, err | 729 | return nil, err | ||
| 730 | } | 730 | } | ||
| 731 | + | var autoMerge *storagepb.AutoMerge | |||
| 732 | + | if am := mr.AutoMerge; am != nil { | |||
| 733 | + | amMode, err := encodeMode(am.Mode) | |||
| 734 | + | if err != nil || amMode == storagepb.MergeMode_MERGE_MODE_UNSPECIFIED { | |||
| 735 | + | return nil, fmt.Errorf("%w: merge mode %q in the auto-merge", domain.ErrInvalid, am.Mode) | |||
| 736 | + | } | |||
| 737 | + | autoMerge = &storagepb.AutoMerge{ | |||
| 738 | + | Mode: amMode, HeadId: am.HeadID.String(), | |||
| 739 | + | EnablerKind: string(am.EnabledBy.Kind), EnablerTokenId: am.EnabledBy.TokenID, | |||
| 740 | + | EnablerLabel: am.EnablerLabel, EnabledAt: encodeTime(am.EnabledAt), | |||
| 741 | + | } | |||
| 742 | + | } | |||
| 731 | return mustMarshal(&storagepb.MergeRequest{ | 743 | return mustMarshal(&storagepb.MergeRequest{ | ||
| 732 | Number: mr.Number, | 744 | Number: mr.Number, | ||
| 733 | Title: mr.Title.String(), | 745 | Title: mr.Title.String(), | ||
| @@ -743,6 +755,8 @@ func encodeMergeRequest(mr domain.MergeRequest) ([]byte, error) { | |||||
| 743 | MergedCommitId: mr.MergedCommitID.String(), | 755 | MergedCommitId: mr.MergedCommitID.String(), | ||
| 744 | MergeMode: mode, | 756 | MergeMode: mode, | ||
| 745 | CommentSeq: mr.CommentSeq, | 757 | CommentSeq: mr.CommentSeq, | ||
| 758 | + | AutoMerge: autoMerge, | |||
| 759 | + | AutoMerged: mr.AutoMerged, | |||
| 746 | }), nil | 760 | }), nil | ||
| 747 | } | 761 | } | ||
| 748 | 762 | ||||
| @@ -773,8 +787,24 @@ func decodeMergeRequest(repo domain.RepoName, item kv.Item) (domain.MergeRequest | |||||
| 773 | CreatedAt: decodeTime(pb.GetCreatedAt()), UpdatedAt: decodeTime(pb.GetUpdatedAt()), | 787 | CreatedAt: decodeTime(pb.GetCreatedAt()), UpdatedAt: decodeTime(pb.GetUpdatedAt()), | ||
| 774 | MergeMode: decodeMode(pb.GetMergeMode()), | 788 | MergeMode: decodeMode(pb.GetMergeMode()), | ||
| 775 | CommentSeq: pb.GetCommentSeq(), | 789 | CommentSeq: pb.GetCommentSeq(), | ||
| 790 | + | AutoMerged: pb.GetAutoMerged(), | |||
| 776 | Version: item.Version, | 791 | Version: item.Version, | ||
| 777 | } | 792 | } | ||
| 793 | + | if am := pb.GetAutoMerge(); am != nil { | |||
| 794 | + | head, err := domain.ParseObjectID(am.GetHeadId()) | |||
| 795 | + | if err != nil { | |||
| 796 | + | return fail(err) | |||
| 797 | + | } | |||
| 798 | + | mode := decodeMode(am.GetMode()) | |||
| 799 | + | if mode == "" { | |||
| 800 | + | return fail(fmt.Errorf("unknown auto-merge mode %d", am.GetMode())) | |||
| 801 | + | } | |||
| 802 | + | mr.AutoMerge = &domain.AutoMerge{ | |||
| 803 | + | Mode: mode, HeadID: head, | |||
| 804 | + | EnabledBy: domain.CIPusher{Kind: domain.CIPusherKind(am.GetEnablerKind()), TokenID: am.GetEnablerTokenId()}, | |||
| 805 | + | EnablerLabel: am.GetEnablerLabel(), EnabledAt: decodeTime(am.GetEnabledAt()), | |||
| 806 | + | } | |||
| 807 | + | } | |||
| 778 | for _, f := range []struct { | 808 | for _, f := range []struct { | ||
| 779 | dst *domain.ObjectID | 809 | dst *domain.ObjectID | ||
| 780 | src string | 810 | src string | ||
| @@ -909,7 +939,7 @@ func decodeSide(s storagepb.DiffSide) domain.DiffSide { | |||||
| 909 | } | 939 | } | ||
| 910 | 940 | ||||
| 911 | func encodeSettings(s domain.RepoSettings) (*storagepb.RepoSettings, error) { | 941 | func encodeSettings(s domain.RepoSettings) (*storagepb.RepoSettings, error) { | ||
| 912 | - | pb := &storagepb.RepoSettings{FailingChecksBlock: s.FailingChecksBlock, MergeModesV2: true} | 942 | + | pb := &storagepb.RepoSettings{FailingChecksBlock: s.FailingChecksBlock, MergeModesV2: true, AllowAutoMerge: s.AllowAutoMerge} |
| 913 | for _, m := range s.AllowedMergeModes { | 943 | for _, m := range s.AllowedMergeModes { | ||
| 914 | mode, err := encodeMode(m) | 944 | mode, err := encodeMode(m) | ||
| 915 | if err != nil || mode == storagepb.MergeMode_MERGE_MODE_UNSPECIFIED { | 945 | if err != nil || mode == storagepb.MergeMode_MERGE_MODE_UNSPECIFIED { | ||
| @@ -949,5 +979,5 @@ func decodeSettings(pb *storagepb.RepoSettings) domain.RepoSettings { | |||||
| 949 | if !pb.GetMergeModesV2() && slices.Equal(normalized, []domain.MergeMode{domain.MergeModeFastForward, domain.MergeModeSquash}) { | 979 | if !pb.GetMergeModesV2() && slices.Equal(normalized, []domain.MergeMode{domain.MergeModeFastForward, domain.MergeModeSquash}) { | ||
| 950 | normalized = domain.MergeModes() | 980 | normalized = domain.MergeModes() | ||
| 951 | } | 981 | } | ||
| 952 | - | return domain.RepoSettings{AllowedMergeModes: normalized, FailingChecksBlock: pb.GetFailingChecksBlock(), Issues: decodeIssuesMode(pb.GetIssues())} | 982 | + | return domain.RepoSettings{AllowedMergeModes: normalized, FailingChecksBlock: pb.GetFailingChecksBlock(), Issues: decodeIssuesMode(pb.GetIssues()), AllowAutoMerge: pb.GetAllowAutoMerge()} |
| 953 | } | 983 | } | ||
M internal/adapters/kvstore/mergerequests_test.go +47 -0
| @@ -94,6 +94,35 @@ func TestMergeRequestRoundTrip(t *testing.T) { | |||
| 94 | 94 | assert.ErrorIs(t, err, domain.ErrNotFound) | |
| 95 | 95 | } | |
| 96 | 96 | ||
| 97 | + | func TestMergeRequestAutoMergeRoundTrip(t *testing.T) { | |
| 98 | + | ctx := context.Background() | |
| 99 | + | _, mrs, n := repoWithMRs(t) | |
| 100 | + | ||
| 101 | + | set := newMR(t, n, "Auto") | |
| 102 | + | set.AutoMerge = &domain.AutoMerge{ | |
| 103 | + | Mode: domain.MergeModeSquash, HeadID: oid('d'), | |
| 104 | + | EnabledBy: domain.CIPusher{Kind: domain.CIPusherToken, TokenID: "tok1"}, | |
| 105 | + | EnablerLabel: "ci-bot", EnabledAt: created, | |
| 106 | + | } | |
| 107 | + | created1, err := mrs.Create(ctx, set) | |
| 108 | + | require.NoError(t, err) | |
| 109 | + | got, err := mrs.Get(ctx, n, created1.Number) | |
| 110 | + | require.NoError(t, err) | |
| 111 | + | require.NotNil(t, got.AutoMerge) | |
| 112 | + | assert.Equal(t, *set.AutoMerge, *got.AutoMerge) | |
| 113 | + | assert.False(t, got.AutoMerged) | |
| 114 | + | ||
| 115 | + | unset := newMR(t, n, "Merged by auto") | |
| 116 | + | unset.State = domain.MRStateMerged | |
| 117 | + | unset.AutoMerged = true | |
| 118 | + | created2, err := mrs.Create(ctx, unset) | |
| 119 | + | require.NoError(t, err) | |
| 120 | + | got, err = mrs.Get(ctx, n, created2.Number) | |
| 121 | + | require.NoError(t, err) | |
| 122 | + | assert.Nil(t, got.AutoMerge) | |
| 123 | + | assert.True(t, got.AutoMerged) | |
| 124 | + | } | |
| 125 | + | ||
| 97 | 126 | func TestMergeRequestListIsNewestFirstAndPerRepository(t *testing.T) { | |
| 98 | 127 | ctx := context.Background() | |
| 99 | 128 | s, mrs, n := repoWithMRs(t) | |
| @@ -453,6 +482,24 @@ func TestRepoSettings(t *testing.T) { | |||
| 453 | 482 | assert.ErrorIs(t, err, domain.ErrInvalid) | |
| 454 | 483 | } | |
| 455 | 484 | ||
| 485 | + | func TestRepoSettingsKeepAllowAutoMerge(t *testing.T) { | |
| 486 | + | ctx := context.Background() | |
| 487 | + | s := openStore(t, t.TempDir()) | |
| 488 | + | n := name(t, "proj") | |
| 489 | + | require.NoError(t, s.Create(ctx, domain.Repo{Name: n, CreatedAt: created, Visibility: domain.VisibilityPrivate})) | |
| 490 | + | got, err := s.Get(ctx, n) | |
| 491 | + | require.NoError(t, err) | |
| 492 | + | assert.False(t, got.Settings.AllowAutoMerge) | |
| 493 | + | ||
| 494 | + | settings := domain.DefaultRepoSettings() | |
| 495 | + | settings.AllowAutoMerge = true | |
| 496 | + | _, err = s.Mutate(ctx, n, func(r *domain.Repo) (bool, error) { r.Settings = settings; return true, nil }) | |
| 497 | + | require.NoError(t, err) | |
| 498 | + | got, err = s.Get(ctx, n) | |
| 499 | + | require.NoError(t, err) | |
| 500 | + | assert.Equal(t, settings, got.Settings) | |
| 501 | + | } | |
| 502 | + | ||
| 456 | 503 | // TestRepoWithoutStoredSettingsReadsTheDefaults: a repository stored before | |
| 457 | 504 | // merge requests existed has no settings field. | |
| 458 | 505 | func TestRepoWithoutStoredSettingsReadsTheDefaults(t *testing.T) { | |
| @@ -94,6 +94,35 @@ func TestMergeRequestRoundTrip(t *testing.T) { | |||||
| 94 | assert.ErrorIs(t, err, domain.ErrNotFound) | 94 | assert.ErrorIs(t, err, domain.ErrNotFound) | ||
| 95 | } | 95 | } | ||
| 96 | 96 | ||||
| 97 | + | func TestMergeRequestAutoMergeRoundTrip(t *testing.T) { | |||
| 98 | + | ctx := context.Background() | |||
| 99 | + | _, mrs, n := repoWithMRs(t) | |||
| 100 | + | ||||
| 101 | + | set := newMR(t, n, "Auto") | |||
| 102 | + | set.AutoMerge = &domain.AutoMerge{ | |||
| 103 | + | Mode: domain.MergeModeSquash, HeadID: oid('d'), | |||
| 104 | + | EnabledBy: domain.CIPusher{Kind: domain.CIPusherToken, TokenID: "tok1"}, | |||
| 105 | + | EnablerLabel: "ci-bot", EnabledAt: created, | |||
| 106 | + | } | |||
| 107 | + | created1, err := mrs.Create(ctx, set) | |||
| 108 | + | require.NoError(t, err) | |||
| 109 | + | got, err := mrs.Get(ctx, n, created1.Number) | |||
| 110 | + | require.NoError(t, err) | |||
| 111 | + | require.NotNil(t, got.AutoMerge) | |||
| 112 | + | assert.Equal(t, *set.AutoMerge, *got.AutoMerge) | |||
| 113 | + | assert.False(t, got.AutoMerged) | |||
| 114 | + | ||||
| 115 | + | unset := newMR(t, n, "Merged by auto") | |||
| 116 | + | unset.State = domain.MRStateMerged | |||
| 117 | + | unset.AutoMerged = true | |||
| 118 | + | created2, err := mrs.Create(ctx, unset) | |||
| 119 | + | require.NoError(t, err) | |||
| 120 | + | got, err = mrs.Get(ctx, n, created2.Number) | |||
| 121 | + | require.NoError(t, err) | |||
| 122 | + | assert.Nil(t, got.AutoMerge) | |||
| 123 | + | assert.True(t, got.AutoMerged) | |||
| 124 | + | } | |||
| 125 | + | ||||
| 97 | func TestMergeRequestListIsNewestFirstAndPerRepository(t *testing.T) { | 126 | func TestMergeRequestListIsNewestFirstAndPerRepository(t *testing.T) { | ||
| 98 | ctx := context.Background() | 127 | ctx := context.Background() | ||
| 99 | s, mrs, n := repoWithMRs(t) | 128 | s, mrs, n := repoWithMRs(t) | ||
| @@ -453,6 +482,24 @@ func TestRepoSettings(t *testing.T) { | |||||
| 453 | assert.ErrorIs(t, err, domain.ErrInvalid) | 482 | assert.ErrorIs(t, err, domain.ErrInvalid) | ||
| 454 | } | 483 | } | ||
| 455 | 484 | ||||
| 485 | + | func TestRepoSettingsKeepAllowAutoMerge(t *testing.T) { | |||
| 486 | + | ctx := context.Background() | |||
| 487 | + | s := openStore(t, t.TempDir()) | |||
| 488 | + | n := name(t, "proj") | |||
| 489 | + | require.NoError(t, s.Create(ctx, domain.Repo{Name: n, CreatedAt: created, Visibility: domain.VisibilityPrivate})) | |||
| 490 | + | got, err := s.Get(ctx, n) | |||
| 491 | + | require.NoError(t, err) | |||
| 492 | + | assert.False(t, got.Settings.AllowAutoMerge) | |||
| 493 | + | ||||
| 494 | + | settings := domain.DefaultRepoSettings() | |||
| 495 | + | settings.AllowAutoMerge = true | |||
| 496 | + | _, err = s.Mutate(ctx, n, func(r *domain.Repo) (bool, error) { r.Settings = settings; return true, nil }) | |||
| 497 | + | require.NoError(t, err) | |||
| 498 | + | got, err = s.Get(ctx, n) | |||
| 499 | + | require.NoError(t, err) | |||
| 500 | + | assert.Equal(t, settings, got.Settings) | |||
| 501 | + | } | |||
| 502 | + | ||||
| 456 | // TestRepoWithoutStoredSettingsReadsTheDefaults: a repository stored before | 503 | // TestRepoWithoutStoredSettingsReadsTheDefaults: a repository stored before | ||
| 457 | // merge requests existed has no settings field. | 504 | // merge requests existed has no settings field. | ||
| 458 | func TestRepoWithoutStoredSettingsReadsTheDefaults(t *testing.T) { | 505 | func TestRepoWithoutStoredSettingsReadsTheDefaults(t *testing.T) { | ||
M internal/domain/event.go +28 -0
| @@ -131,11 +131,39 @@ type MergeRequestMerged struct { | |||
| 131 | 131 | At time.Time | |
| 132 | 132 | Visibility Visibility | |
| 133 | 133 | CreatedAt time.Time | |
| 134 | + | // Auto says that auto-merge made the merge. | |
| 135 | + | Auto bool | |
| 134 | 136 | } | |
| 135 | 137 | ||
| 136 | 138 | // EventKind implements Event. | |
| 137 | 139 | func (MergeRequestMerged) EventKind() string { return "mr.merged" } | |
| 138 | 140 | ||
| 141 | + | // MergeRequestAutoMergeEnabled is published when auto-merge was enabled on a | |
| 142 | + | // merge request. | |
| 143 | + | type MergeRequestAutoMergeEnabled struct { | |
| 144 | + | MergeRequest MergeRequest | |
| 145 | + | At time.Time | |
| 146 | + | Visibility Visibility | |
| 147 | + | CreatedAt time.Time | |
| 148 | + | } | |
| 149 | + | ||
| 150 | + | // EventKind implements Event. | |
| 151 | + | func (MergeRequestAutoMergeEnabled) EventKind() string { return "mr.auto_merge_enabled" } | |
| 152 | + | ||
| 153 | + | // MergeRequestAutoMergeCancelled is published when auto-merge was cancelled | |
| 154 | + | // on a merge request, by hand or by the server. | |
| 155 | + | type MergeRequestAutoMergeCancelled struct { | |
| 156 | + | MergeRequest MergeRequest | |
| 157 | + | // Reason says why, in words. | |
| 158 | + | Reason string | |
| 159 | + | At time.Time | |
| 160 | + | Visibility Visibility | |
| 161 | + | CreatedAt time.Time | |
| 162 | + | } | |
| 163 | + | ||
| 164 | + | // EventKind implements Event. | |
| 165 | + | func (MergeRequestAutoMergeCancelled) EventKind() string { return "mr.auto_merge_cancelled" } | |
| 166 | + | ||
| 139 | 167 | // MergeRequestClosed is published when a merge request was closed without | |
| 140 | 168 | // merging. | |
| 141 | 169 | type MergeRequestClosed struct { | |
| @@ -131,11 +131,39 @@ type MergeRequestMerged struct { | |||||
| 131 | At time.Time | 131 | At time.Time | ||
| 132 | Visibility Visibility | 132 | Visibility Visibility | ||
| 133 | CreatedAt time.Time | 133 | CreatedAt time.Time | ||
| 134 | + | // Auto says that auto-merge made the merge. | |||
| 135 | + | Auto bool | |||
| 134 | } | 136 | } | ||
| 135 | 137 | ||||
| 136 | // EventKind implements Event. | 138 | // EventKind implements Event. | ||
| 137 | func (MergeRequestMerged) EventKind() string { return "mr.merged" } | 139 | func (MergeRequestMerged) EventKind() string { return "mr.merged" } | ||
| 138 | 140 | ||||
| 141 | + | // MergeRequestAutoMergeEnabled is published when auto-merge was enabled on a | |||
| 142 | + | // merge request. | |||
| 143 | + | type MergeRequestAutoMergeEnabled struct { | |||
| 144 | + | MergeRequest MergeRequest | |||
| 145 | + | At time.Time | |||
| 146 | + | Visibility Visibility | |||
| 147 | + | CreatedAt time.Time | |||
| 148 | + | } | |||
| 149 | + | ||||
| 150 | + | // EventKind implements Event. | |||
| 151 | + | func (MergeRequestAutoMergeEnabled) EventKind() string { return "mr.auto_merge_enabled" } | |||
| 152 | + | ||||
| 153 | + | // MergeRequestAutoMergeCancelled is published when auto-merge was cancelled | |||
| 154 | + | // on a merge request, by hand or by the server. | |||
| 155 | + | type MergeRequestAutoMergeCancelled struct { | |||
| 156 | + | MergeRequest MergeRequest | |||
| 157 | + | // Reason says why, in words. | |||
| 158 | + | Reason string | |||
| 159 | + | At time.Time | |||
| 160 | + | Visibility Visibility | |||
| 161 | + | CreatedAt time.Time | |||
| 162 | + | } | |||
| 163 | + | ||||
| 164 | + | // EventKind implements Event. | |||
| 165 | + | func (MergeRequestAutoMergeCancelled) EventKind() string { return "mr.auto_merge_cancelled" } | |||
| 166 | + | ||||
| 139 | // MergeRequestClosed is published when a merge request was closed without | 167 | // MergeRequestClosed is published when a merge request was closed without | ||
| 140 | // merging. | 168 | // merging. | ||
| 141 | type MergeRequestClosed struct { | 169 | type MergeRequestClosed struct { | ||
M internal/domain/event_test.go +7 -0
| @@ -52,3 +52,10 @@ func TestEventKinds(t *testing.T) { | |||
| 52 | 52 | assert.Equal(t, "repo.pushed", domain.PushEvent{}.EventKind()) | |
| 53 | 53 | assert.Equal(t, "gap", domain.EventGap{}.EventKind()) | |
| 54 | 54 | } | |
| 55 | + | ||
| 56 | + | func TestAutoMergeEventKinds(t *testing.T) { | |
| 57 | + | t.Parallel() | |
| 58 | + | assert.Equal(t, "mr.auto_merge_enabled", domain.MergeRequestAutoMergeEnabled{}.EventKind()) | |
| 59 | + | assert.Equal(t, "mr.auto_merge_cancelled", domain.MergeRequestAutoMergeCancelled{}.EventKind()) | |
| 60 | + | assert.Equal(t, "mr.merged", domain.MergeRequestMerged{Auto: true}.EventKind()) | |
| 61 | + | } | |
| @@ -52,3 +52,10 @@ func TestEventKinds(t *testing.T) { | |||||
| 52 | assert.Equal(t, "repo.pushed", domain.PushEvent{}.EventKind()) | 52 | assert.Equal(t, "repo.pushed", domain.PushEvent{}.EventKind()) | ||
| 53 | assert.Equal(t, "gap", domain.EventGap{}.EventKind()) | 53 | assert.Equal(t, "gap", domain.EventGap{}.EventKind()) | ||
| 54 | } | 54 | } | ||
| 55 | + | ||||
| 56 | + | func TestAutoMergeEventKinds(t *testing.T) { | |||
| 57 | + | t.Parallel() | |||
| 58 | + | assert.Equal(t, "mr.auto_merge_enabled", domain.MergeRequestAutoMergeEnabled{}.EventKind()) | |||
| 59 | + | assert.Equal(t, "mr.auto_merge_cancelled", domain.MergeRequestAutoMergeCancelled{}.EventKind()) | |||
| 60 | + | assert.Equal(t, "mr.merged", domain.MergeRequestMerged{Auto: true}.EventKind()) | |||
| 61 | + | } | |||
M internal/domain/mergerequest.go +21 -0
| @@ -50,6 +50,9 @@ type RepoSettings struct { | |||
| 50 | 50 | FailingChecksBlock bool | |
| 51 | 51 | // Issues says who may write issues; the empty mode means IssuesOff. | |
| 52 | 52 | Issues IssuesMode | |
| 53 | + | // AllowAutoMerge says that merge requests may be set to merge themselves | |
| 54 | + | // once their checks pass. Off by default. | |
| 55 | + | AllowAutoMerge bool | |
| 53 | 56 | } | |
| 54 | 57 | ||
| 55 | 58 | // DefaultRepoSettings are the settings of a new repository: every mode, and | |
| @@ -139,11 +142,29 @@ type MergeRequest struct { | |||
| 139 | 142 | MergeMode MergeMode | |
| 140 | 143 | // CommentSeq is the id of the last comment of the request. | |
| 141 | 144 | CommentSeq int64 | |
| 145 | + | // AutoMerge is the pending auto-merge; nil when off. | |
| 146 | + | AutoMerge *AutoMerge | |
| 147 | + | // AutoMerged says that the request was merged by auto-merge. | |
| 148 | + | AutoMerged bool | |
| 142 | 149 | // Version is set by the store on read: Update fails with ErrConflict when | |
| 143 | 150 | // the stored request changed since. Opaque to everyone else. | |
| 144 | 151 | Version uint64 | |
| 145 | 152 | } | |
| 146 | 153 | ||
| 154 | + | // AutoMerge is the pending auto-merge of an open merge request. | |
| 155 | + | type AutoMerge struct { | |
| 156 | + | // Mode is the merge mode chosen when auto-merge was enabled. | |
| 157 | + | Mode MergeMode | |
| 158 | + | // HeadID is the head it was enabled for; a new head cancels it. | |
| 159 | + | HeadID ObjectID | |
| 160 | + | // EnabledBy is who enabled it; the merge is made on their behalf. | |
| 161 | + | EnabledBy CIPusher | |
| 162 | + | // EnablerLabel is the display name of the enabler. | |
| 163 | + | EnablerLabel string | |
| 164 | + | // EnabledAt is when auto-merge was enabled. | |
| 165 | + | EnabledAt time.Time | |
| 166 | + | } | |
| 167 | + | ||
| 147 | 168 | // draftPrefixes mark a draft at the start of a title, compared without regard | |
| 148 | 169 | // to case, as Forgejo and Gitea do. | |
| 149 | 170 | var draftPrefixes = []string{"wip:", "[wip]"} | |
| @@ -50,6 +50,9 @@ type RepoSettings struct { | |||||
| 50 | FailingChecksBlock bool | 50 | FailingChecksBlock bool | ||
| 51 | // Issues says who may write issues; the empty mode means IssuesOff. | 51 | // Issues says who may write issues; the empty mode means IssuesOff. | ||
| 52 | Issues IssuesMode | 52 | Issues IssuesMode | ||
| 53 | + | // AllowAutoMerge says that merge requests may be set to merge themselves | |||
| 54 | + | // once their checks pass. Off by default. | |||
| 55 | + | AllowAutoMerge bool | |||
| 53 | } | 56 | } | ||
| 54 | 57 | ||||
| 55 | // DefaultRepoSettings are the settings of a new repository: every mode, and | 58 | // DefaultRepoSettings are the settings of a new repository: every mode, and | ||
| @@ -139,11 +142,29 @@ type MergeRequest struct { | |||||
| 139 | MergeMode MergeMode | 142 | MergeMode MergeMode | ||
| 140 | // CommentSeq is the id of the last comment of the request. | 143 | // CommentSeq is the id of the last comment of the request. | ||
| 141 | CommentSeq int64 | 144 | CommentSeq int64 | ||
| 145 | + | // AutoMerge is the pending auto-merge; nil when off. | |||
| 146 | + | AutoMerge *AutoMerge | |||
| 147 | + | // AutoMerged says that the request was merged by auto-merge. | |||
| 148 | + | AutoMerged bool | |||
| 142 | // Version is set by the store on read: Update fails with ErrConflict when | 149 | // Version is set by the store on read: Update fails with ErrConflict when | ||
| 143 | // the stored request changed since. Opaque to everyone else. | 150 | // the stored request changed since. Opaque to everyone else. | ||
| 144 | Version uint64 | 151 | Version uint64 | ||
| 145 | } | 152 | } | ||
| 146 | 153 | ||||
| 154 | + | // AutoMerge is the pending auto-merge of an open merge request. | |||
| 155 | + | type AutoMerge struct { | |||
| 156 | + | // Mode is the merge mode chosen when auto-merge was enabled. | |||
| 157 | + | Mode MergeMode | |||
| 158 | + | // HeadID is the head it was enabled for; a new head cancels it. | |||
| 159 | + | HeadID ObjectID | |||
| 160 | + | // EnabledBy is who enabled it; the merge is made on their behalf. | |||
| 161 | + | EnabledBy CIPusher | |||
| 162 | + | // EnablerLabel is the display name of the enabler. | |||
| 163 | + | EnablerLabel string | |||
| 164 | + | // EnabledAt is when auto-merge was enabled. | |||
| 165 | + | EnabledAt time.Time | |||
| 166 | + | } | |||
| 167 | + | ||||
| 147 | // draftPrefixes mark a draft at the start of a title, compared without regard | 168 | // draftPrefixes mark a draft at the start of a title, compared without regard | ||
| 148 | // to case, as Forgejo and Gitea do. | 169 | // to case, as Forgejo and Gitea do. | ||
| 149 | var draftPrefixes = []string{"wip:", "[wip]"} | 170 | var draftPrefixes = []string{"wip:", "[wip]"} | ||
M internal/domain/mergerequest_test.go +6 -0
| @@ -330,3 +330,9 @@ func TestMergeabilityAllowsAndIsFor(t *testing.T) { | |||
| 330 | 330 | assert.False(t, m.IsFor(oid(t, 'a'), oid(t, 'c'))) | |
| 331 | 331 | assert.False(t, domain.Mergeability{}.IsFor(domain.ObjectID{}, domain.ObjectID{})) | |
| 332 | 332 | } | |
| 333 | + | ||
| 334 | + | func TestRepoSettingsAllowAutoMergeDefaultOff(t *testing.T) { | |
| 335 | + | t.Parallel() | |
| 336 | + | assert.False(t, domain.DefaultRepoSettings().AllowAutoMerge) | |
| 337 | + | assert.False(t, domain.RepoSettings{}.AllowAutoMerge) | |
| 338 | + | } | |
| @@ -330,3 +330,9 @@ func TestMergeabilityAllowsAndIsFor(t *testing.T) { | |||||
| 330 | assert.False(t, m.IsFor(oid(t, 'a'), oid(t, 'c'))) | 330 | assert.False(t, m.IsFor(oid(t, 'a'), oid(t, 'c'))) | ||
| 331 | assert.False(t, domain.Mergeability{}.IsFor(domain.ObjectID{}, domain.ObjectID{})) | 331 | assert.False(t, domain.Mergeability{}.IsFor(domain.ObjectID{}, domain.ObjectID{})) | ||
| 332 | } | 332 | } | ||
| 333 | + | ||||
| 334 | + | func TestRepoSettingsAllowAutoMergeDefaultOff(t *testing.T) { | |||
| 335 | + | t.Parallel() | |||
| 336 | + | assert.False(t, domain.DefaultRepoSettings().AllowAutoMerge) | |||
| 337 | + | assert.False(t, domain.RepoSettings{}.AllowAutoMerge) | |||
| 338 | + | } | |||
M proto/ermite/storage/merge_request.proto +15 -0
| @@ -30,6 +30,7 @@ message RepoSettings { | |||
| 30 | 30 | // {fast-forward, squash} was the old default and gains MERGE_MODE_MERGE on | |
| 31 | 31 | // read. | |
| 32 | 32 | bool merge_modes_v2 = 4; | |
| 33 | + | bool allow_auto_merge = 5; | |
| 33 | 34 | } | |
| 34 | 35 | ||
| 35 | 36 | // IssuesMode says who may write issues in a repository. | |
| @@ -78,6 +79,20 @@ message MergeRequest { | |||
| 78 | 79 | MergeMode merge_mode = 13; | |
| 79 | 80 | // Last comment id handed out for this request. | |
| 80 | 81 | int64 comment_seq = 14; | |
| 82 | + | // Pending auto-merge; unset when off. | |
| 83 | + | AutoMerge auto_merge = 15; | |
| 84 | + | bool auto_merged = 16; | |
| 85 | + | } | |
| 86 | + | ||
| 87 | + | // AutoMerge is the pending auto-merge of an open merge request. | |
| 88 | + | message AutoMerge { | |
| 89 | + | MergeMode mode = 1; | |
| 90 | + | string head_id = 2; | |
| 91 | + | // Kind and token id of the CIPusher that enabled it. | |
| 92 | + | string enabler_kind = 3; | |
| 93 | + | string enabler_token_id = 4; | |
| 94 | + | string enabler_label = 5; | |
| 95 | + | google.protobuf.Timestamp enabled_at = 6; | |
| 81 | 96 | } | |
| 82 | 97 | ||
| 83 | 98 | // Verdict is the immutable review decision of a note. | |
| @@ -30,6 +30,7 @@ message RepoSettings { | |||||
| 30 | // {fast-forward, squash} was the old default and gains MERGE_MODE_MERGE on | 30 | // {fast-forward, squash} was the old default and gains MERGE_MODE_MERGE on | ||
| 31 | // read. | 31 | // read. | ||
| 32 | bool merge_modes_v2 = 4; | 32 | bool merge_modes_v2 = 4; | ||
| 33 | + | bool allow_auto_merge = 5; | |||
| 33 | } | 34 | } | ||
| 34 | 35 | ||||
| 35 | // IssuesMode says who may write issues in a repository. | 36 | // IssuesMode says who may write issues in a repository. | ||
| @@ -78,6 +79,20 @@ message MergeRequest { | |||||
| 78 | MergeMode merge_mode = 13; | 79 | MergeMode merge_mode = 13; | ||
| 79 | // Last comment id handed out for this request. | 80 | // Last comment id handed out for this request. | ||
| 80 | int64 comment_seq = 14; | 81 | int64 comment_seq = 14; | ||
| 82 | + | // Pending auto-merge; unset when off. | |||
| 83 | + | AutoMerge auto_merge = 15; | |||
| 84 | + | bool auto_merged = 16; | |||
| 85 | + | } | |||
| 86 | + | ||||
| 87 | + | // AutoMerge is the pending auto-merge of an open merge request. | |||
| 88 | + | message AutoMerge { | |||
| 89 | + | MergeMode mode = 1; | |||
| 90 | + | string head_id = 2; | |||
| 91 | + | // Kind and token id of the CIPusher that enabled it. | |||
| 92 | + | string enabler_kind = 3; | |||
| 93 | + | string enabler_token_id = 4; | |||
| 94 | + | string enabler_label = 5; | |||
| 95 | + | google.protobuf.Timestamp enabled_at = 6; | |||
| 81 | } | 96 | } | ||
| 82 | 97 | ||||
| 83 | // Verdict is the immutable review decision of a note. | 98 | // Verdict is the immutable review decision of a note. | ||