Skip to content

CI/CD with GitHub Actions

This comprehensive guide covers how to set up continuous integration and deployment (CI/CD) pipelines using Simple Container's built-in GitHub Actions integration. Simple Container automatically generates optimized workflow files from your infrastructure configuration, providing seamless deployment automation.

Overview

Simple Container's CI/CD integration provides:

  • Automatic workflow generation from server.yaml configuration
  • Multi-environment deployment with staging and production pipelines
  • Built-in secret management integration with GitHub Secrets
  • Infrastructure provisioning and application deployment workflows
  • Notification support for Slack, Discord, and Telegram
  • Preview deployments for pull requests
  • Rollback capabilities for failed deployments

How It Works

Simple Container generates GitHub Actions workflows based on your infrastructure configuration:

  1. Configuration is read from server.yaml in your .sc/stacks/<stack-name>/ directory
  2. Workflows are generated automatically using the sc cicd command
  3. GitHub Actions execute provisioning and deployment steps
  4. Notifications are sent to your configured channels on success/failure
  5. Environments are managed with proper protection rules and approvals

Prerequisites

Before setting up CI/CD, ensure you have:

  • Simple Container CLI installed
  • GitHub repository with Actions enabled
  • Appropriate cloud provider credentials (AWS, GCP, etc.)
  • Simple Container project with server.yaml configuration

Server Configuration

Basic CI/CD Configuration

Add CI/CD configuration to your server.yaml file:

schemaVersion: 1.0
cicd:
  type: github-actions
  config:
    organization: "your-org-name"

    # Environment configurations
    environments:
      staging:
        type: staging
        protection: false           # No approval required for staging
        auto-deploy: true          # Deploy automatically on main branch push
        runner: "ubuntu-latest"
        deploy-flags: ["--skip-preview"]  # Skip preview for automated deployment
        secrets: ["DATABASE_URL", "API_KEY"]  # Which secrets from secrets.yaml are available
        variables:                 # Non-sensitive environment variables for workflows
          NODE_ENV: "staging"
          LOG_LEVEL: "debug"

      production:
        type: production
        protection: true           # Require approval for production
        reviewers: ["senior-dev", "devops-team"]
        auto-deploy: false         # Manual deployment only
        runner: "ubuntu-latest"
        deploy-flags: ["--skip-preview"]
        secrets: ["DATABASE_URL", "API_KEY"]  # Which secrets from secrets.yaml are available
        variables:                 # Non-sensitive environment variables for workflows
          NODE_ENV: "production"
          LOG_LEVEL: "warn"

    # Notification settings
    notifications:
      slack:
        webhook-url: "${secret:slack-webhook-url}"
        enabled: true
      discord:
        webhook-url: "${secret:discord-webhook-url}"
        enabled: true
      telegram:
        bot-token: "${secret:telegram-bot-token}"
        chat-id: "${secret:telegram-chat-id}"
        enabled: false

    # Workflow generation settings
    workflow-generation:
      enabled: true
      templates: ["deploy", "destroy"]
      auto-update: true
      sc-version: "latest"

Advanced Configuration

For more complex setups, you can configure additional options:

cicd:
  type: github-actions
  config:
    organization: "your-org-name"

    environments:
      staging:
        type: staging
        protection: false
        auto-deploy: true
        runner: "ubuntu-latest"
        secrets: ["STAGING_DATABASE_URL", "STAGING_API_KEY"]
        variables:
          NODE_ENV: "staging"
          LOG_LEVEL: "debug"
        deploy-flags: ["--skip-preview", "--timeout", "15m"]

      production:
        type: production
        protection: true
        reviewers: ["senior-dev", "devops-team"]
        auto-deploy: false
        runner: "self-hosted"
        secrets: ["PRODUCTION_DATABASE_URL", "PRODUCTION_API_KEY"]
        variables:
          NODE_ENV: "production"
          LOG_LEVEL: "warn"
        deploy-flags: ["--timeout", "30m"]

    notifications:
      slack:
        webhook-url: "${secret:slack-webhook-url}"
        enabled: true
      discord:
        webhook-url: "${secret:discord-webhook-url}"
        enabled: true
      telegram:
        bot-token: "${secret:telegram-bot-token}"
        chat-id: "${secret:telegram-chat-id}"
        enabled: true

    workflow-generation:
      enabled: true
      output-path: ".github/workflows/"
      templates: ["deploy", "destroy", "preview"]
      auto-update: true
      custom-actions:
        security-scan: "security/scan@v1"
        performance-test: "perf/test@v2"
      sc-version: "v1.2.0"

Secret Configuration

Create a secrets.yaml file in your stack directory for CI/CD secrets:

schemaVersion: 1.0

