cistack 3.1.0 → 4.0.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.
@@ -0,0 +1,70 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ - master
8
+ pull_request:
9
+
10
+ concurrency:
11
+ group: ${{ github.workflow }}-${{ github.ref }}
12
+ cancel-in-progress: true
13
+
14
+ jobs:
15
+ test:
16
+ name: Node ${{ matrix.node-version }}
17
+ runs-on: ubuntu-latest
18
+ strategy:
19
+ fail-fast: false
20
+ matrix:
21
+ node-version:
22
+ - 18.x
23
+ - 20.x
24
+ - 22.x
25
+
26
+ steps:
27
+ - name: Checkout repository
28
+ uses: actions/checkout@v4
29
+
30
+ - name: Set up Node.js
31
+ uses: actions/setup-node@v4
32
+ with:
33
+ node-version: ${{ matrix.node-version }}
34
+ cache: npm
35
+
36
+ - name: Install dependencies
37
+ run: npm ci
38
+
39
+ - name: Run package smoke test
40
+ run: npm test
41
+
42
+ - name: Verify audit command
43
+ run: node bin/ciflow.js audit --path .
44
+
45
+ - name: Verify upgrade command
46
+ run: node bin/ciflow.js upgrade --path . --dry-run
47
+
48
+ - name: Smoke test init command in temp workspace
49
+ shell: bash
50
+ run: |
51
+ set -euo pipefail
52
+ tmp_dir="$(mktemp -d)"
53
+ node bin/ciflow.js init --path "$tmp_dir"
54
+ test -f "$tmp_dir/cistack.config.js"
55
+
56
+ - name: Smoke test generate command in temp workspace
57
+ shell: bash
58
+ run: |
59
+ set -euo pipefail
60
+ tmp_dir="$(mktemp -d)"
61
+ cat > "$tmp_dir/package.json" <<'JSON'
62
+ {
63
+ "name": "fixture-app",
64
+ "version": "1.0.0",
65
+ "scripts": {
66
+ "test": "echo ok"
67
+ }
68
+ }
69
+ JSON
70
+ node bin/ciflow.js generate --path "$tmp_dir" --dry-run --no-prompt
package/README.md CHANGED
@@ -1,186 +1,258 @@
1
1
  # cistack
2
2
 
3
- > Automatically generate GitHub Actions CI/CD pipelines by analysing your codebase
3
+ > Generate GitHub Actions CI/CD pipelines by analyzing the codebase you already have.
4
4
 
5
- `cistack` scans your project directory and produces production-grade GitHub Actions workflow YAML files. It detects your language, framework, testing tools, and hosting platform then writes the best pipeline for your stack.
5
+ `cistack` scans your project, detects the stack, and writes production-ready GitHub Actions workflows for CI, deployment, Docker, security, and releases. It is designed for real repos, not toy demos: it reads lock files, framework signals, release config, monorepo workspaces, hosting config, and Git branch metadata before generating YAML.
6
6
 
7
- ---
7
+ ## Why cistack
8
8
 
9
- ## Features
10
-
11
- - 🔍 **Deep codebase analysis** — reads `package.json`, lock files, config files, and directory structure
12
- - 🧠 **Smart detection** — identifies 30+ frameworks, 12 languages, 12+ testing tools, and 10+ hosting platforms
13
- - **Native Cache support** speeds up pipelines by 2–4min using native caching for npm, pip, go, cargo, maven, gradle, and bundler
14
- - **PR Preview Deploys** automatic preview environments for Vercel and Netlify on every pull request
15
- - 🚀 **Hosting auto-detect** Firebase, Vercel, Netlify, AWS, GCP, Azure, Heroku, Render, Railway, GitHub Pages, Docker
16
- - 🛡️ **Workflow Audit & Upgrade** — analyse existing `.github/workflows` for outdated actions and missing best practices
17
- - 🏗️ **Multi-workflow output** generates separate `ci.yml`, `deploy.yml`, `docker.yml`, and `security.yml`
18
- - 🔒 **Security built-in** — CodeQL analysis + dependency auditing on every pipeline
19
- - 📦 **Monorepo aware** — detects Turborepo, Nx, Lerna, pnpm workspaces (supports per-package workflows)
20
- - ✅ **Interactive mode** — confirms detected settings before writing files
21
- - 🎯 **Zero config** — works out of the box with `cistack.config.js` for overrides
22
-
23
- ---
9
+ - Detects languages, frameworks, testing tools, hosting providers, and release tooling automatically
10
+ - Uses your repository's default Git branch when available instead of assuming `main`
11
+ - Supports monorepos, per-package workflows, and package-manager-aware commands
12
+ - Generates ecosystem-aware Dependabot config, including Bun when `bun.lock` is present
13
+ - Smart-merges generated workflows with existing files instead of blindly overwriting them
14
+ - Generates deploy pipelines for Vercel, Netlify, Firebase, GitHub Pages, AWS, Azure, Heroku, Render, and Railway
15
+ - Ships with built-in workflow audit and upgrade commands
16
+ - Includes typed `cistack.config.js` support through `index.d.ts`
17
+ - Backed by an automated regression suite covering branch handling, release detection, smart merge behavior, monorepo package scripts, and CLI smoke tests
24
18
 
