Skip to content

dydxopsdao/ci-cd-workflows

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dydxopsdao/ci-cd-workflows

Modular, reusable CI/CD framework for frontend projects. Config-file driven, with pluggable E2E tests, Vercel 0% canary deployments, Datadog deployment gates, and progressive Slack notifications.

How It Works

Each frontend repo adds a config file (.github/cicd.yml) and two thin workflow files. Repos that track an upstream repo add one more thin upstream workflow. The framework handles everything else.

Your Repo                          ci-cd-workflows (this repo)
──────────                         ────────────────────────────
.github/cicd.yml     ──reads──►    config/read action
.github/workflows/                 
  deploy.yml (25 lines) ──uses──►  deploy.yml orchestrator
  ci.yml     (10 lines) ──uses──►  ci.yml orchestrator
  upstream-track.yml  ──uses──►    upstream-sync.yml orchestrator (optional)

Deploy Pipeline Flow

Push to main
  └─► Slack: "Deploying v1.42.3"
  └─► Vercel: Deploy at 0% canary
  └─► E2E tests + Lighthouse (parallel, against canary)
  └─► Datadog gate check
  └─► Execute rollout plan (auto/manual)
  └─► Slack: "Deployed" or "Aborted"

Quick Start

1. Add .github/cicd.yml to your repo

# yaml-language-server: $schema=https://raw.githubusercontent.com/dydxopsdao/ci-cd-workflows/v1/schemas/cicd.schema.json

project:
  name: "my-app"
  emoji: ":rocket:"

slack:
  channels:
    deploy: "C0DEPLOY00"
    alerts: "C0ALERTS00"
    ci: "C0CINOTIFY"
  notify_users:
    - "U0YOURSLACKID"

vercel:
  project_id: "prj_xxxx"
  production_url: "https://my-app.example.com"

modules:
  e2e:
    enabled: true
  lighthouse:
    enabled: false
  datadog_gate:
    enabled: false
  json_validation:
    enabled: false

2. Add .github/workflows/deploy.yml

name: Deploy
on:
  push:
    branches: [main]

jobs:
  pipeline:
    uses: dydxopsdao/ci-cd-workflows/.github/workflows/deploy.yml@v1
    secrets: inherit

  e2e:
    needs: [pipeline]
    if: needs.pipeline.outputs.canary_ready == 'true' && needs.pipeline.outputs.e2e_enabled == 'true'
    runs-on: ubuntu-latest
    outputs:
      result: ${{ steps.tests.outputs.result }}
    steps:
      - uses: your-org/your-e2e-repo/.github/actions/run@v1
        id: tests
        with:
          base_url: "${{ needs.pipeline.outputs.canary_url }}"
          canary_cookie: "${{ needs.pipeline.outputs.canary_cookie }}"
      - uses: dydxopsdao/ci-cd-workflows/actions/slack/update@v1
        if: always()
        with:
          slack_bot_token: "${{ secrets.SLACK_BOT_TOKEN }}"
          channel_id: "${{ needs.pipeline.outputs.slack_channel_id }}"
          message_ts: "${{ needs.pipeline.outputs.slack_message_ts }}"
          step_name: "E2E Tests"
          status: "${{ steps.tests.outputs.result }}"

  promote:
    needs: [pipeline, e2e]
    if: always() && needs.pipeline.outputs.canary_ready == 'true'
    uses: dydxopsdao/ci-cd-workflows/.github/workflows/promote.yml@v1
    with:
      deployment_id: "${{ needs.pipeline.outputs.deployment_id }}"
      e2e_result: "${{ needs.e2e.result == 'skipped' && '' || (needs.e2e.result == 'success' && 'passed' || 'failed') }}"
      lighthouse_result: "${{ needs.pipeline.outputs.lighthouse_result == 'skipped' && '' || needs.pipeline.outputs.lighthouse_result }}"
      datadog_result: "${{ needs.pipeline.outputs.datadog_result == 'skipped' && '' || needs.pipeline.outputs.datadog_result }}"
    secrets: inherit

Important: The promote job must wire through all gate results. Missing results for enabled modules will cause an automatic abort.

3. Add .github/workflows/ci.yml

name: CI
on:
  pull_request:
    types: [opened, edited, reopened, synchronize]

jobs:
  ci:
    uses: dydxopsdao/ci-cd-workflows/.github/workflows/ci.yml@v1
    secrets: inherit

4. Configure Vercel Rolling Releases

Enable Rolling Releases on your Vercel project with a 0% first stage.

5. (Optional) Add .github/workflows/upstream-track.yml

Use this only for repos with modules.upstream_tracker.enabled: true:

name: Upstream Track
on:
  repository_dispatch:
    types: [upstream_release_detected]
  workflow_dispatch:
    inputs:
      upstream_repo:
        required: true
        type: string
      upstream_tag:
        required: true
        type: string

jobs:
  sync:
    uses: dydxopsdao/ci-cd-workflows/.github/workflows/upstream-sync.yml@v1
    with:
      upstream_repo: ${{ github.event.client_payload.upstream_repo || inputs.upstream_repo }}
      upstream_tag: ${{ github.event.client_payload.upstream_tag || inputs.upstream_tag }}
      production_branch: main
    secrets: inherit

6. Set Org-Level Secrets

Secret Required Description
SLACK_BOT_TOKEN Yes Slack bot token with chat:write scope
VERCEL_TOKEN Yes Vercel API token
DD_API_KEY If using Datadog gate Datadog API key
DD_APP_KEY If using Datadog gate Datadog application key
GH_APP_ID If using upstream tracker GitHub App ID
GH_APP_PRIVATE_KEY If using upstream tracker GitHub App private key
UPSTREAM_WEBHOOK_SECRET If using upstream tracker webhook receiver HMAC secret used to validate incoming GitHub webhooks

Config Reference

All project config lives in .github/cicd.yml. See schemas/cicd.schema.json for the full schema, or examples/cicd.yml for a complete example.

Rollout Plans

Control how canaries are promoted after tests pass:

# Auto mode: advance on a timer
rollout:
  mode: "auto"
  stages:
    - percent: 0        # tests run here
    - percent: 10
      duration: 5m
    - percent: 50
      duration: 10m
    - percent: 100
  timeout: 15m

# Manual mode: hold at each stage until approved
rollout:
  mode: "manual"
  stages:
    - percent: 0
    - percent: 25
    - percent: 50
    - percent: 100
  timeout: 24h

# Mixed: auto for early stages, manual approval for the big jump
rollout:
  mode: "auto"
  stages:
    - percent: 0
    - percent: 10
      duration: 5m
    - percent: 50
      require_approval: true
    - percent: 100

Default (when rollout is omitted): auto, 0% -> 100%, 15m timeout.

Repository Structure

.github/workflows/
  ci.yml                        Reusable CI orchestrator
  deploy.yml                    Reusable deploy orchestrator
  promote.yml                   Promote or abort canary
  upstream-sync.yml             Reusable upstream sync orchestrator
actions/
  config/read/                  Parse .github/cicd.yml
  slack/init/                   Post initial Slack progress message
  slack/update/                 Update Slack message in-place
  deploy/vercel-canary/         Manage Vercel Rolling Releases
  deploy/datadog-gate/          Check Datadog monitors
  deploy/upstream-tracker/      Detect upstream releases (for forks)
  test/lighthouse/              Lighthouse audits against canary
  test/json-validate/           JSON config validation
schemas/
  cicd.schema.json              JSON Schema for config validation
templates/slack-blocks/         Block Kit templates
examples/                       Example config and workflow files
webhook-api/                    Webhook receiver (Vercel serverless) for upstream release events

E2E Test Contract

E2E tests live in separate repos. Any test repo that plugs into this framework must expose a composite action with this interface:

inputs:
  base_url:     # URL to test against (required)
  canary_cookie: # Cookie param for canary pinning (optional)
outputs:
  result:       # "passed" or "failed"
  duration:     # Total duration in seconds
  report_url:   # URL to HTML report artifact

See examples/e2e-action.yml for a complete Playwright example.

Webhook-Driven Upstream Tracker

The upstream tracking path is event-driven:

  1. GitHub sends release.published or create(tag) webhook to webhook-api/api/github/upstream-release.
  2. The webhook API validates X-Hub-Signature-256 using UPSTREAM_WEBHOOK_SECRET.
  3. The API scans repos in TARGET_ORG, reads each .github/cicd.yml, and selects repos where:
    • modules.upstream_tracker.enabled: true
    • modules.upstream_tracker.upstream_repo matches the webhook source repo.
  4. For each match, the API sends repository_dispatch with:
    • event_type: upstream_release_detected
    • client_payload: { upstream_repo, upstream_tag, upstream_version, source_event, delivery_id, occurred_at }
  5. Consumer repo upstream-track.yml calls upstream-sync.yml, which:
    • classifies patch vs minor/major using actions/deploy/upstream-tracker
    • auto-creates/updates a sync PR for patches when auto_deploy_patches: true
    • posts Slack alert only for minor/major updates when notify_on_minor_major: true.

Webhook API deployment env vars:

  • GH_APP_ID
  • GH_APP_PRIVATE_KEY
  • UPSTREAM_WEBHOOK_SECRET
  • UPSTREAM_ALLOWED_REPOS (comma-separated owner/repo)
  • TARGET_ORG (consumer repo org to scan)

Versioning

Consumer repos pin to a major version tag:

uses: dydxopsdao/ci-cd-workflows/.github/workflows/deploy.yml@v1
  • v1 always points to the latest v1.x.x (non-breaking updates)
  • Pin to @v1.2.0 for strict version control
  • See CHANGELOG.md for breaking changes

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors