Skip to main content

Storybook Git Metadata Generation

Status: Stable This guide explains how to generate git metadata for Storybook builds, enabling the design tests library to detect the current deployment version being tested.

Overview​

The design tests library can automatically detect the current deployment version by reading /git-metadata.json from your Storybook build. This file contains git commit information and is generated during the Storybook build process.

What it provides:

  • Git commit hash and branch
  • Commit message and author
  • Timestamp and build metadata
  • Link to commit/build for traceability

Why it's needed:

  • Tracks which deployment is being tested
  • Enables baseline version tracking
  • Provides attribution for visual changes
  • Helps debug "what changed" questions

Implementation Steps​

1. Create the Generator Script​

Create .storybook/scripts/generate-git-metadata.js:

const fs = require('fs');
const { execSync } = require('child_process');
const path = require('path');

/**
* Generate git metadata for design tests
*
* Creates a git-metadata.json file with current git state
* to be included in the Storybook static build.
*/
function generateGitMetadata() {
try {
// Extract git information
const gitHash = execSync('git rev-parse HEAD').toString().trim();
const shortHash = execSync('git rev-parse --short HEAD').toString().trim();
const branch = execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
const commitMessage = execSync('git log -1 --pretty=%B | head -n 1').toString().trim();
const author = execSync('git log -1 --pretty="%an <%ae>"').toString().trim();
const timestamp = new Date().toISOString();

// Build reference string (format: {hash}|{branch}|{timestamp})
const reference = `${branch}_${shortHash}_${timestamp}`;

// Generate reference link (customize for your git hosting)
// Examples:
// - Bitbucket: `https://bitbucket.org/your-org/repo/commits/${gitHash}`
// - GitHub: `https://github.com/your-org/repo/commit/${gitHash}`
// - GitLab: `https://gitlab.com/your-org/repo/-/commit/${gitHash}`
const referenceLink = `https://bitbucket.org/your-org/your-repo/commits/${gitHash}`;

// Build metadata object
const metadata = {
reference,
referenceLink,
createdAt: timestamp,
gitHash,
branch,
commitMessage,
author,
};

// Ensure output directory exists
const outputDir = path.join(__dirname, '../generated');
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}

// Write metadata file
const outputPath = path.join(outputDir, 'git-metadata.json');
fs.writeFileSync(outputPath, JSON.stringify(metadata, null, 2), 'utf-8');

console.log('✅ Generated git-metadata.json');
console.log(` Reference: ${reference}`);
console.log(` Link: ${referenceLink}`);
} catch (error) {
console.warn('⚠️ Could not generate git metadata:', error.message);
console.warn(' Design tests will use fallback detection');
// Non-fatal - tests can still run without this metadata
}
}

// Run if called directly
if (require.main === module) {
generateGitMetadata();
}

module.exports = { generateGitMetadata };

Customize the reference link:

  • Update the referenceLink URL to match your git hosting provider
  • Add build number or other metadata if running in CI

2. Configure Storybook to Include the File​

Update .storybook/main.js or .storybook/main.ts:

module.exports = {
// ... other config

staticDirs: [
'../public',
// Serve generated files at root (includes git-metadata.json)
{ from: '../.storybook/generated', to: '/' },
],

// ... rest of config
};

How it works:

  • Files in .storybook/generated/ are served at the root of the Storybook
  • /git-metadata.json becomes accessible at https://your-storybook.com/git-metadata.json
  • Design tests library fetches this file during test preparation

3. Update Build Script​

Update package.json to run the generator before building:

{
"scripts": {
"build-storybook": "node .storybook/scripts/generate-git-metadata.js && storybook build",
"build-storybook:ci": "node .storybook/scripts/generate-git-metadata.js && storybook build --quiet"
}
}

4. Add to .gitignore​

Add the generated directory to .gitignore:

# Storybook generated files
.storybook/generated/

Why ignore it:

  • Generated during build, not source code
  • Contains git hash specific to current commit
  • Should be regenerated on each build

CI Integration (Jenkins Example)​

If you're building Storybook in CI, you might want to include build metadata:

// .storybook/scripts/generate-git-metadata.js (CI section)

function generateGitMetadata() {
try {
// ... git extraction code ...

// Add CI-specific metadata
const metadata = {
reference,
referenceLink,
createdAt: timestamp,
gitHash,
branch,
commitMessage,
author,
// CI-specific fields
...(process.env.JENKINS_URL && {
buildNumber: process.env.BUILD_NUMBER,
buildUrl: `${process.env.JENKINS_URL}job/${process.env.JOB_NAME}/${process.env.BUILD_NUMBER}`,
jobName: process.env.JOB_NAME,
}),
};

// ... rest of code ...
}
}

Testing the Setup​

After implementing, verify the metadata is accessible:

  1. Build Storybook:

    npm run build-storybook
  2. Check the generated file:

    cat .storybook/generated/git-metadata.json

    Should output:

    {
    "reference": "abc123d|develop|2025-10-28T14:00:00.000Z",
    "referenceLink": "https://bitbucket.org/.../commits/abc123d...",
    "createdAt": "2025-10-28T14:00:00.000Z",
    "gitHash": "abc123def456789...",
    "branch": "develop",
    "commitMessage": "feat: add new component",
    "author": "John Doe <john@example.com>"
    }
  3. Serve and test:

    npx http-server storybook-static -p 8080
    curl http://localhost:8080/git-metadata.json
  4. Run design tests:

    # The library will automatically detect the metadata
    pnpm run design-tests run --project storybook

    Look for this in the output:

    🔍 Detecting current deployment metadata...
    ✓ Current metadata detected from /git-metadata.json
    ✓ Current: abc123d|develop|2025-10-28T14:00:00.000Z
    Link: https://bitbucket.org/.../commits/abc123d...

Fallback Detection​

If /git-metadata.json is not available, the design tests library will fall back to:

  1. Environment variables:

    CURRENT_REFERENCE="abc123|develop|2025-10-28T14:00:00Z" \
    CURRENT_REFERENCE_LINK="https://example.com/commit/abc123" \
    pnpm test
  2. Legacy meta tag detection:

    <meta name="git-commit" content="abc123def456">
  3. Unknown fallback:

    reference: "unknown|unknown|{current-timestamp}"

Benefits​

✅ Automatic version tracking - No manual configuration needed ✅ Traceability - Link back to exact commit being tested ✅ Debugging - Know exactly what changed when tests fail ✅ Baseline attribution - Track which commit created current baseline ✅ CI-friendly - Works in Jenkins, GitHub Actions, etc.

Example Repositories​

  • BFH Storybook: bfh-web/.storybook/scripts/generate-git-metadata.js
  • MCHWEB Storybook: mchweb-design-tests/.storybook/scripts/generate-git-metadata.js
  • EWZ Design System: ewz-design-system/.storybook/scripts/generate-git-metadata.js

Troubleshooting​

Q: The file isn't accessible at /git-metadata.json A: Check that staticDirs in .storybook/main.js includes the generated directory with to: '/'

Q: Git commands fail during build A: Ensure the build runs in a git repository (not a shallow clone or .zip download)

Q: Design tests still show "unknown" reference A: Verify the file exists and is valid JSON. Check browser console for fetch errors.

Q: Can I use a different filename? A: Yes, but you'll need to customize the detectCurrentMeta function in the library