25
19
  ## Installation
26
20
 
27
21
  ```bash
28
- # Run without installing (recommended for one-off use)
22
+ # One-off usage
29
23
  npx cistack
30
24
 
31
- # Install globally
25
+ # Global install
32
26
  npm install -g cistack
33
27
  ```
34
28
 
35
- ---
29
+ `cistack` supports Node.js 16+, and the project itself is continuously verified on Node.js 18, 20, and 22 in GitHub Actions.
36
30
 
37
- ## Usage
31
+ ## CLI Usage
38
32
 
39
- ### Generate Pipelines
40
- Analyze your stack and generate best-practice workflows.
41
- ```bash
42
- # In your project directory
43
- npx cistack
33
+ ### Generate workflows
44
34
 
45
- # Show reasoning for detected stack
46
- npx cistack --explain
35
+ `generate` is the default command, so both of these work:
47
36
 
48
- # Specify a project path
49
- npx cistack --path /path/to/project
37
+ ```bash
38
+ npx cistack
39
+ npx cistack generate
40
+ ```
50
41
 
51
- # Custom output directory
52
- npx cistack --output .github/workflows
42
+ Common options:
53
43
 
54
- # Dry run (print YAML without writing files)
55
- npx cistack --dry-run
44
+ ```bash
45
+ npx cistack generate --path /path/to/project
46
+ npx cistack generate --dry-run
47
+ npx cistack generate --explain
48
+ npx cistack generate --output .github/workflows
49
+ npx cistack generate --no-prompt
56
50
  ```
57
51
 
58
- ### Audit Existing Workflows
59
- Analyze your current `.github/workflows` folder for outdated actions or missing features.
52
+ ### Audit existing workflows
53
+
60
54
  ```bash
61
55
  npx cistack audit
62
56
  ```
63
57
 
64
- ### Automatic Upgrade
65
- Automatically bump all action versions (e.g., `actions/checkout@v3` → `@v4`) across all your workflow files to the latest stable releases.
58
+ This checks `.github/workflows` for issues like missing concurrency blocks, outdated actions, old Node versions, and missing dependency caching.
59
+
60
+ ### Upgrade workflow actions
61
+
66
62
  ```bash
67
63
  npx cistack upgrade
64
+ npx cistack upgrade --dry-run
68
65
  ```
69
66
 
70
- ### Initialization
71
- Create a `cistack.config.js` to override auto-detected settings.
67
+ This updates known GitHub Actions to their latest supported stable versions.
68
+
69
+ ### Create a starter config
70
+
72
71
  ```bash
73
72
  npx cistack init
