Skip to content

Instantly share code, notes, and snippets.

@SyNeto
Created November 20, 2025 20:30
Show Gist options
  • Select an option

  • Save SyNeto/0236b04e196e48d553cce3f3bc475c7a to your computer and use it in GitHub Desktop.

Select an option

Save SyNeto/0236b04e196e48d553cce3f3bc475c7a to your computer and use it in GitHub Desktop.
CMS → Infrastructure Repository Dispatch Interface Specification

CMS → Infrastructure Repository Dispatch Interface Specification

Version: 1.0 Date: 2025-11-20 Infrastructure Repo: CoreMemorySquad/cms_infrastructure CMS Repo: CoreMemorySquad/cms


Overview

This document specifies the interface contract between the CMS repository and the Infrastructure repository for automated ephemeral and staging environment deployments.

The CMS repository triggers deployments by sending repository_dispatch events to the infrastructure repository. Infrastructure workflows consume these events and provision the appropriate environments.


Event Types

Infrastructure supports three repository_dispatch event types:

Event Type Triggered By Purpose
deploy-ephemeral /test-deploy PR comment Create or update ephemeral/staging environment
destroy-ephemeral /destroy-test PR comment Manually destroy environment
pr-closed PR closed/merged webhook Auto-cleanup environment

1. Deploy Ephemeral Environment

Event Type: deploy-ephemeral Trigger: User comments /test-deploy on a PR in CMS repo

Required Payload Fields

{
  "pr_number": "string",      // PR number (e.g., "123")
  "branch": "string",         // Head branch name (e.g., "feature/new-feature")
  "base_branch": "string",    // Base/target branch (e.g., "dev" or "main")
  "commit_sha": "string",     // HEAD commit SHA of the branch
  "sender": "string"          // GitHub username who triggered deploy
}

Field Descriptions

  • pr_number (required): The PR number as a string

    • Example: "123"
    • Used for: Workspace naming, PR comments, concurrency control
  • branch (required): The feature branch being deployed

    • Example: "feature/gamification"
    • Used for: Deploying the correct code for ephemeral environments
    • Note: For staging (PR to main), infrastructure deploys dev branch instead
  • base_branch (required): The target branch of the PR

    • Example: "dev" or "main"
    • Used for: Environment type detection
    • Logic:
      • "main" → Staging environment (deploys dev branch)
      • "dev" → Ephemeral environment (deploys feature branch)
  • commit_sha (required): The commit SHA being deployed

    • Example: "a1b2c3d4e5f6"
    • Used for: PR comment information, deployment tracking
  • sender (required): GitHub username who requested deployment

    • Example: "syneto"
    • Used for: PR comment attribution

Example Workflow Step (CMS Repository)

- name: Get PR details
  id: pr
  uses: actions/github-script@v7
  with:
    script: |
      const pr = await github.rest.pulls.get({
        owner: context.repo.owner,
        repo: context.repo.repo,
        pull_number: context.issue.number
      });
      return {
        head_ref: pr.data.head.ref,
        base_ref: pr.data.base.ref,
        head_sha: pr.data.head.sha
      };

- name: Trigger infrastructure deployment
  uses: peter-evans/repository-dispatch@v3
  with:
    token: ${{ secrets.INFRASTRUCTURE_REPO_PAT }}
    repository: CoreMemorySquad/cms_infrastructure
    event-type: deploy-ephemeral
    client-payload: |
      {
        "pr_number": "${{ github.event.issue.number }}",
        "branch": "${{ fromJson(steps.pr.outputs.result).head_ref }}",
        "base_branch": "${{ fromJson(steps.pr.outputs.result).base_ref }}",
        "commit_sha": "${{ fromJson(steps.pr.outputs.result).head_sha }}",
        "sender": "${{ github.event.comment.user.login }}"
      }

Infrastructure Behavior

Base Branch Environment Type Workspace Name Branch Deployed Subdomain
dev Ephemeral pr-{number} Feature branch pr-{number}-testing.ernjv.me
main Staging staging dev branch staging.ernjv.me

Response

Infrastructure will comment on the CMS PR with:

  • ✅ Success: Deployment URL, admin panel URL, environment details
  • ❌ Failure: Error details and manual cleanup instructions

2. Destroy Ephemeral Environment

Event Type: destroy-ephemeral Trigger: User comments /destroy-test on a PR in CMS repo

Required Payload Fields

{
  "pr_number": "string",      // PR number
  "base_branch": "string",    // Base/target branch (for workspace detection)
  "sender": "string"          // GitHub username who triggered destroy
}

Field Descriptions

  • pr_number (required): The PR number
  • base_branch (required): Target branch (to determine if staging or ephemeral)
  • sender (required): GitHub username who requested destroy

Example Workflow Step (CMS Repository)

- name: Get PR details
  id: pr
  uses: actions/github-script@v7
  with:
    script: |
      const pr = await github.rest.pulls.get({
        owner: context.repo.owner,
        repo: context.repo.repo,
        pull_number: context.issue.number
      });
      return {
        base_ref: pr.data.base.ref
      };

