188 lines
6.7 KiB
Go
188 lines
6.7 KiB
Go
package gitlab
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/kandev/kandev/internal/testutil"
|
|
)
|
|
|
|
func TestPostgresStoreSchemaReplay(t *testing.T) {
|
|
ctx := context.Background()
|
|
database := testutil.OpenIsolatedPostgres(t, testutil.PostgresDSNFromEnv(t))
|
|
if _, err := database.Exec(`
|
|
CREATE TABLE workspaces (id TEXT PRIMARY KEY);
|
|
CREATE TABLE tasks (
|
|
id TEXT PRIMARY KEY,
|
|
workspace_id TEXT NOT NULL,
|
|
archived_at TIMESTAMPTZ
|
|
);
|
|
INSERT INTO workspaces (id) VALUES ('ws-1');
|
|
INSERT INTO tasks (id, workspace_id, archived_at) VALUES ('task-1', 'ws-1', NULL)`); err != nil {
|
|
t.Fatalf("create prerequisite tables: %v", err)
|
|
}
|
|
|
|
store, err := NewStore(database, database)
|
|
if err != nil {
|
|
t.Fatalf("first GitLab store schema init: %v", err)
|
|
}
|
|
if _, err := NewStore(database, database); err != nil {
|
|
t.Fatalf("second GitLab store schema init: %v", err)
|
|
}
|
|
|
|
config := &GitLabConfig{
|
|
Host: "https://gitlab.example.com",
|
|
AuthMethod: "pat",
|
|
Username: "alice",
|
|
}
|
|
if err := store.UpsertConfigForWorkspace(ctx, "ws-1", config); err != nil {
|
|
t.Fatalf("upsert GitLab config: %v", err)
|
|
}
|
|
gotConfig, err := store.GetConfigForWorkspace(ctx, "ws-1")
|
|
if err != nil || gotConfig == nil || gotConfig.Host != config.Host {
|
|
t.Fatalf("get GitLab config: config=%+v err=%v", gotConfig, err)
|
|
}
|
|
if updated, err := store.UpdateConfigHealthForRevision(
|
|
ctx, "ws-1", "alice", true, "", time.Now().UTC(), gotConfig.Revision,
|
|
); err != nil || !updated {
|
|
t.Fatalf("update GitLab config health: updated=%v err=%v", updated, err)
|
|
}
|
|
|
|
if err := store.UpsertMentionScope(ctx, &MentionScope{
|
|
WorkspaceID: "ws-1",
|
|
Host: "https://gitlab.example.com",
|
|
Projects: []MentionProjectScope{{ID: 7, Path: "group/project"}},
|
|
}); err != nil {
|
|
t.Fatalf("upsert GitLab mention scope: %v", err)
|
|
}
|
|
gotScope, err := store.GetMentionScope(ctx, "ws-1")
|
|
if err != nil || gotScope == nil || len(gotScope.Projects) != 1 {
|
|
t.Fatalf("get GitLab mention scope: scope=%+v err=%v", gotScope, err)
|
|
}
|
|
|
|
mergeRequest := &TaskMR{
|
|
TaskID: "task-1",
|
|
ProjectPath: "group/project",
|
|
MRIID: 42,
|
|
MRURL: "https://gitlab.example.com/group/project/-/merge_requests/42",
|
|
MRTitle: "Parity",
|
|
HeadBranch: "feature/parity",
|
|
BaseBranch: "main",
|
|
Draft: true,
|
|
}
|
|
if err := store.UpsertTaskMR(ctx, mergeRequest); err != nil {
|
|
t.Fatalf("upsert GitLab task MR: %v", err)
|
|
}
|
|
gotMR, err := store.GetTaskMR(ctx, "task-1", "", "group/project", 42)
|
|
if err != nil || gotMR == nil || !gotMR.Draft {
|
|
t.Fatalf("get GitLab task MR: mr=%+v err=%v", gotMR, err)
|
|
}
|
|
if err := store.UpdateTaskMRUnresolvedDiscussions(ctx, mergeRequest.ID, 3); err != nil {
|
|
t.Fatalf("update GitLab task MR discussions: %v", err)
|
|
}
|
|
|
|
identity := MRIdentity{ProjectPath: "group/project", MRIID: 42}
|
|
trueValue := true
|
|
options, err := store.UpdateTaskMRAutomationOptionsForMR(ctx, "task-1", identity, TaskMRAutomationSwitchPatch{
|
|
AutoMergeEnabled: &trueValue,
|
|
PromptOnReviewRequested: &trueValue,
|
|
})
|
|
if err != nil || options == nil || !options.AutoMergeEnabled || !options.PromptOnReviewRequested {
|
|
t.Fatalf("update GitLab MR automation: options=%+v err=%v", options, err)
|
|
}
|
|
if err := store.SetTaskMRReviewRequestState(ctx, "task-1", "", "group/project", 42, true); err != nil {
|
|
t.Fatalf("set GitLab MR review state: %v", err)
|
|
}
|
|
if err := store.SetTaskMRObservedState(ctx, "task-1", "", "group/project", 42, gitlabStateMerged); err != nil {
|
|
t.Fatalf("set GitLab MR observed state: %v", err)
|
|
}
|
|
if err := store.RecordTaskMRLifecyclePrompt(ctx, TaskMRLifecyclePrompt{
|
|
TaskID: "task-1",
|
|
ProjectPath: "group/project",
|
|
MRIID: 42,
|
|
Event: mrLifecycleEventReviewRequested,
|
|
ReviewRequested: true,
|
|
}); err != nil {
|
|
t.Fatalf("record GitLab MR lifecycle prompt: %v", err)
|
|
}
|
|
if _, err := store.GetTaskMRLifecycleState(ctx, "task-1", "", "group/project", 42); err != nil {
|
|
t.Fatalf("get GitLab MR lifecycle state: %v", err)
|
|
}
|
|
if subscribed, err := store.ListAutomationSubscribedTaskMRs(ctx); err != nil || len(subscribed) != 1 {
|
|
t.Fatalf("list GitLab automation MRs: mrs=%d err=%v", len(subscribed), err)
|
|
}
|
|
|
|
refreshWatch := &MRWatch{
|
|
SessionID: "session-1",
|
|
TaskID: "task-1",
|
|
ProjectPath: "group/project",
|
|
MRIID: 42,
|
|
Branch: "feature/parity",
|
|
}
|
|
if err := store.CreateMRWatch(ctx, refreshWatch); err != nil {
|
|
t.Fatalf("create GitLab MR watch: %v", err)
|
|
}
|
|
if got, err := store.GetMRWatchBySession(ctx, "session-1"); err != nil || got == nil {
|
|
t.Fatalf("get GitLab MR watch: watch=%+v err=%v", got, err)
|
|
}
|
|
|
|
reviewWatch := &ReviewWatch{
|
|
WorkspaceID: "ws-1",
|
|
WorkflowID: "workflow-1",
|
|
WorkflowStepID: "step-1",
|
|
Projects: []ProjectFilter{{Path: "group/project"}},
|
|
AgentProfileID: "agent-1",
|
|
ExecutorProfileID: "executor-1",
|
|
Enabled: true,
|
|
}
|
|
if err := store.CreateReviewWatch(ctx, reviewWatch); err != nil {
|
|
t.Fatalf("create GitLab review watch: %v", err)
|
|
}
|
|
if _, err := store.ListEnabledReviewWatchesForWorkspace(ctx, "ws-1"); err != nil {
|
|
t.Fatalf("list GitLab review watches: %v", err)
|
|
}
|
|
reserved, err := store.ReserveReviewMRTask(ctx, reviewWatch.ID, "group/project", 43, "https://gitlab.example.com/mr/43")
|
|
if err != nil || !reserved {
|
|
t.Fatalf("reserve GitLab review MR task: reserved=%v err=%v", reserved, err)
|
|
}
|
|
if err := store.AssignReviewMRTaskID(ctx, reviewWatch.ID, "group/project", 43, "task-1"); err != nil {
|
|
t.Fatalf("assign GitLab review MR task: %v", err)
|
|
}
|
|
|
|
issueWatch := &IssueWatch{
|
|
WorkspaceID: "ws-1",
|
|
WorkflowID: "workflow-1",
|
|
WorkflowStepID: "step-1",
|
|
Projects: []ProjectFilter{{Path: "group/project"}},
|
|
Labels: []string{"bug"},
|
|
AgentProfileID: "agent-1",
|
|
ExecutorProfileID: "executor-1",
|
|
Enabled: true,
|
|
}
|
|
if err := store.CreateIssueWatch(ctx, issueWatch); err != nil {
|
|
t.Fatalf("create GitLab issue watch: %v", err)
|
|
}
|
|
if _, err := store.ListEnabledIssueWatchesForWorkspace(ctx, "ws-1"); err != nil {
|
|
t.Fatalf("list GitLab issue watches: %v", err)
|
|
}
|
|
reserved, err = store.ReserveIssueWatchTask(ctx, issueWatch.ID, "group/project", 9, "https://gitlab.example.com/issue/9")
|
|
if err != nil || !reserved {
|
|
t.Fatalf("reserve GitLab issue task: reserved=%v err=%v", reserved, err)
|
|
}
|
|
if err := store.AssignIssueWatchTaskID(ctx, issueWatch.ID, "group/project", 9, "task-1"); err != nil {
|
|
t.Fatalf("assign GitLab issue task: %v", err)
|
|
}
|
|
|
|
if err := store.UpsertActionPresets(ctx, &ActionPresets{
|
|
WorkspaceID: "ws-1",
|
|
MR: DefaultMRActionPresets(),
|
|
Issue: DefaultIssueActionPresets(),
|
|
}); err != nil {
|
|
t.Fatalf("upsert GitLab action presets: %v", err)
|
|
}
|
|
if _, err := store.GetActionPresets(ctx, "ws-1"); err != nil {
|
|
t.Fatalf("get GitLab action presets: %v", err)
|
|
}
|
|
}
|