Skip to content

Commit

Permalink
New alerts platform status + Alerts docs (#1098)
Browse files Browse the repository at this point in the history
* debug tooltip now scrolls

* Added a link to subscribe to alerts and improved the project alerts blank state

* Better external link icon

* Docs: Removed webhook tasks

* Docs: removed limits performance

* Docs: removed FAQs

* Docs: Removed Architecture section

* Docs: Removed API reference: CLI

* Docs: Removed API reference: Objects

* Docs: Removed API reference: Functions

* Docs: removed automated tests

* Docs: removed Middleware

* Docs: removed Using APIs

* Docs: removed Rollbacks

* Docs: removed Trigger Filters

* Docs: removed Webhook Tasks

* Docs: removed Zod Tasks

* Docs: Renamed Community page

* Docs: Added a new Troubleshooting section and Alerts docs page

* Hide the New Alerts button again if list is greater than 10 items

* Customers now have to contact us for Slack Connect Support.

* Fix the alerts docs link

* Added env vars for a different alert email address, and whether the feature is enabled or not

* Only show the alerts sidemenu item if the feature is enabled

* Use a separate email client for sending alerts

* Removed the link to Context from v3 docs

* Removed obvious docs links that are now missing pages

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
  • Loading branch information
samejr and matt-aitken committed May 16, 2024
1 parent 6a379e4 commit 89eaef4
Show file tree
Hide file tree
Showing 64 changed files with 161 additions and 406 deletions.
6 changes: 4 additions & 2 deletions apps/webapp/app/components/admin/debugTooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ export function AdminDebugTooltip({ children }: { children: React.ReactNode }) {
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<ShieldCheckIcon className="h-5 w-5" />
<ShieldCheckIcon className="size-5" />
</TooltipTrigger>
<TooltipContent className="flex items-center gap-1">{children}</TooltipContent>
<TooltipContent className="flex max-h-[90vh] items-center gap-1 overflow-y-auto">
{children}
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
Expand Down
43 changes: 19 additions & 24 deletions apps/webapp/app/components/navigation/SideMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -233,31 +233,22 @@ export function SideMenu({ user, project, organization, organizations }: SideMen
</div>
<hr className="border-charcoal-800" />
<div>
<StepNumber stepNumber="1" title="Create a new Slack channel" />
<StepNumber stepNumber="1" title="Email us" />
<StepContentContainer>
<Paragraph>
In your Slack app, create a new channel from the main menu by going to File{" "}
<ArrowRightIcon className="inline h-4 w-4 text-text-dimmed" /> New Channel
</Paragraph>
</StepContentContainer>
<StepNumber stepNumber="2" title="Setup your channel" />
<StepContentContainer>
<Paragraph>
Name your channel, set its visibility and click 'Create'.
</Paragraph>
</StepContentContainer>
<StepNumber stepNumber="3" title="Invite Trigger.dev" />
<StepContentContainer>
<Paragraph>
Invite this email address to your channel:{" "}
Send us an email to this address from your Trigger.dev account email
address:
<ClipboardField
variant="primary/medium"
value="james@trigger.dev"
value="priority-support@trigger.dev"
className="my-2"
/>
</Paragraph>
</StepContentContainer>
<StepNumber stepNumber="2" title="Look out for an invite from Slack" />
<StepContentContainer>
<Paragraph>
As soon as we can, we'll accept your invitation and say hello!
As soon as we can, we'll setup a Slack Connect channel and say hello!
</Paragraph>
</StepContentContainer>
</div>
Expand Down Expand Up @@ -551,6 +542,8 @@ function V3ProjectSideMenu({
project: SideMenuProject;
organization: MatchedOrganization;
}) {
const { alertsEnabled } = useFeatures();

return (
<>
<SideMenuHeader title={"Project (v3)"} />
Expand Down Expand Up @@ -603,13 +596,15 @@ function V3ProjectSideMenu({
to={v3DeploymentsPath(organization, project)}
data-action="deployments"
/>
{/* <SideMenuItem
name="Alerts"
icon={BellAlertIcon}
iconColor="text-red-500"
to={v3ProjectAlertsPath(organization, project)}
data-action="alerts"
/> */}
{alertsEnabled && (
<SideMenuItem
name="Alerts"
icon={BellAlertIcon}
iconColor="text-red-500"
to={v3ProjectAlertsPath(organization, project)}
data-action="alerts"
/>
)}
<SideMenuItem
name="Project settings"
icon="settings"
Expand Down
4 changes: 4 additions & 0 deletions apps/webapp/app/env.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ const EnvironmentSchema = z.object({
ORG_SLACK_INTEGRATION_CLIENT_ID: z.string().optional(),
ORG_SLACK_INTEGRATION_CLIENT_SECRET: z.string().optional(),

/** These enable the alerts feature in v3 */
ALERT_FROM_EMAIL: z.string().optional(),
ALERT_RESEND_API_KEY: z.string().optional(),

MAX_SEQUENTIAL_INDEX_FAILURE_COUNT: z.coerce.number().default(96),
});

Expand Down
2 changes: 2 additions & 0 deletions apps/webapp/app/features.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { requestUrl } from "./utils/requestUrl.server";
export type TriggerFeatures = {
isManagedCloud: boolean;
v3Enabled: boolean;
alertsEnabled: boolean;
};

// If the request host is cloud.trigger.dev then we are on the managed cloud
Expand All @@ -20,5 +21,6 @@ export function featuresForRequest(request: Request): TriggerFeatures {
return {
isManagedCloud,
v3Enabled: env.V3_ENABLED === "true",
alertsEnabled: env.ALERT_FROM_EMAIL !== undefined && env.ALERT_RESEND_API_KEY !== undefined,
};
}
2 changes: 1 addition & 1 deletion apps/webapp/app/hooks/useFeatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ import type { TriggerFeatures } from "~/features.server";
export function useFeatures(): TriggerFeatures {
const routeMatch = useTypedRouteLoaderData<typeof loader>("root");

return routeMatch?.features ?? { isManagedCloud: false, v3Enabled: false };
return routeMatch?.features ?? { isManagedCloud: false, v3Enabled: false, alertsEnabled: false };
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useForm } from "@conform-to/react";
import { parse } from "@conform-to/zod";
import {
ArrowUpRightIcon,
BoltIcon,
BoltSlashIcon,
BookOpenIcon,
Expand All @@ -15,12 +16,14 @@ import { ActionFunctionArgs, LoaderFunctionArgs, json } from "@remix-run/server-
import { SlackIcon } from "@trigger.dev/companyicons";
import { ProjectAlertChannelType, ProjectAlertType } from "@trigger.dev/database";
import assertNever from "assert-never";
import { ExternalLinkIcon } from "lucide-react";
import { typedjson, useTypedLoaderData } from "remix-typedjson";
import { z } from "zod";
import { PageBody, PageContainer } from "~/components/layout/AppLayout";
import { Button, LinkButton } from "~/components/primitives/Buttons";
import { ClipboardField } from "~/components/primitives/ClipboardField";
import { DetailCell } from "~/components/primitives/DetailCell";
import { Header2 } from "~/components/primitives/Headers";
import { NavBar, PageAccessories, PageTitle } from "~/components/primitives/PageHeader";
import { Paragraph } from "~/components/primitives/Paragraph";
import {
Expand Down Expand Up @@ -155,7 +158,7 @@ export default function Page() {
<PageAccessories>
<LinkButton
LeadingIcon={BookOpenIcon}
to={docsPath("v3/project-alerts")}
to={docsPath("v3/troubleshooting-alerts")}
variant="minimal/small"
>
Alerts docs
Expand All @@ -164,16 +167,19 @@ export default function Page() {
</NavBar>
<PageBody>
<div className={cn("flex h-full flex-col gap-3")}>
<div className="flex items-center justify-end gap-2">
<LinkButton
to={v3NewProjectAlertPath(organization, project)}
variant="primary/small"
LeadingIcon={PlusIcon}
shortcut={{ key: "n" }}
>
New alert
</LinkButton>
</div>
{alertChannels.length > 0 && alertChannels.length < 10 && (
<div className="flex items-end justify-between">
<Header2 className="">Project alerts</Header2>
<LinkButton
to={v3NewProjectAlertPath(organization, project)}
variant="primary/small"
LeadingIcon={PlusIcon}
shortcut={{ key: "n" }}
>
New alert
</LinkButton>
</div>
)}
<Table>
<TableHeader>
<TableRow>
Expand Down Expand Up @@ -214,14 +220,42 @@ export default function Page() {
) : (
<TableRow>
<TableCell colSpan={5}>
<div className="flex items-center justify-center">
<Paragraph>No alerts have been created</Paragraph>
<div className="flex flex-col items-center justify-center py-6">
<Header2 spacing className="text-text-bright">
You haven't created any project alerts yet
</Header2>
<Paragraph variant="small" className="mb-4">
Get alerted when runs or deployments fail, or when deployments succeed.
</Paragraph>
<LinkButton
to={v3NewProjectAlertPath(organization, project)}
variant="primary/medium"
LeadingIcon={PlusIcon}
shortcut={{ key: "n" }}
>
New alert
</LinkButton>
</div>
</TableCell>
</TableRow>
)}
</TableBody>
</Table>
<div className="mt-4">
<Header2 className="mb-1">Platform alerts</Header2>
<Paragraph variant="small" className="mb-4">
Get email notifications when Trigger.dev creates, updates or resolves a platform
incident.
</Paragraph>
<LinkButton
variant="tertiary/medium"
TrailingIcon={ArrowUpRightIcon}
to="https://status.trigger.dev/"
target="_blank"
>
Subscribe
</LinkButton>
</div>
</div>
<Outlet />
</PageBody>
Expand Down
15 changes: 15 additions & 0 deletions apps/webapp/app/services/email.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,17 @@ const client = singleton(
})
);

const alertsClient = singleton(
"alerts-email-client",
() =>
new EmailClient({
apikey: env.ALERT_RESEND_API_KEY,
imagesBaseUrl: env.APP_ORIGIN,
from: env.ALERT_FROM_EMAIL ?? "noreply@alerts.trigger.dev",
replyTo: env.REPLY_TO_EMAIL ?? "help@email.trigger.dev",
})
);

export async function sendMagicLinkEmail(options: SendEmailOptions<AuthUser>): Promise<void> {
// Auto redirect when in development mode
if (env.NODE_ENV === "development") {
Expand Down Expand Up @@ -67,3 +78,7 @@ export async function scheduleEmail(data: DeliverEmail, delay?: { seconds: numbe
export async function sendEmail(data: DeliverEmail) {
return client.send(data);
}

export async function sendAlertEmail(data: DeliverEmail) {
return alertsClient.send(data);
}
8 changes: 4 additions & 4 deletions apps/webapp/app/v3/services/alerts/deliverAlert.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
ProjectAlertWebhookProperties,
} from "~/models/projectAlert.server";
import { DeploymentPresenter } from "~/presenters/v3/DeploymentPresenter.server";
import { sendEmail } from "~/services/email.server";
import { sendAlertEmail, sendEmail } from "~/services/email.server";
import { logger } from "~/services/logger.server";
import { decryptSecret } from "~/services/secrets/secretStore.server";
import { workerQueue } from "~/services/worker.server";
Expand Down Expand Up @@ -144,7 +144,7 @@ export class DeliverAlertService extends BaseService {
return;
}

await sendEmail({
await sendAlertEmail({
email: "alert-attempt",
to: emailProperties.data.email,
taskIdentifier: alert.taskRunAttempt.taskRun.taskIdentifier,
Expand Down Expand Up @@ -177,7 +177,7 @@ export class DeliverAlertService extends BaseService {
return;
}

await sendEmail({
await sendAlertEmail({
email: "alert-deployment-failure",
to: emailProperties.data.email,
version: alert.workerDeployment.version,
Expand All @@ -197,7 +197,7 @@ export class DeliverAlertService extends BaseService {
}
case "DEPLOYMENT_SUCCESS": {
if (alert.workerDeployment) {
await sendEmail({
await sendAlertEmail({
email: "alert-deployment-success",
to: emailProperties.data.email,
version: alert.workerDeployment.version,
Expand Down
Binary file added docs/images/v3/troubleshooting-alerts-blank.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 89eaef4

Please sign in to comment.