@standards-kit/conform 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +143 -0
- package/dist/{chunk-P7TIZJ4C.js → chunk-DXIYZR62.js} +2 -2
- package/dist/chunk-DXIYZR62.js.map +1 -0
- package/dist/{chunk-RXA4FO7L.js → chunk-NADY2H35.js} +12 -8
- package/dist/chunk-NADY2H35.js.map +1 -0
- package/dist/chunk-O745CMWG.js +29 -0
- package/dist/chunk-O745CMWG.js.map +1 -0
- package/dist/chunk-RHM53NLG.js +49 -0
- package/dist/chunk-RHM53NLG.js.map +1 -0
- package/dist/{chunk-KHO6NIAI.js → chunk-YGDEM6K5.js} +24 -10
- package/dist/chunk-YGDEM6K5.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +49 -38
- package/dist/cli.js.map +1 -1
- package/dist/{cloudwatch-KSZ4A256.js → cloudwatch-3LTDYG6G.js} +6 -10
- package/dist/cloudwatch-3LTDYG6G.js.map +1 -0
- package/dist/code/index.d.ts +11 -0
- package/dist/code/tools/base.d.ts +51 -0
- package/dist/code/tools/comment-utils.d.ts +17 -0
- package/dist/code/tools/coverage-run.d.ts +37 -0
- package/dist/code/tools/disable-comments.d.ts +42 -0
- package/dist/code/tools/eslint.d.ts +99 -0
- package/dist/code/tools/gitleaks.d.ts +42 -0
- package/dist/code/tools/index.d.ts +13 -0
- package/dist/code/tools/knip.d.ts +20 -0
- package/dist/code/tools/naming.d.ts +64 -0
- package/dist/code/tools/pipaudit.d.ts +24 -0
- package/dist/code/tools/pnpmaudit.d.ts +36 -0
- package/dist/code/tools/ruff.d.ts +46 -0
- package/dist/code/tools/tsc.d.ts +57 -0
- package/dist/code/tools/ty.d.ts +34 -0
- package/dist/code/tools/vulture.d.ts +32 -0
- package/dist/constants.d.ts +69 -0
- package/dist/core/index.d.ts +7 -0
- package/dist/core/loader.d.ts +42 -0
- package/dist/core/registry.d.ts +17 -0
- package/dist/core/schema.d.ts +1857 -0
- package/dist/core/types.d.ts +95 -0
- package/dist/{src-KZRTG3EU.js → core-QRFGIQ42.js} +4 -3
- package/dist/dependencies/index.d.ts +13 -0
- package/dist/dependencies/mappings.d.ts +17 -0
- package/dist/dependencies/output.d.ts +12 -0
- package/dist/dependencies/types.d.ts +34 -0
- package/dist/{dynamodb-5KVESCVJ.js → dynamodb-HQH3IMAI.js} +6 -10
- package/dist/dynamodb-HQH3IMAI.js.map +1 -0
- package/dist/{ec2-HKPE6GZV.js → ec2-AEPT735A.js} +6 -10
- package/dist/ec2-AEPT735A.js.map +1 -0
- package/dist/{ecs-OS3NJZTA.js → ecs-UHKCH5A7.js} +6 -10
- package/dist/ecs-UHKCH5A7.js.map +1 -0
- package/dist/{elasticache-7TCRHYYM.js → elasticache-5Y6K7GKJ.js} +6 -10
- package/dist/elasticache-5Y6K7GKJ.js.map +1 -0
- package/dist/{elb-PEDLXW5R.js → elb-CN6ELVM5.js} +6 -10
- package/dist/elb-CN6ELVM5.js.map +1 -0
- package/dist/{iam-7H5HFWVQ.js → iam-YXMHK2MV.js} +6 -2
- package/dist/iam-YXMHK2MV.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +99 -121
- package/dist/index.js.map +1 -1
- package/dist/infra/arn.d.ts +16 -0
- package/dist/infra/checkers/client-factory.d.ts +45 -0
- package/dist/infra/checkers/cloudwatch.d.ts +8 -0
- package/dist/infra/checkers/dynamodb.d.ts +8 -0
- package/dist/infra/checkers/ec2.d.ts +13 -0
- package/dist/infra/checkers/ecs.d.ts +13 -0
- package/dist/infra/checkers/elasticache.d.ts +13 -0
- package/dist/infra/checkers/elb.d.ts +13 -0
- package/dist/infra/checkers/gcp/artifactregistry.d.ts +5 -0
- package/dist/infra/checkers/gcp/cloudrun.d.ts +5 -0
- package/dist/infra/checkers/gcp/iam.d.ts +5 -0
- package/dist/infra/checkers/gcp/index.d.ts +17 -0
- package/dist/infra/checkers/gcp/secretmanager.d.ts +5 -0
- package/dist/infra/checkers/iam.d.ts +8 -0
- package/dist/infra/checkers/index.d.ts +26 -0
- package/dist/infra/checkers/lambda.d.ts +8 -0
- package/dist/infra/checkers/rds.d.ts +13 -0
- package/dist/infra/checkers/s3.d.ts +8 -0
- package/dist/infra/checkers/secretsmanager.d.ts +8 -0
- package/dist/infra/checkers/sns.d.ts +8 -0
- package/dist/infra/checkers/sqs.d.ts +8 -0
- package/dist/infra/checkers/types.d.ts +28 -0
- package/dist/infra/gcp.d.ts +18 -0
- package/dist/infra/generate.d.ts +74 -0
- package/dist/infra/index.d.ts +59 -0
- package/dist/infra/manifest.d.ts +58 -0
- package/dist/infra/output.d.ts +8 -0
- package/dist/infra/scan.d.ts +25 -0
- package/dist/infra/schemas.d.ts +806 -0
- package/dist/infra/types.d.ts +8 -0
- package/dist/{infra-UXM5XQX3.js → infra-TO54IUSC.js} +21 -19
- package/dist/infra-TO54IUSC.js.map +1 -0
- package/dist/{lambda-NFB5UILT.js → lambda-YTJOCYV5.js} +6 -10
- package/dist/lambda-YTJOCYV5.js.map +1 -0
- package/dist/mcp/index.d.ts +7 -0
- package/dist/mcp/server.d.ts +18 -0
- package/dist/mcp/standards/fetcher.d.ts +29 -0
- package/dist/mcp/standards/index.d.ts +4 -0
- package/dist/mcp/standards/matcher.d.ts +22 -0
- package/dist/mcp/standards/parser.d.ts +46 -0
- package/dist/mcp/standards/types.d.ts +32 -0
- package/dist/mcp/tools/get-guideline.d.ts +26 -0
- package/dist/mcp/tools/get-ruleset.d.ts +26 -0
- package/dist/mcp/tools/get-standards.d.ts +27 -0
- package/dist/mcp/tools/index.d.ts +4 -0
- package/dist/mcp/tools/list-guidelines.d.ts +25 -0
- package/dist/{mcp-O5O7XVFG.js → mcp-73FZXT3P.js} +5 -4
- package/dist/mcp-73FZXT3P.js.map +1 -0
- package/dist/output/index.d.ts +14 -0
- package/dist/process/commands/check-branch.d.ts +13 -0
- package/dist/process/commands/check-commit.d.ts +14 -0
- package/dist/process/commands/index.d.ts +2 -0
- package/dist/process/index.d.ts +11 -0
- package/dist/process/scan/index.d.ts +5 -0
- package/dist/process/scan/remote-fetcher.d.ts +18 -0
- package/dist/process/scan/scanner.d.ts +6 -0
- package/dist/process/scan/types.d.ts +57 -0
- package/dist/process/scan/validators.d.ts +37 -0
- package/dist/process/sync/applier.d.ts +10 -0
- package/dist/process/sync/differ.d.ts +7 -0
- package/dist/process/sync/fetcher.d.ts +14 -0
- package/dist/process/sync/index.d.ts +9 -0
- package/dist/process/sync/types.d.ts +131 -0
- package/dist/process/sync/validator.d.ts +22 -0
- package/dist/process/tools/backups.d.ts +32 -0
- package/dist/process/tools/base.d.ts +52 -0
- package/dist/process/tools/branches.d.ts +41 -0
- package/dist/process/tools/changesets.d.ts +53 -0
- package/dist/process/tools/ci.d.ts +57 -0
- package/dist/process/tools/codeowners.d.ts +68 -0
- package/dist/process/tools/commits.d.ts +39 -0
- package/dist/process/tools/coverage.d.ts +57 -0
- package/dist/process/tools/docs-helpers.d.ts +44 -0
- package/dist/process/tools/docs.d.ts +38 -0
- package/dist/process/tools/forbidden-files.d.ts +40 -0
- package/dist/process/tools/hooks.d.ts +39 -0
- package/dist/process/tools/index.d.ts +14 -0
- package/dist/process/tools/pr.d.ts +59 -0
- package/dist/process/tools/repo.d.ts +65 -0
- package/dist/process/tools/tickets.d.ts +42 -0
- package/dist/projects/detector.d.ts +16 -0
- package/dist/projects/index.d.ts +4 -0
- package/dist/projects/templates.d.ts +15 -0
- package/dist/projects/tier-loader.d.ts +21 -0
- package/dist/projects/types.d.ts +76 -0
- package/dist/{rds-KLG5O5SI.js → rds-GZ5RVPIU.js} +6 -10
- package/dist/rds-GZ5RVPIU.js.map +1 -0
- package/dist/{registry-V65CC7IN.js → registry-JRCQAIHR.js} +3 -2
- package/dist/{s3-2DH7PRVR.js → s3-53UELUWT.js} +16 -12
- package/dist/s3-53UELUWT.js.map +1 -0
- package/dist/s3-S4GXNR7H.js +53 -0
- package/dist/s3-S4GXNR7H.js.map +1 -0
- package/dist/{scan-EELS42BP.js → scan-RHQWHASY.js} +5 -4
- package/dist/{scan-EELS42BP.js.map → scan-RHQWHASY.js.map} +1 -1
- package/dist/{secretsmanager-MOOIHLAO.js → secretsmanager-FJKTPIXI.js} +6 -10
- package/dist/secretsmanager-FJKTPIXI.js.map +1 -0
- package/dist/{sns-Y36LVTWA.js → sns-RV64OMK2.js} +6 -10
- package/dist/sns-RV64OMK2.js.map +1 -0
- package/dist/{sqs-RRS3GRHK.js → sqs-MHBW6UFC.js} +6 -10
- package/dist/sqs-MHBW6UFC.js.map +1 -0
- package/dist/{standards-RXK5G4IG.js → standards-XAZKTKYJ.js} +3 -2
- package/dist/{sync-RLYBGYNY.js → sync-P3UZECLW.js} +4 -3
- package/dist/{sync-RLYBGYNY.js.map → sync-P3UZECLW.js.map} +1 -1
- package/dist/validate/guidelines.d.ts +18 -0
- package/dist/validate/index.d.ts +5 -0
- package/dist/validate/tier.d.ts +17 -0
- package/dist/validate/types.d.ts +50 -0
- package/dist/{validate-AABLVQJS.js → validate-J5E336GX.js} +53 -84
- package/dist/validate-J5E336GX.js.map +1 -0
- package/package.json +22 -25
- package/dist/chunk-KHO6NIAI.js.map +0 -1
- package/dist/chunk-P7TIZJ4C.js.map +0 -1
- package/dist/chunk-RXA4FO7L.js.map +0 -1
- package/dist/cloudwatch-KSZ4A256.js.map +0 -1
- package/dist/dynamodb-5KVESCVJ.js.map +0 -1
- package/dist/ec2-HKPE6GZV.js.map +0 -1
- package/dist/ecs-OS3NJZTA.js.map +0 -1
- package/dist/elasticache-7TCRHYYM.js.map +0 -1
- package/dist/elb-PEDLXW5R.js.map +0 -1
- package/dist/iam-7H5HFWVQ.js.map +0 -1
- package/dist/infra-UXM5XQX3.js.map +0 -1
- package/dist/lambda-NFB5UILT.js.map +0 -1
- package/dist/mcp-O5O7XVFG.js.map +0 -1
- package/dist/rds-KLG5O5SI.js.map +0 -1
- package/dist/s3-2DH7PRVR.js.map +0 -1
- package/dist/secretsmanager-MOOIHLAO.js.map +0 -1
- package/dist/sns-Y36LVTWA.js.map +0 -1
- package/dist/sqs-RRS3GRHK.js.map +0 -1
- package/dist/validate-AABLVQJS.js.map +0 -1
- /package/dist/{registry-V65CC7IN.js.map → core-QRFGIQ42.js.map} +0 -0
- /package/dist/{src-KZRTG3EU.js.map → registry-JRCQAIHR.js.map} +0 -0
- /package/dist/{standards-RXK5G4IG.js.map → standards-XAZKTKYJ.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/process/sync/applier.ts","../src/process/sync/differ.ts","../src/process/sync/fetcher.ts","../src/process/sync/index.ts"],"sourcesContent":["import { execa } from \"execa\";\n\nimport {\n type DesiredBranchProtection,\n type DesiredTagProtection,\n type RepoInfo,\n type SettingDiff,\n type SyncDiffResult,\n type SyncResult,\n type TagProtectionDiffResult,\n} from \"./types.js\";\n\n/** Error thrown when applier encounters an issue */\nexport class ApplierError extends Error {\n constructor(\n message: string,\n public readonly code: \"NO_PERMISSION\" | \"API_ERROR\"\n ) {\n super(message);\n this.name = \"ApplierError\";\n }\n}\n\n/** Apply branch protection ruleset to GitHub */\nexport async function applyBranchProtection(\n repoInfo: RepoInfo,\n branch: string,\n desired: DesiredBranchProtection,\n diffResult: SyncDiffResult\n): Promise<SyncResult> {\n if (!diffResult.hasChanges) {\n return { success: true, applied: [], failed: [] };\n }\n\n const requestBody = buildBranchRulesetBody(branch, desired);\n\n try {\n if (diffResult.currentRulesetId === null) {\n // Create new ruleset\n await execa(\n \"gh\",\n [\"api\", `repos/${repoInfo.owner}/${repoInfo.repo}/rulesets`, \"-X\", \"POST\", \"--input\", \"-\"],\n { input: JSON.stringify(requestBody) }\n );\n } else {\n // Update existing ruleset\n await execa(\n \"gh\",\n [\n \"api\",\n `repos/${repoInfo.owner}/${repoInfo.repo}/rulesets/${diffResult.currentRulesetId}`,\n \"-X\",\n \"PUT\",\n \"--input\",\n \"-\",\n ],\n { input: JSON.stringify(requestBody) }\n );\n }\n\n return { success: true, applied: diffResult.diffs, failed: [] };\n } catch (error) {\n return handleBranchApplyError(error, diffResult.diffs);\n }\n}\n\n/** Handle errors from applying branch protection */\nfunction handleBranchApplyError(error: unknown, diffs: SettingDiff[]): SyncResult {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (errorMessage.includes(\"403\") || errorMessage.includes(\"Must have admin rights\")) {\n throw new ApplierError(\n \"Cannot update branch protection: insufficient permissions (requires admin access)\",\n \"NO_PERMISSION\"\n );\n }\n\n return {\n success: false,\n applied: [],\n failed: diffs.map((diff) => ({ diff, error: errorMessage })),\n };\n}\n\n/** Build GitHub API request body for branch ruleset */\nfunction buildBranchRulesetBody(\n branch: string,\n desired: DesiredBranchProtection\n): Record<string, unknown> {\n const rules: { type: string; parameters?: Record<string, unknown> }[] = [];\n\n // Build pull_request rule if any review settings specified\n const pullRequestRule = buildPullRequestRule(desired);\n if (pullRequestRule) {\n rules.push(pullRequestRule);\n }\n\n // Build required_status_checks rule\n const statusChecksRule = buildStatusChecksRule(desired);\n if (statusChecksRule) {\n rules.push(statusChecksRule);\n }\n\n // Build required_signatures rule\n if (desired.require_signed_commits === true) {\n rules.push({ type: \"required_signatures\" });\n }\n\n // Build bypass actors array\n const bypassActors =\n desired.bypass_actors?.map((actor) => ({\n actor_id: actor.actor_id ?? null,\n actor_type: actor.actor_type,\n bypass_mode: actor.bypass_mode ?? \"always\",\n })) ?? [];\n\n return {\n name: \"Branch Protection\",\n target: \"branch\",\n enforcement: \"active\",\n conditions: {\n ref_name: {\n include: [`refs/heads/${branch}`],\n exclude: [],\n },\n },\n bypass_actors: bypassActors,\n rules,\n };\n}\n\n/** Build pull_request rule for PR review settings */\nfunction buildPullRequestRule(\n desired: DesiredBranchProtection\n): { type: string; parameters: Record<string, unknown> } | null {\n const hasReviewSettings =\n desired.required_reviews !== undefined ||\n desired.dismiss_stale_reviews !== undefined ||\n desired.require_code_owner_reviews !== undefined;\n\n if (!hasReviewSettings) {\n return null;\n }\n\n return {\n type: \"pull_request\",\n parameters: {\n ...(desired.required_reviews !== undefined && {\n required_approving_review_count: desired.required_reviews,\n }),\n ...(desired.dismiss_stale_reviews !== undefined && {\n dismiss_stale_reviews_on_push: desired.dismiss_stale_reviews,\n }),\n ...(desired.require_code_owner_reviews !== undefined && {\n require_code_owner_review: desired.require_code_owner_reviews,\n }),\n },\n };\n}\n\n/** Build required_status_checks rule for status check settings */\nfunction buildStatusChecksRule(\n desired: DesiredBranchProtection\n): { type: string; parameters: Record<string, unknown> } | null {\n const hasStatusSettings =\n desired.require_status_checks !== undefined ||\n desired.require_branches_up_to_date !== undefined;\n\n if (!hasStatusSettings) {\n return null;\n }\n\n const statusChecks =\n desired.require_status_checks?.map((context) => ({\n context,\n })) ?? [];\n\n return {\n type: \"required_status_checks\",\n parameters: {\n required_status_checks: statusChecks,\n strict_required_status_checks_policy: desired.require_branches_up_to_date ?? false,\n },\n };\n}\n\n// =============================================================================\n// Tag Protection (GitHub Rulesets API)\n// =============================================================================\n\n/** Apply tag protection ruleset to GitHub */\nexport async function applyTagProtection(\n repoInfo: RepoInfo,\n desired: DesiredTagProtection,\n diffResult: TagProtectionDiffResult\n): Promise<SyncResult> {\n if (!diffResult.hasChanges) {\n return { success: true, applied: [], failed: [] };\n }\n\n const requestBody = buildTagRulesetBody(desired);\n\n try {\n if (diffResult.currentRulesetId === null) {\n // Create new ruleset\n await execa(\n \"gh\",\n [\"api\", `repos/${repoInfo.owner}/${repoInfo.repo}/rulesets`, \"-X\", \"POST\", \"--input\", \"-\"],\n { input: JSON.stringify(requestBody) }\n );\n } else {\n // Update existing ruleset\n await execa(\n \"gh\",\n [\n \"api\",\n `repos/${repoInfo.owner}/${repoInfo.repo}/rulesets/${diffResult.currentRulesetId}`,\n \"-X\",\n \"PUT\",\n \"--input\",\n \"-\",\n ],\n { input: JSON.stringify(requestBody) }\n );\n }\n\n return { success: true, applied: diffResult.diffs, failed: [] };\n } catch (error) {\n return handleTagApplyError(error, diffResult.diffs);\n }\n}\n\n/** Build GitHub API request body for tag ruleset */\nfunction buildTagRulesetBody(desired: DesiredTagProtection): Record<string, unknown> {\n const rules: { type: string }[] = [];\n\n // Default to true if not specified\n if (desired.prevent_deletion !== false) {\n rules.push({ type: \"deletion\" });\n }\n if (desired.prevent_update !== false) {\n rules.push({ type: \"update\" });\n }\n\n const patterns = desired.patterns ?? [\"v*\"];\n const includePatterns = patterns.map((p) => `refs/tags/${p}`);\n\n return {\n name: \"Tag Protection\",\n target: \"tag\",\n enforcement: \"active\",\n conditions: {\n ref_name: {\n include: includePatterns,\n exclude: [],\n },\n },\n rules,\n };\n}\n\n/** Handle errors from applying tag protection */\nfunction handleTagApplyError(error: unknown, diffs: SettingDiff[]): SyncResult {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (errorMessage.includes(\"403\") || errorMessage.includes(\"Must have admin rights\")) {\n throw new ApplierError(\n \"Cannot update tag protection: insufficient permissions (requires admin access)\",\n \"NO_PERMISSION\"\n );\n }\n\n return {\n success: false,\n applied: [],\n failed: diffs.map((diff) => ({ diff, error: errorMessage })),\n };\n}\n","import {\n type BranchProtectionSettings,\n type BypassActor,\n type DesiredBranchProtection,\n type DesiredTagProtection,\n type RepoInfo,\n type SettingDiff,\n type SyncDiffResult,\n type TagProtectionDiffResult,\n type TagProtectionSettings,\n} from \"./types.js\";\n\n/** Field mapping for comparison */\ninterface FieldMapping {\n name: string;\n getCurrentValue: (c: BranchProtectionSettings) => unknown;\n getDesiredValue: (d: DesiredBranchProtection) => unknown;\n isArray?: boolean;\n}\n\n/** All field mappings for branch protection settings */\nconst fieldMappings: FieldMapping[] = [\n {\n name: \"required_reviews\",\n getCurrentValue: (c) => c.requiredReviews,\n getDesiredValue: (d) => d.required_reviews,\n },\n {\n name: \"dismiss_stale_reviews\",\n getCurrentValue: (c) => c.dismissStaleReviews,\n getDesiredValue: (d) => d.dismiss_stale_reviews,\n },\n {\n name: \"require_code_owner_reviews\",\n getCurrentValue: (c) => c.requireCodeOwnerReviews,\n getDesiredValue: (d) => d.require_code_owner_reviews,\n },\n {\n name: \"require_status_checks\",\n getCurrentValue: (c) => c.requiredStatusChecks,\n getDesiredValue: (d) => d.require_status_checks,\n isArray: true,\n },\n {\n name: \"require_branches_up_to_date\",\n getCurrentValue: (c) => c.requireBranchesUpToDate,\n getDesiredValue: (d) => d.require_branches_up_to_date,\n },\n {\n name: \"require_signed_commits\",\n getCurrentValue: (c) => c.requireSignedCommits,\n getDesiredValue: (d) => d.require_signed_commits,\n },\n {\n name: \"enforce_admins\",\n getCurrentValue: (c) => c.enforceAdmins,\n getDesiredValue: (d) => d.enforce_admins,\n },\n];\n\n/** Compare current settings with desired and generate diffs */\nexport function computeDiff(\n repoInfo: RepoInfo,\n current: BranchProtectionSettings,\n desired: DesiredBranchProtection\n): SyncDiffResult {\n const diffs = collectDiffs(current, desired);\n\n // Add bypass_actors diff\n const bypassDiff = compareBypassActors(\n current.bypassActors,\n desired.bypass_actors,\n current.rulesetId\n );\n if (bypassDiff) {\n diffs.push(bypassDiff);\n }\n\n return {\n repoInfo,\n branch: current.branch,\n diffs,\n hasChanges: diffs.length > 0,\n currentRulesetId: current.rulesetId,\n };\n}\n\n/** Collect all diffs between current and desired settings */\nfunction collectDiffs(\n current: BranchProtectionSettings,\n desired: DesiredBranchProtection\n): SettingDiff[] {\n const diffs: SettingDiff[] = [];\n\n for (const mapping of fieldMappings) {\n const desiredValue = mapping.getDesiredValue(desired);\n if (desiredValue === undefined) {\n continue;\n }\n\n const currentValue = mapping.getCurrentValue(current);\n const diff = mapping.isArray\n ? compareArrayValue(mapping.name, currentValue as string[] | null, desiredValue as string[])\n : compareValue(mapping.name, currentValue, desiredValue);\n\n if (diff) {\n diffs.push(diff);\n }\n }\n\n return diffs;\n}\n\n/** Compare a single value and return diff if different */\nfunction compareValue(setting: string, current: unknown, desired: unknown): SettingDiff | null {\n const currentValue = current ?? null;\n if (currentValue === desired) {\n return null;\n }\n\n return {\n setting,\n current: currentValue,\n desired,\n action: currentValue === null ? \"add\" : \"change\",\n };\n}\n\n/** Compare arrays and return diff if different */\nfunction compareArrayValue(\n setting: string,\n current: string[] | null,\n desired: string[]\n): SettingDiff | null {\n const currentArray = current ?? [];\n const sortedCurrent = [...currentArray].sort();\n const sortedDesired = [...desired].sort();\n\n const areEqual =\n sortedCurrent.length === sortedDesired.length &&\n sortedCurrent.every((v, i) => v === sortedDesired[i]);\n\n if (areEqual) {\n return null;\n }\n\n return {\n setting,\n current: currentArray,\n desired,\n action: currentArray.length === 0 ? \"add\" : \"change\",\n };\n}\n\n/** Compare bypass actors arrays */\nfunction compareBypassActors(\n current: BypassActor[] | null,\n desired: BypassActor[] | undefined,\n rulesetId: number | null\n): SettingDiff | null {\n if (desired === undefined) {\n return null;\n }\n\n const currentActors = current ?? [];\n\n // Normalize and sort for comparison\n const sortKey = (a: BypassActor): string =>\n `${a.actor_type}:${a.actor_id ?? \"\"}:${a.bypass_mode ?? \"always\"}`;\n\n const sortedCurrent = [...currentActors].sort((a, b) => sortKey(a).localeCompare(sortKey(b)));\n const sortedDesired = [...desired].sort((a, b) => sortKey(a).localeCompare(sortKey(b)));\n\n // Normalize bypass_mode defaults for comparison\n const normalize = (actors: BypassActor[]): BypassActor[] =>\n actors.map((a) => ({\n actor_type: a.actor_type,\n actor_id: a.actor_id,\n bypass_mode: a.bypass_mode ?? \"always\",\n }));\n\n const normalizedCurrent = normalize(sortedCurrent);\n const normalizedDesired = normalize(sortedDesired);\n\n const areEqual =\n normalizedCurrent.length === normalizedDesired.length &&\n normalizedCurrent.every(\n (c, i) =>\n c.actor_type === normalizedDesired[i].actor_type &&\n c.actor_id === normalizedDesired[i].actor_id &&\n c.bypass_mode === normalizedDesired[i].bypass_mode\n );\n\n if (areEqual) {\n return null;\n }\n\n return {\n setting: \"bypass_actors\",\n current: currentActors,\n desired,\n action: rulesetId === null ? \"add\" : \"change\",\n };\n}\n\n/** Format a value for display */\nexport function formatValue(value: unknown): string {\n if (value === null || value === undefined) {\n return \"not set\";\n }\n if (Array.isArray(value)) {\n return value.length === 0 ? \"[]\" : `[${value.join(\", \")}]`;\n }\n return String(value);\n}\n\n// =============================================================================\n// Tag Protection Diff\n// =============================================================================\n\n/** Compare current tag protection with desired and generate diffs */\nexport function computeTagDiff(\n repoInfo: RepoInfo,\n current: TagProtectionSettings,\n desired: DesiredTagProtection\n): TagProtectionDiffResult {\n const diffs: SettingDiff[] = [];\n const rulesetId = current.rulesetId;\n\n collectPatternDiff(diffs, current, desired);\n collectBooleanDiff(diffs, {\n s: \"prevent_deletion\",\n c: current.preventDeletion,\n d: desired.prevent_deletion,\n r: rulesetId,\n });\n collectBooleanDiff(diffs, {\n s: \"prevent_update\",\n c: current.preventUpdate,\n d: desired.prevent_update,\n r: rulesetId,\n });\n\n return { repoInfo, diffs, hasChanges: diffs.length > 0, currentRulesetId: rulesetId };\n}\n\n/** Collect pattern diff if patterns don't match */\nfunction collectPatternDiff(\n diffs: SettingDiff[],\n current: TagProtectionSettings,\n desired: DesiredTagProtection\n): void {\n if (desired.patterns === undefined) {\n return;\n }\n const curr = [...current.patterns].sort();\n const des = [...desired.patterns].sort();\n const match = curr.length === des.length && curr.every((v, i) => v === des[i]);\n if (!match) {\n diffs.push({\n setting: \"patterns\",\n current: current.patterns,\n desired: desired.patterns,\n action: curr.length === 0 ? \"add\" : \"change\",\n });\n }\n}\n\n/** Collect boolean setting diff (s=setting, c=current, d=desired, r=rulesetId) */\nfunction collectBooleanDiff(\n diffs: SettingDiff[],\n o: { s: string; c: boolean; d: boolean | undefined; r: number | null }\n): void {\n if (o.d !== undefined && o.c !== o.d) {\n diffs.push({\n setting: o.s,\n current: o.c,\n desired: o.d,\n action: o.r === null ? \"add\" : \"change\",\n });\n }\n}\n","import { execa } from \"execa\";\n\nimport {\n type BranchProtectionSettings,\n type BypassActor,\n type GitHubRuleset,\n type GitHubRulesetBypassActor,\n type RepoInfo,\n type TagProtectionSettings,\n} from \"./types.js\";\n\n/** Error thrown when fetcher encounters an issue */\nexport class FetcherError extends Error {\n constructor(\n message: string,\n public readonly code: \"NO_GH\" | \"NO_REPO\" | \"NO_PERMISSION\" | \"API_ERROR\"\n ) {\n super(message);\n this.name = \"FetcherError\";\n }\n}\n\n/** Check if gh CLI is available */\nexport async function isGhAvailable(): Promise<boolean> {\n try {\n await execa(\"gh\", [\"--version\"]);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Get repository info from git remote */\nexport async function getRepoInfo(projectRoot: string): Promise<RepoInfo> {\n try {\n const result = await execa(\"gh\", [\"repo\", \"view\", \"--json\", \"owner,name\"], {\n cwd: projectRoot,\n });\n const data = JSON.parse(result.stdout) as { owner: { login: string }; name: string };\n return { owner: data.owner.login, repo: data.name };\n } catch {\n throw new FetcherError(\"Could not determine GitHub repository from git remote\", \"NO_REPO\");\n }\n}\n\n/** Fetch current branch protection settings from GitHub Rulesets */\nexport async function fetchBranchProtection(\n repoInfo: RepoInfo,\n branch: string\n): Promise<BranchProtectionSettings> {\n try {\n const result = await execa(\"gh\", [\"api\", `repos/${repoInfo.owner}/${repoInfo.repo}/rulesets`]);\n\n const rulesets = JSON.parse(result.stdout) as GitHubRuleset[];\n return parseBranchRuleset(rulesets, branch);\n } catch (error) {\n return handleBranchFetchError(error, branch);\n }\n}\n\n/** Handle errors from fetching branch protection */\nfunction handleBranchFetchError(error: unknown, branch: string): BranchProtectionSettings {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n // 404 means no rulesets exist - return empty settings\n if (errorMessage.includes(\"404\")) {\n return createEmptySettings(branch);\n }\n\n if (errorMessage.includes(\"403\") || errorMessage.includes(\"Must have admin rights\")) {\n throw new FetcherError(\n \"Cannot read branch protection: insufficient permissions (requires admin access)\",\n \"NO_PERMISSION\"\n );\n }\n\n throw new FetcherError(`Failed to fetch branch protection: ${errorMessage}`, \"API_ERROR\");\n}\n\n/** Find and parse the branch protection ruleset */\n// eslint-disable-next-line complexity\nfunction parseBranchRuleset(rulesets: GitHubRuleset[], branch: string): BranchProtectionSettings {\n // Find ruleset targeting branches that includes the specified branch\n const branchRuleset = rulesets.find(\n (r) =>\n r.target === \"branch\" &&\n r.enforcement === \"active\" &&\n matchesBranch(r.conditions?.ref_name?.include ?? [], branch)\n );\n\n if (!branchRuleset) {\n return createEmptySettings(branch);\n }\n\n const rules = branchRuleset.rules ?? [];\n const prRule = rules.find((r) => r.type === \"pull_request\");\n const statusRule = rules.find((r) => r.type === \"required_status_checks\");\n const signaturesRule = rules.find((r) => r.type === \"required_signatures\");\n\n // Parse bypass actors\n const bypassActors = parseBypassActors(branchRuleset.bypass_actors);\n\n // enforceAdmins is true when there are no bypass actors\n const enforceAdmins = bypassActors === null || bypassActors.length === 0;\n\n return {\n branch,\n requiredReviews: prRule?.parameters?.required_approving_review_count ?? null,\n dismissStaleReviews: prRule?.parameters?.dismiss_stale_reviews_on_push ?? null,\n requireCodeOwnerReviews: prRule?.parameters?.require_code_owner_review ?? null,\n requiredStatusChecks:\n statusRule?.parameters?.required_status_checks?.map((c) => c.context) ?? null,\n requireBranchesUpToDate: statusRule?.parameters?.strict_required_status_checks_policy ?? null,\n requireSignedCommits: signaturesRule !== undefined,\n enforceAdmins,\n bypassActors,\n rulesetId: branchRuleset.id,\n rulesetName: branchRuleset.name,\n };\n}\n\n/** Check if branch matches any of the include patterns */\nfunction matchesBranch(patterns: string[], branch: string): boolean {\n for (const pattern of patterns) {\n const cleanPattern = pattern.replace(/^refs\\/heads\\//, \"\");\n if (cleanPattern === branch) {\n return true;\n }\n if (cleanPattern === \"~DEFAULT_BRANCH\" && branch === \"main\") {\n return true;\n }\n if (cleanPattern === \"~ALL\") {\n return true;\n }\n // Simple wildcard matching for patterns like \"release/*\"\n if (cleanPattern.includes(\"*\")) {\n const regex = new RegExp(`^${cleanPattern.replace(/\\*/g, \".*\")}$`);\n if (regex.test(branch)) {\n return true;\n }\n }\n }\n return false;\n}\n\n/** Parse bypass actors from GitHub API response */\nfunction parseBypassActors(actors: GitHubRulesetBypassActor[] | undefined): BypassActor[] | null {\n if (!actors || actors.length === 0) {\n return null;\n }\n\n return actors.map((actor) => ({\n actor_type: actor.actor_type,\n actor_id: actor.actor_id ?? undefined,\n bypass_mode: actor.bypass_mode,\n }));\n}\n\n/** Create empty settings for unprotected branch */\nfunction createEmptySettings(branch: string): BranchProtectionSettings {\n return {\n branch,\n requiredReviews: null,\n dismissStaleReviews: null,\n requireCodeOwnerReviews: null,\n requiredStatusChecks: null,\n requireBranchesUpToDate: null,\n requireSignedCommits: null,\n enforceAdmins: null,\n bypassActors: null,\n rulesetId: null,\n rulesetName: null,\n };\n}\n\n// =============================================================================\n// Tag Protection (GitHub Rulesets API)\n// =============================================================================\n\n/** Fetch current tag protection rulesets from GitHub */\nexport async function fetchTagProtection(repoInfo: RepoInfo): Promise<TagProtectionSettings> {\n try {\n const result = await execa(\"gh\", [\"api\", `repos/${repoInfo.owner}/${repoInfo.repo}/rulesets`]);\n\n const rulesets = JSON.parse(result.stdout) as GitHubRuleset[];\n return parseTagRuleset(rulesets);\n } catch (error) {\n return handleTagFetchError(error);\n }\n}\n\n/** Find and parse the tag protection ruleset */\nfunction parseTagRuleset(rulesets: GitHubRuleset[]): TagProtectionSettings {\n // Find existing tag protection ruleset (by target type and name)\n const tagRuleset = rulesets.find((r) => r.target === \"tag\" && r.name === \"Tag Protection\");\n\n if (!tagRuleset) {\n return createEmptyTagSettings();\n }\n\n const patterns =\n tagRuleset.conditions?.ref_name?.include?.map((p) => p.replace(/^refs\\/tags\\//, \"\")) ?? [];\n\n const rules = tagRuleset.rules ?? [];\n const preventDeletion = rules.some((r) => r.type === \"deletion\");\n const preventUpdate = rules.some((r) => r.type === \"update\");\n\n return {\n patterns,\n preventDeletion,\n preventUpdate,\n rulesetId: tagRuleset.id,\n rulesetName: tagRuleset.name,\n };\n}\n\n/** Create empty settings when no tag ruleset exists */\nfunction createEmptyTagSettings(): TagProtectionSettings {\n return {\n patterns: [],\n preventDeletion: false,\n preventUpdate: false,\n rulesetId: null,\n rulesetName: null,\n };\n}\n\n/** Handle errors from fetching tag protection */\nfunction handleTagFetchError(error: unknown): TagProtectionSettings {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n // 404 means no rulesets exist - return empty settings\n if (errorMessage.includes(\"404\")) {\n return createEmptyTagSettings();\n }\n\n if (errorMessage.includes(\"403\") || errorMessage.includes(\"Must have admin rights\")) {\n throw new FetcherError(\n \"Cannot read tag protection: insufficient permissions (requires admin access)\",\n \"NO_PERMISSION\"\n );\n }\n\n throw new FetcherError(`Failed to fetch tag protection: ${errorMessage}`, \"API_ERROR\");\n}\n","import { getProjectRoot, loadConfig } from \"@standards-kit/core\";\nimport { ApplierError, applyBranchProtection, applyTagProtection } from \"./applier.js\";\nimport { computeDiff, computeTagDiff, formatValue } from \"./differ.js\";\nimport {\n fetchBranchProtection,\n FetcherError,\n fetchTagProtection,\n getRepoInfo,\n isGhAvailable,\n} from \"./fetcher.js\";\nimport {\n type SyncDiffResult,\n type SyncOptions,\n type SyncResult,\n type TagProtectionDiffResult,\n} from \"./types.js\";\n\n/** Helper to write to stdout */\nfunction writeLine(text: string): void {\n process.stdout.write(`${text}\\n`);\n}\n\n/** Run diff command - show what would change */\nexport async function runDiff(options: SyncOptions): Promise<void> {\n try {\n const diffResult = await getDiffResult(options);\n outputDiff(diffResult, options.format);\n process.exit(diffResult.hasChanges ? 1 : 0);\n } catch (error) {\n handleError(error, options.format);\n }\n}\n\n/** Run sync command - apply changes (or preview if --apply not set) */\n// eslint-disable-next-line max-statements\nexport async function runSync(options: SyncOptions): Promise<void> {\n try {\n const diffResult = await getDiffResult(options);\n\n if (!diffResult.hasChanges) {\n outputNoChanges(diffResult, options.format);\n process.exit(0);\n }\n\n // Validate actors if requested\n if (options.validateActors) {\n const validationPassed = await validateActorsBeforeApply(options);\n if (!validationPassed) {\n process.exit(1);\n }\n }\n\n if (!options.apply) {\n outputPreview(diffResult, options.format);\n process.exit(0);\n }\n\n const result = await applyChanges(options, diffResult);\n outputSyncResult(diffResult, result, options.format);\n process.exit(result.success ? 0 : 1);\n } catch (error) {\n handleError(error, options.format);\n }\n}\n\n/** Apply changes to GitHub */\nasync function applyChanges(options: SyncOptions, diffResult: SyncDiffResult): Promise<SyncResult> {\n const { config } = loadConfig(options.config);\n const projectRoot = getProjectRoot(loadConfig(options.config).configPath);\n const repoInfo = await getRepoInfo(projectRoot);\n const desired = config.process?.repo?.ruleset ?? {};\n\n return applyBranchProtection(repoInfo, diffResult.branch, desired, diffResult);\n}\n\n/** Validate bypass actors before applying changes */\nasync function validateActorsBeforeApply(options: SyncOptions): Promise<boolean> {\n const { validateBypassActors, formatValidationResult } = await import(\"./validator.js\");\n const { config } = loadConfig(options.config);\n const projectRoot = getProjectRoot(loadConfig(options.config).configPath);\n const repoInfo = await getRepoInfo(projectRoot);\n\n const rulesetConfig = config.process?.repo?.ruleset;\n const actors = rulesetConfig?.bypass_actors ?? [];\n\n if (actors.length === 0) {\n return true;\n }\n\n const result = await validateBypassActors(repoInfo, actors);\n\n if (options.format === \"json\") {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n } else {\n process.stdout.write(`${formatValidationResult(result)}\\n`);\n }\n\n return result.valid;\n}\n\n/** Get the diff result (shared by diff and sync) */\nasync function getDiffResult(options: SyncOptions): Promise<SyncDiffResult> {\n if (!(await isGhAvailable())) {\n throw new FetcherError(\"GitHub CLI (gh) not available\", \"NO_GH\");\n }\n\n const { config, configPath } = loadConfig(options.config);\n const projectRoot = getProjectRoot(configPath);\n const repoInfo = await getRepoInfo(projectRoot);\n\n const repoConfig = config.process?.repo;\n const desired = repoConfig?.ruleset;\n if (!desired) {\n throw new Error(\"No [process.repo.ruleset] configured in standards.toml\");\n }\n const branch = getBranch(desired.branch);\n const current = await fetchBranchProtection(repoInfo, branch);\n\n return computeDiff(repoInfo, current, desired);\n}\n\n/** Get branch name with default */\nfunction getBranch(configuredBranch: string | undefined): string {\n return configuredBranch ?? \"main\";\n}\n\n/** Output diff result */\nfunction outputDiff(result: SyncDiffResult, format: \"text\" | \"json\"): void {\n if (format === \"json\") {\n writeLine(JSON.stringify(result, null, 2));\n } else {\n outputDiffText(result);\n }\n}\n\n/** Output diff in text format */\nfunction outputDiffText(result: SyncDiffResult): void {\n writeRepoHeader(result);\n\n if (!result.hasChanges) {\n writeLine(\"No changes needed. Settings match configuration.\");\n return;\n }\n\n writeDiffTable(result);\n writeLine(\"\");\n writeLine(\n `${result.diffs.length} setting(s) differ. Run 'conform process sync --apply' to apply changes.`\n );\n}\n\n/** Write repository header */\nfunction writeRepoHeader(result: SyncDiffResult): void {\n writeLine(`Repository: ${result.repoInfo.owner}/${result.repoInfo.repo}`);\n writeLine(`Branch: ${result.branch}`);\n writeLine(\"\");\n}\n\n/** Write diff table */\nfunction writeDiffTable(result: SyncDiffResult): void {\n const settingWidth = Math.max(...result.diffs.map((d) => d.setting.length), 7);\n const currentWidth = Math.max(...result.diffs.map((d) => formatValue(d.current).length), 7);\n\n writeLine(`${\"Setting\".padEnd(settingWidth)} ${\"Current\".padEnd(currentWidth)} Desired`);\n writeLine(\"-\".repeat(settingWidth + currentWidth + 20));\n\n for (const diff of result.diffs) {\n const currentStr = formatValue(diff.current);\n const desiredStr = formatValue(diff.desired);\n writeLine(\n `${diff.setting.padEnd(settingWidth)} ${currentStr.padEnd(currentWidth)} ${desiredStr}`\n );\n }\n}\n\n/** Output when no changes are needed */\nfunction outputNoChanges(result: SyncDiffResult, format: \"text\" | \"json\"): void {\n if (format === \"json\") {\n writeLine(JSON.stringify({ ...result, message: \"No changes needed\" }, null, 2));\n } else {\n writeRepoHeader(result);\n writeLine(\"No changes needed. Settings match configuration.\");\n }\n}\n\n/** Output preview (sync without --apply) */\nfunction outputPreview(result: SyncDiffResult, format: \"text\" | \"json\"): void {\n if (format === \"json\") {\n writeLine(JSON.stringify({ ...result, preview: true }, null, 2));\n } else {\n writeRepoHeader(result);\n writeLine(\"Would apply the following changes:\");\n for (const diff of result.diffs) {\n writeLine(` ${diff.setting}: ${formatValue(diff.current)} -> ${formatValue(diff.desired)}`);\n }\n writeLine(\"\");\n writeLine(\"Run with --apply to make these changes.\");\n }\n}\n\n/** Output sync result */\nfunction outputSyncResult(\n diffResult: SyncDiffResult,\n result: SyncResult,\n format: \"text\" | \"json\"\n): void {\n if (format === \"json\") {\n writeLine(\n JSON.stringify(\n { repoInfo: diffResult.repoInfo, branch: diffResult.branch, ...result },\n null,\n 2\n )\n );\n } else {\n outputSyncResultText(diffResult, result);\n }\n}\n\n/** Output sync result in text format */\nfunction outputSyncResultText(diffResult: SyncDiffResult, result: SyncResult): void {\n writeRepoHeader(diffResult);\n writeLine(\"Applying changes...\");\n\n for (const diff of result.applied) {\n writeLine(` + ${diff.setting}: ${formatValue(diff.current)} -> ${formatValue(diff.desired)}`);\n }\n\n for (const { diff, error } of result.failed) {\n writeLine(` x ${diff.setting}: ${error}`);\n }\n\n writeLine(\"\");\n if (result.success) {\n writeLine(`+ ${result.applied.length} setting(s) synchronized successfully.`);\n } else {\n writeLine(`x ${result.failed.length} setting(s) failed to sync.`);\n }\n}\n\n/** Handle errors */\nfunction handleError(error: unknown, format: \"text\" | \"json\"): void {\n const { message, code } = extractErrorInfo(error);\n\n if (format === \"json\") {\n writeLine(JSON.stringify({ error: true, code, message }, null, 2));\n } else {\n writeLine(`Error: ${message}`);\n }\n\n process.exit(2);\n}\n\n/** Extract error message and code */\nfunction extractErrorInfo(error: unknown): { message: string; code: string } {\n if (error instanceof FetcherError) {\n return { message: error.message, code: error.code };\n }\n if (error instanceof ApplierError) {\n return { message: error.message, code: error.code };\n }\n if (error instanceof Error) {\n return { message: error.message, code: \"ERROR\" };\n }\n return { message: String(error), code: \"ERROR\" };\n}\n\n// =============================================================================\n// Tag Protection Sync\n// =============================================================================\n\n/** Run tag protection diff command - show what would change */\nexport async function runTagDiff(options: SyncOptions): Promise<void> {\n try {\n const diffResult = await getTagDiffResult(options);\n outputTagDiff(diffResult, options.format);\n process.exit(diffResult.hasChanges ? 1 : 0);\n } catch (error) {\n handleError(error, options.format);\n }\n}\n\n/** Run tag protection sync command - apply changes (or preview if --apply not set) */\nexport async function runTagSync(options: SyncOptions): Promise<void> {\n try {\n const diffResult = await getTagDiffResult(options);\n\n if (!diffResult.hasChanges) {\n outputTagNoChanges(diffResult, options.format);\n process.exit(0);\n }\n\n if (!options.apply) {\n outputTagPreview(diffResult, options.format);\n process.exit(0);\n }\n\n const result = await applyTagChanges(options, diffResult);\n outputTagSyncResult(diffResult, result, options.format);\n process.exit(result.success ? 0 : 1);\n } catch (error) {\n handleError(error, options.format);\n }\n}\n\n/** Get the tag diff result */\nasync function getTagDiffResult(options: SyncOptions): Promise<TagProtectionDiffResult> {\n if (!(await isGhAvailable())) {\n throw new FetcherError(\"GitHub CLI (gh) not available\", \"NO_GH\");\n }\n\n const { config, configPath } = loadConfig(options.config);\n const projectRoot = getProjectRoot(configPath);\n const repoInfo = await getRepoInfo(projectRoot);\n\n const repoConfig = config.process?.repo;\n if (!repoConfig?.tag_protection?.patterns || repoConfig.tag_protection.patterns.length === 0) {\n throw new Error(\"No [process.repo.tag_protection] patterns configured in standards.toml\");\n }\n\n const desired = repoConfig.tag_protection;\n const current = await fetchTagProtection(repoInfo);\n\n return computeTagDiff(repoInfo, current, desired);\n}\n\n/** Apply tag protection changes to GitHub */\nasync function applyTagChanges(\n options: SyncOptions,\n diffResult: TagProtectionDiffResult\n): Promise<SyncResult> {\n const { config } = loadConfig(options.config);\n const desired = config.process?.repo?.tag_protection ?? {};\n\n return applyTagProtection(diffResult.repoInfo, desired, diffResult);\n}\n\n/** Output tag diff result */\nfunction outputTagDiff(result: TagProtectionDiffResult, format: \"text\" | \"json\"): void {\n if (format === \"json\") {\n writeLine(JSON.stringify(result, null, 2));\n } else {\n outputTagDiffText(result);\n }\n}\n\n/** Output tag diff in text format */\nfunction outputTagDiffText(result: TagProtectionDiffResult): void {\n writeTagRepoHeader(result);\n\n if (!result.hasChanges) {\n writeLine(\"No changes needed. Tag protection settings match configuration.\");\n return;\n }\n\n writeTagDiffTable(result);\n writeLine(\"\");\n writeLine(\n `${result.diffs.length} setting(s) differ. Run 'conform process sync-tags --apply' to apply changes.`\n );\n}\n\n/** Write tag repository header */\nfunction writeTagRepoHeader(result: TagProtectionDiffResult): void {\n writeLine(`Repository: ${result.repoInfo.owner}/${result.repoInfo.repo}`);\n writeLine(`Target: Tag Protection Ruleset`);\n writeLine(\"\");\n}\n\n/** Write tag diff table */\nfunction writeTagDiffTable(result: TagProtectionDiffResult): void {\n const settingWidth = Math.max(...result.diffs.map((d) => d.setting.length), 7);\n const currentWidth = Math.max(...result.diffs.map((d) => formatValue(d.current).length), 7);\n\n writeLine(`${\"Setting\".padEnd(settingWidth)} ${\"Current\".padEnd(currentWidth)} Desired`);\n writeLine(\"-\".repeat(settingWidth + currentWidth + 20));\n\n for (const diff of result.diffs) {\n const currentStr = formatValue(diff.current);\n const desiredStr = formatValue(diff.desired);\n writeLine(\n `${diff.setting.padEnd(settingWidth)} ${currentStr.padEnd(currentWidth)} ${desiredStr}`\n );\n }\n}\n\n/** Output when no tag changes are needed */\nfunction outputTagNoChanges(result: TagProtectionDiffResult, format: \"text\" | \"json\"): void {\n if (format === \"json\") {\n writeLine(JSON.stringify({ ...result, message: \"No changes needed\" }, null, 2));\n } else {\n writeTagRepoHeader(result);\n writeLine(\"No changes needed. Tag protection settings match configuration.\");\n }\n}\n\n/** Output tag preview (sync without --apply) */\nfunction outputTagPreview(result: TagProtectionDiffResult, format: \"text\" | \"json\"): void {\n if (format === \"json\") {\n writeLine(JSON.stringify({ ...result, preview: true }, null, 2));\n } else {\n writeTagRepoHeader(result);\n writeLine(\"Would apply the following changes:\");\n for (const diff of result.diffs) {\n writeLine(` ${diff.setting}: ${formatValue(diff.current)} -> ${formatValue(diff.desired)}`);\n }\n writeLine(\"\");\n writeLine(\"Run with --apply to make these changes.\");\n }\n}\n\n/** Output tag sync result */\nfunction outputTagSyncResult(\n diffResult: TagProtectionDiffResult,\n result: SyncResult,\n format: \"text\" | \"json\"\n): void {\n if (format === \"json\") {\n writeLine(JSON.stringify({ repoInfo: diffResult.repoInfo, ...result }, null, 2));\n } else {\n outputTagSyncResultText(diffResult, result);\n }\n}\n\n/** Output tag sync result in text format */\nfunction outputTagSyncResultText(diffResult: TagProtectionDiffResult, result: SyncResult): void {\n writeTagRepoHeader(diffResult);\n writeLine(\"Applying tag protection changes...\");\n\n for (const diff of result.applied) {\n writeLine(` + ${diff.setting}: ${formatValue(diff.current)} -> ${formatValue(diff.desired)}`);\n }\n\n for (const { diff, error } of result.failed) {\n writeLine(` x ${diff.setting}: ${error}`);\n }\n\n writeLine(\"\");\n if (result.success) {\n writeLine(`+ ${result.applied.length} setting(s) synchronized successfully.`);\n } else {\n writeLine(`x ${result.failed.length} setting(s) failed to sync.`);\n }\n}\n"],"mappings":"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","names":["execa"]}
|
|
1
|
+
{"version":3,"sources":["../src/process/sync/applier.ts","../src/process/sync/differ.ts","../src/process/sync/fetcher.ts","../src/process/sync/index.ts"],"sourcesContent":["import { execa } from \"execa\";\n\nimport {\n type DesiredBranchProtection,\n type DesiredTagProtection,\n type RepoInfo,\n type SettingDiff,\n type SyncDiffResult,\n type SyncResult,\n type TagProtectionDiffResult,\n} from \"./types.js\";\n\n/** Error thrown when applier encounters an issue */\nexport class ApplierError extends Error {\n constructor(\n message: string,\n public readonly code: \"NO_PERMISSION\" | \"API_ERROR\"\n ) {\n super(message);\n this.name = \"ApplierError\";\n }\n}\n\n/** Apply branch protection ruleset to GitHub */\nexport async function applyBranchProtection(\n repoInfo: RepoInfo,\n branch: string,\n desired: DesiredBranchProtection,\n diffResult: SyncDiffResult\n): Promise<SyncResult> {\n if (!diffResult.hasChanges) {\n return { success: true, applied: [], failed: [] };\n }\n\n const requestBody = buildBranchRulesetBody(branch, desired);\n\n try {\n if (diffResult.currentRulesetId === null) {\n // Create new ruleset\n await execa(\n \"gh\",\n [\"api\", `repos/${repoInfo.owner}/${repoInfo.repo}/rulesets`, \"-X\", \"POST\", \"--input\", \"-\"],\n { input: JSON.stringify(requestBody) }\n );\n } else {\n // Update existing ruleset\n await execa(\n \"gh\",\n [\n \"api\",\n `repos/${repoInfo.owner}/${repoInfo.repo}/rulesets/${diffResult.currentRulesetId}`,\n \"-X\",\n \"PUT\",\n \"--input\",\n \"-\",\n ],\n { input: JSON.stringify(requestBody) }\n );\n }\n\n return { success: true, applied: diffResult.diffs, failed: [] };\n } catch (error) {\n return handleBranchApplyError(error, diffResult.diffs);\n }\n}\n\n/** Handle errors from applying branch protection */\nfunction handleBranchApplyError(error: unknown, diffs: SettingDiff[]): SyncResult {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (errorMessage.includes(\"403\") || errorMessage.includes(\"Must have admin rights\")) {\n throw new ApplierError(\n \"Cannot update branch protection: insufficient permissions (requires admin access)\",\n \"NO_PERMISSION\"\n );\n }\n\n return {\n success: false,\n applied: [],\n failed: diffs.map((diff) => ({ diff, error: errorMessage })),\n };\n}\n\n/** Build GitHub API request body for branch ruleset */\nfunction buildBranchRulesetBody(\n branch: string,\n desired: DesiredBranchProtection\n): Record<string, unknown> {\n const rules: { type: string; parameters?: Record<string, unknown> }[] = [];\n\n // Build pull_request rule if any review settings specified\n const pullRequestRule = buildPullRequestRule(desired);\n if (pullRequestRule) {\n rules.push(pullRequestRule);\n }\n\n // Build required_status_checks rule\n const statusChecksRule = buildStatusChecksRule(desired);\n if (statusChecksRule) {\n rules.push(statusChecksRule);\n }\n\n // Build required_signatures rule\n if (desired.require_signed_commits === true) {\n rules.push({ type: \"required_signatures\" });\n }\n\n // Build bypass actors array\n const bypassActors =\n desired.bypass_actors?.map((actor) => ({\n actor_id: actor.actor_id ?? null,\n actor_type: actor.actor_type,\n bypass_mode: actor.bypass_mode ?? \"always\",\n })) ?? [];\n\n return {\n name: \"Branch Protection\",\n target: \"branch\",\n enforcement: \"active\",\n conditions: {\n ref_name: {\n include: [`refs/heads/${branch}`],\n exclude: [],\n },\n },\n bypass_actors: bypassActors,\n rules,\n };\n}\n\n/** Build pull_request rule for PR review settings */\nfunction buildPullRequestRule(\n desired: DesiredBranchProtection\n): { type: string; parameters: Record<string, unknown> } | null {\n const hasReviewSettings =\n desired.required_reviews !== undefined ||\n desired.dismiss_stale_reviews !== undefined ||\n desired.require_code_owner_reviews !== undefined;\n\n if (!hasReviewSettings) {\n return null;\n }\n\n return {\n type: \"pull_request\",\n parameters: {\n ...(desired.required_reviews !== undefined && {\n required_approving_review_count: desired.required_reviews,\n }),\n ...(desired.dismiss_stale_reviews !== undefined && {\n dismiss_stale_reviews_on_push: desired.dismiss_stale_reviews,\n }),\n ...(desired.require_code_owner_reviews !== undefined && {\n require_code_owner_review: desired.require_code_owner_reviews,\n }),\n },\n };\n}\n\n/** Build required_status_checks rule for status check settings */\nfunction buildStatusChecksRule(\n desired: DesiredBranchProtection\n): { type: string; parameters: Record<string, unknown> } | null {\n const hasStatusSettings =\n desired.require_status_checks !== undefined ||\n desired.require_branches_up_to_date !== undefined;\n\n if (!hasStatusSettings) {\n return null;\n }\n\n const statusChecks =\n desired.require_status_checks?.map((context) => ({\n context,\n })) ?? [];\n\n return {\n type: \"required_status_checks\",\n parameters: {\n required_status_checks: statusChecks,\n strict_required_status_checks_policy: desired.require_branches_up_to_date ?? false,\n },\n };\n}\n\n// =============================================================================\n// Tag Protection (GitHub Rulesets API)\n// =============================================================================\n\n/** Apply tag protection ruleset to GitHub */\nexport async function applyTagProtection(\n repoInfo: RepoInfo,\n desired: DesiredTagProtection,\n diffResult: TagProtectionDiffResult\n): Promise<SyncResult> {\n if (!diffResult.hasChanges) {\n return { success: true, applied: [], failed: [] };\n }\n\n const requestBody = buildTagRulesetBody(desired);\n\n try {\n if (diffResult.currentRulesetId === null) {\n // Create new ruleset\n await execa(\n \"gh\",\n [\"api\", `repos/${repoInfo.owner}/${repoInfo.repo}/rulesets`, \"-X\", \"POST\", \"--input\", \"-\"],\n { input: JSON.stringify(requestBody) }\n );\n } else {\n // Update existing ruleset\n await execa(\n \"gh\",\n [\n \"api\",\n `repos/${repoInfo.owner}/${repoInfo.repo}/rulesets/${diffResult.currentRulesetId}`,\n \"-X\",\n \"PUT\",\n \"--input\",\n \"-\",\n ],\n { input: JSON.stringify(requestBody) }\n );\n }\n\n return { success: true, applied: diffResult.diffs, failed: [] };\n } catch (error) {\n return handleTagApplyError(error, diffResult.diffs);\n }\n}\n\n/** Build GitHub API request body for tag ruleset */\nfunction buildTagRulesetBody(desired: DesiredTagProtection): Record<string, unknown> {\n const rules: { type: string }[] = [];\n\n // Default to true if not specified\n if (desired.prevent_deletion !== false) {\n rules.push({ type: \"deletion\" });\n }\n if (desired.prevent_update !== false) {\n rules.push({ type: \"update\" });\n }\n\n const patterns = desired.patterns ?? [\"v*\"];\n const includePatterns = patterns.map((p) => `refs/tags/${p}`);\n\n return {\n name: \"Tag Protection\",\n target: \"tag\",\n enforcement: \"active\",\n conditions: {\n ref_name: {\n include: includePatterns,\n exclude: [],\n },\n },\n rules,\n };\n}\n\n/** Handle errors from applying tag protection */\nfunction handleTagApplyError(error: unknown, diffs: SettingDiff[]): SyncResult {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n if (errorMessage.includes(\"403\") || errorMessage.includes(\"Must have admin rights\")) {\n throw new ApplierError(\n \"Cannot update tag protection: insufficient permissions (requires admin access)\",\n \"NO_PERMISSION\"\n );\n }\n\n return {\n success: false,\n applied: [],\n failed: diffs.map((diff) => ({ diff, error: errorMessage })),\n };\n}\n","import {\n type BranchProtectionSettings,\n type BypassActor,\n type DesiredBranchProtection,\n type DesiredTagProtection,\n type RepoInfo,\n type SettingDiff,\n type SyncDiffResult,\n type TagProtectionDiffResult,\n type TagProtectionSettings,\n} from \"./types.js\";\n\n/** Field mapping for comparison */\ninterface FieldMapping {\n name: string;\n getCurrentValue: (c: BranchProtectionSettings) => unknown;\n getDesiredValue: (d: DesiredBranchProtection) => unknown;\n isArray?: boolean;\n}\n\n/** All field mappings for branch protection settings */\nconst fieldMappings: FieldMapping[] = [\n {\n name: \"required_reviews\",\n getCurrentValue: (c) => c.requiredReviews,\n getDesiredValue: (d) => d.required_reviews,\n },\n {\n name: \"dismiss_stale_reviews\",\n getCurrentValue: (c) => c.dismissStaleReviews,\n getDesiredValue: (d) => d.dismiss_stale_reviews,\n },\n {\n name: \"require_code_owner_reviews\",\n getCurrentValue: (c) => c.requireCodeOwnerReviews,\n getDesiredValue: (d) => d.require_code_owner_reviews,\n },\n {\n name: \"require_status_checks\",\n getCurrentValue: (c) => c.requiredStatusChecks,\n getDesiredValue: (d) => d.require_status_checks,\n isArray: true,\n },\n {\n name: \"require_branches_up_to_date\",\n getCurrentValue: (c) => c.requireBranchesUpToDate,\n getDesiredValue: (d) => d.require_branches_up_to_date,\n },\n {\n name: \"require_signed_commits\",\n getCurrentValue: (c) => c.requireSignedCommits,\n getDesiredValue: (d) => d.require_signed_commits,\n },\n {\n name: \"enforce_admins\",\n getCurrentValue: (c) => c.enforceAdmins,\n getDesiredValue: (d) => d.enforce_admins,\n },\n];\n\n/** Compare current settings with desired and generate diffs */\nexport function computeDiff(\n repoInfo: RepoInfo,\n current: BranchProtectionSettings,\n desired: DesiredBranchProtection\n): SyncDiffResult {\n const diffs = collectDiffs(current, desired);\n\n // Add bypass_actors diff\n const bypassDiff = compareBypassActors(\n current.bypassActors,\n desired.bypass_actors,\n current.rulesetId\n );\n if (bypassDiff) {\n diffs.push(bypassDiff);\n }\n\n return {\n repoInfo,\n branch: current.branch,\n diffs,\n hasChanges: diffs.length > 0,\n currentRulesetId: current.rulesetId,\n };\n}\n\n/** Collect all diffs between current and desired settings */\nfunction collectDiffs(\n current: BranchProtectionSettings,\n desired: DesiredBranchProtection\n): SettingDiff[] {\n const diffs: SettingDiff[] = [];\n\n for (const mapping of fieldMappings) {\n const desiredValue = mapping.getDesiredValue(desired);\n if (desiredValue === undefined) {\n continue;\n }\n\n const currentValue = mapping.getCurrentValue(current);\n const diff = mapping.isArray\n ? compareArrayValue(mapping.name, currentValue as string[] | null, desiredValue as string[])\n : compareValue(mapping.name, currentValue, desiredValue);\n\n if (diff) {\n diffs.push(diff);\n }\n }\n\n return diffs;\n}\n\n/** Compare a single value and return diff if different */\nfunction compareValue(setting: string, current: unknown, desired: unknown): SettingDiff | null {\n const currentValue = current ?? null;\n if (currentValue === desired) {\n return null;\n }\n\n return {\n setting,\n current: currentValue,\n desired,\n action: currentValue === null ? \"add\" : \"change\",\n };\n}\n\n/** Compare arrays and return diff if different */\nfunction compareArrayValue(\n setting: string,\n current: string[] | null,\n desired: string[]\n): SettingDiff | null {\n const currentArray = current ?? [];\n const sortedCurrent = [...currentArray].sort();\n const sortedDesired = [...desired].sort();\n\n const areEqual =\n sortedCurrent.length === sortedDesired.length &&\n sortedCurrent.every((v, i) => v === sortedDesired[i]);\n\n if (areEqual) {\n return null;\n }\n\n return {\n setting,\n current: currentArray,\n desired,\n action: currentArray.length === 0 ? \"add\" : \"change\",\n };\n}\n\n/** Compare bypass actors arrays */\nfunction compareBypassActors(\n current: BypassActor[] | null,\n desired: BypassActor[] | undefined,\n rulesetId: number | null\n): SettingDiff | null {\n if (desired === undefined) {\n return null;\n }\n\n const currentActors = current ?? [];\n\n // Normalize and sort for comparison\n const sortKey = (a: BypassActor): string =>\n `${a.actor_type}:${a.actor_id ?? \"\"}:${a.bypass_mode ?? \"always\"}`;\n\n const sortedCurrent = [...currentActors].sort((a, b) => sortKey(a).localeCompare(sortKey(b)));\n const sortedDesired = [...desired].sort((a, b) => sortKey(a).localeCompare(sortKey(b)));\n\n // Normalize bypass_mode defaults for comparison\n const normalize = (actors: BypassActor[]): BypassActor[] =>\n actors.map((a) => ({\n actor_type: a.actor_type,\n actor_id: a.actor_id,\n bypass_mode: a.bypass_mode ?? \"always\",\n }));\n\n const normalizedCurrent = normalize(sortedCurrent);\n const normalizedDesired = normalize(sortedDesired);\n\n const areEqual =\n normalizedCurrent.length === normalizedDesired.length &&\n normalizedCurrent.every(\n (c, i) =>\n c.actor_type === normalizedDesired[i].actor_type &&\n c.actor_id === normalizedDesired[i].actor_id &&\n c.bypass_mode === normalizedDesired[i].bypass_mode\n );\n\n if (areEqual) {\n return null;\n }\n\n return {\n setting: \"bypass_actors\",\n current: currentActors,\n desired,\n action: rulesetId === null ? \"add\" : \"change\",\n };\n}\n\n/** Format a value for display */\nexport function formatValue(value: unknown): string {\n if (value === null || value === undefined) {\n return \"not set\";\n }\n if (Array.isArray(value)) {\n return value.length === 0 ? \"[]\" : `[${value.join(\", \")}]`;\n }\n return String(value);\n}\n\n// =============================================================================\n// Tag Protection Diff\n// =============================================================================\n\n/** Compare current tag protection with desired and generate diffs */\nexport function computeTagDiff(\n repoInfo: RepoInfo,\n current: TagProtectionSettings,\n desired: DesiredTagProtection\n): TagProtectionDiffResult {\n const diffs: SettingDiff[] = [];\n const rulesetId = current.rulesetId;\n\n collectPatternDiff(diffs, current, desired);\n collectBooleanDiff(diffs, {\n s: \"prevent_deletion\",\n c: current.preventDeletion,\n d: desired.prevent_deletion,\n r: rulesetId,\n });\n collectBooleanDiff(diffs, {\n s: \"prevent_update\",\n c: current.preventUpdate,\n d: desired.prevent_update,\n r: rulesetId,\n });\n\n return { repoInfo, diffs, hasChanges: diffs.length > 0, currentRulesetId: rulesetId };\n}\n\n/** Collect pattern diff if patterns don't match */\nfunction collectPatternDiff(\n diffs: SettingDiff[],\n current: TagProtectionSettings,\n desired: DesiredTagProtection\n): void {\n if (desired.patterns === undefined) {\n return;\n }\n const curr = [...current.patterns].sort();\n const des = [...desired.patterns].sort();\n const match = curr.length === des.length && curr.every((v, i) => v === des[i]);\n if (!match) {\n diffs.push({\n setting: \"patterns\",\n current: current.patterns,\n desired: desired.patterns,\n action: curr.length === 0 ? \"add\" : \"change\",\n });\n }\n}\n\n/** Collect boolean setting diff (s=setting, c=current, d=desired, r=rulesetId) */\nfunction collectBooleanDiff(\n diffs: SettingDiff[],\n o: { s: string; c: boolean; d: boolean | undefined; r: number | null }\n): void {\n if (o.d !== undefined && o.c !== o.d) {\n diffs.push({\n setting: o.s,\n current: o.c,\n desired: o.d,\n action: o.r === null ? \"add\" : \"change\",\n });\n }\n}\n","import { execa } from \"execa\";\n\nimport {\n type BranchProtectionSettings,\n type BypassActor,\n type GitHubRuleset,\n type GitHubRulesetBypassActor,\n type RepoInfo,\n type TagProtectionSettings,\n} from \"./types.js\";\n\n/** Error thrown when fetcher encounters an issue */\nexport class FetcherError extends Error {\n constructor(\n message: string,\n public readonly code: \"NO_GH\" | \"NO_REPO\" | \"NO_PERMISSION\" | \"API_ERROR\"\n ) {\n super(message);\n this.name = \"FetcherError\";\n }\n}\n\n/** Check if gh CLI is available */\nexport async function isGhAvailable(): Promise<boolean> {\n try {\n await execa(\"gh\", [\"--version\"]);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Get repository info from git remote */\nexport async function getRepoInfo(projectRoot: string): Promise<RepoInfo> {\n try {\n const result = await execa(\"gh\", [\"repo\", \"view\", \"--json\", \"owner,name\"], {\n cwd: projectRoot,\n });\n const data = JSON.parse(result.stdout) as { owner: { login: string }; name: string };\n return { owner: data.owner.login, repo: data.name };\n } catch {\n throw new FetcherError(\"Could not determine GitHub repository from git remote\", \"NO_REPO\");\n }\n}\n\n/** Fetch current branch protection settings from GitHub Rulesets */\nexport async function fetchBranchProtection(\n repoInfo: RepoInfo,\n branch: string\n): Promise<BranchProtectionSettings> {\n try {\n const result = await execa(\"gh\", [\"api\", `repos/${repoInfo.owner}/${repoInfo.repo}/rulesets`]);\n\n const rulesets = JSON.parse(result.stdout) as GitHubRuleset[];\n return parseBranchRuleset(rulesets, branch);\n } catch (error) {\n return handleBranchFetchError(error, branch);\n }\n}\n\n/** Handle errors from fetching branch protection */\nfunction handleBranchFetchError(error: unknown, branch: string): BranchProtectionSettings {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n // 404 means no rulesets exist - return empty settings\n if (errorMessage.includes(\"404\")) {\n return createEmptySettings(branch);\n }\n\n if (errorMessage.includes(\"403\") || errorMessage.includes(\"Must have admin rights\")) {\n throw new FetcherError(\n \"Cannot read branch protection: insufficient permissions (requires admin access)\",\n \"NO_PERMISSION\"\n );\n }\n\n throw new FetcherError(`Failed to fetch branch protection: ${errorMessage}`, \"API_ERROR\");\n}\n\n/** Find and parse the branch protection ruleset */\n// eslint-disable-next-line complexity\nfunction parseBranchRuleset(rulesets: GitHubRuleset[], branch: string): BranchProtectionSettings {\n // Find ruleset targeting branches that includes the specified branch\n const branchRuleset = rulesets.find(\n (r) =>\n r.target === \"branch\" &&\n r.enforcement === \"active\" &&\n matchesBranch(r.conditions?.ref_name?.include ?? [], branch)\n );\n\n if (!branchRuleset) {\n return createEmptySettings(branch);\n }\n\n const rules = branchRuleset.rules ?? [];\n const prRule = rules.find((r) => r.type === \"pull_request\");\n const statusRule = rules.find((r) => r.type === \"required_status_checks\");\n const signaturesRule = rules.find((r) => r.type === \"required_signatures\");\n\n // Parse bypass actors\n const bypassActors = parseBypassActors(branchRuleset.bypass_actors);\n\n // enforceAdmins is true when there are no bypass actors\n const enforceAdmins = bypassActors === null || bypassActors.length === 0;\n\n return {\n branch,\n requiredReviews: prRule?.parameters?.required_approving_review_count ?? null,\n dismissStaleReviews: prRule?.parameters?.dismiss_stale_reviews_on_push ?? null,\n requireCodeOwnerReviews: prRule?.parameters?.require_code_owner_review ?? null,\n requiredStatusChecks:\n statusRule?.parameters?.required_status_checks?.map((c) => c.context) ?? null,\n requireBranchesUpToDate: statusRule?.parameters?.strict_required_status_checks_policy ?? null,\n requireSignedCommits: signaturesRule !== undefined,\n enforceAdmins,\n bypassActors,\n rulesetId: branchRuleset.id,\n rulesetName: branchRuleset.name,\n };\n}\n\n/** Check if branch matches any of the include patterns */\nfunction matchesBranch(patterns: string[], branch: string): boolean {\n for (const pattern of patterns) {\n const cleanPattern = pattern.replace(/^refs\\/heads\\//, \"\");\n if (cleanPattern === branch) {\n return true;\n }\n if (cleanPattern === \"~DEFAULT_BRANCH\" && branch === \"main\") {\n return true;\n }\n if (cleanPattern === \"~ALL\") {\n return true;\n }\n // Simple wildcard matching for patterns like \"release/*\"\n if (cleanPattern.includes(\"*\")) {\n const regex = new RegExp(`^${cleanPattern.replace(/\\*/g, \".*\")}$`);\n if (regex.test(branch)) {\n return true;\n }\n }\n }\n return false;\n}\n\n/** Parse bypass actors from GitHub API response */\nfunction parseBypassActors(actors: GitHubRulesetBypassActor[] | undefined): BypassActor[] | null {\n if (!actors || actors.length === 0) {\n return null;\n }\n\n return actors.map((actor) => ({\n actor_type: actor.actor_type,\n actor_id: actor.actor_id ?? undefined,\n bypass_mode: actor.bypass_mode,\n }));\n}\n\n/** Create empty settings for unprotected branch */\nfunction createEmptySettings(branch: string): BranchProtectionSettings {\n return {\n branch,\n requiredReviews: null,\n dismissStaleReviews: null,\n requireCodeOwnerReviews: null,\n requiredStatusChecks: null,\n requireBranchesUpToDate: null,\n requireSignedCommits: null,\n enforceAdmins: null,\n bypassActors: null,\n rulesetId: null,\n rulesetName: null,\n };\n}\n\n// =============================================================================\n// Tag Protection (GitHub Rulesets API)\n// =============================================================================\n\n/** Fetch current tag protection rulesets from GitHub */\nexport async function fetchTagProtection(repoInfo: RepoInfo): Promise<TagProtectionSettings> {\n try {\n const result = await execa(\"gh\", [\"api\", `repos/${repoInfo.owner}/${repoInfo.repo}/rulesets`]);\n\n const rulesets = JSON.parse(result.stdout) as GitHubRuleset[];\n return parseTagRuleset(rulesets);\n } catch (error) {\n return handleTagFetchError(error);\n }\n}\n\n/** Find and parse the tag protection ruleset */\nfunction parseTagRuleset(rulesets: GitHubRuleset[]): TagProtectionSettings {\n // Find existing tag protection ruleset (by target type and name)\n const tagRuleset = rulesets.find((r) => r.target === \"tag\" && r.name === \"Tag Protection\");\n\n if (!tagRuleset) {\n return createEmptyTagSettings();\n }\n\n const patterns =\n tagRuleset.conditions?.ref_name?.include?.map((p) => p.replace(/^refs\\/tags\\//, \"\")) ?? [];\n\n const rules = tagRuleset.rules ?? [];\n const preventDeletion = rules.some((r) => r.type === \"deletion\");\n const preventUpdate = rules.some((r) => r.type === \"update\");\n\n return {\n patterns,\n preventDeletion,\n preventUpdate,\n rulesetId: tagRuleset.id,\n rulesetName: tagRuleset.name,\n };\n}\n\n/** Create empty settings when no tag ruleset exists */\nfunction createEmptyTagSettings(): TagProtectionSettings {\n return {\n patterns: [],\n preventDeletion: false,\n preventUpdate: false,\n rulesetId: null,\n rulesetName: null,\n };\n}\n\n/** Handle errors from fetching tag protection */\nfunction handleTagFetchError(error: unknown): TagProtectionSettings {\n const errorMessage = error instanceof Error ? error.message : String(error);\n\n // 404 means no rulesets exist - return empty settings\n if (errorMessage.includes(\"404\")) {\n return createEmptyTagSettings();\n }\n\n if (errorMessage.includes(\"403\") || errorMessage.includes(\"Must have admin rights\")) {\n throw new FetcherError(\n \"Cannot read tag protection: insufficient permissions (requires admin access)\",\n \"NO_PERMISSION\"\n );\n }\n\n throw new FetcherError(`Failed to fetch tag protection: ${errorMessage}`, \"API_ERROR\");\n}\n","import { getProjectRoot, loadConfig } from \"../../core/index.js\";\nimport { ApplierError, applyBranchProtection, applyTagProtection } from \"./applier.js\";\nimport { computeDiff, computeTagDiff, formatValue } from \"./differ.js\";\nimport {\n fetchBranchProtection,\n FetcherError,\n fetchTagProtection,\n getRepoInfo,\n isGhAvailable,\n} from \"./fetcher.js\";\nimport {\n type SyncDiffResult,\n type SyncOptions,\n type SyncResult,\n type TagProtectionDiffResult,\n} from \"./types.js\";\n\n/** Helper to write to stdout */\nfunction writeLine(text: string): void {\n process.stdout.write(`${text}\\n`);\n}\n\n/** Run diff command - show what would change */\nexport async function runDiff(options: SyncOptions): Promise<void> {\n try {\n const diffResult = await getDiffResult(options);\n outputDiff(diffResult, options.format);\n process.exit(diffResult.hasChanges ? 1 : 0);\n } catch (error) {\n handleError(error, options.format);\n }\n}\n\n/** Run sync command - apply changes (or preview if --apply not set) */\n// eslint-disable-next-line max-statements\nexport async function runSync(options: SyncOptions): Promise<void> {\n try {\n const diffResult = await getDiffResult(options);\n\n if (!diffResult.hasChanges) {\n outputNoChanges(diffResult, options.format);\n process.exit(0);\n }\n\n // Validate actors if requested\n if (options.validateActors) {\n const validationPassed = await validateActorsBeforeApply(options);\n if (!validationPassed) {\n process.exit(1);\n }\n }\n\n if (!options.apply) {\n outputPreview(diffResult, options.format);\n process.exit(0);\n }\n\n const result = await applyChanges(options, diffResult);\n outputSyncResult(diffResult, result, options.format);\n process.exit(result.success ? 0 : 1);\n } catch (error) {\n handleError(error, options.format);\n }\n}\n\n/** Apply changes to GitHub */\nasync function applyChanges(options: SyncOptions, diffResult: SyncDiffResult): Promise<SyncResult> {\n const { config } = loadConfig(options.config);\n const projectRoot = getProjectRoot(loadConfig(options.config).configPath);\n const repoInfo = await getRepoInfo(projectRoot);\n const desired = config.process?.repo?.ruleset ?? {};\n\n return applyBranchProtection(repoInfo, diffResult.branch, desired, diffResult);\n}\n\n/** Validate bypass actors before applying changes */\nasync function validateActorsBeforeApply(options: SyncOptions): Promise<boolean> {\n const { validateBypassActors, formatValidationResult } = await import(\"./validator.js\");\n const { config } = loadConfig(options.config);\n const projectRoot = getProjectRoot(loadConfig(options.config).configPath);\n const repoInfo = await getRepoInfo(projectRoot);\n\n const rulesetConfig = config.process?.repo?.ruleset;\n const actors = rulesetConfig?.bypass_actors ?? [];\n\n if (actors.length === 0) {\n return true;\n }\n\n const result = await validateBypassActors(repoInfo, actors);\n\n if (options.format === \"json\") {\n process.stdout.write(`${JSON.stringify(result, null, 2)}\\n`);\n } else {\n process.stdout.write(`${formatValidationResult(result)}\\n`);\n }\n\n return result.valid;\n}\n\n/** Get the diff result (shared by diff and sync) */\nasync function getDiffResult(options: SyncOptions): Promise<SyncDiffResult> {\n if (!(await isGhAvailable())) {\n throw new FetcherError(\"GitHub CLI (gh) not available\", \"NO_GH\");\n }\n\n const { config, configPath } = loadConfig(options.config);\n const projectRoot = getProjectRoot(configPath);\n const repoInfo = await getRepoInfo(projectRoot);\n\n const repoConfig = config.process?.repo;\n const desired = repoConfig?.ruleset;\n if (!desired) {\n throw new Error(\"No [process.repo.ruleset] configured in standards.toml\");\n }\n const branch = getBranch(desired.branch);\n const current = await fetchBranchProtection(repoInfo, branch);\n\n return computeDiff(repoInfo, current, desired);\n}\n\n/** Get branch name with default */\nfunction getBranch(configuredBranch: string | undefined): string {\n return configuredBranch ?? \"main\";\n}\n\n/** Output diff result */\nfunction outputDiff(result: SyncDiffResult, format: \"text\" | \"json\"): void {\n if (format === \"json\") {\n writeLine(JSON.stringify(result, null, 2));\n } else {\n outputDiffText(result);\n }\n}\n\n/** Output diff in text format */\nfunction outputDiffText(result: SyncDiffResult): void {\n writeRepoHeader(result);\n\n if (!result.hasChanges) {\n writeLine(\"No changes needed. Settings match configuration.\");\n return;\n }\n\n writeDiffTable(result);\n writeLine(\"\");\n writeLine(\n `${result.diffs.length} setting(s) differ. Run 'conform process sync --apply' to apply changes.`\n );\n}\n\n/** Write repository header */\nfunction writeRepoHeader(result: SyncDiffResult): void {\n writeLine(`Repository: ${result.repoInfo.owner}/${result.repoInfo.repo}`);\n writeLine(`Branch: ${result.branch}`);\n writeLine(\"\");\n}\n\n/** Write diff table */\nfunction writeDiffTable(result: SyncDiffResult): void {\n const settingWidth = Math.max(...result.diffs.map((d) => d.setting.length), 7);\n const currentWidth = Math.max(...result.diffs.map((d) => formatValue(d.current).length), 7);\n\n writeLine(`${\"Setting\".padEnd(settingWidth)} ${\"Current\".padEnd(currentWidth)} Desired`);\n writeLine(\"-\".repeat(settingWidth + currentWidth + 20));\n\n for (const diff of result.diffs) {\n const currentStr = formatValue(diff.current);\n const desiredStr = formatValue(diff.desired);\n writeLine(\n `${diff.setting.padEnd(settingWidth)} ${currentStr.padEnd(currentWidth)} ${desiredStr}`\n );\n }\n}\n\n/** Output when no changes are needed */\nfunction outputNoChanges(result: SyncDiffResult, format: \"text\" | \"json\"): void {\n if (format === \"json\") {\n writeLine(JSON.stringify({ ...result, message: \"No changes needed\" }, null, 2));\n } else {\n writeRepoHeader(result);\n writeLine(\"No changes needed. Settings match configuration.\");\n }\n}\n\n/** Output preview (sync without --apply) */\nfunction outputPreview(result: SyncDiffResult, format: \"text\" | \"json\"): void {\n if (format === \"json\") {\n writeLine(JSON.stringify({ ...result, preview: true }, null, 2));\n } else {\n writeRepoHeader(result);\n writeLine(\"Would apply the following changes:\");\n for (const diff of result.diffs) {\n writeLine(` ${diff.setting}: ${formatValue(diff.current)} -> ${formatValue(diff.desired)}`);\n }\n writeLine(\"\");\n writeLine(\"Run with --apply to make these changes.\");\n }\n}\n\n/** Output sync result */\nfunction outputSyncResult(\n diffResult: SyncDiffResult,\n result: SyncResult,\n format: \"text\" | \"json\"\n): void {\n if (format === \"json\") {\n writeLine(\n JSON.stringify(\n { repoInfo: diffResult.repoInfo, branch: diffResult.branch, ...result },\n null,\n 2\n )\n );\n } else {\n outputSyncResultText(diffResult, result);\n }\n}\n\n/** Output sync result in text format */\nfunction outputSyncResultText(diffResult: SyncDiffResult, result: SyncResult): void {\n writeRepoHeader(diffResult);\n writeLine(\"Applying changes...\");\n\n for (const diff of result.applied) {\n writeLine(` + ${diff.setting}: ${formatValue(diff.current)} -> ${formatValue(diff.desired)}`);\n }\n\n for (const { diff, error } of result.failed) {\n writeLine(` x ${diff.setting}: ${error}`);\n }\n\n writeLine(\"\");\n if (result.success) {\n writeLine(`+ ${result.applied.length} setting(s) synchronized successfully.`);\n } else {\n writeLine(`x ${result.failed.length} setting(s) failed to sync.`);\n }\n}\n\n/** Handle errors */\nfunction handleError(error: unknown, format: \"text\" | \"json\"): void {\n const { message, code } = extractErrorInfo(error);\n\n if (format === \"json\") {\n writeLine(JSON.stringify({ error: true, code, message }, null, 2));\n } else {\n writeLine(`Error: ${message}`);\n }\n\n process.exit(2);\n}\n\n/** Extract error message and code */\nfunction extractErrorInfo(error: unknown): { message: string; code: string } {\n if (error instanceof FetcherError) {\n return { message: error.message, code: error.code };\n }\n if (error instanceof ApplierError) {\n return { message: error.message, code: error.code };\n }\n if (error instanceof Error) {\n return { message: error.message, code: \"ERROR\" };\n }\n return { message: String(error), code: \"ERROR\" };\n}\n\n// =============================================================================\n// Tag Protection Sync\n// =============================================================================\n\n/** Run tag protection diff command - show what would change */\nexport async function runTagDiff(options: SyncOptions): Promise<void> {\n try {\n const diffResult = await getTagDiffResult(options);\n outputTagDiff(diffResult, options.format);\n process.exit(diffResult.hasChanges ? 1 : 0);\n } catch (error) {\n handleError(error, options.format);\n }\n}\n\n/** Run tag protection sync command - apply changes (or preview if --apply not set) */\nexport async function runTagSync(options: SyncOptions): Promise<void> {\n try {\n const diffResult = await getTagDiffResult(options);\n\n if (!diffResult.hasChanges) {\n outputTagNoChanges(diffResult, options.format);\n process.exit(0);\n }\n\n if (!options.apply) {\n outputTagPreview(diffResult, options.format);\n process.exit(0);\n }\n\n const result = await applyTagChanges(options, diffResult);\n outputTagSyncResult(diffResult, result, options.format);\n process.exit(result.success ? 0 : 1);\n } catch (error) {\n handleError(error, options.format);\n }\n}\n\n/** Get the tag diff result */\nasync function getTagDiffResult(options: SyncOptions): Promise<TagProtectionDiffResult> {\n if (!(await isGhAvailable())) {\n throw new FetcherError(\"GitHub CLI (gh) not available\", \"NO_GH\");\n }\n\n const { config, configPath } = loadConfig(options.config);\n const projectRoot = getProjectRoot(configPath);\n const repoInfo = await getRepoInfo(projectRoot);\n\n const repoConfig = config.process?.repo;\n if (!repoConfig?.tag_protection?.patterns || repoConfig.tag_protection.patterns.length === 0) {\n throw new Error(\"No [process.repo.tag_protection] patterns configured in standards.toml\");\n }\n\n const desired = repoConfig.tag_protection;\n const current = await fetchTagProtection(repoInfo);\n\n return computeTagDiff(repoInfo, current, desired);\n}\n\n/** Apply tag protection changes to GitHub */\nasync function applyTagChanges(\n options: SyncOptions,\n diffResult: TagProtectionDiffResult\n): Promise<SyncResult> {\n const { config } = loadConfig(options.config);\n const desired = config.process?.repo?.tag_protection ?? {};\n\n return applyTagProtection(diffResult.repoInfo, desired, diffResult);\n}\n\n/** Output tag diff result */\nfunction outputTagDiff(result: TagProtectionDiffResult, format: \"text\" | \"json\"): void {\n if (format === \"json\") {\n writeLine(JSON.stringify(result, null, 2));\n } else {\n outputTagDiffText(result);\n }\n}\n\n/** Output tag diff in text format */\nfunction outputTagDiffText(result: TagProtectionDiffResult): void {\n writeTagRepoHeader(result);\n\n if (!result.hasChanges) {\n writeLine(\"No changes needed. Tag protection settings match configuration.\");\n return;\n }\n\n writeTagDiffTable(result);\n writeLine(\"\");\n writeLine(\n `${result.diffs.length} setting(s) differ. Run 'conform process sync-tags --apply' to apply changes.`\n );\n}\n\n/** Write tag repository header */\nfunction writeTagRepoHeader(result: TagProtectionDiffResult): void {\n writeLine(`Repository: ${result.repoInfo.owner}/${result.repoInfo.repo}`);\n writeLine(`Target: Tag Protection Ruleset`);\n writeLine(\"\");\n}\n\n/** Write tag diff table */\nfunction writeTagDiffTable(result: TagProtectionDiffResult): void {\n const settingWidth = Math.max(...result.diffs.map((d) => d.setting.length), 7);\n const currentWidth = Math.max(...result.diffs.map((d) => formatValue(d.current).length), 7);\n\n writeLine(`${\"Setting\".padEnd(settingWidth)} ${\"Current\".padEnd(currentWidth)} Desired`);\n writeLine(\"-\".repeat(settingWidth + currentWidth + 20));\n\n for (const diff of result.diffs) {\n const currentStr = formatValue(diff.current);\n const desiredStr = formatValue(diff.desired);\n writeLine(\n `${diff.setting.padEnd(settingWidth)} ${currentStr.padEnd(currentWidth)} ${desiredStr}`\n );\n }\n}\n\n/** Output when no tag changes are needed */\nfunction outputTagNoChanges(result: TagProtectionDiffResult, format: \"text\" | \"json\"): void {\n if (format === \"json\") {\n writeLine(JSON.stringify({ ...result, message: \"No changes needed\" }, null, 2));\n } else {\n writeTagRepoHeader(result);\n writeLine(\"No changes needed. Tag protection settings match configuration.\");\n }\n}\n\n/** Output tag preview (sync without --apply) */\nfunction outputTagPreview(result: TagProtectionDiffResult, format: \"text\" | \"json\"): void {\n if (format === \"json\") {\n writeLine(JSON.stringify({ ...result, preview: true }, null, 2));\n } else {\n writeTagRepoHeader(result);\n writeLine(\"Would apply the following changes:\");\n for (const diff of result.diffs) {\n writeLine(` ${diff.setting}: ${formatValue(diff.current)} -> ${formatValue(diff.desired)}`);\n }\n writeLine(\"\");\n writeLine(\"Run with --apply to make these changes.\");\n }\n}\n\n/** Output tag sync result */\nfunction outputTagSyncResult(\n diffResult: TagProtectionDiffResult,\n result: SyncResult,\n format: \"text\" | \"json\"\n): void {\n if (format === \"json\") {\n writeLine(JSON.stringify({ repoInfo: diffResult.repoInfo, ...result }, null, 2));\n } else {\n outputTagSyncResultText(diffResult, result);\n }\n}\n\n/** Output tag sync result in text format */\nfunction outputTagSyncResultText(diffResult: TagProtectionDiffResult, result: SyncResult): void {\n writeTagRepoHeader(diffResult);\n writeLine(\"Applying tag protection changes...\");\n\n for (const diff of result.applied) {\n writeLine(` + ${diff.setting}: ${formatValue(diff.current)} -> ${formatValue(diff.desired)}`);\n }\n\n for (const { diff, error } of result.failed) {\n writeLine(` x ${diff.setting}: ${error}`);\n }\n\n writeLine(\"\");\n if (result.success) {\n writeLine(`+ ${result.applied.length} setting(s) synchronized successfully.`);\n } else {\n writeLine(`x ${result.failed.length} setting(s) failed to sync.`);\n }\n}\n"],"mappings":"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","names":["execa"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** Single file validation error */
|
|
2
|
+
export interface GuidelineValidationError {
|
|
3
|
+
file: string;
|
|
4
|
+
errors: string[];
|
|
5
|
+
}
|
|
6
|
+
/** Overall validation result */
|
|
7
|
+
export interface GuidelineValidationResult {
|
|
8
|
+
valid: boolean;
|
|
9
|
+
validCount: number;
|
|
10
|
+
invalidCount: number;
|
|
11
|
+
errors: GuidelineValidationError[];
|
|
12
|
+
}
|
|
13
|
+
/** Validate a directory of guideline files */
|
|
14
|
+
export declare function validateGuidelinesDir(dirPath: string): GuidelineValidationResult;
|
|
15
|
+
/** Run the validate guidelines command */
|
|
16
|
+
export declare function runValidateGuidelines(dirPath: string, options: {
|
|
17
|
+
format: string;
|
|
18
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { runValidateGuidelines, validateGuidelinesDir } from "./guidelines.js";
|
|
2
|
+
export type { GuidelineValidationError, GuidelineValidationResult } from "./guidelines.js";
|
|
3
|
+
export { formatTierResultJson, formatTierResultText, validateTierRuleset } from "./tier.js";
|
|
4
|
+
export type { Tier, TierSourceDetail, ValidateTierOptions, ValidateTierResult, } from "./types.js";
|
|
5
|
+
export { VALID_TIERS } from "./types.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ValidateTierOptions, type ValidateTierResult } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Validate that project tier matches its rulesets.
|
|
4
|
+
* This is the programmatic API exported for library consumers.
|
|
5
|
+
*
|
|
6
|
+
* Tier is loaded from standards.toml [metadata].tier
|
|
7
|
+
* Defaults to "internal" if not specified
|
|
8
|
+
*/
|
|
9
|
+
export declare function validateTierRuleset(options?: ValidateTierOptions): ValidateTierResult;
|
|
10
|
+
/**
|
|
11
|
+
* Format tier validation result as text
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatTierResultText(result: ValidateTierResult): string;
|
|
14
|
+
/**
|
|
15
|
+
* Format tier validation result as JSON
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatTierResultJson(result: ValidateTierResult): string;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Valid project tiers
|
|
3
|
+
*/
|
|
4
|
+
export type Tier = "production" | "internal" | "prototype";
|
|
5
|
+
/**
|
|
6
|
+
* Valid tier values as a constant array for validation and export
|
|
7
|
+
*/
|
|
8
|
+
export declare const VALID_TIERS: readonly Tier[];
|
|
9
|
+
/**
|
|
10
|
+
* Detailed tier source indicating why a default was used
|
|
11
|
+
*/
|
|
12
|
+
export type TierSourceDetail = "standards.toml" | "default" | "default (file not found)" | "default (no metadata)" | "default (tier not specified)" | "default (invalid value)";
|
|
13
|
+
/**
|
|
14
|
+
* Options for the tier validation command
|
|
15
|
+
*/
|
|
16
|
+
export interface ValidateTierOptions {
|
|
17
|
+
/** Path to standards.toml config file */
|
|
18
|
+
config?: string;
|
|
19
|
+
/** Output format */
|
|
20
|
+
format?: "text" | "json";
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Result of tier validation
|
|
24
|
+
*/
|
|
25
|
+
export interface ValidateTierResult {
|
|
26
|
+
/** Whether validation passed */
|
|
27
|
+
valid: boolean;
|
|
28
|
+
/** Project tier from standards.toml [metadata] (defaults to "internal") */
|
|
29
|
+
tier: Tier;
|
|
30
|
+
/** Source of tier value */
|
|
31
|
+
tierSource: "standards.toml" | "default";
|
|
32
|
+
/** Detailed source of tier value with reason for default */
|
|
33
|
+
tierSourceDetail?: TierSourceDetail;
|
|
34
|
+
/** Rulesets from standards.toml extends section */
|
|
35
|
+
rulesets: string[];
|
|
36
|
+
/** Expected ruleset suffix pattern */
|
|
37
|
+
expectedPattern: string;
|
|
38
|
+
/** Matched rulesets (those that satisfy the tier requirement) */
|
|
39
|
+
matchedRulesets: string[];
|
|
40
|
+
/** Error message if invalid */
|
|
41
|
+
error?: string;
|
|
42
|
+
/** Invalid tier value that was rejected (for error messages) */
|
|
43
|
+
invalidTierValue?: string;
|
|
44
|
+
/** Whether extends is configured but has empty rulesets */
|
|
45
|
+
hasEmptyRulesets?: boolean;
|
|
46
|
+
/** Registry URL if extends is configured */
|
|
47
|
+
registryUrl?: string;
|
|
48
|
+
/** Warnings about configuration */
|
|
49
|
+
warnings?: string[];
|
|
50
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
frontmatterSchema
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NADY2H35.js";
|
|
4
4
|
import {
|
|
5
5
|
ExitCode
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-DXIYZR62.js";
|
|
7
7
|
import {
|
|
8
|
-
findConfigFile
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
findConfigFile
|
|
9
|
+
} from "./chunk-YGDEM6K5.js";
|
|
10
|
+
import "./chunk-RHM53NLG.js";
|
|
11
11
|
|
|
12
12
|
// src/validate/guidelines.ts
|
|
13
13
|
import * as fs from "fs";
|
|
@@ -87,63 +87,16 @@ async function runValidateGuidelines(dirPath, options) {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
// src/validate/tier.ts
|
|
90
|
-
import { execSync } from "child_process";
|
|
91
90
|
import * as fs2 from "fs";
|
|
92
91
|
import * as path2 from "path";
|
|
93
92
|
import TOML from "@iarna/toml";
|
|
94
93
|
import chalk2 from "chalk";
|
|
95
|
-
import * as yaml from "js-yaml";
|
|
96
94
|
|
|
97
95
|
// src/validate/types.ts
|
|
98
96
|
var VALID_TIERS = ["production", "internal", "prototype"];
|
|
99
97
|
|
|
100
98
|
// src/validate/tier.ts
|
|
101
99
|
var DEFAULT_TIER = "internal";
|
|
102
|
-
function findGitRoot(startDir) {
|
|
103
|
-
try {
|
|
104
|
-
const gitRoot = execSync("git rev-parse --show-toplevel", {
|
|
105
|
-
cwd: startDir,
|
|
106
|
-
encoding: "utf-8",
|
|
107
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
108
|
-
}).trim();
|
|
109
|
-
return gitRoot;
|
|
110
|
-
} catch {
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
function readFileContent(filePath) {
|
|
115
|
-
if (!fs2.existsSync(filePath)) {
|
|
116
|
-
return null;
|
|
117
|
-
}
|
|
118
|
-
try {
|
|
119
|
-
return fs2.readFileSync(filePath, "utf-8");
|
|
120
|
-
} catch {
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
function parseYamlContent(content) {
|
|
125
|
-
try {
|
|
126
|
-
const parsed = yaml.load(content);
|
|
127
|
-
if (parsed === void 0 || parsed === null) {
|
|
128
|
-
return { metadata: null, sourceDetail: "default (file empty)" };
|
|
129
|
-
}
|
|
130
|
-
return { metadata: parsed, sourceDetail: "repo-metadata.yaml" };
|
|
131
|
-
} catch (error) {
|
|
132
|
-
const parseError = error instanceof Error ? error.message : String(error);
|
|
133
|
-
return { metadata: null, sourceDetail: "default (parse error)", parseError };
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
function loadRepoMetadata(projectRoot) {
|
|
137
|
-
const metadataPath = path2.join(projectRoot, "repo-metadata.yaml");
|
|
138
|
-
const content = readFileContent(metadataPath);
|
|
139
|
-
if (content === null) {
|
|
140
|
-
return { metadata: null, sourceDetail: "default (file not found)" };
|
|
141
|
-
}
|
|
142
|
-
if (!content.trim()) {
|
|
143
|
-
return { metadata: null, sourceDetail: "default (file empty)" };
|
|
144
|
-
}
|
|
145
|
-
return parseYamlContent(content);
|
|
146
|
-
}
|
|
147
100
|
function loadExtendsConfig(configPath) {
|
|
148
101
|
try {
|
|
149
102
|
const content = fs2.readFileSync(configPath, "utf-8");
|
|
@@ -153,24 +106,48 @@ function loadExtendsConfig(configPath) {
|
|
|
153
106
|
return null;
|
|
154
107
|
}
|
|
155
108
|
}
|
|
156
|
-
function
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
109
|
+
function loadTierFromStandardsToml(configPath) {
|
|
110
|
+
if (!fs2.existsSync(configPath)) {
|
|
111
|
+
return {
|
|
112
|
+
tier: DEFAULT_TIER,
|
|
113
|
+
source: "default",
|
|
114
|
+
sourceDetail: "default (file not found)"
|
|
115
|
+
};
|
|
163
116
|
}
|
|
164
|
-
|
|
165
|
-
|
|
117
|
+
try {
|
|
118
|
+
const content = fs2.readFileSync(configPath, "utf-8");
|
|
119
|
+
const parsed = TOML.parse(content);
|
|
120
|
+
if (!parsed.metadata) {
|
|
121
|
+
return {
|
|
122
|
+
tier: DEFAULT_TIER,
|
|
123
|
+
source: "default",
|
|
124
|
+
sourceDetail: "default (no metadata)"
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
if (parsed.metadata.tier === void 0) {
|
|
128
|
+
return {
|
|
129
|
+
tier: DEFAULT_TIER,
|
|
130
|
+
source: "default",
|
|
131
|
+
sourceDetail: "default (tier not specified)"
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const tier = parsed.metadata.tier;
|
|
135
|
+
if (!VALID_TIERS.includes(tier)) {
|
|
136
|
+
return {
|
|
137
|
+
tier: DEFAULT_TIER,
|
|
138
|
+
source: "default",
|
|
139
|
+
sourceDetail: "default (invalid value)",
|
|
140
|
+
invalidValue: String(tier)
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
return { tier, source: "standards.toml", sourceDetail: "standards.toml" };
|
|
144
|
+
} catch {
|
|
166
145
|
return {
|
|
167
146
|
tier: DEFAULT_TIER,
|
|
168
147
|
source: "default",
|
|
169
|
-
sourceDetail: "default (
|
|
170
|
-
invalidValue: String(tier)
|
|
148
|
+
sourceDetail: "default (file not found)"
|
|
171
149
|
};
|
|
172
150
|
}
|
|
173
|
-
return { tier, source: "repo-metadata.yaml", sourceDetail: "repo-metadata.yaml" };
|
|
174
151
|
}
|
|
175
152
|
function findMatchingRulesets(rulesets, tier) {
|
|
176
153
|
const suffix = `-${tier}`;
|
|
@@ -188,6 +165,7 @@ function createNotFoundResult() {
|
|
|
188
165
|
valid: false,
|
|
189
166
|
tier: DEFAULT_TIER,
|
|
190
167
|
tierSource: "default",
|
|
168
|
+
tierSourceDetail: "default (file not found)",
|
|
191
169
|
rulesets: [],
|
|
192
170
|
expectedPattern: `*-${DEFAULT_TIER}`,
|
|
193
171
|
matchedRulesets: [],
|
|
@@ -203,20 +181,16 @@ function buildResult(options) {
|
|
|
203
181
|
matchedRulesets,
|
|
204
182
|
invalidTierValue,
|
|
205
183
|
hasEmptyRulesets,
|
|
206
|
-
registryUrl
|
|
207
|
-
parseError
|
|
184
|
+
registryUrl
|
|
208
185
|
} = options;
|
|
209
186
|
const warnings = options.warnings ?? [];
|
|
210
187
|
const expectedPattern = `*-${tier}`;
|
|
211
188
|
const valid = rulesets.length === 0 || matchedRulesets.length > 0;
|
|
212
189
|
if (invalidTierValue) {
|
|
213
190
|
warnings.push(
|
|
214
|
-
`Invalid tier '${invalidTierValue}' in
|
|
191
|
+
`Invalid tier '${invalidTierValue}' in standards.toml [metadata]. Valid values are: ${VALID_TIERS.join(", ")}`
|
|
215
192
|
);
|
|
216
193
|
}
|
|
217
|
-
if (parseError) {
|
|
218
|
-
warnings.push(`Failed to parse repo-metadata.yaml: ${parseError}`);
|
|
219
|
-
}
|
|
220
194
|
if (hasEmptyRulesets && registryUrl) {
|
|
221
195
|
warnings.push(
|
|
222
196
|
`[extends] is configured with registry '${registryUrl}' but rulesets is empty - no standards will be inherited`
|
|
@@ -242,26 +216,21 @@ function validateTierRuleset(options = {}) {
|
|
|
242
216
|
if (!configPath) {
|
|
243
217
|
return createNotFoundResult();
|
|
244
218
|
}
|
|
245
|
-
const
|
|
246
|
-
const gitRoot = findGitRoot(configDir);
|
|
247
|
-
const metadataSearchPath = gitRoot ?? configDir;
|
|
248
|
-
const metadataResult = loadRepoMetadata(metadataSearchPath);
|
|
249
|
-
const { tier, source, sourceDetail, invalidValue } = getTier(metadataResult);
|
|
219
|
+
const tierResult = loadTierFromStandardsToml(configPath);
|
|
250
220
|
const extendsConfig = loadExtendsConfig(configPath);
|
|
251
221
|
const rulesets = extendsConfig?.rulesets ?? [];
|
|
252
|
-
const matchedRulesets = rulesets.length > 0 ? findMatchingRulesets(rulesets, tier) : [];
|
|
222
|
+
const matchedRulesets = rulesets.length > 0 ? findMatchingRulesets(rulesets, tierResult.tier) : [];
|
|
253
223
|
const hasEmptyRulesets = extendsConfig !== null && rulesets.length === 0;
|
|
254
224
|
const registryUrl = extendsConfig?.registry;
|
|
255
225
|
return buildResult({
|
|
256
|
-
tier,
|
|
257
|
-
source,
|
|
258
|
-
sourceDetail,
|
|
226
|
+
tier: tierResult.tier,
|
|
227
|
+
source: tierResult.source,
|
|
228
|
+
sourceDetail: tierResult.sourceDetail,
|
|
259
229
|
rulesets,
|
|
260
230
|
matchedRulesets,
|
|
261
|
-
invalidTierValue: invalidValue,
|
|
231
|
+
invalidTierValue: tierResult.invalidValue,
|
|
262
232
|
hasEmptyRulesets,
|
|
263
|
-
registryUrl
|
|
264
|
-
parseError: metadataResult.parseError
|
|
233
|
+
registryUrl
|
|
265
234
|
});
|
|
266
235
|
}
|
|
267
236
|
function formatWarnings(warnings) {
|
|
@@ -295,7 +264,7 @@ function formatFailedValidation(result, sourceDisplay) {
|
|
|
295
264
|
lines.push("");
|
|
296
265
|
lines.push(
|
|
297
266
|
chalk2.cyan(
|
|
298
|
-
` Hint: Update
|
|
267
|
+
` Hint: Update standards.toml [metadata].tier to use a valid value: ${VALID_TIERS.join(", ")}`
|
|
299
268
|
)
|
|
300
269
|
);
|
|
301
270
|
}
|
|
@@ -324,4 +293,4 @@ export {
|
|
|
324
293
|
validateGuidelinesDir,
|
|
325
294
|
validateTierRuleset
|
|
326
295
|
};
|
|
327
|
-
//# sourceMappingURL=validate-
|
|
296
|
+
//# sourceMappingURL=validate-J5E336GX.js.map
|