cistack 5.3.0 → 5.5.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/README.md CHANGED
@@ -89,6 +89,8 @@ By default, `cistack` now generates a single GitHub Actions workflow that combin
89
89
 
90
90
  Dependabot remains a separate file in `.github/dependabot.yml`, because it is not a GitHub Actions workflow.
91
91
 
92
+ If you want preview deployments on Dependabot pull requests, add deployment credentials as Dependabot secrets too, not only Actions secrets. For Vercel, that means `VERCEL_TOKEN`, `VERCEL_ORG_ID`, and `VERCEL_PROJECT_ID`.
93
+
92
94
  ### Split mode
93
95
 
94
96
  If you prefer the old multi-file layout, set:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cistack",
3
- "version": "5.3.0",
3
+ "version": "5.5.0",
4
4
  "description": "Automatically generate GitHub Actions CI/CD pipelines by analysing your codebase",
5
5
  "main": "src/index.js",
6
6
  "types": "index.d.ts",
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ const fs = require('fs');
4
+ const path = require('path');
3
5
  const yaml = require('js-yaml');
4
6
  const { version } = require('../../package.json');
5
7
 
@@ -45,9 +47,6 @@ class WorkflowGenerator {
45
47
  }
46
48
 
47
49
  _detectRuntimeVersions() {
48
- const fs = require('fs');
49
- const path = require('path');
50
-
51
50
  // 1. Node.js
52
51
  if (!this.primaryLang.nodeVersion) {
53
52
  const nvmrcPath = path.join(this.projectPath, '.nvmrc');
@@ -204,7 +203,7 @@ class WorkflowGenerator {
204
203
  with: {
205
204
  uploadArtifacts: true,
206
205
  temporaryPublicStorage: true,
207
- configPath: './.lighthouserc.json',
206
+ ...this._lighthouseActionConfig(),
208
207
  },
209
208
  },
210
209
  ],
@@ -422,7 +421,7 @@ class WorkflowGenerator {
422
421
  if (previewSteps.length > 0) {
423
422
  jobs.preview = {
424
423
  name: `✨ Deploy → ${h.name} (Preview)`,
425
- if: "github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' && github.event.pull_request.head.repo.full_name == github.repository",
424
+ if: "github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository",
426
425
  'runs-on': 'ubuntu-latest',
427
426
  environment: 'preview',
428
427
  steps: [
@@ -430,7 +429,7 @@ class WorkflowGenerator {
430
429
  ...previewSteps,
431
430
  {
432
431
  name: 'Comment PR',
433
- if: 'always()',
432
+ if: "always() && github.actor != 'dependabot[bot]'",
434
433
  uses: 'actions/github-script@v7',
435
434
  with: {
436
435
  script: `
@@ -699,6 +698,11 @@ class WorkflowGenerator {
699
698
  return steps;
700
699
  }
701
700
 
701
+ _lighthouseActionConfig() {
702
+ const configPath = path.join(this.projectPath, '.lighthouserc.json');
703
+ return fs.existsSync(configPath) ? { configPath: './.lighthouserc.json' } : {};
704
+ }
705
+
702
706
  _stepInstallDeps(lang) {
703
707
  const pm = lang.packageManager;
704
708
  if (pm === 'npm') return { name: 'Install dependencies', run: this.lockFiles.has('package-lock.json') ? 'npm ci' : 'npm install' };
package/tests/run.js CHANGED
@@ -494,6 +494,64 @@ test('Frontend Lighthouse is omitted when no build job exists', () => {
494
494
  assert(!parsed.jobs.lighthouse);
495
495
  });
496
496
 
497
+ test('Lighthouse job does not require .lighthouserc.json when the file is absent', () => {
498
+ const projectDir = makeTempDir();
499
+ writeFiles(projectDir, {
500
+ 'package.json': json({
501
+ name: 'lighthouse-default-app',
502
+ version: '1.0.0',
503
+ scripts: {
504
+ build: 'echo build',
505
+ },
506
+ }),
507
+ });
508
+
509
+ const generator = new WorkflowGenerator(
510
+ makeJsProject({
511
+ frameworks: [{ name: 'React', confidence: 1, buildDir: 'dist' }],
512
+ }),
513
+ projectDir
514
+ );
515
+
516
+ const parsed = parseWorkflow(generator._buildCIWorkflow());
517
+ const lighthouseStep = parsed.jobs.lighthouse.steps.find((step) => step.name === 'Run Lighthouse on build output');
518
+
519
+ assert(lighthouseStep);
520
+ assert(!('configPath' in lighthouseStep.with));
521
+ });
522
+
523
+ test('Lighthouse job uses .lighthouserc.json when the file exists', () => {
524
+ const projectDir = makeTempDir();
525
+ writeFiles(projectDir, {
526
+ 'package.json': json({
527
+ name: 'lighthouse-config-app',
528
+ version: '1.0.0',
529
+ scripts: {
530
+ build: 'echo build',
531
+ },
532
+ }),
533
+ '.lighthouserc.json': json({
534
+ ci: {
535
+ collect: {
536
+ numberOfRuns: 1,
537
+ },
538
+ },
539
+ }),
540
+ });
541
+
542
+ const generator = new WorkflowGenerator(
543
+ makeJsProject({
544
+ frameworks: [{ name: 'React', confidence: 1, buildDir: 'dist' }],
545
+ }),
546
+ projectDir
547
+ );
548
+
549
+ const parsed = parseWorkflow(generator._buildCIWorkflow());
550
+ const lighthouseStep = parsed.jobs.lighthouse.steps.find((step) => step.name === 'Run Lighthouse on build output');
551
+
552
+ assert.equal(lighthouseStep.with.configPath, './.lighthouserc.json');
553
+ });
554
+
497
555
  test('E2E jobs fall back to existing jobs instead of depending on a missing build job', () => {
498
556
  const projectDir = makeTempDir();
499
557
  const generator = new WorkflowGenerator(
@@ -560,7 +618,7 @@ test('Netlify preview configuration uses the detected production branch instead
560
618
  assert.equal(previewStep.with['production-branch'], 'release');
561
619
  });
562
620
 
563
- test('Preview deploy jobs only run for same-repo pull requests with secrets access', () => {
621
+ test('Preview deploy jobs run for same-repo pull requests, including Dependabot PRs', () => {
564
622
  const projectDir = makeTempDir();
565
623
  writeFiles(projectDir, {
566
624
  'package.json': json({
@@ -582,11 +640,13 @@ test('Preview deploy jobs only run for same-repo pull requests with secrets acce
582
640
 
583
641
  const deploy = generator.generate().find((workflow) => workflow.filename === 'deploy.yml');
584
642
  const parsed = parseWorkflow(deploy.content);
643
+ const commentStep = parsed.jobs.preview.steps.find((step) => step.name === 'Comment PR');
585
644
 
586
645
  assert.equal(
587
646
  parsed.jobs.preview.if,
588
- "github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' && github.event.pull_request.head.repo.full_name == github.repository"
647
+ "github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository"
589
648
  );
649
+ assert.equal(commentStep.if, "always() && github.actor != 'dependabot[bot]'");
590
650
  });
591
651
 
592
652
  test('Generic JavaScript builds no longer upload a fake dist artifact when no build directory is known', () => {