Skip to content
Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

1 Commit

Repository files navigation

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 Buildon:
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: booleandefault: trueenvironment:
description: "Target environment"type: choiceoptions: [development, staging, production]default: developmentterraform_action:
description: "Terraform action"type: choiceoptions: [apply, destroy]default: applypermissions:
contents: readpull-requests: writeid-token: writejobs:
deploy:
runs-on: ubuntu-lateststeps:
- uses: actions/checkout@v4
- uses: udx/github-rabbit-action@v1with:
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-route53id: my-domaindomain: example.comrecords:
- type: Aname: ""alias:
name: d1234.cloudfront.netzone_id: Z2FDTNDATAQYW2

.rabbit/production/20-cdn.yaml

services:
- module: aws-cloudfront-distributionid: my-cdn-#{Environment}domain: example.comorigins:
- domain_name: my-app.example.comorigin_id: app-origin

.rabbit/production/30-app.yaml

services:
- module: k8s-namespaceid: my-app
- module: k8s-deploymentid: my-appimage: my-org/my-app:latestreplicas: 2ports:
- containerPort: 8080
- module: k8s-http-gateway-routeid: my-apphostname: my-app.example.comservice_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 useid: <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-deploymentid: 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-secretid: app-secretsdata:
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: readpull-requests: write # For PR comments with plan summaryid-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@v1with:
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@v1with:
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 deletedpush:
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@v1with:
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

About

Declare cloud infrastructure in YAML.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages