All files / src/entities/deploy-keys schema.ts

100% Statements 10/10
100% Branches 3/3
100% Functions 1/1
100% Lines 10/10

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 7417x 17x 17x                   17x         17x                         17x                 17x                 17x             17x                   6x                
import { z } from 'zod';
import { flexibleBoolean } from '../utils';
import { projectIdField, keyIdField } from './schema-readonly';
 
// ============================================================================
// manage_deploy_key - CQRS Command Tool (discriminated union schema)
// Actions: add, enable, update, delete
//
// Manages a project's deploy keys: the SSH public keys that let CI/automation
// access the repository without a user PAT. Project-level, Free tier.
// ============================================================================
 
const canPushField = flexibleBoolean
  .optional()
  .describe('Whether the key may push to the repository (read/write). Default false (read-only).');
 
// --- Action: add ---
const AddDeployKeySchema = z.object({
  action: z.literal('add').describe('Add a deploy key to the project'),
  project_id: projectIdField,
  title: z.string().describe('Human-readable name for the deploy key.'),
  key: z.string().describe('The SSH public key (e.g. "ssh-ed25519 AAAA... comment").'),
  can_push: canPushField,
  expires_at: z
    .string()
    .optional()
    .describe('Optional expiry date in YYYY-MM-DD format (e.g. "2026-12-31").'),
});
 
// --- Action: enable ---
const EnableDeployKeySchema = z.object({
  action: z
    .literal('enable')
    .describe('Enable an existing deploy key (from another project) on this project'),
  project_id: projectIdField,
  key_id: keyIdField,
});
 
// --- Action: update ---
const UpdateDeployKeySchema = z.object({
  action: z.literal('update').describe('Update a deploy key title or push permission'),
  project_id: projectIdField,
  key_id: keyIdField,
  title: z.string().optional().describe('New title for the deploy key.'),
  can_push: canPushField,
});
 
// --- Action: delete ---
const DeleteDeployKeySchema = z.object({
  action: z.literal('delete').describe('Remove a deploy key from the project'),
  project_id: projectIdField,
  key_id: keyIdField,
});
 
// --- Discriminated union combining all actions ---
export const ManageDeployKeySchema = z
  .discriminatedUnion('action', [
    AddDeployKeySchema,
    EnableDeployKeySchema,
    UpdateDeployKeySchema,
    DeleteDeployKeySchema,
  ])
  // An update with no fields would send an empty body and be rejected by GitLab;
  // require at least one updatable field.
  .refine(
    (data) => data.action !== 'update' || data.title !== undefined || data.can_push !== undefined,
    {
      message: 'update requires at least one of: title, can_push',
      path: ['title'],
    },
  );
 
export type ManageDeployKeyInput = z.infer<typeof ManageDeployKeySchema>;