|
1 | 1 | # Workflow Concurrency Validator |
2 | | - |
3 | 2 | This GitHub Action validates that the concurrency usage across workflows in a repository does not exceed a specified limit. It helps prevent abuse of GitHub's concurrent job limits by analyzing workflow files and detecting potential parallel execution. |
4 | 3 |
|
5 | 4 | ## What it checks |
6 | | - |
7 | 5 | - Top-level concurrency settings in workflows |
8 | 6 | - Job-level concurrency settings |
9 | 7 | - Implicit concurrency from jobs that run in parallel (no dependencies) |
10 | | -- Respects `cancel-in-progress: true` which doesn't count toward concurrency limits |
| 8 | +- Matrix job combinations |
| 9 | +- Jobs within the same workflow run that can execute in parallel |
| 10 | + |
| 11 | +## Important Notes |
| 12 | +- Jobs within the same workflow run can execute in parallel even with `cancel-in-progress: true` |
| 13 | +- `cancel-in-progress` only affects concurrent workflow runs, not jobs within the same workflow |
| 14 | +- Matrix jobs are counted by their total number of combinations |
| 15 | +- Dependencies between jobs (`needs:`) are properly analyzed to identify truly parallel execution paths |
11 | 16 |
|
12 | 17 | ## Installation |
13 | 18 |
|
@@ -189,28 +194,87 @@ jobs: |
189 | 194 | | `details` | JSON object with detailed information about concurrency usage | |
190 | 195 |
|
191 | 196 | ## Development and Building |
| 197 | +This action is written in TypeScript and uses [@vercel/ncc](https://github.com/vercel/ncc) to bundle all dependencies into a single file. |
192 | 198 |
|
193 | | -This action uses [@vercel/ncc](https://github.com/vercel/ncc) to bundle all dependencies into a single file. If you make changes to the action, follow these steps to rebuild it: |
194 | | - |
| 199 | +### Setting Up Development Environment |
195 | 200 | 1. Install dependencies: |
196 | 201 | ```bash |
197 | 202 | npm install |
198 | 203 | ``` |
199 | | - |
200 | 204 | 2. Install development dependencies: |
201 | 205 | ```bash |
202 | 206 | npm install --save-dev @vercel/ncc |
203 | 207 | ``` |
204 | 208 |
|
205 | | -3. Make your changes to `validate-concurrency.js` |
206 | | - |
| 209 | +### Development Workflow |
| 210 | +1. Make changes to files in the `src/` directory |
| 211 | +2. Run type checking: |
| 212 | + ```bash |
| 213 | + npm run type-check |
| 214 | + ``` |
| 215 | +3. Run tests: |
| 216 | + ```bash |
| 217 | + npm test |
| 218 | + ``` |
207 | 219 | 4. Build the bundled version: |
208 | 220 | ```bash |
209 | 221 | npm run build |
210 | 222 | ``` |
211 | | - |
212 | 223 | 5. Commit your changes, including the updated `dist/index.js` file |
213 | 224 |
|
| 225 | +### TypeScript Implementation Details |
| 226 | +The action's core functionality is implemented with the following TypeScript interfaces: |
| 227 | +- `WorkflowConcurrency`: Defines the structure of concurrency settings |
| 228 | +- `WorkflowJob`: Represents a job in a workflow file |
| 229 | +- `WorkflowFile`: Describes the overall workflow file structure |
| 230 | +- `ConcurrencyDetail`: Contains detailed information about concurrency usage |
| 231 | + |
| 232 | +### Output Format Examples |
| 233 | +The action provides detailed output in JSON format. Here are examples of the output structure: |
| 234 | + |
| 235 | +#### Details Output |
| 236 | +```json |
| 237 | +[ |
| 238 | + { |
| 239 | + "file": ".github/workflows/build.yml", |
| 240 | + "level": "workflow", |
| 241 | + "type": "standard", |
| 242 | + "counted": true |
| 243 | + }, |
| 244 | + { |
| 245 | + "file": ".github/workflows/test.yml", |
| 246 | + "level": "workflow", |
| 247 | + "type": "cancel-in-progress", |
| 248 | + "counted": false, |
| 249 | + "note": "Only affects concurrent workflow runs" |
| 250 | + }, |
| 251 | + { |
| 252 | + "file": ".github/workflows/matrix.yml", |
| 253 | + "level": "implicit", |
| 254 | + "jobs": ["test"], |
| 255 | + "count": 6, |
| 256 | + "counted": true, |
| 257 | + "note": "Matrix job with 6 combinations" |
| 258 | + }, |
| 259 | + { |
| 260 | + "file": ".github/workflows/deploy.yml", |
| 261 | + "level": "implicit", |
| 262 | + "jobs": ["deploy-staging", "deploy-prod"], |
| 263 | + "count": 2, |
| 264 | + "counted": true, |
| 265 | + "note": "Jobs running in parallel" |
| 266 | + } |
| 267 | +] |
| 268 | +``` |
| 269 | + |
| 270 | +### Issues Output |
| 271 | +```json |
| 272 | +[ |
| 273 | + "Error processing .github/workflows/invalid.yml: Unexpected token in YAML", |
| 274 | + "Total concurrency (12) exceeds maximum allowed (10)" |
| 275 | +] |
| 276 | +``` |
| 277 | + |
214 | 278 | ## Testing |
215 | 279 |
|
216 | 280 | You can test the action with various workflow patterns. The repository includes several example workflow files that demonstrate different concurrency patterns: |
@@ -261,6 +325,104 @@ This action uses a bundled approach to avoid dependency issues. If you encounter |
261 | 325 |
|
262 | 326 | The action uses the modern GitHub Actions output method with environment files. If you're seeing warnings about deprecated commands, make sure you're using the latest version of the action. |
263 | 327 |
|
| 328 | +### Debugging TypeScript Issues |
| 329 | +1. Check the TypeScript configuration in `tsconfig.json` |
| 330 | +2. Run `npm run type-check` to verify types |
| 331 | +3. Ensure all imported modules have proper type definitions |
| 332 | +4. Check the `lib` directory for compiled JavaScript files |
| 333 | + |
| 334 | +### Understanding Concurrency Detection |
| 335 | +The action detects concurrency in several ways: |
| 336 | + |
| 337 | +1. **Explicit workflow-level concurrency**: Set via `concurrency:` at the workflow root |
| 338 | + - Simple string format: `concurrency: group1` |
| 339 | + - Object format with cancel-in-progress: |
| 340 | + ```yaml |
| 341 | + concurrency: |
| 342 | + group: build-group |
| 343 | + cancel-in-progress: true |
| 344 | + ``` |
| 345 | + Note: cancel-in-progress only affects concurrent workflow runs, not jobs within the same workflow |
| 346 | + |
| 347 | +2. **Explicit job-level concurrency**: Set via `concurrency:` in individual jobs |
| 348 | + ```yaml |
| 349 | + jobs: |
| 350 | + job1: |
| 351 | + concurrency: group1 |
| 352 | + job2: |
| 353 | + concurrency: group2 |
| 354 | + ``` |
| 355 | + |
| 356 | +3. **Implicit parallel jobs**: Jobs that can run in parallel based on: |
| 357 | + - No `needs:` dependencies between them |
| 358 | + - Being in the same dependency level |
| 359 | + Example: |
| 360 | + ```yaml |
| 361 | + jobs: |
| 362 | + build: |
| 363 | + runs-on: ubuntu-latest |
| 364 | + steps: [...] |
| 365 | + test: |
| 366 | + runs-on: ubuntu-latest |
| 367 | + steps: [...] |
| 368 | + deploy: |
| 369 | + needs: [build, test] |
| 370 | + runs-on: ubuntu-latest |
| 371 | + steps: [...] |
| 372 | + ``` |
| 373 | + Here, `build` and `test` can run in parallel (count: 2), while `deploy` runs after them (different level) |
| 374 | + |
| 375 | +4. **Matrix jobs**: Count based on total combinations |
| 376 | + ```yaml |
| 377 | + jobs: |
| 378 | + test: |
| 379 | + strategy: |
| 380 | + matrix: |
| 381 | + os: [ubuntu, windows, macos] |
| 382 | + node: [14, 16] |
| 383 | + runs-on: ${{ matrix.os }} |
| 384 | + steps: [...] |
| 385 | + ``` |
| 386 | + This counts as 6 concurrent jobs (3 OS × 2 Node.js versions) |
| 387 | + |
| 388 | +#### Example Concurrency Calculations |
| 389 | + |
| 390 | +1. Simple workflow with two parallel jobs: |
| 391 | + ```yaml |
| 392 | + jobs: |
| 393 | + job1: |
| 394 | + runs-on: ubuntu-latest |
| 395 | + job2: |
| 396 | + runs-on: ubuntu-latest |
| 397 | + ``` |
| 398 | + Total concurrency: 2 (both jobs can run in parallel) |
| 399 | + |
| 400 | +2. Workflow with cancel-in-progress and parallel jobs: |
| 401 | + ```yaml |
| 402 | + concurrency: |
| 403 | + group: build |
| 404 | + cancel-in-progress: true |
| 405 | + jobs: |
| 406 | + job1: |
| 407 | + runs-on: ubuntu-latest |
| 408 | + job2: |
| 409 | + runs-on: ubuntu-latest |
| 410 | + ``` |
| 411 | + Total concurrency: 2 (jobs can still run in parallel within the same workflow) |
| 412 | + |
| 413 | +3. Matrix job with dependencies: |
| 414 | + ```yaml |
| 415 | + jobs: |
| 416 | + test: |
| 417 | + strategy: |
| 418 | + matrix: |
| 419 | + os: [ubuntu, windows] |
| 420 | + node: [14, 16] |
| 421 | + deploy: |
| 422 | + needs: [test] |
| 423 | + ``` |
| 424 | + Total concurrency: 4 (2 OS × 2 Node.js versions in parallel, deploy runs after) |
| 425 | + |
264 | 426 | ## How to Contribute |
265 | 427 |
|
266 | 428 | Contributions are welcome! Please feel free to submit a Pull Request. |
|
0 commit comments