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.
- package/.github/workflows/ci.yml +70 -0
- package/README.md +202 -130
- package/bin/ciflow.js +1 -1
- package/index.d.ts +90 -0
- package/package.json +4 -2
- package/src/analyzers/codebase.js +43 -6
- package/src/analyzers/monorepo.js +7 -7
- package/src/analyzers/workflow.js +10 -2
- package/src/config/loader.js +65 -10
- package/src/detectors/framework.js +29 -25
- package/src/detectors/hosting.js +25 -10
- package/src/detectors/language.js +2 -2
- package/src/detectors/release.js +29 -8
- package/src/detectors/testing.js +18 -2
- package/src/generators/dependabot.js +24 -3
- package/src/generators/release.js +25 -10
- package/src/generators/workflow.js +348 -92
- package/src/index.js +34 -17
- package/src/utils/helpers.js +21 -7
- package/tests/run.js +808 -0
|
@@ -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
|
-
>
|
|
3
|
+
> Generate GitHub Actions CI/CD pipelines by analyzing the codebase you already have.
|
|
4
4
|
|
|
5
|
-
`cistack` scans your project
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
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
|
-
#
|
|
22
|
+
# One-off usage
|
|
29
23
|
npx cistack
|
|
30
24
|
|
|
31
|
-
#
|
|
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
|
|
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
|
-
|
|
46
|
-
npx cistack --explain
|
|
35
|
+
`generate` is the default command, so both of these work:
|
|
47
36
|
|
|
48
|
-
|
|
49
|
-
npx cistack
|
|
37
|
+
```bash
|
|
38
|
+
npx cistack
|
|
39
|
+
npx cistack generate
|
|
40
|
+
```
|
|
50
41
|
|
|
51
|
-
|
|
52
|
-
npx cistack --output .github/workflows
|
|
42
|
+
Common options:
|
|
53
43
|
|
|
54
|
-
|
|
55
|
-
npx cistack --
|
|
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
|
|
59
|
-
|
|
52
|
+
### Audit existing workflows
|
|
53
|
+
|
|
60
54
|
```bash
|
|
61
55
|
npx cistack audit
|
|
62
56
|
```
|
|
63
57
|
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
71
|
-
|
|
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
|
-
|
|
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
|
-
|
|
81
|
+
Continuous integration for linting, tests, builds, coverage upload, and optional E2E jobs.
|
|
109
82
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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
|
-
|
|
206
|
+
Supported top-level config keys:
|
|
137
207
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
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
|
-
|
|
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
|
-
|
|
153
|
-
|
|
154
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
230
|
+
`GitHub -> Settings -> Secrets and variables -> Actions`
|
|
166
231
|
|
|
167
|
-
|
|
168
|
-
`Settings → Secrets and variables → Actions`
|
|
232
|
+
## Development and Quality
|
|
169
233
|
|
|
170
|
-
|
|
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
|
-
|
|
246
|
+
Run the checks locally:
|
|
175
247
|
|
|
176
|
-
**Next.js + Vercel project with Audit:**
|
|
177
248
|
```bash
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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:
|
|
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
|
+
"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
|
|
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
|
|
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:
|
|
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
|
-
'
|
|
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;
|