@scrymore/scry-deployer 0.3.2 → 0.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.
Files changed (3) hide show
  1. package/bin/cli.js +6 -2
  2. package/lib/init.js +40 -43
  3. package/package.json +1 -1
package/bin/cli.js CHANGED
@@ -409,9 +409,13 @@ async function main() {
409
409
  alias: 'skipGhSetup'
410
410
  })
411
411
  .option('commit-api-key', {
412
- describe: 'Commit API key in config file (not recommended)',
412
+ describe: 'Write the API key into the committed config file (not recommended)',
413
413
  type: 'boolean',
414
- default: true,
414
+ // False by default. The description has always said "not
415
+ // recommended" while the default said otherwise, and the
416
+ // default won: every `init` wrote a customer's key into a
417
+ // file it then committed.
418
+ default: false,
415
419
  alias: 'commitApiKey'
416
420
  })
417
421
  .option('verbose', {
package/lib/init.js CHANGED
@@ -47,19 +47,27 @@ async function runInit(argv) {
47
47
  // Step 3: Create config file
48
48
  const step3Start = Date.now();
49
49
  logger.info('3/8: Creating configuration file...');
50
- createConfigFile(argv.project, argv.apiKey, argv.apiUrl, envInfo);
50
+ createConfigFile(argv.project, argv.apiKey, argv.apiUrl, envInfo, argv.commitApiKey);
51
51
  const step3Duration = Date.now() - step3Start;
52
52
  logger.success(`✅ Created .storybook-deployer.json [${step3Duration}ms]\n`);
53
53
 
54
- // Step 4: Add to gitignore (optional - keep API key out of git if user prefers)
54
+ // Step 4: Report what the committed config does and does not contain.
55
+ //
56
+ // This step used to add `.storybook-deployer.json` to .gitignore, which was
57
+ // wrong in both directions. The config now holds no credential, so ignoring
58
+ // it would only stop a team sharing its project id — and the entry it wrote,
59
+ // `.storybook-deployer.json # Contains API key`, never matched anything:
60
+ // in .gitignore a `#` is only a comment at the start of a line, so the
61
+ // pattern included the trailing text and git ignored no file.
55
62
  const step4Start = Date.now();
56
- if (!argv.commitApiKey) {
57
- logger.info('4/8: Updating .gitignore...');
58
- updateGitignore();
59
- const step4Duration = Date.now() - step4Start;
60
- logger.success(`✅ Updated .gitignore (API key will use env vars in CI) [${step4Duration}ms]\n`);
63
+ if (argv.commitApiKey) {
64
+ logger.info('4/8: Checking credentials...');
65
+ logger.error(`⚠️ --commit-api-key: your API key will be written to .storybook-deployer.json and committed.
66
+ Git history keeps it after rotation, and CI does not need it — the key is
67
+ already stored as the SCRY_API_KEY repository secret. [${Date.now() - step4Start}ms]\n`);
61
68
  } else {
62
- logger.info('4/8: Skipping .gitignore update (--commit-api-key flag set)\n');
69
+ logger.info('4/8: Checking credentials...');
70
+ logger.success(`✅ .storybook-deployer.json holds no credentials — safe to commit [${Date.now() - step4Start}ms]\n`);
63
71
  }
64
72
 
65
73
  // Step 5: Generate workflow files
@@ -94,7 +102,7 @@ async function runInit(argv) {
94
102
  // Step 7: Git commit
95
103
  const step7Start = Date.now();
96
104
  logger.info('7/8: Committing changes...');
97
- const commitResult = gitCommit(argv.commitApiKey, logger);
105
+ const commitResult = gitCommit(logger);
98
106
  const step7Duration = Date.now() - step7Start;
99
107
  if (commitResult.success) {
100
108
  logger.success(`✅ Changes committed: ${commitResult.sha} [${step7Duration}ms]\n`);
@@ -236,7 +244,7 @@ function parseGitHubRemote(remote) {
236
244
  /**
237
245
  * Create the configuration file
238
246
  */
239
- function createConfigFile(projectId, apiKey, apiUrl, envInfo) {
247
+ function createConfigFile(projectId, apiKey, apiUrl, envInfo, commitApiKey) {
240
248
  const config = {
241
249
  apiUrl: apiUrl,
242
250
  project: projectId,
@@ -245,10 +253,19 @@ function createConfigFile(projectId, apiKey, apiUrl, envInfo) {
245
253
  verbose: false
246
254
  };
247
255
 
248
- // Only include apiKey in config if user wants it committed
249
- // Otherwise it should be set via environment variable
250
- // For now, we'll include it but note in .gitignore
251
- config.apiKey = apiKey;
256
+ // The key is deliberately absent unless explicitly asked for.
257
+ //
258
+ // This file gets committed, and CI never reads the key from it `init` sets
259
+ // SCRY_API_KEY as a GitHub *secret* and the generated workflow reads
260
+ // ${{ secrets.SCRY_API_KEY }}. So a copy here buys nothing and lands
261
+ // somewhere git history makes permanent: rotating the key afterwards does
262
+ // not remove it, and on a public repository it is simply disclosed.
263
+ //
264
+ // Local runs read SCRY_API_KEY from the environment, which lib/config.js
265
+ // already resolves.
266
+ if (commitApiKey) {
267
+ config.apiKey = apiKey;
268
+ }
252
269
 
253
270
  const configPath = '.storybook-deployer.json';
254
271
  fs.writeFileSync(
@@ -258,28 +275,6 @@ function createConfigFile(projectId, apiKey, apiUrl, envInfo) {
258
275
  );
259
276
  }
260
277
 
261
- /**
262
- * Update .gitignore to exclude sensitive files (optional)
263
- */
264
- function updateGitignore() {
265
- const gitignorePath = '.gitignore';
266
- const entries = [
267
- '# Scry Storybook Deployer',
268
- '.storybook-deployer.json # Contains API key'
269
- ];
270
-
271
- let gitignoreContent = '';
272
- if (fs.existsSync(gitignorePath)) {
273
- gitignoreContent = fs.readFileSync(gitignorePath, 'utf8');
274
- }
275
-
276
- // Check if already added
277
- if (!gitignoreContent.includes('.storybook-deployer.json')) {
278
- gitignoreContent += '\n' + entries.join('\n') + '\n';
279
- fs.writeFileSync(gitignorePath, gitignoreContent, 'utf8');
280
- }
281
- }
282
-
283
278
  /**
284
279
  * Generate workflow files
285
280
  */
@@ -367,7 +362,7 @@ Or install GitHub CLI and run:
367
362
  /**
368
363
  * Commit the changes to git
369
364
  */
370
- function gitCommit(commitApiKey, logger) {
365
+ function gitCommit(logger) {
371
366
  try {
372
367
  // Check if there are changes to commit
373
368
  const status = execSync('git status --porcelain', { encoding: 'utf8' });
@@ -382,10 +377,6 @@ function gitCommit(commitApiKey, logger) {
382
377
  '.storybook-deployer.json'
383
378
  ];
384
379
 
385
- if (!commitApiKey) {
386
- filesToAdd.push('.gitignore');
387
- }
388
-
389
380
  for (const file of filesToAdd) {
390
381
  if (fs.existsSync(file)) {
391
382
  execSync(`git add "${file}"`, { stdio: 'pipe' });
@@ -449,7 +440,7 @@ function showSuccessMessage(projectId, envInfo, apiUrl, pushed) {
449
440
  Your Storybook deployment is configured and ready to go.
450
441
 
451
442
  📦 What was set up:
452
- ✅ Configuration file (.storybook-deployer.json)
443
+ ✅ Configuration file (.storybook-deployer.json — no credentials, safe to commit)
453
444
  ✅ GitHub Actions workflows (.github/workflows/)
454
445
  ✅ Repository variables (SCRY_PROJECT_ID, SCRY_API_URL)
455
446
  ✅ Repository secret (SCRY_API_KEY)
@@ -461,6 +452,12 @@ ${!pushed ? `
461
452
  git push
462
453
  ` : ''}
463
454
 
455
+ 🔑 Running a deploy locally:
456
+ CI reads the key from the SCRY_API_KEY secret. On your own machine, export it
457
+ rather than writing it into the config file, which is committed:
458
+
459
+ export SCRY_API_KEY=<your key>
460
+
464
461
  🚀 Deployment:
465
462
  Your Storybook will deploy automatically on:
466
463
  • Every push to ${envInfo.currentBranch || 'main'} branch
@@ -477,4 +474,4 @@ Happy deploying! ✨
477
474
  `);
478
475
  }
479
476
 
480
- module.exports = { runInit };
477
+ module.exports = { runInit, createConfigFile };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrymore/scry-deployer",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "A CLI to automate the deployment of Storybook static builds.",
5
5
  "main": "index.js",
6
6
  "bin": {