74
73
  ```
75
74
 
76
- ---
77
-
78
- ## Flags
79
-
80
- - `--explain` — Show detailed reasoning for every detection (build trust)
81
- - `--dry-run` — Print YAML to terminal without writing to disk
82
- - `--force` — Overwrite existing files instead of smart-merging
83
- - `--no-prompt` — Skip interactive confirmation
84
- - `--verbose` — Show raw analysis data
85
- - `--path <dir>` — Project root directory
86
- - `--output <dir>` — Workflow output directory (default: `.github/workflows`)
87
-
88
- ---
89
-
90
- ## Detected Hosting Platforms
75
+ This writes `cistack.config.js` with the supported override keys.
91
76
 
92
- | Platform | Detection Signal |
93
- |---|---|
94
- | **Firebase** | `firebase.json`, `.firebaserc`, `firebase-tools` dep |
95
- | **Vercel** | `vercel.json`, `.vercel` dir, `vercel` dep |
96
- | **Netlify** | `netlify.toml`, `_redirects`, `netlify-cli` dep |
97
- | **GitHub Pages** | `gh-pages` dep, `github.io` homepage in `package.json` |
98
- | **AWS** | `serverless.yml`, `appspec.yml`, `cdk.json`, `aws-sdk` dep |
99
- | **GCP App Engine** | `app.yaml` |
100
- | **Azure** | `azure/pipelines.yml`, `@azure/*` deps |
101
- | **Heroku** | `Procfile`, `heroku.yml` |
102
- | **Render** | `render.yaml` |
103
- | **Railway** | `railway.json`, `railway.toml` |
104
- | **Docker** | `Dockerfile`, `docker-compose.yml` |
77
+ ## What gets generated
105
78
 
106
- ---
79
+ ### `ci.yml`
107
80
 
108
- ## Detected Frameworks
81
+ Continuous integration for linting, tests, builds, coverage upload, and optional E2E jobs.
109
82
 
110
- Next.js, Nuxt, SvelteKit, Remix, Astro, Vite, React, Vue, Angular, Svelte, Gatsby,
111
- Express, Fastify, NestJS, Hono, Koa, tRPC,
112
- Django, Flask, FastAPI,
113
- Ruby on Rails,
114
- Spring Boot,
115
- Laravel,
116
- Go (gin), Rust (Cargo)
117
-
118
- ---
119
-
120
- ## Detected Testing Tools
121
-
122
- | Tool | Type |
123
- |---|---|
124
- | Jest, Vitest, Mocha | Unit |
125
- | Cypress, Playwright | E2E |
126
- | Pytest | Python unit |
127
- | RSpec | Ruby unit |
128
- | Go Test | Go unit |
129
- | Cargo Test | Rust unit |
130
- | PHPUnit | PHP unit |
131
- | JUnit/Maven | JVM unit |
132
- | Storybook | Visual |
133
-
134
- ---
83
+ - Runs on pushes and pull requests
84
+ - Uses the detected default branch or your configured `branches`
85
+ - Uses runtime matrices where appropriate
86
+ - Uses package-manager-aware install and script commands
87
+
88
+ ### `deploy.yml`
89
+
90
+ Continuous deployment for the primary hosting provider.
91
+
92
+ - Runs on production pushes plus manual dispatch
93
+ - Uses preview deployments on pull requests for providers that support them cleanly
94
+ - Documents the required secrets in the file header
95
+ - Avoids empty push branch lists when a repo is `develop`-only
96
+
97
+ ### `docker.yml`
98
+
99
+ Builds and optionally pushes Docker images to GHCR.
100
+
101
+ - Runs on configured branches, pull requests, and semantic version tags
102
+ - Uses Buildx and GitHub Actions cache
103
+
104
+ ### `security.yml`
105
+
106
+ Dependency audit plus CodeQL analysis.
107
+
108
+ - Runs on push, pull request, and a weekly schedule
109
+ - Uses the detected default branch or configured branch overrides
110
+
111
+ ### `release.yml`
112
+
113
+ Generated when `semantic-release`, `changesets`, `release-it`, `standard-version`, or a custom release command is detected or configured.
114
+
115
+ - Uses the detected package manager for release commands
116
+ - Respects configured branches and detected default branch
117
+ - Documents additional required secrets such as `NPM_TOKEN`
118
+
119
+ ## Supported detection
120
+
121
+ ### Hosting
122
+
123
+ - Firebase
124
+ - Vercel
125
+ - Netlify
126
+ - GitHub Pages
127
+ - AWS
128
+ - GCP App Engine
129
+ - Azure
130
+ - Heroku
131
+ - Render
132
+ - Railway
133
+ - Docker
134
+
135
+ ### Frameworks
136
+
137
+ - Next.js
138
+ - Nuxt
139
+ - SvelteKit
140
+ - Remix
141
+ - Astro
142
+ - Vite
143
+ - React
144
+ - Vue
145
+ - Angular
146
+ - Svelte
147
+ - Gatsby
148
+ - Express
149
+ - Fastify
150
+ - NestJS
151
+ - Hono
152
+ - Koa
153
+ - Django
154
+ - Flask
155
+ - FastAPI
156
+ - Rails
157
+ - Spring Boot
158
+ - Laravel
159
+ - Go
160
+ - Rust
161
+
162
+ ### Testing tools
163
+
164
+ - Jest
165
+ - Vitest
166
+ - Mocha
167
+ - Cypress
168
+ - Playwright
169
+ - Pytest
170
+ - RSpec
171
+ - Go test
172
+ - Cargo test
173
+ - PHPUnit
174
+ - Maven / JUnit
175
+ - Storybook
176
+
177
+ ## Configuration
178
+
179
+ Create `cistack.config.js` when you want to override detection:
180
+
181
+ ```js
182
+ /** @type {import('cistack').Config} */
183
+ module.exports = {
184
+ nodeVersion: '20',
185
+ packageManager: 'pnpm',
186
+ branches: ['main', 'staging'],
187
+ hosting: ['Vercel'],
188
+ outputDir: '.github/workflows',
189
+
190
+ cache: {
191
+ npm: true,
192
+ cargo: true,
193
+ pip: true,
194
+ },
195
+
196
+ monorepo: {
197
+ perPackage: true,
198
+ },
199
+
200
+ release: {
201
+ tool: 'semantic-release',
202
+ },
203
+ };
204
+ ```
135
205
 
136
- ## Generated Workflows
206
+ Supported top-level config keys:
137
207
 
138
- ### `ci.yml` — Continuous Integration
139
- Runs on every push and pull request:
140
- 1. **Lint** — ESLint, TypeScript type-check, formatter check
141
- 2. **Test** — unit tests with coverage upload (matrix across Node versions)
142
- 3. **Build** — production build, artifact upload
143
- 4. **E2E** — Cypress / Playwright (if detected)
144
- 5. **Caching** — Full dependency caching for faster runs
208
+ - `nodeVersion`
209
+ - `packageManager`
210
+ - `hosting`
211
+ - `frameworks`
212
+ - `testing`
213
+ - `branches`
214
+ - `cache`
215
+ - `monorepo`
216
+ - `release`
217
+ - `secrets`
218
+ - `outputDir`
145
219
 
146
- ### `deploy.yml` — Continuous Deployment
147
- Triggers on push to `main`/`master` + manual dispatch:
148
- - Platform-specific deploy using official GitHub Actions
149
- - **PR Preview Deploys** — automatic previews for Vercel and Netlify pull requests
150
- - Proper secret references documented in the file header
220
+ Branch behavior:
151
221
 
152
- ### `docker.yml` Docker Build & Push
153
- Triggers on push to `main` and version tags:
154
- - Multi-platform build via Docker Buildx
155
- - Pushes to GitHub Container Registry (GHCR)
156
- - Build cache via GitHub Actions cache (GHA)
222
+ - If `branches` is set in config, `cistack` uses it exactly
223
+ - Otherwise it reads the repository's default branch from Git metadata when available
224
+ - If Git metadata is unavailable, it falls back to safe defaults like `main`, `master`, and `develop` depending on the workflow type
157
225
 
158
- ### `security.yml` — Security Audit
159
- Runs on push, PRs, and weekly schedule:
160
- - Dependency vulnerability audit (npm audit / safety / cargo audit)
161
- - GitHub CodeQL analysis for the detected language
226
+ ## Secrets
162
227
 
163
- ---
228
+ Generated deploy and release workflows document the secrets they need at the top of each file. Add them in:
164
229
 
165
- ## Required Secrets
230
+ `GitHub -> Settings -> Secrets and variables -> Actions`
166
231
 
167
- After generating, add the required secrets to your repository at:
168
- `Settings → Secrets and variables → Actions`
232
+ ## Development and Quality
169
233
 
170
- Each generated `deploy.yml` has a comment at the top listing the exact secrets needed.
234
+ The project now includes a regression suite for the areas that were historically the easiest to break:
171
235
 
172
- ---
236
+ - config override handling
237
+ - default branch detection
238
+ - deploy branch selection
239
+ - Netlify production branch handling
240
+ - smart merge behavior
241
+ - monorepo per-package build script lookup
242
+ - release config detection
243
+ - release workflow generation
244
+ - CLI dry-run smoke testing
173
245
 
174
- ## Examples
246
+ Run the checks locally:
175
247
 
176
- **Next.js + Vercel project with Audit:**
177
248
  ```bash
