fix(github): scope PR CI automation switches per linked PR (#2512)
Co-authored-by: ayattara <alassane.yattara@savoirfairelinux.com> Co-authored-by: Carlos Florencio <carlosmflorencio@gmail.com>
This commit is contained in:
@@ -1202,6 +1202,121 @@ func TestHttpTaskCIOptions_DefaultAndPatch(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestHttpPatchTaskCIOptions_TargetsOnePRWithoutAffectingSibling covers AC6:
|
||||
// a PATCH naming one linked PR's repository_id/pr_number sets the switch for
|
||||
// that PR only; a second linked PR's row is unchanged.
|
||||
func TestHttpPatchTaskCIOptions_TargetsOnePRWithoutAffectingSibling(t *testing.T) {
|
||||
router, store := setupControllerStoreTest(t)
|
||||
ctx := context.Background()
|
||||
for _, prNumber := range []int{1, 2} {
|
||||
if err := store.CreateTaskPR(ctx, &TaskPR{
|
||||
TaskID: "task-1", RepositoryID: "repo-1",
|
||||
Owner: "acme", Repo: "widget", PRNumber: prNumber,
|
||||
State: "open", CreatedAt: time.Now().UTC(),
|
||||
}); err != nil {
|
||||
t.Fatalf("seed task pr #%d: %v", prNumber, err)
|
||||
}
|
||||
}
|
||||
|
||||
body := bytes.NewBufferString(`{"repository_id":"repo-1","pr_number":1,"auto_fix_enabled":true}`)
|
||||
req := httptest.NewRequest(http.MethodPatch, "/api/v1/github/tasks/task-1/ci-options", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
|
||||
opts1, err := store.GetTaskPRAutomationOptions(ctx, "task-1", "repo-1", 1)
|
||||
if err != nil {
|
||||
t.Fatalf("get PR 1 options: %v", err)
|
||||
}
|
||||
if !opts1.AutoFixEnabled {
|
||||
t.Fatalf("PR 1 auto_fix_enabled = false, want true")
|
||||
}
|
||||
opts2, err := store.GetTaskPRAutomationOptions(ctx, "task-1", "repo-1", 2)
|
||||
if err != nil {
|
||||
t.Fatalf("get PR 2 options: %v", err)
|
||||
}
|
||||
if opts2.AutoFixEnabled {
|
||||
t.Fatalf("PR 2 auto_fix_enabled = true, want unaffected false")
|
||||
}
|
||||
}
|
||||
|
||||
// TestHttpPatchTaskCIOptions_UnlinkedPRReturns400AndWritesNothing covers AC8.
|
||||
func TestHttpPatchTaskCIOptions_UnlinkedPRReturns400AndWritesNothing(t *testing.T) {
|
||||
router, store := setupControllerStoreTest(t)
|
||||
ctx := context.Background()
|
||||
if err := store.CreateTaskPR(ctx, &TaskPR{
|
||||
TaskID: "task-1", RepositoryID: "repo-1",
|
||||
Owner: "acme", Repo: "widget", PRNumber: 1,
|
||||
State: "open", CreatedAt: time.Now().UTC(),
|
||||
}); err != nil {
|
||||
t.Fatalf("seed task pr: %v", err)
|
||||
}
|
||||
|
||||
body := bytes.NewBufferString(`{"repository_id":"repo-1","pr_number":999,"auto_fix_enabled":true,"auto_fix_prompt_override":"must-not-persist"}`)
|
||||
req := httptest.NewRequest(http.MethodPatch, "/api/v1/github/tasks/task-1/ci-options", body)
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Fatalf("expected 400, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
|
||||
opts, err := store.GetTaskPRAutomationOptions(ctx, "task-1", "repo-1", 999)
|
||||
if err != nil {
|
||||
t.Fatalf("get unlinked PR options: %v", err)
|
||||
}
|
||||
if opts.AutoFixEnabled {
|
||||
t.Fatal("PATCH for an unlinked PR wrote a row instead of writing nothing")
|
||||
}
|
||||
taskOptions, err := store.GetTaskCIOptions(ctx, "task-1")
|
||||
if err != nil {
|
||||
t.Fatalf("get task options: %v", err)
|
||||
}
|
||||
if taskOptions.AutoFixPromptOverride != nil {
|
||||
t.Fatalf("invalid PR identity partially updated task options: %+v", taskOptions)
|
||||
}
|
||||
}
|
||||
|
||||
// TestHttpPatchTaskCIOptions_PartialPRIdentityRejected pins the client error
|
||||
// for a patch that supplies only one side of the PR identity.
|
||||
func TestHttpPatchTaskCIOptions_PartialPRIdentityRejected(t *testing.T) {
|
||||
for name, body := range map[string]string{
|
||||
"repository only": `{"repository_id":"repo-1","auto_fix_enabled":true}`,
|
||||
"PR number only": `{"pr_number":1,"auto_fix_enabled":true}`,
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
router, store := setupControllerStoreTest(t)
|
||||
ctx := context.Background()
|
||||
if err := store.CreateTaskPR(ctx, &TaskPR{
|
||||
TaskID: "task-1", RepositoryID: "repo-1",
|
||||
Owner: "acme", Repo: "widget", PRNumber: 1,
|
||||
State: "open", CreatedAt: time.Now().UTC(),
|
||||
}); err != nil {
|
||||
t.Fatalf("seed task pr: %v", err)
|
||||
}
|
||||
|
||||
req := httptest.NewRequest(http.MethodPatch, "/api/v1/github/tasks/task-1/ci-options", bytes.NewBufferString(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
w := httptest.NewRecorder()
|
||||
router.ServeHTTP(w, req)
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Fatalf("expected 400, got %d: %s", w.Code, w.Body.String())
|
||||
}
|
||||
|
||||
opts, err := store.GetTaskPRAutomationOptions(ctx, "task-1", "repo-1", 1)
|
||||
if err != nil {
|
||||
t.Fatalf("get PR options: %v", err)
|
||||
}
|
||||
if opts.AutoFixEnabled {
|
||||
t.Fatal("partial identity patch wrote a row instead of writing nothing")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHttpTaskCIOptions_DeniesForeignWorkspaceReadAndUpdate(t *testing.T) {
|
||||
store := newTestStore(t)
|
||||
log := newControllerTestLogger()
|
||||
|
||||
Reference in New Issue
Block a user