Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Local script defaults for direct merge testing.
# The composite action normally receives these values from action inputs and
# udx/rabbit-lifecycle outputs.

INPUT_SOURCE_DIR=.rabbit
INPUT_ENV_NAME=development
INPUT_LIFECYCLE=development
INPUT_IS_PROTECTED=false
INPUT_RESOLUTION_REASON=local-example
INPUT_OUTPUT_FORMAT=yaml
INPUT_RECURSIVE=true
INPUT_FILE_PATTERNS=*.yml,*.yaml
INPUT_EXCLUDE=**/merged*.yml,**/merged*.yaml
INPUT_DEBUG=false
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: weekly
40 changes: 40 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: ci

on:
pull_request:
push:
branches:
- production
- lifecycle-action-integration

permissions:
contents: read

jobs:
validate:
name: validate action contract
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5

- name: Install pinned yq
shell: bash
run: |
set -euo pipefail
version="v4.44.3"
sha256="a2c097180dd884a8d50c956ee16a9cec070f30a7947cf4ebf87d5f36213e9ed7"
install_dir="${RUNNER_TEMP}/rabbit-action-bin"
mkdir -p "$install_dir"
curl -fsSL "https://github.com/mikefarah/yq/releases/download/${version}/yq_linux_amd64" -o "$install_dir/yq"
printf '%s %s\n' "$sha256" "$install_dir/yq" | sha256sum --check --status
chmod +x "$install_dir/yq"
echo "$install_dir" >> "$GITHUB_PATH"

Comment thread
fqjony marked this conversation as resolved.
- name: Run validation
shell: bash
run: make test

- name: Refresh repo context
shell: bash
run: npx -y @udx/dev-kit@0.12.0 repo
7 changes: 7 additions & 0 deletions .rabbit/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Rabbit Context

This directory keeps Rabbit-facing repo context and generated `dev.kit` evidence.

- `context.yaml` is generated by `dev.kit repo`; do not edit it manually.
- Keep human-authored Rabbit CI notes, delivery entry points, and repo-specific workflow guidance in this README.
- After changing repo docs, manifests, scripts, or workflows, run `dev.kit repo` to refresh generated context.
76 changes: 76 additions & 0 deletions .rabbit/context.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Generated by dev.kit repo — do not edit manually.
# Run `dev.kit repo` to refresh.
kind: repoContext
version: udx.dev/dev.kit/v1
generator:
tool: dev.kit
repo: https://github.com/udx/dev.kit
version: 0.20.1
generated_at: 2026-07-29T14:41:16Z
sources:
homepage: https://udx.dev/kit
repository: https://github.com/udx/dev.kit
package: https://www.npmjs.com/package/@udx/dev-kit
installation: https://github.com/udx/dev.kit/blob/latest/docs/installation.md

repo:
name: github-rabbit-action
archetype: manifest-repo

# Refs — Direct-read files and paths that define the repo contract.
# Note: Include only files or directories a repo consumer should read before code exploration.
# Note: Prefer README, focused docs, workflows, manifests, and explicit operational files.
# Note: Exclude broad implementation directories unless they are the contract themselves.

refs:
- ./README.md
- ./Makefile
- ./docs/configuration.md
- ./docs/validation.md
- ./src/configs/lifecycle-policy.yaml
- ./action.yml
- ./.github/workflows
- ./docs

# Commands — Canonical repo entrypoints detected from strong repo signals.
# Note: Prefer declared make targets and package scripts before regex matches in docs.
# Note: Emit only commands that can be traced to a concrete source.
# Note: Record the source path so the command can be reviewed and corrected.

commands:
verify:
run: make test
source: Makefile

# Dependencies — Meaningful dependency-repo contracts such as reusable workflows, images, or versioned manifests this repo relies on.
# Note: Capture execution-shaping behavior defined outside the current checkout.
# Note: Avoid promoting standard package inventory or ordinary GitHub action refs into top-level context.
# Note: Normalize same-org versioned refs into repo slugs when possible.

dependencies:
- repo: udx/rabbit-infra-config
kind: manifest contract (v1)
resolved: false
declared_as: udx.dev/rabbit-infra-config/v1
used_by:
- src/configs/lifecycle-policy.yaml

# Manifests — YAML files that define repo-specific workflow, deploy, or contract behavior.
# Note: Include custom config/manifests that materially shape repo behavior or contract understanding.
# Note: Do not include workflow YAML only because it lives under .github/workflows.
# Note: Promote workflow files only when they declare reusable workflow refs or other repo-specific execution contracts.
# Note: Prefer structured kind and description metadata from the manifest itself.
# Note: Include hidden or nested contract dirs when they contain repo-owned manifests with meaningful metadata.

manifests:
- path: src/configs/lifecycle-policy.yaml
kind: rabbitConfigLayout
declared_as: udx.dev/rabbit-infra-config/v1
source_repo: udx/rabbit-infra-config
used_by:
- bin/lib/config.sh
- docs/configuration.md
evidence:
- version: udx.dev/rabbit-infra-config/v1
- path reference: bin/lib/config.sh
- path reference: docs/configuration.md
21 changes: 21 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.PHONY: test validate-shell validate-action validate-workflow

test: validate-shell validate-action validate-workflow
tests/run-merge-tests.sh

validate-shell:
bash -n \
bin/merge-configs.sh \
bin/resolve-lifecycle.sh \
bin/lib/config.sh \
bin/lib/github.sh \
bin/lib/lifecycle.sh \
bin/lib/validation.sh \
bin/lib/environment.sh \
tests/run-merge-tests.sh

validate-action:
yq eval '.' action.yml >/dev/null

