npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bernierllc/validators-ci-workflow

v1.5.0

Published

Primitive validator for CI/CD workflow validation - GitHub Actions cache, secrets, matrix strategies, and triggers

Readme

@bernierllc/validators-ci-workflow

Primitive validator for GitHub Actions CI/CD workflow validation including cache configuration, secrets handling, matrix strategies, triggers, and job dependencies.

Installation

npm install @bernierllc/validators-ci-workflow

Overview

This validator provides comprehensive validation for GitHub Actions workflows, ensuring best practices for:

  • Cache Configuration - Validates cache keys, paths, and restore strategies
  • Secrets Handling - Detects insecure secret usage and potential exposure
  • Matrix Strategies - Validates matrix job configurations and limits
  • Workflow Triggers - Ensures proper trigger configuration
  • Job Dependencies - Detects circular dependencies and validates job chains

Usage

Basic Validation

import { validateCIWorkflow } from '@bernierllc/validators-ci-workflow';

const workflowContent = JSON.stringify({
  name: 'CI',
  on: { push: { branches: ['main'] } },
  jobs: {
    test: {
      'runs-on': 'ubuntu-latest',
      steps: [{ uses: 'actions/checkout@v3' }]
    }
  }
});

const problems = await validateCIWorkflow(workflowContent);

if (problems.length === 0) {
  console.log('✓ Workflow validation passed');
} else {
  problems.forEach(p => {
    console.log(`${p.severity}: ${p.message} [${p.ruleId}]`);
  });
}

Validate Specific Aspects

import {
  hasValidCacheConfig,
  hasSecureSecretsHandling,
  validateMatrixStrategy,
  validateWorkflowTriggers,
  validateJobDependencies,
} from '@bernierllc/validators-ci-workflow';

// Check cache configuration
const workflow = {
  jobs: {
    build: {
      steps: [
        {
          uses: 'actions/cache@v3',
          with: {
            key: 'node-${{ hashFiles(\'**/package-lock.json\') }}',
            path: 'node_modules'
          }
        }
      ]
    }
  }
};

const hasValidCache = await hasValidCacheConfig(workflow);
const isSecure = await hasSecureSecretsHandling(workflow);

// Validate matrix with custom limits
const matrixProblems = await validateMatrixStrategy(workflow, 50);

// Validate allowed triggers
const triggerProblems = await validateWorkflowTriggers(
  workflow,
  ['push', 'pull_request', 'workflow_dispatch']
);

// Check for dependency issues
const depProblems = await validateJobDependencies(workflow);

Custom Validation Options

import { validateCIWorkflow } from '@bernierllc/validators-ci-workflow';

const problems = await validateCIWorkflow(workflowContent, {
  // Cache configuration
  validateCacheConfig: true,
  requireCacheKey: true,
  allowDynamicCacheKeys: true,

  // Secrets handling
  validateSecretsHandling: true,
  requireSecretPrefix: 'PROD_',
  forbiddenSecretNames: ['PASSWORD', 'SECRET', 'API_KEY'],

  // Matrix strategy
  validateMatrixStrategy: true,
  maxMatrixJobs: 100,
  requireFailFast: true,

  // Workflow triggers
  validateTriggers: true,
  allowedTriggers: ['push', 'pull_request'],
  requirePullRequestTrigger: true,

  // Job dependencies
  validateJobDependencies: true,
  maxDependencyDepth: 5,
  allowCircularDependencies: false,

  // General workflow
  maxWorkflowDuration: 360, // minutes
  requireTimeoutMinutes: true,
  allowedRunners: ['ubuntu-latest', 'macos-latest'],
});

Validation Rules

Cache Configuration Rules

  • cache-config - Validates GitHub Actions cache usage
    • Requires cache key and path
    • Warns about static cache keys
    • Detects secrets in cache keys
    • Validates restore-keys format
