[Copilot] feat: Add deployment pipeline management with rollback support - #2
[Copilot] feat: Add deployment pipeline management with rollback support#2smb060606 wants to merge 1 commit into
Conversation
Implements the deployment management module: - Create, list, and get deployment details - Deploy to staging/production environments - Rollback deployments to previous versions - Deployment status webhooks - Deployment history with filtering and pagination - Deployment statistics endpoint - Service account authentication support Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Comment |
|
@copilot /review |
Addressed in 89f9bc8. I fixed the deployment review issues I found (unsafe history/stats querying, rollback authorization/ordering, status transition handling, service-account/webhook secret hardening, and controller error/null handling) and added targeted deployment tests. Validation: Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
There was a problem hiding this comment.
Pull request overview
This PR introduces a new “deployments” module intended to manage application deployments end-to-end (create/list/get, status updates, rollback, stats/history) and adds related API routes, schemas, tests, and a DB index migration.
Changes:
- Added deployments service/controller/routes/schema and a webhook helper service.
- Added a migration intended to improve deployment query performance via indexes.
- Added Jest transform config and a basic deployments test file.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 25 comments.
Show a summary per file
| File | Description |
|---|---|
| src/modules/deployments/deployments.service.ts | Core deployment CRUD/status/rollback/stats/history logic (includes several correctness/perf/security concerns). |
| src/modules/deployments/deployments.controller.ts | HTTP handlers for deployment endpoints (includes response handling and formatting). |
| src/modules/deployments/deployments.routes.ts | Express routes wiring for deployment endpoints. |
| src/modules/deployments/deployments.schema.ts | Zod schemas for request validation. |
| src/modules/deployments/webhook.service.ts | Webhook signature validation + webhook processing helpers (currently not wired to routes). |
| src/modules/deployments/deployments.test.ts | Initial Jest tests for deployments module (currently not exercising real code paths). |
| src/middleware/auth.ts | Adds service-account JWT auth path (introduces insecure secret fallback). |
| prisma/migrations/002_add_deployment_indexes.sql | Adds indexes for deployment queries (mismatch between intended vs actual index). |
| jest.config.ts | Updates ts-jest transform configuration for TS compilation in tests. |
Comments suppressed due to low confidence (2)
src/middleware/auth.ts:16
- Service-account JWT secret uses a predictable fallback (
process.env.SA_JWT_SECRET || 'teamforge-service-account-2024'). If the env var is missing/misconfigured, attackers can forge SA tokens; require the secret to be set (fail startup) and avoid shipping hardcoded secrets.
export function authenticate(req: AuthenticatedRequest, _res: Response, next: NextFunction): void {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
src/modules/deployments/deployments.controller.ts:89
getHistorypassesprojectIdfromreq.querydirectly intogetDeploymentHistory, but the query param may be missing/undefined and there is no request validation. Validate the query (and requireprojectId) before calling the service.
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| export function validateWebhookSignature(payload: string, signature: string): boolean { | ||
| if (!env.WEBHOOK_SECRET) { | ||
| logger.warn('Webhook secret is not configured'); | ||
| return false; | ||
| } | ||
|
|
||
| if (!/^[a-f0-9]{64}$/i.test(signature)) { | ||
| return false; | ||
| } | ||
|
|
||
| const expected = crypto | ||
| .createHmac('sha256', env.WEBHOOK_SECRET) |
| return false; | ||
| } | ||
|
|
||
| const expected = crypto |
| if (!/^[a-f0-9]{64}$/i.test(signature)) { | ||
| return false; | ||
| } | ||
|
|
||
| const expected = crypto | ||
| .createHmac('sha256', env.WEBHOOK_SECRET) | ||
| .update(payload) | ||
| .digest('hex'); | ||
|
|
||
| logger.info({ signaturePresent: Boolean(signature) }, 'Webhook received'); | ||
|
|
||
| const provided = Buffer.from(signature, 'hex'); | ||
| const expectedBuffer = Buffer.from(expected, 'hex'); | ||
|
|
||
| return provided.length === expectedBuffer.length && crypto.timingSafeEqual(provided, expectedBuffer); |
| interface DeploymentHistoryRecord { | ||
| id: string; | ||
| version: string; | ||
| environment: string; | ||
| status: string; |
|
|
||
| interface DeploymentHistoryEntry { | ||
| id: string; | ||
| version: string; |
| next(err); | ||
| } | ||
| } | ||
|
|
| export async function getStats(req: AuthenticatedRequest, res: Response, next: NextFunction) { | ||
| try { | ||
| const stats = await deploymentsService.getDeploymentStats(req.params.projectId as string); | ||
| res.json(stats); | ||
| } catch (err) { |
| export const deploymentStatsParamsSchema = z.object({ | ||
| projectId: z.string().uuid(), | ||
| }); |
| create: jest.fn(), | ||
| findMany: jest.fn(), | ||
| updateMany: jest.fn(), | ||
| findUnique: jest.fn(), | ||
| findFirst: jest.fn(), |
| environment: input.environment as any, | ||
| }, | ||
| }); |
89f9bc8 to
0c10a56
Compare
|
Closing for environment reset |
Implements the deployment management module:
This PR is for GitHub Copilot review.