validate-workflow:
yq eval '.' .github/workflows/ci.yml >/dev/null
80 changes: 52 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,22 @@ jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5

- uses: google-github-actions/auth@v3
with:
workload_identity_provider: ${{ vars.GCP_AUTH_PROVIDER }}
service_account: ${{ vars.GCP_SERVICE_ACCOUNT }}

- uses: aws-actions/configure-aws-credentials@v6
if: vars.AWS_REGION != ''
with:
role-to-assume: ${{ secrets.AWS_GITHUB_ACTIONS_ROLE_ARN }}
aws-region: ${{ vars.AWS_REGION }}

- 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 }}
Expand Down Expand Up @@ -132,31 +139,29 @@ services:
│ GitHub Action Trigger (push / PR / delete / manual) │
└──────────────────────┬──────────────────────────────┘
┌─────────────▼──────────────┐
│ 1. Merge Configs │
│ Discover .rabbit/ YAML │
│ Resolve lifecycle │
│ Deep merge by module::id │
┌─────────────▼──────────────┐
│ 1. Resolve Lifecycle │
│ In-repo branch/env │
│ policy and protection │
└─────────────┬──────────────┘
┌─────────────▼──────────────┐
│ 2. Merge Configs │
│ Discover .rabbit/ YAML │
│ Deep merge by module::id │
└─────────────┬──────────────┘
┌─────────────▼──────────────┐
2. Safety Checks │
3. 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 │
│ Caller credentials │
│ passed into R2A │
└─────────────┬──────────────┘
┌─────────────▼──────────────┐
Expand All @@ -170,7 +175,7 @@ services:

### Environment Detection

The environment is automatically resolved from:
The environment is automatically resolved from the workflow event, then resolved against this action's lifecycle policy:

| Trigger | Environment Source |
| --- | --- |
Expand Down Expand Up @@ -201,7 +206,10 @@ Infrastructure configs live in `.rabbit/` directories organized by lifecycle:

- 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)
- Root-level files in the configured `source_dir` are ignored (must be in a lifecycle directory)
- Only direct lifecycle roots under `source_dir` are eligible; use `source_dir: .rabbit/infra_configs` for nested config roots

See [docs/configuration.md](docs/configuration.md) for the repo-owned Rabbit config layout and merge contract.

### Plan Mode

Expand Down Expand Up @@ -449,15 +457,19 @@ The workflow dispatch inputs provide safe manual control:

---

## Authentication and state ownership

The caller workflow owns cloud authentication. Authenticate with Google Cloud before invoking the action; the action mounts the resulting `GOOGLE_APPLICATION_CREDENTIALS` file read-only into the R2A container and never copies it into the workspace. Configure AWS credentials in the caller when the configuration uses AWS; the action forwards the resulting AWS session variables to R2A.

The optional state-backend inputs are passed through to the IaC engine. Omit them to retain its existing GCS default; provide the backend type, configuration, and state-path key only when the selected backend requires an override.

---

## Inputs Reference

| Input | Required | Default | Description |
| --- | --- | --- | --- |
| `project_id` | ✅ | — | GCP project ID |
| `gcp_auth_provider` | ✅ | — | GCP Workload Identity Provider |
| `gcp_service_account` | ✅ | — | GCP Service Account email |
| `aws_role_arn` | — | — | AWS IAM OIDC role ARN |
| `aws_region` | — | — | AWS region |
| `project_id` | ✅ | — | Project identifier for state and resource operations |
| `dockerhub_username` | — | — | Docker Hub username |
| `dockerhub_token` | — | — | Docker Hub pull token |
| `dockerhub_helm_token` | — | — | Docker Hub Helm OCI token |
Expand All @@ -472,15 +484,22 @@ The workflow dispatch inputs provide safe manual control:
| `newrelic_account_id` | — | — | New Relic account ID |
| `newrelic_api_key` | — | — | New Relic API key |
| `slack_webhook` | — | — | Slack webhook URL |
| `state_backend` | — | container default (GCS) | Optional backend override, such as `s3`, `azurerm`, `http`, or `consul` |
| `state_backend_config` | — | — | Backend configuration as `key=value` lines |
| `state_prefix_key` | — | — | Backend configuration key for the state path, such as `prefix` or `key` |
| `source_dir` | — | `.rabbit` | Config source directory |
| `github_token` | — | `github.token` | GitHub token for PR comments |
| `lifecycle_policy_path` | — | bundled policy | Optional caller-repository lifecycle policy shared by resolution and config merging |
| `github_token` | — | `github.token` | GitHub token passed to lifecycle resolution and used for PR comments |

## Outputs

| Output | Description |
| --- | --- |
| `environment` | Resolved environment name |
| `lifecycle` | Resolved lifecycle (production/staging/development) |
| `is_protected` | Whether GitHub reported the environment branch as protected |
| `resolution_reason` | Lifecycle rule that selected the lifecycle |
| `lifecycle_policy_path` | Lifecycle policy used for resolution and config merging |
| `plan_only` | Whether run was plan-only |
| `terraform_action` | Action executed (apply/destroy/skip) |
| `has_changes` | Whether Terraform detected changes |
Expand Down Expand Up @@ -528,9 +547,14 @@ Notifications include environment, change counts, failure stage, and a link to t
- **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
- **Set `source_dir` explicitly** when configs live below `.rabbit/infra_configs` or another nested root
- **Schedule nightly runs** (`cron: "0 2 * * *"`) to detect infrastructure drift
- **Keep `.rabbit/` configs small and focused** — one concern per file

## Development

The local validation contract is documented in [docs/validation.md](docs/validation.md). Run `make test` and `dev.kit repo` before updating a PR.

---

## License
Expand Down
Loading