// ✓ Good - Dynamic cache key with hashFiles
{
  uses: 'actions/cache@v3',
  with: {
    key: 'node-${{ hashFiles(\'**/package-lock.json\') }}',
    path: 'node_modules'
  }
}

// ✗ Bad - Static cache key
{
  uses: 'actions/cache@v3',
  with: {
    key: 'my-static-key',
    path: 'node_modules'
  }
}

// ✗ Bad - Secret in cache key
{
  uses: 'actions/cache@v3',
  with: {
    key: 'cache-${{ secrets.API_KEY }}',
    path: 'data'
  }
}

Secrets Handling Rules

  • secrets-handling - Validates secure secrets usage
    • Detects secrets in echo commands
    • Warns about secrets written to files
    • Validates secret naming conventions
    • Checks for forbidden secret names
// ✓ Good - Secure secrets usage
{
  env: {
    API_KEY: '${{ secrets.API_KEY }}'
  },
  steps: [
    { run: 'curl -H "Authorization: Bearer $API_KEY" api.example.com' }
  ]
}

// ✗ Bad - Echoing secrets
{
  steps: [
    { run: 'echo ${{ secrets.API_KEY }}' }
  ]
}

// ✗ Bad - Writing secrets to file
{
  steps: [
    { run: 'echo ${{ secrets.API_KEY }} > key.txt' }
  ]
}

Matrix Strategy Rules

  • matrix-strategy - Validates matrix configurations
    • Calculates total matrix jobs
    • Enforces max matrix jobs limit
    • Validates variable names
    • Checks include/exclude consistency
// ✓ Good - Valid matrix
{
  strategy: {
    matrix: {
      os: ['ubuntu-latest', 'macos-latest'],
      node: [16, 18, 20]
    },
    'fail-fast': false
  }
}

// ✗ Bad - Invalid variable name
{
  strategy: {
    matrix: {
      'Invalid-Name': ['value']
    }
  }
}

// ✗ Bad - Too many jobs
{
  strategy: {
    matrix: {
      os: [1,2,3,4,5],
      node: [1,2,3,4,5],
      arch: [1,2,3,4,5]
    }
  }
  // 125 jobs exceeds typical limits
}

Workflow Triggers Rules

  • workflow-triggers - Validates trigger configuration
    • Validates push/pull_request filters
    • Checks schedule cron syntax
    • Validates workflow_dispatch inputs
    • Warns about overly broad triggers
// ✓ Good - Specific triggers
{
  on: {
    push: {
      branches: ['main', 'develop'],
      paths: ['src/**']
    },
    pull_request: {
      types: ['opened', 'synchronize']
    }
  }
}

// ✗ Bad - Overly broad trigger
{
  on: {
    push: {} // Runs on ALL branches
  }
}

// ✗ Bad - Invalid cron syntax
{
  on: {
    schedule: [
      { cron: 'invalid cron' }
    ]
  }
}

Job Dependencies Rules

  • job-dependencies - Validates job dependency chains
    • Detects circular dependencies
    • Validates job references
    • Checks dependency depth
    • Validates timeout configurations
// ✓ Good - Linear dependency chain
{
  jobs: {
    build: { steps: [] },
    test: { needs: 'build', steps: [] },
    deploy: { needs: 'test', steps: [] }
  }
}

// ✗ Bad - Circular dependency
{
  jobs: {
    job1: { needs: 'job2', steps: [] },
    job2: { needs: 'job1', steps: [] }
  }
}

// ✗ Bad - Non-existent dependency
{
  jobs: {
    test: { needs: 'build', steps: [] }
    // 'build' job doesn't exist
  }
}

API Reference

validateCIWorkflow(content, options?, utils?)

Main validation function for GitHub Actions workflows.

Parameters:

  • content (string) - Workflow JSON or YAML string
  • options (Partial) - Optional validation options
  • utils (SharedUtils) - Optional shared utilities

