cistack 5.2.0 → 5.4.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 +2 -0
- package/package.json +1 -1
- package/src/generators/workflow.js +14 -5
- package/tests/run.js +63 -0
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
|
@@ -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.event.pull_request.head.repo.full_name == github.repository",
|
|
426
426
|
'runs-on': 'ubuntu-latest',
|
|
427
427
|
environment: 'preview',
|
|
428
428
|
steps: [
|
|
@@ -430,7 +430,7 @@ class WorkflowGenerator {
|
|
|
430
430
|
...previewSteps,
|
|
431
431
|
{
|
|
432
432
|
name: 'Comment PR',
|
|
433
|
-
if:
|
|
433
|
+
if: "always() && github.actor != 'dependabot[bot]'",
|
|
434
434
|
uses: 'actions/github-script@v7',
|
|
435
435
|
with: {
|
|
436
436
|
script: `
|
|
@@ -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
|
|
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
|
|
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
|
|
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,37 @@ 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 run for same-repo pull requests, including Dependabot PRs', () => {
|
|
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
|
+
const commentStep = parsed.jobs.preview.steps.find((step) => step.name === 'Comment PR');
|
|
586
|
+
|
|
587
|
+
assert.equal(
|
|
588
|
+
parsed.jobs.preview.if,
|
|
589
|
+
"github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository"
|
|
590
|
+
);
|
|
591
|
+
assert.equal(commentStep.if, "always() && github.actor != 'dependabot[bot]'");
|
|
592
|
+
});
|
|
593
|
+
|
|
531
594
|
test('Generic JavaScript builds no longer upload a fake dist artifact when no build directory is known', () => {
|
|
532
595
|
const projectDir = makeTempDir();
|
|
533
596
|
writeFiles(projectDir, {
|