Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Trigger release for all resources when moving deployment #257

Merged
merged 2 commits into from
Dec 10, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 14 additions & 46 deletions packages/job-dispatch/src/deployment-update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,76 +9,44 @@ import {
FilterType,
} from "@ctrlplane/validators/conditions";

import { handleEvent } from "./events/index.js";
import { getEventsForDeploymentRemoved, handleEvent } from "./events/index.js";
import { dispatchReleaseJobTriggers } from "./job-dispatch.js";
import { isPassingReleaseStringCheckPolicy } from "./policies/release-string-check.js";
import { isPassingAllPolicies } from "./policy-checker.js";
import { createJobApprovals } from "./policy-create.js";
import { createReleaseJobTriggers } from "./release-job-trigger.js";

const getResourcesOnlyInNewSystem = async (
newSystemId: string,
oldSystemId: string,
export const handleDeploymentSystemChanged = async (
deployment: SCHEMA.Deployment,
prevSystemId: string,
userId?: string,
) => {
const hasFilter = isNotNull(SCHEMA.environment.resourceFilter);
const newSystem = await db.query.system.findFirst({
where: eq(SCHEMA.system.id, newSystemId),
with: { environments: { where: hasFilter } },
});

const oldSystem = await db.query.system.findFirst({
where: eq(SCHEMA.system.id, oldSystemId),
where: eq(SCHEMA.system.id, deployment.systemId),
with: { environments: { where: hasFilter } },
});

if (newSystem == null || oldSystem == null) return [];
if (newSystem == null) return;

const newSystemFilter: ResourceCondition = {
const systemFilter: ResourceCondition = {
type: FilterType.Comparison,
operator: ComparisonOperator.Or,
conditions: newSystem.environments
.flatMap((env) => env.resourceFilter)
.filter(isPresent),
};
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Handle empty conditions in systemFilter

If newSystem.environments have no resourceFilter, the conditions array may be empty, which could lead to unintended behavior in SCHEMA.resourceMatchesMetadata. Consider adding a check to handle the case when conditions is empty.

Apply this diff to add a check:

 const systemFilter: ResourceCondition = {
   type: FilterType.Comparison,
   operator: ComparisonOperator.Or,
   conditions: newSystem.environments
     .flatMap((env) => env.resourceFilter)
     .filter(isPresent),
 };
+
+ if (systemFilter.conditions.length === 0) {
+   // No conditions to filter resources; handle accordingly
+   return;
+ }

Committable suggestion skipped: line range outside the PR's diff.


const notInOldSystemFilter: ResourceCondition = {
type: FilterType.Comparison,
operator: ComparisonOperator.Or,
not: true,
conditions: oldSystem.environments
.flatMap((env) => env.resourceFilter)
.filter(isPresent),
};

const filter: ResourceCondition = {
type: FilterType.Comparison,
operator: ComparisonOperator.And,
conditions: [newSystemFilter, notInOldSystemFilter],
};
await getEventsForDeploymentRemoved(deployment, prevSystemId).then((events) =>
Promise.allSettled(events.map(handleEvent)),
);
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Process results of Promise.allSettled to handle rejections

Currently, any rejections from handleEvent are silently ignored. Consider processing the results of Promise.allSettled to handle any errors appropriately.

Apply this diff to handle the results:

 await getEventsForDeploymentRemoved(deployment, prevSystemId).then((events) =>
-  Promise.allSettled(events.map(handleEvent)),
+  Promise.allSettled(events.map(handleEvent)).then((results) => {
+    results.forEach((result, index) => {
+      if (result.status === 'rejected') {
+        console.error(`Error handling event:`, result.reason);
+        // Additional error handling logic if necessary
+      }
+    });
+  }),
 );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
await getEventsForDeploymentRemoved(deployment, prevSystemId).then((events) =>
Promise.allSettled(events.map(handleEvent)),
);
await getEventsForDeploymentRemoved(deployment, prevSystemId).then((events) =>
Promise.allSettled(events.map(handleEvent)).then((results) => {
results.forEach((result, index) => {
if (result.status === 'rejected') {
console.error(`Error handling event:`, result.reason);
// Additional error handling logic if necessary
}
});
}),
);


return db.query.resource.findMany({
const resources = await db.query.resource.findMany({
where: and(
SCHEMA.resourceMatchesMetadata(db, filter),
SCHEMA.resourceMatchesMetadata(db, systemFilter),
isNull(SCHEMA.resource.deletedAt),
),
});
};

export const handleDeploymentSystemChanged = async (
deployment: SCHEMA.Deployment,
prevSystemId: string,
userId?: string,
) => {
const resourcesOnlyInNewSystem = await getResourcesOnlyInNewSystem(
deployment.systemId,
prevSystemId,
);

const events = resourcesOnlyInNewSystem.map((resource) => ({
action: "deployment.resource.removed" as const,
payload: { deployment, resource },
}));
await Promise.allSettled(events.map(handleEvent));

const isDeploymentHook = and(
eq(SCHEMA.hook.scopeType, "deployment"),
Expand All @@ -105,7 +73,7 @@ export const handleDeploymentSystemChanged = async (
: createReleaseJobTriggers(db, "new_release");
await createTriggers
.deployments([deployment.id])
.resources(resourcesOnlyInNewSystem.map((r) => r.id))
.resources(resources.map((r) => r.id))
.filter(isPassingReleaseStringCheckPolicy)
.then(createJobApprovals)
.insert()
Expand Down
Loading