cistack 5.2.0 → 5.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cistack",
3
- "version": "5.2.0",
3
+ "version": "5.3.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",
@@ -422,7 +422,7 @@ class WorkflowGenerator {
422
422
  if (previewSteps.length > 0) {
423
423
  jobs.preview = {
424
424
  name: `✨ Deploy → ${h.name} (Preview)`,
425
- if: "github.event_name == 'pull_request'",
425
+ if: "github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' && github.event.pull_request.head.repo.full_name == github.repository",
426
426
  'runs-on': 'ubuntu-latest',
427
427
  environment: 'preview',
428
428
  steps: [
@@ -883,20 +883,29 @@ class WorkflowGenerator {
883
883
  };
884
884
  steps.push(
885
885
  { name: 'Install Vercel CLI', run: 'npm install -g vercel' },
886
+ {
887
+ name: 'Validate Vercel credentials',
888
+ run: [
889
+ 'test -n "$VERCEL_TOKEN" || (echo "Missing VERCEL_TOKEN secret. Add it in GitHub Actions secrets." && exit 1)',
890
+ 'test -n "$VERCEL_ORG_ID" || (echo "Missing VERCEL_ORG_ID secret. Add it in GitHub Actions secrets." && exit 1)',
891
+ 'test -n "$VERCEL_PROJECT_ID" || (echo "Missing VERCEL_PROJECT_ID secret. Add it in GitHub Actions secrets." && exit 1)',
892
+ ].join('\n'),
893
+ env: vercelEnv,
894
+ },
886
895
  {
887
896
  name: 'Pull Vercel environment',
888
- run: `vercel pull --yes --environment=${isPreview ? 'preview' : 'production'} --token=\${{ secrets.VERCEL_TOKEN }}`,
897
+ run: `vercel pull --yes --environment=${isPreview ? 'preview' : 'production'} --token="$VERCEL_TOKEN"`,
889
898
  env: vercelEnv,
890
899
  },
891
900
  {
892
901
  name: 'Build project',
893
- run: `vercel build${prodFlag ? ' ' + prodFlag : ''} --token=\${{ secrets.VERCEL_TOKEN }}`,
902
+ run: `vercel build${prodFlag ? ' ' + prodFlag : ''} --token="$VERCEL_TOKEN"`,
894
903
  env: vercelEnv,
895
904
  },
896
905
  {
897
906
  name: 'Deploy to Vercel',
898
907
  id: 'deploy',
899
- run: `vercel deploy --prebuilt${prodFlag ? ' ' + prodFlag : ''} --token=\${{ secrets.VERCEL_TOKEN }} > deployment_url.txt && echo "DEPLOYMENT_URL=$(cat deployment_url.txt)" >> $GITHUB_ENV`,
908
+ run: `vercel deploy --prebuilt${prodFlag ? ' ' + prodFlag : ''} --token="$VERCEL_TOKEN" > deployment_url.txt && echo "DEPLOYMENT_URL=$(cat deployment_url.txt)" >> $GITHUB_ENV`,
900
909
  env: vercelEnv,
901
910
  },
902
911
  );
package/tests/run.js CHANGED
@@ -414,6 +414,38 @@ test('combineWorkflows preserves workflow-specific trigger scoping in the unifie
414
414
  assert(!combined.jobs.deploy_deploy.if.includes("github.ref_name == 'develop'"));
415
415
  });
416
416
 
417
+ test('Vercel deploy workflows validate secrets before running vercel pull', () => {
418
+ const projectDir = makeTempDir();
419
+ writeFiles(projectDir, {
420
+ 'package.json': json({
421
+ name: 'vercel-secrets-app',
422
+ version: '1.0.0',
423
+ scripts: {
424
+ build: 'next build',
425
+ },
426
+ }),
427
+ });
428
+
429
+ const workflows = new WorkflowGenerator(
430
+ makeJsProject({
431
+ hosting: [{ name: 'Vercel', secrets: ['VERCEL_TOKEN', 'VERCEL_ORG_ID', 'VERCEL_PROJECT_ID'] }],
432
+ frameworks: [{ name: 'Next.js', confidence: 1, buildDir: '.next' }],
433
+ }),
434
+ projectDir
435
+ ).generate();
436
+
437
+ const deploy = parseWorkflow(workflows.find((workflow) => workflow.filename === 'deploy.yml').content);
438
+ const deploySteps = deploy.jobs.deploy.steps;
439
+ const validateStep = deploySteps.find((step) => step.name === 'Validate Vercel credentials');
440
+ const pullStep = deploySteps.find((step) => step.name === 'Pull Vercel environment');
441
+
442
+ assert(validateStep);
443
+ assert(validateStep.run.includes('Missing VERCEL_TOKEN secret'));
444
+ assert(validateStep.run.includes('Missing VERCEL_ORG_ID secret'));
445
+ assert(validateStep.run.includes('Missing VERCEL_PROJECT_ID secret'));
446
+ assert.equal(pullStep.run, 'vercel pull --yes --environment=production --token="$VERCEL_TOKEN"');
447
+ });
448
+
417
449
  test('Single-layout monorepos still generate the root workspace matrix CI', () => {
418
450
  const projectDir = makeTempDir();
419
451
  const packages = [
@@ -528,6 +560,35 @@ test('Netlify preview configuration uses the detected production branch instead
528
560
  assert.equal(previewStep.with['production-branch'], 'release');
529
561
  });
530
562
 
563
+ test('Preview deploy jobs only run for same-repo pull requests with secrets access', () => {
564
+ const projectDir = makeTempDir();
565
+ writeFiles(projectDir, {
566
+ 'package.json': json({
567
+ name: 'preview-guard-app',
568
+ version: '1.0.0',
569
+ scripts: {
570
+ build: 'next build',
571
+ },
572
+ }),
573
+ });
574
+
575
+ const generator = new WorkflowGenerator(
576
+ makeJsProject({
577
+ hosting: [{ name: 'Vercel', secrets: ['VERCEL_TOKEN', 'VERCEL_ORG_ID', 'VERCEL_PROJECT_ID'] }],
578
+ frameworks: [{ name: 'Next.js', confidence: 1, buildDir: '.next' }],
579
+ }),
580
+ projectDir
581
+ );
582
+
583
+ const deploy = generator.generate().find((workflow) => workflow.filename === 'deploy.yml');
584
+ const parsed = parseWorkflow(deploy.content);
585
+
586
+ assert.equal(
587
+ parsed.jobs.preview.if,
588
+ "github.event_name == 'pull_request' && github.actor != 'dependabot[bot]' && github.event.pull_request.head.repo.full_name == github.repository"
589
+ );
590
+ });
591
+
531
592
  test('Generic JavaScript builds no longer upload a fake dist artifact when no build directory is known', () => {
532
593
  const projectDir = makeTempDir();
533
594
  writeFiles(projectDir, {