cistack 3.2.0 → 5.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,245 @@
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
- ---
75
+ This writes `cistack.config.js` with the supported override keys.
77
76
 
78
- ## Flags
77
+ ## What gets generated
79
78
 
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`)
79
+ ### `pipeline.yml`
87
80
 
88
- ---
81
+ By default, `cistack` now generates a single GitHub Actions workflow that combines CI, deploy, Docker, security, and release jobs into one place so teams can track the whole pipeline from one file.
89
82
 
90
- ## Detected Hosting Platforms
83
+ - Includes lint, test, build, E2E, deploy, Docker, security, and release jobs when those parts of the stack are detected
84
+ - Uses the detected default branch or your configured `branches`
85
+ - Keeps preview deploys, release jobs, and scheduled security scans in the same workflow file
86
+ - Documents required secrets in the file header
91
87
 
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` |
88
+ ### `dependabot.yml`
105
89
 
106
- ---
90
+ Dependabot remains a separate file in `.github/dependabot.yml`, because it is not a GitHub Actions workflow.
107
91
 
108
- ## Detected Frameworks
92
+ ### Split mode
109
93
 
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)
94
+ If you prefer the old multi-file layout, set:
117
95
 
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 |
96
+ ```js
97
+ module.exports = {
98
+ workflowLayout: 'split',
99
+ };
100
+ ```
133
101
 
134
- ---
102
+ In split mode, `cistack` writes separate `ci.yml`, `deploy.yml`, `docker.yml`, `security.yml`, and `release.yml` files again.
103
+
104
+ ## Supported detection
105
+
106
+ ### Hosting
107
+
108
+ - Firebase
109
+ - Vercel
110
+ - Netlify
111
+ - GitHub Pages
112
+ - AWS
113
+ - GCP App Engine
114
+ - Azure
115
+ - Heroku
116
+ - Render
117
+ - Railway
118
+ - Docker
119
+
120
+ ### Frameworks
121
+
122
+ - Next.js
123
+ - Nuxt
124
+ - SvelteKit
125
+ - Remix
126
+ - Astro
127
+ - Vite
128
+ - React
129
+ - Vue
130
+ - Angular
131
+ - Svelte
132
+ - Gatsby
133
+ - Express
134
+ - Fastify
135
+ - NestJS
136
+ - Hono
137
+ - Koa
138
+ - Django
139
+ - Flask
140
+ - FastAPI
141
+ - Rails
142
+ - Spring Boot
143
+ - Laravel
144
+ - Go
145
+ - Rust
146
+
147
+ ### Testing tools
148
+
149
+ - Jest
150
+ - Vitest
151
+ - Mocha
152
+ - Cypress
153
+ - Playwright
154
+ - Pytest
155
+ - RSpec
156
+ - Go test
157
+ - Cargo test
158
+ - PHPUnit
159
+ - Maven / JUnit
160
+ - Storybook
161
+
162
+ ## Configuration
163
+
164
+ Create `cistack.config.js` when you want to override detection:
165
+
166
+ ```js
167
+ /** @type {import('cistack').Config} */
168
+ module.exports = {
169
+ nodeVersion: '20',
170
+ packageManager: 'pnpm',
171
+ branches: ['main', 'staging'],
172
+ workflowLayout: 'single',
173
+ hosting: ['Vercel'],
174
+ outputDir: '.github/workflows',
175
+
176
+ cache: {
177
+ npm: true,
178
+ cargo: true,
179
+ pip: true,
180
+ },
181
+
182
+ monorepo: {
183
+ perPackage: true,
184
+ },
185
+
186
+ release: {
187
+ tool: 'semantic-release',
188
+ },
189
+ };
190
+ ```
135
191
 
136
- ## Generated Workflows
192
+ Supported top-level config keys:
137
193
 
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
194
+ - `nodeVersion`
195
+ - `packageManager`
196
+ - `hosting`
197
+ - `frameworks`
198
+ - `testing`
199
+ - `branches`
200
+ - `workflowLayout`
201
+ - `cache`
202
+ - `monorepo`
203
+ - `release`
204
+ - `secrets`
205
+ - `outputDir`
145
206
 
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
207
+ Branch behavior:
151
208
 
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)
209
+ - If `branches` is set in config, `cistack` uses it exactly
210
+ - Otherwise it reads the repository's default branch from Git metadata when available
211
+ - If Git metadata is unavailable, it falls back to safe defaults like `main`, `master`, and `develop` depending on the workflow type
157
212
 
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
213
+ ## Secrets
162
214
 
163
- ---
215
+ Generated deploy and release workflows document the secrets they need at the top of each file. Add them in:
164
216
 
165
- ## Required Secrets
217
+ `GitHub -> Settings -> Secrets and variables -> Actions`
166
218
 
167
- After generating, add the required secrets to your repository at:
168
- `Settings → Secrets and variables → Actions`
219
+ ## Development and Quality
169
220
 
170
- Each generated `deploy.yml` has a comment at the top listing the exact secrets needed.
221
+ The project now includes a regression suite for the areas that were historically the easiest to break:
171
222
 
172
- ---
223
+ - config override handling
224
+ - default branch detection
225
+ - deploy branch selection
226
+ - Netlify production branch handling
227
+ - smart merge behavior
228
+ - monorepo per-package build script lookup
229
+ - release config detection
230
+ - release workflow generation
231
+ - CLI dry-run smoke testing
173
232
 
174
- ## Examples
233
+ Run the checks locally:
175
234
 
176
- **Next.js + Vercel project with Audit:**
177
235
  ```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
236
+ npm test
237
+ npm run test:smoke
238
+ node bin/ciflow.js audit --path .
239
+ node bin/ciflow.js upgrade --path . --dry-run
181
240
  ```
182
241
 
183
- ---
242
+ If you are using the published package, the executable is `cistack`. In this repository, the local entrypoint is `bin/ciflow.js`.
184
243
 
185
244
  ## License
186
245
 
package/bin/ciflow.js CHANGED
@@ -87,7 +87,8 @@ 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
+ // workflowLayout: 'single', // 'single' (default) or 'split'
91
92
  // outputDir: '.github/workflows', // Where to write workflow files
92
93
 
93
94
  // cache: {
@@ -101,7 +102,7 @@ module.exports = {
101
102
  // },
102
103
 
103
104
  // monorepo: {
104
- // perPackage: true, // Generate one ci-<name>.yml per workspace
105
+ // perPackage: true, // Generate one ci-<name>.yml per workspace (split layout only)
105
106
  // },
106
107
 
107
108
  // release: {
package/index.d.ts ADDED
@@ -0,0 +1,91 @@
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
+ workflowLayout?: 'single' | 'split';
67
+ cache?: CacheConfig;
68
+ monorepo?: MonorepoConfig;
69
+ release?: ReleaseTool | ReleaseConfig;
70
+ secrets?: string[];
71
+ outputDir?: string;
72
+ }
73
+
74
+ export interface CIFlowOptions {
75
+ projectPath: string;
76
+ outputDir?: string;
77
+ dryRun?: boolean;
78
+ force?: boolean;
79
+ prompt?: boolean;
80
+ verbose?: boolean;
81
+ explain?: boolean;
82
+ }
83
+
84
+ declare class CIFlow {
85
+ constructor(options: CIFlowOptions);
86
+ run(): Promise<void>;
87
+ audit(): Promise<void>;
88
+ upgrade(): Promise<void>;
89
+ }
90
+
91
+ export default CIFlow;
package/package.json CHANGED
@@ -1,14 +1,16 @@
1
1
  {
2
2
  "name": "cistack",
3
- "version": "3.2.0",
3
+ "version": "5.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;