usabilitydynamics/rabbit-automation-action

By usabilitydynamics

Updated 9 days ago

Deploy Your Cloud from YAML

Image
Security
Integration & delivery
Developer tools
0

10K+

usabilitydynamics/rabbit-automation-action repository overview

Rabbit Automation Action

Declare cloud infrastructure in YAML. Deploy with git push.

A GitHub Marketplace composite action that discovers YAML configuration from your .rabbit/ directory and deploys cloud infrastructure across AWS, GCP, and Kubernetes using Terraform — all from a single uses: step.


Quick Start

1. Add the workflow

Create .github/workflows/infra-build.yaml in your repository:

name: Infrastructure Build

on:
  pull_request:
    branches: ["production", "staging", "develop-*"]
  push:
    branches: ["production", "staging", "develop-*"]
    paths: [".rabbit/**"]
  delete:
  schedule:
    - cron: "0 2 * * *"
  workflow_dispatch:
    inputs:
      plan_only:
        description: "Plan only (no apply)"
        type: boolean
        default: true
      environment:
        description: "Target environment"
        type: choice
        options: [development, staging, production]
        default: development
      terraform_action:
        description: "Terraform action"
        type: choice
        options: [apply, destroy]
        default: apply

permissions:
  contents: read
  pull-requests: write
  id-token: write

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: udx/github-rabbit-action@v1
        with:
          project_id: ${{ vars.GCP_PROJECT_ID }}
          gcp_auth_provider: ${{ vars.GCP_AUTH_PROVIDER }}
          gcp_service_account: ${{ vars.GCP_SERVICE_ACCOUNT }}
          aws_region: ${{ vars.AWS_REGION }}
          aws_role_arn: ${{ secrets.AWS_GITHUB_ACTIONS_ROLE_ARN }}
          slack_webhook: ${{ secrets.SLACK_WEBHOOK_ROUTINE }}
          dockerhub_username: ${{ vars.DOCKERHUB_USER_LOGIN }}
          dockerhub_token: ${{ secrets.DOCKERHUB_TOKEN_PULL_R2A }}
          r2a_version: "4.8.0"
          terraform_action: ${{ inputs.terraform_action || 'apply' }}
2. Define your infrastructure

Create YAML files inside .rabbit/<environment>/:

.rabbit/production/10-dns.yaml
services:
  - module: aws-route53
    id: my-domain
    domain: example.com
    records:
      - type: A
        name: ""
        alias:
          name: d1234.cloudfront.net
          zone_id: Z2FDTNDATAQYW2
.rabbit/production/20-cdn.yaml
services:
  - module: aws-cloudfront-distribution
    id: my-cdn-#{Environment}
    domain: example.com
    origins:
      - domain_name: my-app.example.com
        origin_id: app-origin
.rabbit/production/30-app.yaml
services:
  - module: k8s-namespace
    id: my-app

  - module: k8s-deployment
    id: my-app
    image: my-org/my-app:latest
    replicas: 2
    ports:
      - containerPort: 8080

  - module: k8s-http-gateway-route
    id: my-app
    hostname: my-app.example.com
    service_port: 8080
3. Push and watch
  • Open a PR → automatic plan preview posted as PR comment
  • Merge to production → infrastructure applied automatically
  • Delete a branch → ephemeral environment destroyed

How It Works

┌─────────────────────────────────────────────────────┐
│ GitHub Action Trigger (push / PR / delete / manual) │
└──────────────────────┬──────────────────────────────┘
                       │
         ┌─────────────▼──────────────┐
         │   1. Merge Configs         │
         │   Discover .rabbit/ YAML   │
         │   Resolve lifecycle        │
         │   Deep merge by module::id │
         └─────────────┬──────────────┘
                       │
         ┌─────────────▼──────────────┐
         │   2. Safety Checks         │
         │   Block production manual  │
         │   Block production destroy │
         │   Auto plan-only for PRs   │
         └─────────────┬──────────────┘
                       │
         ┌─────────────▼──────────────┐
         │   3. Cloud Auth            │
         │   GCP Workload Identity    │
         │   AWS OIDC (optional)      │
         └─────────────┬──────────────┘
                       │
         ┌─────────────▼──────────────┐
         │   4. Terraform Engine      │
         │   Docker: r2a container    │
         │   Per-service init/plan/   │
         │   apply in deploy order    │
         └─────────────┬──────────────┘
                       │
         ┌─────────────▼──────────────┐
         │   5. Reporting             │
         │   Plan summary table       │
         │   PR comment               │
         │   GitHub step summary      │
         │   Slack notification       │
         └────────────────────────────┘
Environment Detection

The environment is automatically resolved from:

TriggerEnvironment Source
pushBranch name (production, staging, develop-foo)
pull_requestBase branch (github.base_ref)
deleteDeleted branch ref
workflow_dispatchUser-selected input
scheduleBranch name (default branch)
Lifecycle Model

Infrastructure configs live in .rabbit/ directories organized by lifecycle:

.rabbit/
├── production/           # Protected branches → production lifecycle
│   ├── 10-infra.yaml
│   ├── 20-app.yaml
│   └── us-east-1/        # Environment-specific overrides (smart merged)
│       └── 10-infra.yaml
├── staging/              # Root-only (no subdirectories)
│   └── infra.yaml
└── development/          # Fallback lifecycle
    ├── infra.yaml
    └── dev-andy/          # Per-developer environments
        └── infra.yaml
  • Files are sorted by name (10-infra.yaml before 20-monitoring.yaml)
  • Services with the same module::id are deep-merged across files
  • Root-level files in .rabbit/ are ignored (must be in a lifecycle directory)
Plan Mode
TriggerMode
pull_requestPlan only (preview changes)
schedulePlan only (drift detection)
pushApply (deploy changes)
workflow_dispatchUser choice
deleteDestroy (remove environment)
Safety Guardrails
  • Manual production apply blocked — production changes must go through the merge pipeline
  • Production destroy blocked — production infrastructure cannot be destroyed
  • Delete environment mismatch — aborts if branch name doesn't match resolved environment
  • PR always plans — pull requests never apply changes

List of Modules

AWS
ModuleDescriptionOrder
aws-route53DNS zones and records5
aws-acmSSL/TLS certificates8
aws-wafWeb Application Firewall rules125
aws-cloudfront-distributionCDN distribution with origins, behaviors, cache130
GCP
ModuleDescriptionOrder
gcp-networkingVPC networks and firewall rules10
gcp-static-ipRegional/global static IP addresses15
gcp-postgresql-instanceCloud SQL PostgreSQL instances20
gcp-sql-instanceCloud SQL MySQL instances20
gcp-gke-clusterGKE cluster provisioning30
gcp-gke-nodepoolGKE node pool configuration40
gcp-iamIAM roles and service accounts
gcp-secret-managerSecret Manager entries
gcp-storageCloud Storage buckets
gcp-monitoringMonitoring alert policies140
Kubernetes
ModuleDescriptionOrder
k8s-shared-http-gatewayShared HTTP gateway for routing55
k8s-namespaceNamespace with labels and annotations60
k8s-secretKubernetes secrets from config or GCP Secret Manager70
k8s-accessRBAC roles and bindings80
k8s-serviceClusterIP/LoadBalancer/NodePort services90
k8s-http-health-check-policyHealth check policies for gateway routes92
k8s-http-gateway-routeHTTP routing rules for gateway93
k8s-configmapConfigMaps from inline data or files95
k8s-deploymentDeployments with rolling updates100
k8s-memcachedMemcached StatefulSet102
k8s-hpaHorizontal Pod Autoscaler110
k8s-pdbPod Disruption Budget120
Monitoring
ModuleDescriptionOrder
newrelic-synthetic-monitorsNew Relic synthetic monitoring150

Deployment Order — services are deployed in ascending order by their module's deployment order. Destroy operations reverse the order.


Configuration Reference

Service Shape

Each service in your YAML config follows this structure:

services:
  - module: <module-name>       # Required: Terraform module to use
    id: <unique-id>             # Required: Unique identifier for this service
    # ... module-specific fields
Placeholders

Use #{Variable} syntax in YAML values — they're replaced at runtime:

PlaceholderValue
#{Environment}Resolved environment name
#{Lifecycle}Resolved lifecycle (production/staging/development)
#{GcpProject}GCP project ID
#{GitOwner}GitHub repository owner
#{GitRepository}GitHub repository name
#{Namespace}Kubernetes namespace (derived from repo name)
#{SharedProject}Shared GCP project ID

Example:

services:
  - module: k8s-deployment
    id: my-app-#{Environment}
    namespace: #{Namespace}
    image: gcr.io/#{GcpProject}/my-app:latest
GCP Secret Manager References

Reference secrets directly in your YAML:

services:
  - module: k8s-secret
    id: app-secrets
    data:
      DATABASE_URL: gcp://projects/my-project/secrets/db-url/versions/latest

The action automatically resolves gcp:// prefixed values to actual secret values at deploy time.


Setup Guide

Required GitHub Variables

Set these in your repository or organization settings → Variables:

VariableDescription
GCP_PROJECT_IDGoogle Cloud project ID
GCP_AUTH_PROVIDERGCP Workload Identity Provider resource name
GCP_SERVICE_ACCOUNTGCP Service Account email
Optional GitHub Variables
VariableDescription
AWS_REGIONAWS region (e.g., us-east-1)
DOCKERHUB_USER_LOGINDocker Hub username for image pulls
K8S_CLUSTER_NAMEGKE cluster name
NEWRELIC_ACCOUNT_IDNew Relic account ID
SHARED_PROJECTShared GCP project for cross-project access
Required GitHub Secrets
SecretDescription
SLACK_WEBHOOK_ROUTINESlack incoming webhook for notifications
Optional GitHub Secrets
SecretDescription
AWS_GITHUB_ACTIONS_ROLE_ARNAWS IAM OIDC role for Route53/CloudFront/WAF/ACM
DOCKERHUB_TOKEN_PULL_R2ADocker Hub token (paired with DOCKERHUB_USER_LOGIN)
DOCKERHUB_HELM_TOKENDocker Hub token for Helm OCI charts
NEWRELIC_API_KEYNew Relic API key
Workflow Permissions
permissions:
  contents: read
  pull-requests: write    # For PR comments with plan summary
  id-token: write         # For GCP Workload Identity & AWS OIDC

