Skip to content

subhamay-bhattacharyya-gha/cfn-stack-params-action

CloudFormation Configuration Processor Action

Built with Kiro GitHub Action Release Commit Activity Bash CloudFormation Last Commit Release Date Repo Size File Count Issues Top Language Custom Endpoint

A GitHub Action that processes CloudFormation deployment configurations, merges parameter and tag files with environment-specific overrides, and generates outputs for CloudFormation stack deployment. Features include parameter and tag processing, dynamic stack naming with CI build integration, automatic GitHub metadata tagging, GitHub Action summaries, and deployment artifact creation.

Features

  • 📁 Flexible Configuration: Reads CloudFormation configurations from customizable folder structures
  • 🔄 Parameter Merging: Automatically merges default parameters with environment-specific overrides
  • 🏷️ Dynamic Stack Naming: Generates appropriate stack names for both CI builds and environment deployments
  • 🎲 CI Build Identifiers: Creates unique identifiers for CI builds to enable parallel deployments
  • 🏷️ Tag Management: Merges default and environment-specific tags with automatic GitHub metadata
  • Comprehensive Validation: Validates JSON files and required fields with clear error messages
  • 📊 GitHub Action Summary: Displays processed parameters, tags, and configuration in the workflow summary
  • 📦 Deployment Artifacts: Creates and uploads deployment JSON files for reuse and audit trails
  • 🧪 Well Tested: Extensive unit and integration test coverage

Quick Start

- name: Process CloudFormation Configuration
  uses: subhamay-bhattacharyya-gha/cfn-stack-params-action@main
  with:
    cfn-directory: 'infrastructure'
    ci-build: 'false'
    environment: 'sb-prod-us-east-1'
  id: cfn-config

- name: Deploy CloudFormation Stack
  uses: subhamay-bhattacharyya/cfn-create-stack-action@main
  with:
    name: ${{ steps.cfn-config.outputs.stack-name }}
    template: infrastructure/template.yaml
    parameter-overrides: ${{ steps.cfn-config.outputs.parameters }}

Table of Contents

Inputs

Name Description Required Default Example
cfn-directory Folder containing CloudFormation configuration files No cfn infrastructure
ci-build Whether this is a CI build (true/false) No false true
environment Target environment name No '' sb-prod-us-east-1
retention-days Number of days to retain the deployment artifact No 7 30

Input Details

cfn-directory

Specifies the folder path (relative to repository root) containing your CloudFormation configuration files. The folder must contain:

  • cloudformation.json - Main configuration file
  • params/ - Subfolder with parameter files

ci-build

Boolean flag that determines the stack naming strategy:

  • true: Uses current Git branch name in stack name (for feature branch deployments)
  • false: Uses environment name in stack name (for environment deployments)

environment

Environment identifier used for:

  • Loading environment-specific parameter files (params/{environment}.json)
  • Stack naming when ci-build is false

retention-days

Specifies how many days to retain the deployment artifact in GitHub Actions. The deployment JSON file containing parameters and stack name will be uploaded as an artifact and retained for the specified number of days. Useful for audit trails and debugging deployment issues.

Outputs

Name Description Type Example
parameters CloudFormation parameters in JSON array format String [{"ParameterName":"VpcId","ParameterValue":"vpc-123"}]
stack-name Generated CloudFormation stack name String myproject-api-sb-prod-us-east-1
template CloudFormation template filename from configuration String infrastructure.yaml
tags CloudFormation tags in JSON array format String [{"Key":"Environment","Value":"production"}]

Output Details

parameters

JSON string containing an array of CloudFormation parameters in the format:

[
  {
    "ParameterName": "ParameterKey",
    "ParameterValue": "ParameterValue"
  }
]

template

CloudFormation template filename as specified in the cloudformation.json configuration file.

tags

JSON string containing an array of CloudFormation tags in the format:

[
  {
    "Key": "TagKey",
    "Value": "TagValue"
  }
]

Tags include user-defined tags from the tags/ directory plus automatically added GitHub metadata tags.

stack-name

Generated stack name following these patterns:

  • CI Build: {project}-{stack-prefix}-{sanitized-branch-name}-{ci-build-id} (automatically includes CI build ID suffix)
  • Environment: {project}-{stack-prefix}-{environment}

For CI builds, the stack name automatically includes a unique CI build identifier suffix and is trimmed to 128 characters if needed to comply with CloudFormation limits.

Configuration Structure

Your CloudFormation configuration should follow this directory structure:

{cfn-directory}/
├── cloudformation.json          # Main configuration
├── params/
│   ├── default.json            # Default parameters (required)
│   ├── sb-devl-us-east-1.json  # Environment-specific parameters
│   ├── sb-test-us-east-1.json  # Environment-specific parameters
│   └── sb-prod-us-east-1.json  # Environment-specific parameters
└── tags/                       # Tags directory (optional)
    ├── default.json            # Default tags
    ├── sb-devl-us-east-1.json  # Environment-specific tags
    ├── sb-test-us-east-1.json  # Environment-specific tags
    └── sb-prod-us-east-1.json  # Environment-specific tags

cloudformation.json

Main configuration file with required fields:

{
  "project": "my-application",
  "template": "infrastructure.yaml",
  "stack-prefix": "api"
}
Field Description Required Example
project Project identifier used in stack naming Yes my-application
template CloudFormation template filename Yes infrastructure.yaml
stack-prefix Stack prefix used in stack naming Yes api

Parameter Files

default.json (Required)

Contains default parameter values that apply to all environments:

{
  "VpcId": "vpc-default",
  "InstanceType": "t3.micro",
  "Environment": "default",
  "EnableLogging": true,
  "BackupRetention": 7
}

{environment}.json (Optional)

Environment-specific parameters that override defaults:

{
  "VpcId": "vpc-prod-123456",
  "InstanceType": "t3.large",
  "Environment": "sb-prod-us-east-1",
  "BackupRetention": 30,
  "AlarmEmail": "alerts@company.com"
}

Tag Files

tags/default.json (Optional)

Contains default tag values that apply to all environments:

{
  "Environment": "default",
  "Project": "my-application",
  "Owner": "DevOps",
  "CostCenter": "Engineering"
}

tags/{environment}.json (Optional)

Environment-specific tags that override defaults:

{
  "Environment": "production",
  "CostCenter": "Production",
  "BackupRequired": "true",
  "Compliance": "SOX"
}

Automatic GitHub Metadata Tags

The action automatically adds these GitHub metadata tags to every deployment:

Tag Name Description Example Value
GitCommit Short commit hash (8 characters) a1b2c3d4
GitLastModifiedBy GitHub actor who triggered the workflow john.doe
GitLastModifiedAt ISO timestamp of action execution 2025-08-01T01:30:45.123Z
GitFile Workflow name Deploy to Production
GitOrg GitHub organization name my-company
GitRepo Repository name my-application

These tags are automatically added and cannot be overridden by user-defined tags.

Parameter Merging Rules:

  1. Default parameters are loaded first
  2. Environment-specific parameters override matching keys
  3. Environment-specific parameters can add new keys
  4. For CI builds, a CiBuildId parameter is automatically added with value -{ci-build-id}
  5. Final output contains merged parameters in CloudFormation format

Tag Merging Rules:

  1. Default tags are loaded first from tags/default.json (optional)
  2. Environment-specific tags override matching keys from tags/{environment}.json (optional)
  3. GitHub metadata tags are automatically added:
    • GitCommit: Short commit hash (8 characters)
    • GitLastModifiedBy: GitHub actor who triggered the workflow
    • GitLastModifiedAt: ISO timestamp of action execution
    • GitFile: Workflow name
    • GitOrg: GitHub organization name
    • GitRepo: Repository name
  4. Final output contains merged tags in CloudFormation format

Deployment Artifacts: The action automatically creates a deployment.json file containing:

  • Processed CloudFormation parameters
  • Processed CloudFormation tags
  • Generated stack name
  • Template path
  • Uploaded as a GitHub Actions artifact for the specified retention period

Usage Examples

Basic Environment Deployment

name: Deploy to Production

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Process CloudFormation Configuration
        uses: subhamay-bhattacharyya-gha/cfn-stack-params-action@main
        with:
          cfn-directory: 'infrastructure'
          ci-build: 'false'
          environment: 'sb-prod-us-east-1'
        id: cfn-config
      
      - name: Deploy Stack
        run: |
          aws cloudformation deploy \
            --stack-name ${{ steps.cfn-config.outputs.stack-name }} \
            --template-file infrastructure/template.yaml \
            --parameter-overrides '${{ steps.cfn-config.outputs.parameters }}' \
            --tags '${{ steps.cfn-config.outputs.tags }}'

CI Build with Feature Branch

name: Feature Branch Deployment

on:
  pull_request:
    branches: [main]

jobs:
  deploy-feature:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Process CloudFormation Configuration
        uses: subhamay-bhattacharyya-gha/cfn-stack-params-action@main
        with:
          cfn-directory: 'cfn'
          ci-build: 'true'
          environment: 'sb-devl-us-east-1'
        id: cfn-config
      
      - name: Deploy Feature Stack
        run: |
          echo "Stack Name: ${{ steps.cfn-config.outputs.stack-name }}"
          echo "Parameters: ${{ steps.cfn-config.outputs.parameters }}"
          echo "Tags: ${{ steps.cfn-config.outputs.tags }}"

Multi-Environment Matrix Deployment

name: Multi-Environment Deployment

on:
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        environment: 
          - sb-devl-us-east-1
          - sb-test-us-east-1
          - sb-prod-us-east-1
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Process CloudFormation Configuration
        uses: subhamay-bhattacharyya-gha/cfn-stack-params-action@main
        with:
          cfn-directory: 'infrastructure'
          ci-build: 'false'
          environment: ${{ matrix.environment }}
        id: cfn-config
      
      - name: Deploy to ${{ matrix.environment }}
        run: |
          aws cloudformation deploy \
            --stack-name ${{ steps.cfn-config.outputs.stack-name }} \
            --template-file infrastructure/template.yaml \
            --parameter-overrides '${{ steps.cfn-config.outputs.parameters }}' \
            --tags '${{ steps.cfn-config.outputs.tags }}'

Custom Configuration Directory

- name: Process CloudFormation Configuration
  uses: subhamay-bhattacharyya-gha/cfn-stack-params-action@main
  with:
    cfn-directory: 'aws/cloudformation'
    ci-build: 'false'
    environment: 'production'
    retention-days: '30'  # Keep artifacts for 30 days
  id: cfn-config

Using Deployment Artifacts

- name: Process CloudFormation Configuration
  uses: subhamay-bhattacharyya-gha/cfn-stack-params-action@main
  with:
    cfn-directory: 'infrastructure'
    ci-build: 'false'
    environment: 'production'
    retention-days: '90'  # Long retention for production
  id: cfn-config

- name: Download Deployment Artifact (in another job)
  uses: actions/download-artifact@v4
  with:
    name: deployment-parameters
    path: ./deployment

- name: Use Deployment Configuration
  run: |
    STACK_NAME=$(jq -r '.["stack-name"]' deployment/deployment.json)
    TEMPLATE_PATH=$(jq -r '.["template-path"]' deployment/deployment.json)
    PARAMETERS=$(jq -r '.parameters' deployment/deployment.json)
    TAGS=$(jq -r '.tags' deployment/deployment.json)
    echo "Deploying to stack: $STACK_NAME"
    aws cloudformation deploy \
      --stack-name "$STACK_NAME" \
      --template-file "$TEMPLATE_PATH" \
      --parameter-overrides "$PARAMETERS" \
      --tags "$TAGS"

Error Scenarios

The action provides clear error messages for common issues:

Missing Configuration Files

Error: Configuration directory not found

Error: Configuration directory 'cfn' does not exist

Error: Missing cloudformation.json

Error: cloudformation.json not found in cfn directory

Error: Missing default parameters

Error: default.json not found in cfn/params directory

Invalid JSON Format

Error: Malformed JSON

Error: Invalid JSON in cloudformation.json: Unexpected token } in JSON at position 45

Error: Missing required fields

Error: Missing required field 'project' in cloudformation.json

Git Operation Errors (CI Build Mode)

Error: Unable to determine branch

Error: Unable to determine current branch name for CI build

Error: Not a Git repository

Error: Current directory is not a Git repository

Parameter File Issues

Warning: Missing environment parameters (non-fatal)

Warning: Environment parameter file 'sb-test-us-east-1.json' not found, using default parameters only

Error: Invalid parameter JSON

Error: Invalid JSON in params/default.json: Unexpected token ] in JSON at position 23

Troubleshooting

Common Issues and Solutions

Issue: "Configuration directory does not exist"

Cause: The specified cfn-directory path doesn't exist in your repository.

Solutions:

  1. Verify the directory path is correct relative to repository root
  2. Ensure the directory is committed to your repository
  3. Check for typos in the cfn-directory input