# Cloud provider authentication for infrastructure provisioning
auth:
  aws:
    type: aws-token
    config:
      account: "123456789012"
      accessKey: "${secret:aws-access-key}"
      secretAccessKey: "${secret:aws-secret-key}"
      region: us-east-1

values:
  # Cloud provider credentials
  aws-access-key: your-aws-access-key-here
  aws-secret-key: your-aws-secret-key-here

  # Notification webhooks managed by Simple Container
  slack-webhook-url: "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
  discord-webhook-url: "https://discord.com/api/webhooks/YOUR/WEBHOOK/URL"
  telegram-bot-token: your-telegram-bot-token-here
  telegram-chat-id: your-telegram-chat-id-here

  # Application secrets for deployment
  staging-database-url: your-staging-database-connection-string
  production-database-url: your-production-database-connection-string
  staging-api-key: your-staging-api-key
  production-api-key: your-production-api-key

Command Usage

Generate Workflows

Generate GitHub Actions workflows from your configuration:

# Generate workflows for a specific stack
sc cicd generate --stack myorg/infrastructure --output .github/workflows/

# Generate with custom configuration file
sc cicd generate --config .sc/stacks/myapp/server.yaml --output .github/workflows/

# Force overwrite existing workflows
sc cicd generate --stack myorg/infrastructure --force

Validate Configuration

Validate your CI/CD configuration and existing workflows:

# Validate CI/CD configuration for a stack
sc cicd validate --stack myorg/infrastructure

# Validate with specific configuration file
sc cicd validate --stack myorg/infrastructure --config .sc/stacks/myorg-infrastructure/server.yaml

# Show differences between configuration and existing workflows
sc cicd validate --stack myorg/infrastructure --show-diff

Sync Workflows

Synchronize existing workflows with updated configuration:

# Sync workflows for a specific stack
sc cicd sync --stack myorg/infrastructure

# Sync with dry-run to see what would change
sc cicd sync --stack myorg/infrastructure --dry-run

# Force sync without confirmation
sc cicd sync --stack myorg/infrastructure --force

Preview Workflows

Preview generated workflows before writing files:

# Preview all workflow templates
sc cicd preview --stack myorg/infrastructure

# Preview with detailed output
sc cicd preview --stack myorg/infrastructure --format detailed

# Show workflow content
sc cicd preview --stack myorg/infrastructure --show-content

Generated Workflows

Simple Container generates optimized GitHub Actions workflows for different deployment scenarios:

Deploy Workflow

Generated at .github/workflows/deploy-<stack-name>.yml:

name: Deploy Stack
on:
  push:
    branches: [main]
  workflow_dispatch:
    inputs:
      environment:
        description: 'Environment to deploy to'
        required: true
        default: 'staging'
        type: choice
        options:
        - staging
        - production
      verbose:
        description: 'Enable verbose logging for debugging'
        type: boolean
        default: false

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: ${{ github.event.inputs.environment || 'staging' }}
    outputs:
      stack-name: ${{ steps.deploy.outputs.stack-name }}
      status: ${{ steps.deploy.outputs.status }}
    steps:
    - name: Deploy Infrastructure
      id: deploy
      uses: simple-container-com/api/.github/actions/provision@v2025.10.4
      with:
        stack-name: myorg/infrastructure
        sc-config: ${{ secrets.SC_CONFIG }}
        verbose: ${{ github.event.inputs.verbose || 'false' }}
        # Built-in notifications automatically configured via SC secrets

Available Inputs:

All Simple Container GitHub Actions support these common inputs:

  • stack-name (required) - Name of the stack to operate on
  • sc-config (required) - Simple Container configuration (use ${{ secrets.SC_CONFIG }})
  • environment - Target environment (e.g., staging, production)
  • verbose - Enable verbose logging for detailed debugging information (true/false, default: false)
  • dry-run - Run in preview mode without making actual changes (true/false, default: false)
  • notify-on-completion - Send notifications when operation completes (true/false, default: true)

Available Outputs: - stack-name - Name of the deployed stack - status - Deployment status ("success")

For deploy@v2025.10.4 action: - version - Deployed application version - environment - Target environment name

Destroy Workflow

Generated at .github/workflows/destroy-<stack-name>.yml for cleanup operations:

name: Destroy Stack
on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Environment to destroy'
        required: true
        type: choice
        options:
        - staging
        - production
      confirm:
        description: 'Type "destroy" to confirm'
        required: true

jobs:
  destroy:
    runs-on: ubuntu-latest
    if: github.event.inputs.confirm == 'destroy'
    environment: ${{ github.event.inputs.environment }}
    steps:
    # Similar steps to deploy workflow but with destroy action

GitHub Repository Setup

Required Secrets

Configure these secrets in your GitHub repository settings:

Only ONE GitHub secret required: - SC_CONFIG - Simple Container configuration with SSH key pair to decrypt repository secrets