Advanced Usage

Multi-Environment Overrides

Override specific values per environment using subdirectories:

.rabbit/
└── production/
    ├── 10-infra.yaml          # Base production config
    └── us-east-1/
        └── 10-infra.yaml      # Overrides for us-east-1 environment

Files in subdirectories are deep-merged on top of the parent directory files. Services with matching module::id pairs are merged, not duplicated.

Multi-Repo Projects

For monorepo or multi-repo setups where multiple repositories share infrastructure:

- uses: udx/github-rabbit-action@v1
  with:
    multi_repo: "true"
    shared_project: "shared-infra-project"
    # ... other inputs

This isolates Terraform state per repository while allowing shared GCP project access.

Pinning R2A Version

Always pin to a specific version for reproducible builds:

- uses: udx/github-rabbit-action@v1
  with:
    r2a_version: "4.8.0"
Ephemeral Environments (Branch Delete → Destroy)

Add delete to your workflow triggers and matching feature branches:

on:
  delete:  # Triggers destroy when branch is deleted
  push:
    branches: ["production", "staging", "develop-*"]

When a develop-* branch is deleted, the action automatically runs terraform destroy for that environment.

Debug Mode

Enable detailed config output in logs:

- uses: udx/github-rabbit-action@v1
  with:
    print_config: "true"
Manual Dispatch with Safety Controls

The workflow dispatch inputs provide safe manual control:

  • Plan only = true → preview changes without applying
  • Environment = production + Plan only = false → blocked (safety guardrail)
  • Terraform action = destroy + Environment = production → blocked

Inputs Reference

InputRequiredDefaultDescription
project_idGCP project ID
gcp_auth_providerGCP Workload Identity Provider
gcp_service_accountGCP Service Account email
aws_role_arnAWS IAM OIDC role ARN
aws_regionAWS region
dockerhub_usernameDocker Hub username
dockerhub_tokenDocker Hub pull token
dockerhub_helm_tokenDocker Hub Helm OCI token
r2a_versionlatestR2A Docker image tag
terraform_actionapplyapply or destroy
plan_onlyautoOverride plan mode
environmentautoOverride environment
print_configtrueDebug config output
multi_repofalsePer-repo state isolation
shared_projectShared GCP project
k8s_cluster_nameGKE cluster name
newrelic_account_idNew Relic account ID
newrelic_api_keyNew Relic API key
slack_webhookSlack webhook URL
source_dir.rabbitConfig source directory
github_tokengithub.tokenGitHub token for PR comments

Outputs

OutputDescription
environmentResolved environment name
lifecycleResolved lifecycle (production/staging/development)
plan_onlyWhether run was plan-only
terraform_actionAction executed (apply/destroy/skip)
has_changesWhether Terraform detected changes
changes_msgHuman-readable change summary
cloudfront_distribution_idCloudFront distribution ID (if applicable)
k8s_namespaceKubernetes namespace
config_pathPath to merged config file

What You'll See

GitHub Step Summary

Every run writes a configuration summary and deployment results to the GitHub Actions step summary — visible directly on the Actions run page.

PR Comments

Pull requests get an automatically updated comment with a detailed Terraform plan breakdown:

## Terraform Plan Summary

| Module / Service | Add | Change | Destroy |
| --- | --- | --- | --- |
| **Total** | 5 | 2 | 0 |
| `aws-cloudfront-distribution/my-cdn` | 0 | 1 | 0 |
| `k8s-deployment/my-app` | 3 | 1 | 0 |
| `k8s-http-gateway-route/my-app` | 2 | 0 | 0 |
Slack Notifications

Notifications are sent when:

  • Infrastructure changes are detected or applied
  • Any step fails

Notifications include environment, change counts, failure stage, and a link to the action run.


Pro Tips

  • Use a Docker Hub token (dockerhub_username + dockerhub_token) to prevent rate limits when pulling the R2A image
  • Pin r2a_version to a specific tag for reproducible deploys (e.g., 4.8.0 instead of latest)
  • Name files with numeric prefixes (10-dns.yaml, 20-cdn.yaml, 30-app.yaml) for deterministic ordering
  • Use #{Environment} placeholders in service IDs to keep configs environment-aware
  • Schedule nightly runs (cron: "0 2 * * *") to detect infrastructure drift
  • Keep .rabbit/ configs small and focused — one concern per file

License

GPL-2.0

Tag summary

Content type

Image

Digest

sha256:23b5d07c0

Size

433.4 MB

Last updated

9 days ago

docker pull usabilitydynamics/rabbit-automation-action