Skip to content

feat: instatus importer#1973

Open
mxkaske wants to merge 5 commits intomainfrom
feat/instatus-importer
Open

feat: instatus importer#1973
mxkaske wants to merge 5 commits intomainfrom
feat/instatus-importer

Conversation

@mxkaske
Copy link
Member

@mxkaske mxkaske commented Mar 12, 2026

No description provided.

@vercel
Copy link

vercel bot commented Mar 12, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openstatus-dashboard Ready Ready Preview, Comment Mar 26, 2026 8:34pm
openstatus-status-page Ready Ready Preview, Comment Mar 26, 2026 8:34pm
openstatus-web Ready Ready Preview, Comment Mar 26, 2026 8:34pm

Request Review

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 16 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/importers/src/providers/instatus/mapper.ts">

<violation number="1" location="packages/importers/src/providers/instatus/mapper.ts:142">
P2: `to` and `from` share the same `Date` reference when `duration` is 0 or null. Any downstream mutation of one will silently affect the other. Create a new `Date` to avoid reference aliasing.</violation>
</file>

<file name="packages/importers/src/providers/instatus/client.ts">

<violation number="1" location="packages/importers/src/providers/instatus/client.ts:68">
P2: `getPages` doesn't paginate, unlike all other list endpoints. The Instatus API returns at most 50 pages per request by default. Use `requestAllPages` so that accounts with more than 50 status pages aren't silently truncated.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@mxkaske
Copy link
Member Author

mxkaske commented Mar 26, 2026

@claude review

@claude
Copy link

claude bot commented Mar 26, 2026

Claude finished @mxkaske's task in 1m 45s —— View job


Code Review: feat/instatus-importer

  • Gather context and understand request
  • Read core changed files
  • Review client, mapper, provider, and API integration
  • Post findings

Overall this is a solid, well-structured implementation. Good test coverage, clean separation between the client/mapper/provider layers, idempotency checks throughout the write phase, and sensible limit enforcement. A few real bugs and UX issues worth addressing before merge.


Bugs

1. Date reference aliasing in mapMaintenanceToMaintenance (mapper.ts:167)

const to = duration > 0 ? new Date(from.getTime() + duration * 60_000) : from;

When duration is 0 or null, to and from point to the same Date instance. Any mutation of one silently affects the other. The fix is straightforward:

const to = duration > 0 ? new Date(from.getTime() + duration * 60_000) : new Date(from);

Fix this →


2. getPages doesn't paginate (client.ts:68)

getPages: () => request("/v2/pages", z.array(InstatusPageSchema)),

Every other list endpoint uses requestAllPages, but getPages uses plain request. The Instatus API returns at most 50 pages per call by default, so accounts with more than 50 status pages will be silently truncated. Should be:

getPages: () => requestAllPages("/v2/pages", InstatusPageSchema),

Fix this →


3. Silent no-op when instatusPageId doesn't match (provider.ts:50-51)

let pages = await client.getPages();
if (config.instatusPageId) {
  pages = pages.filter((p) => p.id === config.instatusPageId);
}

If the user passes an instatusPageId that doesn't match any page, pages becomes []. The for loop does nothing and the function returns status: "completed" with no phases — a false success with no feedback. Consider throwing or surfacing an error when the filter produces no results.


UX Issues

4. Misleading description for Instatus Page ID field (form-import.tsx:278)

<FormDescription>
  Import a specific page. Leave empty to import the first page.
</FormDescription>

The actual behavior (per provider.ts) is that leaving the field empty imports all pages, not just the first one. The description should say something like "Leave empty to import all pages."


5. Import button blocked by non-fatal plan warnings (form-import.tsx:389-393)

disabled={
  !previewMutation.data ||
  isPending ||
  previewMutation.data.errors.length > 0
}

summary.errors is used for both hard errors (auth failure) and soft plan-limit warnings like "Only 8 of 12 components can be imported due to plan limit" or "Custom domain will be stripped". With this logic, users hit by a plan limit can never proceed even though a partial import would succeed. Consider distinguishing between blocking errors and informational warnings in the summary type.


Minor Notes

  • service/import.ts:707 — there's a // TODO: migrate to new pageSubscription + pageSubscriptionToPageComponent tables left in the code. Worth tracking as a follow-up issue rather than leaving in the PR.
  • mapper.ts:105-116mapIncidentStatus accepts string but the Zod schema already enforces the exact enum upstream, so the default fallback to "investigating" is dead code.
  • service/import.ts:233-240 — the splice-then-push pattern to handle the component limit is functionally correct but non-obvious. A simple slice + keeping them separate would be clearer.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 6 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/importers/src/providers/instatus/provider.ts">

<violation number="1" location="packages/importers/src/providers/instatus/provider.ts:56">
P2: Use the already-declared `startedAt` variable instead of creating a new `Date`. The successful return path (line 188) uses the captured `startedAt`, so the error path should be consistent.</violation>

<violation number="2" location="packages/importers/src/providers/instatus/provider.ts:77">
P2: The `warnings` returned by `partitionComponents` are silently discarded. These warnings inform users when a referenced component group wasn't found and a synthetic group was created. Previously they were surfaced in the result's `errors` array. Either collect them into `errors` or remove the warning logic from `partitionComponents` if it's intentionally no longer needed.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/importers/src/providers/instatus/mapper.test.ts">

<violation number="1" location="packages/importers/src/providers/instatus/mapper.test.ts:208">
P3: This test is a duplicate of "maps email subscriber with specific components" above, which already asserts the full result including `sourceComponentIds: ["in_comp_001", "in_comp_003"]` via `toEqual`. If the intent is to verify extraction from *object* references (as opposed to plain string IDs), the test should use a distinct fixture whose `components` field contains object shapes rather than reusing `MOCK_SUBSCRIBERS[1]` with the same expected output.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

});
});

it("extracts component IDs from object references", () => {
Copy link

@cubic-dev-ai cubic-dev-ai bot Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This test is a duplicate of "maps email subscriber with specific components" above, which already asserts the full result including sourceComponentIds: ["in_comp_001", "in_comp_003"] via toEqual. If the intent is to verify extraction from object references (as opposed to plain string IDs), the test should use a distinct fixture whose components field contains object shapes rather than reusing MOCK_SUBSCRIBERS[1] with the same expected output.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/importers/src/providers/instatus/mapper.test.ts, line 208:

<comment>This test is a duplicate of "maps email subscriber with specific components" above, which already asserts the full result including `sourceComponentIds: ["in_comp_001", "in_comp_003"]` via `toEqual`. If the intent is to verify extraction from *object* references (as opposed to plain string IDs), the test should use a distinct fixture whose `components` field contains object shapes rather than reusing `MOCK_SUBSCRIBERS[1]` with the same expected output.</comment>

<file context>
@@ -204,6 +205,11 @@ describe("mapSubscriber", () => {
     });
   });
 
+  it("extracts component IDs from object references", () => {
+    const result = mapSubscriber(MOCK_SUBSCRIBERS[1], 10);
+    expect(result?.sourceComponentIds).toEqual(["in_comp_001", "in_comp_003"]);
</file context>
Fix with Cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant