import {z} from 'zod' export type ProtosProjectsV1SyncRepoRequest = {deploymentId?: string | undefined, repoId?: string | undefined}; export type CreateApiApiAgentDeploymentsDeploymentIdReposRepoIdSyncArgs = {deploymentId: string, repoId: string, body: ProtosProjectsV1SyncRepoRequest}; export type CreateApiApiAgentDeploymentsDeploymentIdReposRepoIdSyncOptions = {baseUrl: string, SemgrepWebToken?: string | undefined, fetch?: typeof fetch | undefined}; export const protosScanV1ScanSummary = z.object({id: z.string().optional(), startedAt: z.string().optional(), completedAt: z.string().optional(), exitCode: z.string().optional(), hasLogs: z.boolean().optional(), status: z.enum(["SCAN_STATUS_RUNNING", "SCAN_STATUS_COMPLETED", "SCAN_STATUS_PENDING", "SCAN_STATUS_CANCELLED", "SCAN_STATUS_ERROR", "SCAN_STATUS_NEVER_FINISHED"]).optional(), isManagedScanPlaceholder: z.boolean().optional(), aiFailureReason: z.enum(["AI_SCAN_JOB_FAILURE_REASON_GIT_BRANCH_NOT_FOUND", "AI_SCAN_JOB_FAILURE_REASON_GIT_UNAUTHORIZED", "AI_SCAN_JOB_FAILURE_REASON_TIMED_OUT", "AI_SCAN_JOB_FAILURE_REASON_INTERNAL_ERROR", "AI_SCAN_JOB_FAILURE_REASON_GIT_TRANSIENT_ERROR", "AI_SCAN_JOB_FAILURE_REASON_GIT_UPSTREAM_UNAVAILABLE", "AI_SCAN_JOB_FAILURE_REASON_BUDGET_EXCEEDED"]).optional()}); export const protosProjectsV1ProductIgnoredFilesMap = z.object({sast: z.array(z.string()).optional(), sca: z.array(z.string()).optional(), secrets: z.array(z.string()).optional()}); export const protosProjectsV1ManagedScanSettings = z.object({diffScan: z.boolean().optional(), numConfigs: z.number().int().optional(), fullScan: z.boolean().optional()}); export const protosProjectsV1RepositoryRefItem = z.object({repoRefId: z.string().optional(), ref: z.string().optional(), isDefault: z.boolean().optional(), isPrimary: z.boolean().optional()}); export const protosProjectsV1PrimaryRefItem = z.object({id: z.string().optional(), ref: z.string().optional(), isOverride: z.boolean().optional()}); export const protosProjectsV1SimpleRefItem = z.object({id: z.string().optional(), ref: z.string().optional()}); export const protosScaV1CodeLocation = z.object({path: z.string().optional(), startLine: z.string().optional(), startCol: z.string().optional(), endLine: z.string().optional(), endCol: z.string().optional(), url: z.string().optional(), committedAt: z.string().optional()}); export const protosScaV1DependencyParserError = z.object({location: protosScaV1CodeLocation.optional(), reason: z.string().optional(), parser: z.string().optional(), text: z.string().optional()}); export const protosScaV1DependencyParserErrors = z.object({errors: z.array(protosScaV1DependencyParserError).optional()}); export const protosProjectsV1ScaInfo = z.object({dependencyCounts: z.record(z.string(), z.string()).optional()}); export const protosScmV1ScmTokenScopes = z.object({readMetadata: z.boolean().optional(), readPullRequest: z.boolean().optional(), writePullRequestComment: z.boolean().optional(), readContents: z.boolean().optional(), readMembers: z.boolean().optional(), manageWebhooks: z.boolean().optional(), writeContents: z.boolean().optional(), writePullRequest: z.boolean().optional()}); export const protosCloudContextV1CloudContext = z.object({id: z.string().optional(), cnappInstallationId: z.string().optional(), cnappInstallationBaseUrl: z.string().optional(), source: z.enum(["CLOUD_CONTEXT_SOURCE_MANUAL", "CLOUD_CONTEXT_SOURCE_PALO_ALTO_NETWORKS", "CLOUD_CONTEXT_SOURCE_SYSDIG"]).optional(), isDeployed: z.boolean().optional(), publicExposure: z.boolean().optional(), lastSuccessfulIngestionCompletedAt: z.string().optional()}); export const protosProjectsV1AiScanSettings = z.object({fullScan: z.boolean().optional()}); export const protosProjectsV1Repository = z.object({id: z.string().optional(), name: z.string().optional(), tags: z.array(z.string()).optional(), provisionedAt: z.string().optional(), latestScan: protosScanV1ScanSummary.optional(), deploymentId: z.string().optional(), url: z.string().optional(), ignoredFiles: z.array(z.string()).optional(), productIgnoredFiles: protosProjectsV1ProductIgnoredFilesMap.optional(), firstScanId: z.string().optional(), isArchived: z.boolean().optional(), isDisconnected: z.boolean().optional(), hasCodeAccess: z.boolean().optional(), managedScans: protosProjectsV1ManagedScanSettings.optional(), isSetup: z.boolean().optional(), scmLastSyncedAt: z.number().optional(), authorizedScopes: z.array(z.enum(["REPO_SCOPE_UNSPECIFIED", "REPO_SCOPE_READ_FINDING", "REPO_SCOPE_TRIAGE_FINDING", "REPO_SCOPE_MANAGE_PROJECT_SETTINGS", "REPO_SCOPE_AUTOINSTALL", "REPO_SCOPE_DELETE_PROJECT", "REPO_SCOPE_ASSIGN_TEAM"])).optional(), provider: z.literal("PROVIDER_GITHUB").optional(), defaultBranch: z.string().optional(), refs: z.array(protosProjectsV1RepositoryRefItem).optional(), primaryRef: protosProjectsV1PrimaryRefItem.optional(), defaultRef: protosProjectsV1SimpleRefItem.optional(), lastScannedRef: protosProjectsV1SimpleRefItem.optional(), latestFullScaScanParserErrors: protosScaV1DependencyParserErrors.optional(), latestFullScaScanAt: z.string().optional(), scaInfo: protosProjectsV1ScaInfo.optional(), linkedRepos: z.array(z.string()).optional(), scmType: z.enum(["SCM_TYPE_GITHUB", "SCM_TYPE_GITHUB_ENTERPRISE", "SCM_TYPE_GITLAB", "SCM_TYPE_GITLAB_SELFMANAGED", "SCM_TYPE_BITBUCKET", "SCM_TYPE_BITBUCKET_DATACENTER", "SCM_TYPE_AZURE_DEVOPS", "SCM_TYPE_UNKNOWN", "SCM_TYPE_HARNESS"]).optional(), repositoryScmLinkId: z.string().optional(), tokenScopes: protosScmV1ScmTokenScopes.optional(), cloudContext: protosCloudContextV1CloudContext.optional(), aiScans: protosProjectsV1AiScanSettings.optional(), isScmArchived: z.boolean().optional(), isSemgrepArchived: z.boolean().optional(), archivedAt: z.string().optional()}); export const protosProjectsV1SyncRepoResponse = z.object({repo: protosProjectsV1Repository.optional()}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Sync Project to SCM * * POST /api/agent/deployments/{deploymentId}/repos/{repoId}/_sync * * Also accepts auth: SemgrepJWT */ export const createApiApiAgentDeploymentsDeploymentIdReposRepoIdSync = async (args: CreateApiApiAgentDeploymentsDeploymentIdReposRepoIdSyncArgs, options: CreateApiApiAgentDeploymentsDeploymentIdReposRepoIdSyncOptions) => { const {baseUrl, fetch: fetchFn = fetch, SemgrepWebToken} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('content-type', "application/json") headers.set('accept', "application/json") if (SemgrepWebToken !== undefined) headers.set('authorization', `Bearer ${SemgrepWebToken}`) const url = `${baseUrl.replace(/\/+$/, '')}/api/agent/deployments/${encodeURIComponent(String(args.deploymentId))}/repos/${encodeURIComponent(String(args.repoId))}/_sync${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "POST", headers, body: JSON.stringify(args.body)}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(protosProjectsV1SyncRepoResponse, await res.json()) };