All other secrets are managed in Simple Container's encrypted secrets.yaml files: - Cloud provider credentials - AWS, GCP, Azure authentication - Notification webhooks - Slack, Discord, Telegram configurations
- Application secrets - Database URLs, API keys, environment-specific values - Infrastructure secrets - Service accounts, certificates, access tokens

Simple Container handles ALL secret management through its encrypted secrets system - no individual GitHub Actions secrets needed.

Environment Protection

Configure environment protection rules in GitHub:

  1. Go to SettingsEnvironments in your repository
  2. Create environments for staging and production
  3. For production environment:
  4. Enable Required reviewers and add team members
  5. Set Wait timer if needed (e.g., 10 minutes)
  6. Configure Deployment branches to restrict to main/master
  7. For staging environment:
  8. No protection rules needed for automatic deployment

Workflow Triggers

Automatic Deployment

Configure automatic deployment triggers:

# In your workflow file
on:
  push:
    branches: [main]           # Deploy staging on main branch push
    paths: ['.sc/**', 'src/**'] # Only deploy on relevant file changes

  pull_request:
    types: [opened, synchronize]  # Preview deployments on PRs
    paths: ['.sc/**', 'src/**']

Manual Deployment

Enable manual deployment with workflow_dispatch:

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Environment to deploy to'
        required: true
        default: 'staging'
        type: choice
        options: [staging, production]

      dry_run:
        description: 'Run in preview mode'
        type: boolean
        default: false

      verbose:
        description: 'Enable verbose logging for detailed debugging'
        type: boolean
        default: false

Best Practices

Security

  1. Use environment-specific secrets - Never share production secrets with staging
  2. Enable branch protection - Require PRs and reviews for main branch
  3. Configure environment protection - Require approvals for production deployments
  4. Rotate secrets regularly - Update cloud provider and application credentials
  5. Use least privilege access - Grant minimal required permissions to GitHub Actions

Deployment Strategy

  1. Deploy to staging first - Always test changes in staging environment
  2. Use preview deployments - Review infrastructure changes before applying
  3. Implement rollback procedures - Maintain previous deployment artifacts
  4. Monitor deployment health - Set up alerts and health checks
  5. Gradual production rollout - Use blue-green or canary deployment patterns

Workflow Organization

  1. Separate workflows by purpose - Deploy, destroy, and maintenance workflows
  2. Use meaningful names - Clear workflow and job names for easy identification
  3. Add comprehensive logging - Debug deployment issues with detailed logs
  4. Implement notification strategy - Alert on failures, summarize on success
  5. Version your workflows - Track changes to CI/CD configuration

Troubleshooting

Common Issues

Workflow fails with "Stack not found":

# Ensure your stack exists and configuration is valid
sc cicd validate --stack myorg/infrastructure

# Check if server.yaml exists in the correct location
ls -la .sc/stacks/myorg-infrastructure/server.yaml

Authentication errors:

# Verify cloud provider credentials
aws sts get-caller-identity

# Check GitHub secrets are properly configured
# Go to Settings → Secrets and variables → Actions

Configuration validation errors:

# Validate your server.yaml configuration
sc cicd validate --stack myorg/infrastructure --show-diff

# Check the generated workflows
sc cicd preview --stack myorg/infrastructure --show-content

Debugging Workflows

  1. Enable verbose logging in Simple Container GitHub Actions:
    - name: Deploy with verbose logging
      uses: simple-container-com/api/.github/actions/deploy-client-stack@main
      with:
        stack-name: "myapp"
        environment: "staging"
        sc-config: ${{ secrets.SC_CONFIG }}
        verbose: 'true'  # Enable detailed debugging information
    

Verbose logging provides: - Detailed environment variable information - Step-by-step execution progress - Parent repository cloning details - Secret revelation process information - Provisioner parameter debugging - Git repository initialization details

  1. Enable GitHub Actions debug logging (additional system-level debugging):
  2. Go to repository SettingsSecrets
  3. Add secret ACTIONS_STEP_DEBUG with value true

  4. Check workflow logs in the Actions tab of your repository

  5. Use workflow artifacts to debug generated files:

    - name: Upload deployment logs
      if: failure()
      uses: actions/upload-artifact@v4
      with:
        name: deployment-logs
        path: logs/
    

  6. Test locally before pushing to GitHub:

    # Test deployment locally
    sc deploy -s myorg/infrastructure -e staging --preview
    
    # Validate configuration
    sc cicd validate --stack myorg/infrastructure --show-diff
    

Example Workflows

Check out complete examples in the examples/cicd-github-actions/ directory:

Next Steps

After setting up CI/CD:

  1. Explore Advanced Deployment Patterns for complex scenarios
  2. Review Secrets Management for secure credential handling
  3. Check DNS Management for custom domain configuration
  4. Set up Monitoring and Alerting for deployment health

Need Help?