- name: Trigger infrastructure destroy
  uses: peter-evans/repository-dispatch@v3
  with:
    token: ${{ secrets.INFRASTRUCTURE_REPO_PAT }}
    repository: CoreMemorySquad/cms_infrastructure
    event-type: destroy-ephemeral
    client-payload: |
      {
        "pr_number": "${{ github.event.issue.number }}",
        "base_branch": "${{ fromJson(steps.pr.outputs.result).base_ref }}",
        "sender": "${{ github.event.comment.user.login }}"
      }

Response

Infrastructure will comment on the CMS PR with destroy status.


3. PR Closed Cleanup

Event Type: pr-closed Trigger: PR closed or merged webhook in CMS repo

Required Payload Fields

{
  "pr_number": "string",      // PR number
  "base_branch": "string",    // Base/target branch
  "merged": "boolean"         // true if PR was merged, false if just closed
}

Field Descriptions

  • pr_number (required): The PR number
  • base_branch (required): Target branch (to determine workspace name)
  • merged (required): Whether PR was merged or just closed

Example Workflow Step (CMS Repository)

on:
  pull_request:
    types: [closed]

jobs:
  cleanup:
    runs-on: ubuntu-latest
    steps:
      - name: Trigger infrastructure cleanup
        uses: peter-evans/repository-dispatch@v3
        with:
          token: ${{ secrets.INFRASTRUCTURE_REPO_PAT }}
          repository: CoreMemorySquad/cms_infrastructure
          event-type: pr-closed
          client-payload: |
            {
              "pr_number": "${{ github.event.pull_request.number }}",
              "base_branch": "${{ github.event.pull_request.base.ref }}",
              "merged": ${{ github.event.pull_request.merged }}
            }

Response

No PR comment (environment already closed), but workflow logs available.


Required Secrets in CMS Repository

Secret Name Description Scope
INFRASTRUCTURE_REPO_PAT GitHub Personal Access Token with repo scope Repository-level

Creating the PAT

  1. Go to GitHub Settings → Developer settings → Personal access tokens → Tokens (classic)
  2. Generate new token with repo scope
  3. Add as repository secret in CMS repo: INFRASTRUCTURE_REPO_PAT

Important: The PAT must have write access to the infrastructure repository to trigger repository_dispatch events.


Testing

Manual Testing with workflow_dispatch

Infrastructure workflows support manual triggering for testing:

# In infrastructure repo workflows, these inputs exist:
workflow_dispatch:
  inputs:
    pr_number:
      description: 'PR number'
      required: true
      type: string
    branch:
      description: 'Branch name'
      required: true
      type: string

You can test infrastructure workflows directly before implementing CMS triggers.


Environment Lifecycle

Environment Created When Destroyed When
Ephemeral (pr-{number}) /test-deploy on PR to dev /destroy-test OR PR closed
Staging (staging) /test-deploy on PR to main /destroy-test OR PR to main closed

Infrastructure Response Format

Infrastructure will comment on the PR with markdown formatted messages.

Ephemeral Success Message

🚀 **Ephemeral Environment Deployed Successfully!**

**Environment**: `pr-123`
**URL**: https://pr-123-testing.ernjv.me
**Admin Panel**: https://pr-123-testing.ernjv.me/admin
**Mailpit**: https://pr-123-testing.ernjv.me/mailpit

**Database**: `pr_123` (isolated)
**Files**: `pr-123/*` (prefix-isolated in shared bucket)
**Region**: NYC3
**Instance**: Basic XXS

**Email Testing (Mailpit)**:
- Web UI: https://pr-123-testing.ernjv.me/mailpit
- All emails captured for testing (registration, password reset, etc.)
- No real emails sent

...

Staging Success Message

🚀 **Staging Environment Deployed Successfully!**

**Environment**: `staging`
**URL**: https://staging.ernjv.me
**Admin Panel**: https://staging.ernjv.me/admin

**Database**: `staging` (isolated)
**Files**: `staging/*` (prefix-isolated in shared bucket)
**Region**: NYC3
**Instance**: Basic XS

**Production Services Integrated**:
- Twilio SendGrid (real email delivery)
- Twilio SMS (real SMS delivery)
- All production-like external services

...

Summary Checklist for CMS Repository

  • Create .github/workflows/pr-commands.yml to handle PR comments
  • Implement /test-deploy command detection
  • Implement /destroy-test command detection
  • Create .github/workflows/pr-closed.yml for auto-cleanup
  • Get PR details using actions/github-script
  • Send repository_dispatch with correct event types
  • Include all required payload fields
  • Add INFRASTRUCTURE_REPO_PAT secret
  • Test with a real PR

References

  • ADR-006: Staging environment architecture (infrastructure repo)
  • ADR-002: GitHub Actions automation (infrastructure repo)
  • Infrastructure Workflows: .github/workflows/ephemeral-*.yml

Questions or Issues?

If payload format needs adjustment, infrastructure should update this specification and notify CMS team.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment