Skip to content

Commit

Permalink
cancel jobs when you reject the release (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
zacharyblasczyk authored Oct 8, 2024
1 parent 41df79a commit de2b7d9
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,60 @@ import type {
import { useRouter } from "next/navigation";

import { Button } from "@ctrlplane/ui/button";
import { toast } from "@ctrlplane/ui/toast";

import { api } from "~/trpc/react";

export const PolicyApprovalRow: React.FC<{
type PolicyApprovalRowProps = {
approval: EnvironmentPolicyApproval;
environments: Environment[];
}> = ({ approval, environments }) => {
const reject = api.environment.policy.approval.reject.useMutation();
const approve = api.environment.policy.approval.approve.useMutation();
};

export const PolicyApprovalRow: React.FC<PolicyApprovalRowProps> = ({
approval,
environments,
}) => {
const router = useRouter();
const utils = api.useUtils();

const { releaseId, policyId } = approval;

const rejectMutation = api.environment.policy.approval.reject.useMutation({
onSuccess: ({ cancelledJobCount }) => {
router.refresh();
utils.environment.policy.invalidate();
utils.job.config.invalidate();
toast.success(
`Rejected release to ${environmentNames} and cancelled ${cancelledJobCount} job${cancelledJobCount !== 1 ? "s" : ""}`,
);
},
onError: () => toast.error("Error rejecting release"),
});

const approveMutation = api.environment.policy.approval.approve.useMutation({
onSuccess: () => {
router.refresh();
utils.environment.policy.invalidate();
utils.job.config.invalidate();
toast.success(`Approved release to ${environmentNames}`);
},
onError: () => toast.error("Error approving release"),
});

const environmentNames = environments.map((e) => e.name).join(", ");
const handleReject = () => rejectMutation.mutate({ releaseId, policyId });
const handleApprove = () => approveMutation.mutate(approval);

return (
<div className="flex items-center gap-2 rounded-md border border-blue-400/50 bg-blue-500/10 p-2 text-sm">
<div className="ml-2 flex-grow">
Approve deploying to {environments.map((e) => e.name).join(", ")}
Approve deploying to {environmentNames}
</div>

<div className="flex shrink-0 items-center gap-2">
<Button
variant="secondary"
size="sm"
onClick={async () => {
await reject.mutateAsync(approval);
router.refresh();
utils.environment.policy.invalidate();
utils.job.config.invalidate();
}}
>
<Button variant="secondary" size="sm" onClick={handleReject}>
Reject
</Button>
<Button
size="sm"
onClick={async () => {
await approve.mutateAsync(approval);
router.refresh();
utils.environment.policy.invalidate();
utils.job.config.invalidate();
}}
>
<Button size="sm" onClick={handleApprove}>
Approve
</Button>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export default async function ReleasePage({
params,
}: {
params: {
release: { id: string; version: string };
workspaceSlug: string;
systemSlug: string;
deploymentSlug: string;
Expand Down
40 changes: 27 additions & 13 deletions packages/api/src/router/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
eq,
isNull,
not,
sql,
takeFirst,
takeFirstOrNull,
} from "@ctrlplane/db";
Expand Down Expand Up @@ -207,19 +208,32 @@ const policyRouter = createTRPCRouter({
.input(
z.object({ releaseId: z.string().uuid(), policyId: z.string().uuid() }),
)
.mutation(async ({ ctx, input }) => {
return ctx.db
.update(environmentPolicyApproval)
.set({ status: "rejected" })
.where(
and(
eq(environmentPolicyApproval.policyId, input.policyId),
eq(environmentPolicyApproval.releaseId, input.releaseId),
),
)
.returning()
.then(takeFirst);
}),
.mutation(({ ctx, input }) =>
ctx.db.transaction(async (tx) => {
await tx
.update(environmentPolicyApproval)
.set({ status: "rejected" })
.where(
and(
eq(environmentPolicyApproval.policyId, input.policyId),
eq(environmentPolicyApproval.releaseId, input.releaseId),
),
);

const updateResult = await tx.execute(
sql`UPDATE job
SET status = 'cancelled'
FROM release_job_trigger rjt
INNER JOIN environment env ON rjt.environment_id = env.id
WHERE job.status = 'pending'
AND rjt.job_id = job.id
AND rjt.release_id = ${input.releaseId}
AND env.policy_id = ${input.policyId}`,
);

return { cancelledJobCount: updateResult.rowCount };
}),
),

statusByReleasePolicyId: protectedProcedure
.meta({
Expand Down

0 comments on commit de2b7d9

Please sign in to comment.