Returns: Promise<Problem[]>

hasValidCacheConfig(workflowData)

Checks if workflow has valid cache configuration.

Parameters:

  • workflowData (unknown) - Workflow object

Returns: Promise<boolean>

hasSecureSecretsHandling(workflowData)

Checks if workflow handles secrets securely.

Parameters:

  • workflowData (unknown) - Workflow object

Returns: Promise<boolean>

validateMatrixStrategy(workflowData, maxJobs?)

Validates matrix strategy configuration.

Parameters:

  • workflowData (unknown) - Workflow object
  • maxJobs (number) - Optional max matrix jobs limit

Returns: Promise<Problem[]>

validateWorkflowTriggers(workflowData, allowedTriggers?)

Validates workflow trigger configuration.

Parameters:

  • workflowData (unknown) - Workflow object
  • allowedTriggers (string[]) - Optional allowed trigger types

Returns: Promise<Problem[]>

validateJobDependencies(workflowData)

Validates job dependencies and detects issues.

Parameters:

  • workflowData (unknown) - Workflow object

Returns: Promise<Problem[]>

Configuration Options

CIWorkflowOptions

interface CIWorkflowOptions {
  // Cache configuration validation
  validateCacheConfig?: boolean;
  requireCacheKey?: boolean;
  allowDynamicCacheKeys?: boolean;

  // Secrets management validation
  validateSecretsHandling?: boolean;
  requireSecretPrefix?: string;
  forbiddenSecretNames?: string[];

  // Matrix strategy validation
  validateMatrixStrategy?: boolean;
  maxMatrixJobs?: number;
  requireFailFast?: boolean;

  // Workflow trigger validation
  validateTriggers?: boolean;
  allowedTriggers?: string[];
  requirePullRequestTrigger?: boolean;

  // Job dependency validation
  validateJobDependencies?: boolean;
  maxDependencyDepth?: number;
  allowCircularDependencies?: boolean;

  // General workflow validation
  maxWorkflowDuration?: number; // minutes
  requireTimeoutMinutes?: boolean;
  allowedRunners?: string[];
}

Integration

With Validators Runner

import { createValidatorRunner } from '@bernierllc/validators-runner';
import { ciWorkflowValidator } from '@bernierllc/validators-ci-workflow';

const runner = createValidatorRunner({
  validators: [ciWorkflowValidator],
  stopOnError: false,
});

const results = await runner.validate(workflowContent);

With CI/CD Pipeline

# .github/workflows/validate-workflows.yml
name: Validate Workflows

on:
  pull_request:
    paths:
      - '.github/workflows/**'

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
      - run: npm install -g @bernierllc/validators-cli
      - run: validators-cli validate-workflow .github/workflows/*.yml

Error Handling

All validation functions return Problem[] with the following structure:

interface Problem {
  ruleId: string;
  message: string;
  severity: 'error' | 'warning' | 'info';
  location: {
    start: number;
    end: number;
  };
  source?: string;
}

Severity Levels:

  • error - Critical issues that must be fixed
  • warning - Potential problems that should be reviewed
  • info - Informational messages for best practices

Best Practices

  1. Always validate workflows in CI - Catch issues before they reach production
  2. Use dynamic cache keys - Include file hashes for better cache invalidation
  3. Never echo secrets - Secrets should only be used in secure contexts
  4. Limit matrix jobs - Set reasonable limits to prevent resource exhaustion
  5. Specify trigger filters - Avoid overly broad triggers that run unnecessarily
  6. Set job timeouts - Prevent runaway jobs from consuming resources
  7. Avoid circular dependencies - Keep job dependency chains linear and shallow

License

Copyright (c) 2025 Bernier LLC. All rights reserved.

Integration Status

  • Logger: Optional - Can integrate for validation event logging
  • Docs-Suite: Ready - Full API documentation with TypeDoc
  • NeverHub: Not applicable - Primitive validator