switchman-dev 0.1.1 → 0.1.3

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/src/core/ci.js ADDED
@@ -0,0 +1,114 @@
1
+ import { existsSync, mkdirSync, writeFileSync } from 'fs';
2
+ import { dirname, join } from 'path';
3
+
4
+ function summarizeUnclaimedChanges(result) {
5
+ if (!result.unclaimed_changes?.length) return ['- None'];
6
+ return result.unclaimed_changes.map((entry) => `- ${entry.worktree}: ${entry.files.join(', ')}`);
7
+ }
8
+
9
+ function summarizeFileConflicts(result) {
10
+ if (!result.file_conflicts?.length) return ['- None'];
11
+ return result.file_conflicts.map((entry) => `- ${entry.file}: ${entry.worktrees.join(', ')}`);
12
+ }
13
+
14
+ function summarizeBranchConflicts(result) {
15
+ if (!result.branch_conflicts?.length) return ['- None'];
16
+ return result.branch_conflicts.map((entry) => `- ${entry.worktreeA} vs ${entry.worktreeB}`);
17
+ }
18
+
19
+ export function formatCiGateMarkdown(result) {
20
+ return [
21
+ '# Switchman CI Gate',
22
+ '',
23
+ `- Status: ${result.ok ? 'pass' : 'blocked'}`,
24
+ `- Summary: ${result.summary}`,
25
+ '',
26
+ '## Compliance',
27
+ `- Managed: ${result.compliance?.managed ?? 0}`,
28
+ `- Observed: ${result.compliance?.observed ?? 0}`,
29
+ `- Non-compliant: ${result.compliance?.non_compliant ?? 0}`,
30
+ `- Stale: ${result.compliance?.stale ?? 0}`,
31
+ '',
32
+ '## Unclaimed Changes',
33
+ ...summarizeUnclaimedChanges(result),
34
+ '',
35
+ '## File Conflicts',
36
+ ...summarizeFileConflicts(result),
37
+ '',
38
+ '## Branch Conflicts',
39
+ ...summarizeBranchConflicts(result),
40
+ ].join('\n');
41
+ }
42
+
43
+ export function writeGitHubCiStatus({ result, stepSummaryPath = null, outputPath = null }) {
44
+ const markdown = formatCiGateMarkdown(result);
45
+
46
+ if (stepSummaryPath) {
47
+ writeFileSync(stepSummaryPath, `${markdown}\n`);
48
+ }
49
+
50
+ if (outputPath) {
51
+ const lines = [
52
+ `switchman_ok=${result.ok ? 'true' : 'false'}`,
53
+ `switchman_summary=${JSON.stringify(result.summary)}`,
54
+ `switchman_non_compliant=${result.compliance?.non_compliant ?? 0}`,
55
+ `switchman_stale=${result.compliance?.stale ?? 0}`,
56
+ `switchman_unclaimed_changes=${result.unclaimed_changes?.length ?? 0}`,
57
+ `switchman_file_conflicts=${result.file_conflicts?.length ?? 0}`,
58
+ `switchman_branch_conflicts=${result.branch_conflicts?.length ?? 0}`,
59
+ ];
60
+ writeFileSync(outputPath, `${lines.join('\n')}\n`);
61
+ }
62
+
63
+ return {
64
+ markdown,
65
+ wrote_step_summary: Boolean(stepSummaryPath),
66
+ wrote_output: Boolean(outputPath),
67
+ };
68
+ }
69
+
70
+ export function installGitHubActionsWorkflow(repoRoot, workflowName = 'switchman-gate.yml') {
71
+ const workflowsDir = join(repoRoot, '.github', 'workflows');
72
+ if (!existsSync(workflowsDir)) {
73
+ mkdirSync(workflowsDir, { recursive: true });
74
+ }
75
+
76
+ const workflowPath = join(workflowsDir, workflowName);
77
+ const workflow = `name: Switchman Gate
78
+
79
+ on:
80
+ pull_request:
81
+ push:
82
+ branches:
83
+ - main
84
+
85
+ jobs:
86
+ switchman-gate:
87
+ runs-on: ubuntu-latest
88
+ steps:
89
+ - name: Checkout
90
+ uses: actions/checkout@v4
91
+
92
+ - name: Setup Node
93
+ uses: actions/setup-node@v4
94
+ with:
95
+ node-version: 20
96
+
97
+ - name: Install Switchman
98
+ run: npm install -g switchman-dev
99
+
100
+ - name: Run Switchman CI gate
101
+ run: switchman gate ci --github
102
+ `;
103
+
104
+ writeFileSync(workflowPath, workflow);
105
+ return workflowPath;
106
+ }
107
+
108
+ export function resolveGitHubOutputTargets(opts = {}, env = process.env) {
109
+ const githubMode = Boolean(opts.github);
110
+ return {
111
+ stepSummaryPath: opts.githubStepSummary || (githubMode ? env.GITHUB_STEP_SUMMARY || null : null),
112
+ outputPath: opts.githubOutput || (githubMode ? env.GITHUB_OUTPUT || null : null),
113
+ };
114
+ }