# Correct
cfn-directory: 'infrastructure'  # Directory exists at repo root

# Incorrect
cfn-directory: 'infrastucture'   # Typo in directory name

Issue: "Missing required field in cloudformation.json"

Cause: The cloudformation.json file is missing required fields.

Solution: Ensure your cloudformation.json contains all required fields:

{
  "project": "your-project-name",      // Required
  "template": "template.yaml",         // Required  
  "stack-prefix": "api"               // Required
}

Issue: "Unable to determine current branch name for CI build"

Cause: Git operations failed when ci-build is set to true.

Solutions:

  1. Ensure you're using actions/checkout@v4 before this action
  2. Verify the repository has Git history
  3. Check that the workflow has proper Git access
steps:
  - uses: actions/checkout@v4  # Required for Git operations
  - name: Process CloudFormation Configuration
    uses: subhamay-bhattacharyya-gha/cfn-stack-params-action@main
    with:
      ci-build: 'true'

Issue: Parameters not merging correctly

Cause: Parameter files have incorrect structure or naming.

Solutions:

  1. Verify default.json exists in the params/ subdirectory
  2. Ensure environment parameter files are named exactly {environment}.json
  3. Check that all JSON files have valid syntax
cfn/
├── cloudformation.json
└── params/
    ├── default.json                    ✅ Correct
    ├── sb-prod-us-east-1.json         ✅ Correct
    ├── prod.json                      ❌ Won't match environment 'sb-prod-us-east-1'
    └── sb-prod-us-east-1.JSON         ❌ Wrong file extension case

Issue: Stack name contains invalid characters

Cause: Branch names or environment names contain characters not allowed in CloudFormation stack names.

Solution: The action automatically sanitizes branch names, but ensure environment names follow CloudFormation naming rules:

  • Only alphanumeric characters and hyphens
  • Must start with a letter
  • Maximum 128 characters

Issue: Action fails with permission errors

Cause: Insufficient permissions to read files or execute Git commands.

Solutions:

  1. Ensure the workflow has proper repository permissions
  2. Check that files are not in .gitignore
  3. Verify file permissions in the repository

Debug Mode

Enable debug logging by setting the ACTIONS_STEP_DEBUG secret to true in your repository settings. This will provide detailed logs of the action's execution.

Getting Help

For detailed troubleshooting information, see the Troubleshooting Guide.

If you encounter issues not covered in the guides:

  1. Check the Issues page for similar problems
  2. Review the action logs for detailed error messages
  3. Ensure your configuration follows the documented structure
  4. Test your JSON files with a JSON validator

Best Practices

Security Considerations

When using this action in production environments:

  • Parameter Encryption: Store sensitive parameters in AWS Systems Manager Parameter Store or AWS Secrets Manager
  • IAM Permissions: Use least-privilege IAM roles for CloudFormation deployments
  • Environment Isolation: Keep environment-specific configurations in separate branches or repositories
  • Secrets Management: Never commit sensitive values to parameter files

Performance Optimization

  • Parameter File Size: Keep parameter files small and focused to reduce processing time
  • CI Build Strategy: Use ci-build: true for feature branches to enable parallel deployments
  • Caching: Consider caching CloudFormation configuration files in multi-step workflows

Monitoring and Logging

  • Stack Drift Detection: Regularly check for configuration drift between your parameter files and deployed stacks
  • Deployment Tracking: Use the generated ci-build-id for correlating logs across deployment steps
  • Error Handling: Implement proper error handling in your workflows to catch configuration issues early

Migration Guide

From v1.0.x to v1.1.x

This action maintains backward compatibility. No changes required for existing workflows.

Upgrading from Custom Scripts

If you're migrating from custom parameter processing scripts:

  1. Create Configuration Structure: Set up the required cloudformation.json and params/ directory
  2. Update Workflow: Replace custom scripts with this action
  3. Test Environment Mapping: Verify environment parameter files are correctly named
  4. Validate Outputs: Ensure the generated parameters work with your CloudFormation deployment actions

Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

  1. Clone the repository
  2. Install dependencies: npm install
  3. Run tests: npm test
  4. Run linting: npm run lint

Running Tests

# Run all tests
npm test

# Run unit tests only
npm run test:unit

# Run integration tests only
npm run test:integration

# Run with coverage
npm run test:coverage

License

This project is licensed under the MIT License - see the LICENSE file for details.