178
- npx cistack audit # Check existing workflows
179
- npx cistack upgrade # Update versions to v4
180
- npx cistack generate # Refresh with latest caching & previews
249
+ npm test
250
+ npm run test:smoke
251
+ node bin/ciflow.js audit --path .
252
+ node bin/ciflow.js upgrade --path . --dry-run
181
253
  ```
182
254
 
183
- ---
255
+ If you are using the published package, the executable is `cistack`. In this repository, the local entrypoint is `bin/ciflow.js`.
184
256
 
185
257
  ## License
186
258
 
package/bin/ciflow.js CHANGED
@@ -87,7 +87,7 @@ module.exports = {
87
87
  // nodeVersion: '20', // Override detected Node.js version
88
88
  // packageManager: 'pnpm', // 'npm' | 'yarn' | 'pnpm' | 'bun'
89
89
  // hosting: ['Firebase'], // Force a specific hosting provider
90
- // branches: ['main', 'staging'], // CI branches (default: main, master, develop)
90
+ // branches: ['main', 'staging'], // CI branches (default: detected git default branch, then main/master/develop)
91
91
  // outputDir: '.github/workflows', // Where to write workflow files
92
92
 
93
93
  // cache: {
package/index.d.ts ADDED
@@ -0,0 +1,90 @@
1
+ export type PackageManager =
2
+ | 'npm'
3
+ | 'yarn'
4
+ | 'pnpm'
5
+ | 'bun'
6
+ | 'pip'
7
+ | 'poetry'
8
+ | 'pipenv'
9
+ | 'bundler'
10
+ | 'go mod'
11
+ | 'cargo'
12
+ | 'maven'
13
+ | 'gradle'
14
+ | 'composer';
15
+
16
+ export type HostingName =
17
+ | 'Firebase'
18
+ | 'Vercel'
19
+ | 'Netlify'
20
+ | 'AWS'
21
+ | 'GCP App Engine'
22
+ | 'Azure'
23
+ | 'Heroku'
24
+ | 'Render'
25
+ | 'Railway'
26
+ | 'GitHub Pages'
27
+ | 'Docker';
28
+
29
+ export type ReleaseTool =
30
+ | 'semantic-release'
31
+ | 'changesets'
32
+ | 'release-it'
33
+ | 'standard-version'
34
+ | 'custom';
35
+
36
+ export interface CacheConfig {
37
+ npm?: boolean;
38
+ pip?: boolean;
39
+ cargo?: boolean;
40
+ maven?: boolean;
41
+ gradle?: boolean;
42
+ go?: boolean;
43
+ composer?: boolean;
44
+ bundler?: boolean;
45
+ }
46
+
47
+ export interface MonorepoConfig {
48
+ perPackage?: boolean;
49
+ }
50
+
51
+ export interface ReleaseConfig {
52
+ tool: ReleaseTool;
53
+ command?: string;
54
+ publishToNpm?: boolean;
55
+ requiresNpmToken?: boolean;
56
+ branches?: string[];
57
+ }
58
+
59
+ export interface Config {
60
+ nodeVersion?: string | number;
61
+ packageManager?: PackageManager;
62
+ hosting?: HostingName | HostingName[];
63
+ frameworks?: string | string[];
64
+ testing?: string | string[];
65
+ branches?: string[];
66
+ cache?: CacheConfig;
67
+ monorepo?: MonorepoConfig;
68
+ release?: ReleaseTool | ReleaseConfig;
69
+ secrets?: string[];
70
+ outputDir?: string;
71
+ }
72
+
73
+ export interface CIFlowOptions {
74
+ projectPath: string;
75
+ outputDir?: string;
76
+ dryRun?: boolean;
77
+ force?: boolean;
78
+ prompt?: boolean;
79
+ verbose?: boolean;
80
+ explain?: boolean;
81
+ }
82
+
83
+ declare class CIFlow {
84
+ constructor(options: CIFlowOptions);
85
+ run(): Promise<void>;
86
+ audit(): Promise<void>;
87
+ upgrade(): Promise<void>;
88
+ }
89
+
90
+ export default CIFlow;
package/package.json CHANGED
@@ -1,14 +1,16 @@
1
1
  {
2
2
  "name": "cistack",
3
- "version": "3.1.0",
3
+ "version": "4.0.0",
4
4
  "description": "Automatically generate GitHub Actions CI/CD pipelines by analysing your codebase",
5
5
  "main": "src/index.js",
6
+ "types": "index.d.ts",
6
7
  "bin": {
7
8
  "cistack": "./bin/ciflow.js"
8
9
  },
9
10
  "scripts": {
10
11
  "start": "node bin/ciflow.js",
11
- "test": "node bin/ciflow.js --dry-run --no-prompt"
12
+ "test": "node tests/run.js",
13
+ "test:smoke": "node bin/ciflow.js generate --path . --dry-run --no-prompt"
12
14
  },
13
15
  "keywords": [
14
16
  "github-actions",
@@ -2,6 +2,7 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
+ const { execFileSync } = require('child_process');
5
6
  const { globSync } = require('glob');
6
7
 
7
8
  /**
@@ -25,9 +26,11 @@ class CodebaseAnalyzer {
25
26
  srcStructure: {},
26
27
  hasMonorepo: false,
27
28
  workspaces: [],
29
+ defaultBranch: null,
30
+ currentBranch: null,
28
31
  };
29
32
 
30
- // ── gather all file paths (ignore node_modules, .git, dist, build) ────
33
+ // ── gather notable file paths (avoid giant deep scans) ──────────────
31
34
  const allFiles = globSync('**/*', {
32
35
  cwd: this.root,
33
36
  ignore: [
@@ -38,11 +41,16 @@ class CodebaseAnalyzer {
38
41
  '.next/**',
39
42
  '.nuxt/**',
40
43
  'coverage/**',
44
+ 'public/**',
45
+ 'assets/**',
46
+ 'static/**',
47
+ 'vendor/**',
41
48
  '*.min.js',
42
49
  '*.min.css',
43
50
  ],
44
- nodir: true,
51
+ nodir: false,
45
52
  dot: true,
53
+ maxDepth: 5, // Avoid extreme depth for general discovery
46
54
  });
47
55
 
48
56
  info.files = allFiles;
@@ -60,6 +68,7 @@ class CodebaseAnalyzer {
60
68
  'package-lock.json',
61
69
  'yarn.lock',
62
70
  'pnpm-lock.yaml',
71
+ 'bun.lock',
63
72
  'bun.lockb',
64
73
  'Pipfile.lock',
65
74
  'poetry.lock',
@@ -149,7 +158,7 @@ class CodebaseAnalyzer {
149
158
  'biome.json',
150
159
  // CI already present
151
160
  '.travis.yml',
152
- 'circle.ci/config.yml',
161
+ '.circleci/config.yml',
153
162
  'Jenkinsfile',
154
163
  ];
155
164
 
@@ -188,9 +197,7 @@ class CodebaseAnalyzer {
188
197
  fs.existsSync(path.join(this.root, 'turbo.json')) ||
189
198
  fs.existsSync(path.join(this.root, 'nx.json')) ||
190
199
  fs.existsSync(path.join(this.root, 'lerna.json')) ||
191
- (info.packageJson &&
192
- (info.packageJson.workspaces ||
193
- info.packageJson.private === true));
200
+ (info.packageJson && info.packageJson.workspaces);
194
201
 
195
202
  info.hasMonorepo = !!hasMonorepoMarker;
196
203
  if (info.packageJson && info.packageJson.workspaces) {
@@ -198,8 +205,38 @@ class CodebaseAnalyzer {
198
205
  info.workspaces = Array.isArray(ws) ? ws : ws.packages || [];
199
206
  }
200
207
 
208
+ // ── git branch hints ───────────────────────────────────────────────────
209
+ const gitInfo = this._detectGitBranches();
210
+ info.defaultBranch = gitInfo.defaultBranch;
211
+ info.currentBranch = gitInfo.currentBranch;
212
+
201
213
  return info;
202
214
  }
215
+
216
+ _detectGitBranches() {
217
+ const readGit = (args) => {
218
+ try {
219
+ return execFileSync('git', args, {
220
+ cwd: this.root,
221
+ encoding: 'utf8',
222
+ stdio: ['ignore', 'pipe', 'ignore'],
223
+ }).trim();
224
+ } catch (_) {
225
+ return '';
226
+ }
227
+ };
228
+
229
+ const remoteHead = readGit(['symbolic-ref', '--quiet', '--short', 'refs/remotes/origin/HEAD']);
230
+ const currentBranch = readGit(['symbolic-ref', '--quiet', '--short', 'HEAD']) || null;
231
+ const defaultBranch = remoteHead
232
+ ? remoteHead.replace(/^origin\//, '')
233
+ : currentBranch;
234
+
235
+ return {
236
+ defaultBranch: defaultBranch || null,
237
+ currentBranch,
238
+ };
239
+ }
203
240
  }
204
241
 
205
242
  module.exports = CodebaseAnalyzer;