Skip to content

DevOps & Development Flow

Full CI/CD pipeline, PR lifecycle, and notification architecture across all repos.

For the rendered version with interactive diagrams, see the docs site.

Overview

All repos follow GitHub Flow: trunk-based development with feature branches and squash merge to main. The pipeline is fully automated from PR creation through merge, release tagging, and Discord notifications.

PR Lifecycle

sequenceDiagram
    participant Agent as Developer / AI Agent
    participant Git as GitHub
    participant CI as CI Runner
    participant Copilot as Copilot Review
    participant Auto as Auto-merge
    participant Discord as Discord #tasks

    Agent->>Git: git push + gh pr create
    activate Git

    par Parallel triggers
        Git->>CI: build-and-test.yml
        Git->>Copilot: Automatic code review
        Git->>Discord: request-review.yml<br/>(create thread)
        Git->>Auto: auto-merge.yml<br/>(start waiting)
    end

    CI-->>Git: Check result (pass/fail)
    Git->>Discord: build-status-to-discord.yml

    Copilot-->>Git: Review (approve/request changes)
    Git->>Discord: forward-copilot-reviews.yml

    Note over Auto: Wait for CI (10 min timeout)
    Note over Auto: Wait for Copilot (60s)
    Note over Auto: Check unresolved conversations

    alt All checks pass + no unresolved threads
        Auto->>Git: Enable auto-merge (squash)
        Git-->>Auto: PR merged
        Auto->>Discord: Merge notification + author mention
        Auto->>Git: Trigger release-please
        Auto->>Git: Close linked issues
    else Checks failed or unresolved threads
        Auto-->>Discord: Failure notification
    end

    deactivate Git

Auto-merge Decision Flow

flowchart TD
    A[PR opened/synchronized] --> B{manual-merge label?}
    B -->|Yes| Z[Skip - manual merge required]
    B -->|No| C[Wait for CI checks]

    C --> D{All checks completed?}
    D -->|No, timeout 10min| Z2[Fail - timeout]
    D -->|Yes| E{All passed or skipped?}
    E -->|No| Z3[Fail - checks failed]
    E -->|Yes| F[Wait 60s for Copilot]

    F --> G[Query review threads via GraphQL]
    G --> H{Unresolved conversations?}
    H -->|Yes| Z4[Fail - unresolved threads]
    H -->|No| I[Try GraphQL enableAutoMerge]

    I --> J{GraphQL succeeded?}
    J -->|Yes| K[Auto-merge enabled]
    J -->|No| L[Fallback: REST pulls.merge]
    L --> M{REST merge succeeded?}
    M -->|Yes| K
    M -->|No| Z5[Fail - merge blocked]

    K --> N[Poll for merged_at - 2 min]
    N --> O{PR merged?}
    O -->|Yes| P[Post-merge actions]
    O -->|No, timeout| Z6[Skip post-merge]

    P --> P1[Trigger release-please]
    P --> P2{ios/ files changed?}
    P2 -->|Yes| P3[Trigger Xcode Cloud monitor]
    P2 -->|No| P4[Skip]
    P --> P5[Discord merge notification]
    P --> P6[Close linked issues]

    style Z fill:#f66,color:#fff
    style Z2 fill:#f66,color:#fff
    style Z3 fill:#f66,color:#fff
    style Z4 fill:#f66,color:#fff
    style Z5 fill:#f66,color:#fff
    style K fill:#6f6,color:#000

Discord Notification Architecture

flowchart LR
    subgraph GitHub Events
        E1[PR opened]
        E2[CI completed]
        E3[Review submitted]
        E4[PR push]
        E5[PR merged]
    end

    subgraph Workflows
        W1[request-review.yml]
        W2[build-status-to-discord.yml]
        W3[pr-comments-to-discord.yml]
        W4[forward-copilot-reviews.yml]
        W5[auto-merge.yml]
    end

    subgraph Discord Thread
        T1[New PR notification]
        T2[CI pass/fail]
        T3[Review comments]
        T4[Copilot review]
        T5[Merge notification]
    end

    E1 --> W1 --> T1
    E2 --> W2 --> T2
    E3 --> W3 --> T3
    E4 --> W4 --> T4
    E5 --> W5 --> T5

    T1 -. "thread ID stored as<br>PR comment" .-> W2
    T1 -. "thread ID" .-> W3
    T1 -. "thread ID" .-> W4
    T1 -. "thread ID" .-> W5

Release Flow

flowchart TD
    A[PR merged to main] --> B[release-please.yml triggered]
    B --> C{Releasable commits?}
    C -->|No| D[No action]
    C -->|Yes| E[Open/update Release PR]

    E --> F[Release PR contains:<br>- version bump in version.txt<br>- CHANGELOG.md update]

    F --> G{Release PR merged?}
    G -->|No| H[Accumulate more commits]
    H --> C
    G -->|Yes| I[Create GitHub Release + git tag]

    I --> J[post-release-check.yml]
    J --> K[Verify release tag and assets]

    I --> L{iOS files changed?}
    L -->|Yes| M[Xcode Cloud builds new version]
    M --> N[TestFlight distribution]
    L -->|No| O[Done]

    style I fill:#6f6,color:#000

PR State Machine

stateDiagram-v2
    [*] --> Open: PR created

    Open --> ChecksRunning: CI triggered
    ChecksRunning --> ChecksPassed: All pass
    ChecksRunning --> ChecksFailed: Any fail

    ChecksFailed --> ChecksRunning: New push (synchronize)

    ChecksPassed --> UnderReview: Copilot + Review-E
    UnderReview --> ChangesRequested: Reviewer requests changes
    ChangesRequested --> ChecksRunning: Agent pushes fix

    UnderReview --> Approved: All reviews approve
    Approved --> ConversationCheck: Auto-merge checks threads

    ConversationCheck --> Blocked: Unresolved threads
    Blocked --> ConversationCheck: Threads resolved

    ConversationCheck --> Merging: No unresolved threads
    Merging --> Merged: Squash merge

    Merged --> Released: release-please tags
    Released --> [*]

Workflow Inventory

Standard Workflows (all repos)

Workflow Trigger Purpose
auto-merge.yml pull_request: [opened, synchronize, reopened] Wait for checks, merge PR
request-review.yml pull_request: [opened] Post new PR to Discord #tasks
pr-comments-to-discord.yml pull_request_review, review_comment, issue_comment Forward review comments to Discord
forward-copilot-reviews.yml pull_request: [opened, synchronize] Forward Copilot reviews (bypasses actor gate)
build-status-to-discord.yml workflow_run: [completed] Post CI result to Discord
auto-resolve-copilot-conversations.yml pull_request_review: [submitted] Auto-resolve Copilot suggestions
notify-failure.yml workflow_run: [completed] Notify on workflow failures
release-please.yml push: [main] or workflow_dispatch Version bump, changelog, GitHub Release

iOS-specific Workflows

Workflow Trigger Purpose
build-and-test.yml pull_request Build iOS app, run tests
monitor-xcode-cloud.yml workflow_dispatch Monitor Xcode Cloud build after merge
post-release-check.yml release: [published] Verify release artifacts

Infrastructure

Type Host Labels
macOS runners MacBook Air M4 [self-hosted, macOS, ARM64, ios] per-repo
Linux runners Dell k3s (ARC 0.13.1) arc-linux-{repo} per-repo

All uses: actions are SHA-pinned. Branch protection requires PR, CI pass, and Copilot review. No force push or direct push to main.

Discord Thread Model

Each PR gets a dedicated Discord thread:

  1. request-review.yml creates thread on PR open
  2. Thread ID stored as HTML comment in PR: <!-- discord-review-msg-id:XXXX -->
  3. Channel ID stored as: <!-- discord-review-channel:XXXX -->
  4. All workflows look up thread ID from PR comments to post updates

Known Issues

  1. GitHub Contents API workflow registration: Workflows added via API sometimes don't register their name: field. Events may not trigger. Fix: re-push the file.

  2. Copilot actor approval gate: GitHub requires manual approval for Copilot-triggered workflow runs. Workaround: forward-copilot-reviews.yml triggers on PR push events instead.

  3. Webhook payload case sensitivity: pull_request_review webhook payloads use lowercase review.state. REST API returns uppercase. Always normalize with .toUpperCase().

  4. Release-please pipeline gap: Release-please PRs (bot-opened) bypass the entire pipeline: no CI, no Discord, no review, no auto-merge. Tracked in #312.

Repo Status Matrix

Repo auto-merge request-review pr-comments forward-copilot build-status auto-resolve notify-failure release-please monitor-xcode post-release
nutri-e old yes yes yes yes yes yes yes yes yes
star-rewards partial yes yes yes yes yes yes yes yes yes
fast-e partial yes yes yes yes yes yes yes yes yes
count-e latest yes yes yes yes yes yes yes yes yes
drink-e fixed yes yes yes yes yes yes yes no no
heart-e template yes yes yes yes yes yes yes no no
cutie yes yes yes no yes no no yes n/a n/a

Standardization tracked in #309.