Files
moko-platform/docs/workflows/workflow-architecture.md
T
2026-04-26 19:30:30 -05:00

17 KiB

MokoStandards

Workflow Architecture

Overview

Important (v2): All workflows MUST be in .gitea/workflows/ only. Gitea Actions does not run workflows from .github/workflows/. Having files in .github/workflows/ creates ghost queued runs that block the runner.

This document explains the workflow architecture used across Moko Consulting repositories, including the hierarchy, design patterns, reusable workflow patterns, and decision-making processes for workflow selection.

Purpose

This architecture guide provides:

  • Understanding: Clear mental model of workflow organization
  • Guidance: Decision trees for workflow selection
  • Patterns: Reusable patterns and best practices
  • Relationships: How workflows interact and depend on each other
  • Evolution: How to extend and improve the workflow architecture

Three-Tier Workflow Architecture

Moko Consulting uses a three-tier architecture for GitHub Actions workflows:

┌─────────────────────────────────────────────────────────────┐
│ Tier 1: Organization-Wide Reusable Workflows               │
│ Location: .github-private repository                        │
│ Visibility: Private                                         │
│ Purpose: Shared across all organization repositories        │
│ Examples: Deployment, compliance audits, security scanning  │
└─────────────────────────────────────────────────────────────┘
                          ↓ (called by)
┌─────────────────────────────────────────────────────────────┐
│ Tier 2: Public Reusable Workflows                          │
│ Location: MokoStandards repository                          │
│ Visibility: Public                                          │
│ Purpose: Templates and patterns for community use           │
│ Examples: CI validation, build automation, health checks    │
└─────────────────────────────────────────────────────────────┘
                          ↓ (called by)
┌─────────────────────────────────────────────────────────────┐
│ Tier 3: Local Workflows                                    │
│ Location: Individual repository .gitea/workflows/         │
│ Visibility: Matches repository visibility                   │
│ Purpose: Repository-specific automation                    │
│ Examples: Project builds, tests, custom deployments        │
└─────────────────────────────────────────────────────────────┘

Tier 1: Organization-Wide Reusable Workflows

Location: mokoconsulting-tech/.github-private/.gitea/workflows/

Characteristics:

  • Private and secure
  • Contains sensitive organizational logic
  • Requires organization secrets
  • Enforces organization-wide compliance
  • Centrally maintained with high governance
  • Performs cross-repository operations

Examples:

  • reusable-compliance-audit.yml - Monthly compliance audits
  • reusable-standards-scan.yml - Organization-wide standards scanning
  • reusable-branch-cleanup.yml - Automated branch cleanup
  • reusable-auto-label.yml - Automated issue/PR labeling
  • reusable-stale-management.yml - Stale issue/PR management

When to Use:

  • Workflow contains proprietary logic
  • Workflow requires organization-level secrets
  • Workflow performs cross-repository operations
  • Workflow enforces organization-wide policies
  • Workflow handles sensitive data or operations

Tier 2: Public Reusable Workflows

Location: MokoConsulting/MokoStandards/.gitea/workflows/

Characteristics:

  • Public and community-accessible
  • Demonstrates best practices
  • Platform-agnostic where possible
  • Well-documented with examples
  • Follows standards defined in /docs/policy/
  • Suitable for open-source sharing

Examples:

  • reusable-ci-validation.yml - CI validation with project detection
  • reusable-build.yml - Universal build workflow
  • reusable-deploy.yml - Deployment workflow template
  • reusable-joomla-testing.yml - Joomla-specific testing
  • reusable-php-quality.yml - PHP code quality checks
  • reusable-project-detector.yml - Automatic project type detection

When to Use:

  • Workflow is a common pattern across repositories
  • Workflow can be public and shared
  • Workflow demonstrates best practices
  • Workflow is platform-agnostic or extensible
  • Workflow serves as template for community

Tier 3: Local Workflows

Location: Individual repository .gitea/workflows/

Characteristics:

  • Repository-specific
  • Calls reusable workflows from Tier 1 or Tier 2
  • Contains minimal logic (orchestration only)
  • Easy to understand and maintain
  • Project-specific configuration

Examples:

  • ci.yml - Calls reusable CI validation workflow
  • release-pipeline.yml - Orchestrates release process
  • repo-health.yml - Repository health monitoring
  • standards-compliance.yml - Standards validation

When to Use:

  • Workflow is specific to one repository
  • Workflow doesn't fit reusable pattern
  • Workflow is experimental or temporary
  • Workflow orchestrates multiple reusable workflows

Workflow Design Patterns

Pattern 1: Project Detection and Conditional Execution

Automatically detect project type and execute appropriate build/test strategy.

jobs:
  detect:
    uses: MokoConsulting/MokoStandards/.gitea/workflows/reusable-project-detector.yml@main

  build-joomla:
    needs: detect
    if: needs.detect.outputs.project-type == 'joomla'
    uses: MokoConsulting/MokoStandards/.gitea/workflows/reusable-joomla-testing.yml@main

  build-generic:
    needs: detect
    if: needs.detect.outputs.project-type == 'generic'
    uses: MokoConsulting/MokoStandards/.gitea/workflows/reusable-build.yml@main

Benefits:

  • Single workflow supports multiple project types
  • No manual configuration needed
  • Easy to maintain and extend

Pattern 2: Composition through Reusable Workflows

Build complex workflows by composing simple reusable workflows.

jobs:
  # Step 1: Validate code
  validate:
    uses: MokoConsulting/MokoStandards/.gitea/workflows/reusable-ci-validation.yml@main

  # Step 2: Build if validation passes
  build:
    needs: validate
    uses: MokoConsulting/MokoStandards/.gitea/workflows/reusable-build.yml@main

  # Step 3: Deploy if build passes
  deploy:
    needs: build
    if: github.ref == 'refs/heads/main'
    uses: MokoConsulting/MokoStandards/.gitea/workflows/reusable-deploy.yml@main
    secrets: inherit

Benefits:

  • Clear separation of concerns
  • Reusable components
  • Easy to test and debug
  • Flexible composition

Pattern 3: Matrix Strategy for Multi-Platform Testing

Test across multiple versions or platforms using matrix strategy.

jobs:
  test:
    strategy:
      matrix:
        php-version: ['7.4', '8.0', '8.1', '8.2']
        os: [ubuntu-latest, windows-latest]
    uses: MokoConsulting/MokoStandards/.gitea/workflows/reusable-php-quality.yml@main
    with:
      php-version: ${{ matrix.php-version }}

Benefits:

  • Comprehensive testing coverage
  • Parallel execution
  • Configurable test matrix

Pattern 4: Conditional Deployment Based on Environment

Deploy to different environments based on branch or tag.

jobs:
  deploy-staging:
    if: github.ref == 'refs/heads/dev'
    uses: MokoConsulting/MokoStandards/.gitea/workflows/reusable-deploy.yml@main
    with:
      environment: staging

  deploy-production:
    if: startsWith(github.ref, 'refs/tags/v')
    uses: MokoConsulting/MokoStandards/.gitea/workflows/reusable-deploy.yml@main
    with:
      environment: production

Benefits:

  • Safe deployment practices
  • Environment-specific configuration
  • Clear deployment triggers

Pattern 5: Workflow Dispatch with Manual Controls

Allow manual triggering with customizable inputs.

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Deployment environment'
        required: true
        type: choice
        options:
          - staging
          - production
      dry-run:
        description: 'Perform dry run'
        required: false
        type: boolean
        default: true

jobs:
  deploy:
    uses: MokoConsulting/MokoStandards/.gitea/workflows/reusable-deploy.yml@main
    with:
      environment: ${{ inputs.environment }}
      dry-run: ${{ inputs.dry-run }}

Benefits:

  • Manual control when needed
  • Safe defaults (dry-run)
  • Clear input options

Workflow Relationships

Dependency Graph

repo-health.yml
    │
    └──> Uses: reusable-project-detector.yml
                │
                └──> Provides: project-type output

ci.yml
    │
    ├──> Uses: reusable-ci-validation.yml
    │         │
    │         ├──> Uses: reusable-project-detector.yml
    │         └──> Uses: reusable-php-quality.yml (if PHP)
    │
    └──> Uses: reusable-build.yml
              │
              └──> Uses: reusable-project-detector.yml

release-pipeline.yml
    │
    ├──> Uses: reusable-build.yml
    ├──> Uses: reusable-release.yml
    └──> Uses: reusable-deploy.yml

Workflow Inheritance

Workflows inherit behavior through composition:

  1. Base Workflows: Provide core functionality

    • reusable-project-detector.yml
    • reusable-build.yml
  2. Specialized Workflows: Add domain-specific logic

    • reusable-joomla-testing.yml (extends base build)
    • reusable-php-quality.yml (extends base validation)
  3. Orchestration Workflows: Combine multiple workflows

    • ci.yml (combines validation + build)
    • release-pipeline.yml (combines build + release + deploy)

Decision Trees

Choosing the Right Tier

Start: Need to create/modify workflow
    │
    ├──> Contains sensitive/proprietary logic?
    │    └──> YES: Use Tier 1 (.github-private)
    │
    ├──> Common pattern across repositories?
    │    └──> YES: Use Tier 2 (MokoStandards)
    │
    └──> Repository-specific?
         └──> YES: Use Tier 3 (local workflow)

Choosing Between Reusable vs Local

Start: Creating new workflow
    │
    ├──> Used by multiple repositories?
    │    └──> YES: Create reusable workflow
    │
    ├──> Complex multi-step process?
    │    └──> YES: Break into reusable components
    │
    └──> Simple repository-specific task?
         └──> YES: Create local workflow

Choosing Workflow Trigger

Start: When should workflow run?
    │
    ├──> On code changes?
    │    └──> Use: on.push, on.pull_request
    │
    ├──> On schedule?
    │    └──> Use: on.schedule (cron)
    │
    ├──> Manual trigger needed?
    │    └──> Use: on.workflow_dispatch
    │
    └──> Called by other workflows?
         └──> Use: on.workflow_call

Workflow Evolution

Adding New Workflows

  1. Identify Need: What problem does this workflow solve?
  2. Check Existing: Can existing workflow be extended?
  3. Design Interface: Define inputs, outputs, secrets
  4. Choose Tier: Public (Tier 2) or Private (Tier 1)?
  5. Implement: Follow Workflow Standards
  6. Document: Add to REUSABLE_WORKFLOWS.md
  7. Test: Validate in test repository
  8. Deploy: Merge and communicate

Refactoring Workflows

Signs a workflow needs refactoring:

  • Duplicated logic across repositories
  • Complex, hard-to-maintain workflow
  • Frequent changes to same workflow across repos
  • Lack of clear purpose or focus

Refactoring process:

  1. Identify common patterns
  2. Extract to reusable workflow
  3. Define clear interface
  4. Update calling workflows
  5. Test thoroughly
  6. Document changes
  7. Deprecate old approach

Deprecating Workflows

Process for deprecating workflows:

  1. Add deprecation notice to workflow
  2. Provide migration path
  3. Update documentation
  4. Communicate to users
  5. Wait minimum 90 days
  6. Move to archived/ directory
  7. Update inventories

Best Practices

Keep Workflows Focused

Good: Single-purpose workflow

# reusable-php-quality.yml - PHP quality checks only
jobs:
  quality:
    runs-on: ubuntu-latest
    steps:
      - name: Run PHP CodeSniffer
      - name: Run PHPStan
      - name: Run PHP Mess Detector

Bad: Kitchen-sink workflow

# mega-workflow.yml - Too many responsibilities
jobs:
  everything:
    steps:
      - name: Lint
      - name: Test
      - name: Build
      - name: Deploy
      - name: Notify
      - name: Update docs

Use Composition Over Duplication

Good: Compose from reusable workflows

jobs:
  validate:
    uses: org/repo/.gitea/workflows/reusable-validate.yml@main
  build:
    uses: org/repo/.gitea/workflows/reusable-build.yml@main

Bad: Duplicate logic

jobs:
  validate-and-build:
    steps:
      - name: Checkout
      - name: Setup
      - name: Lint (duplicated across repos)
      - name: Test (duplicated across repos)
      - name: Build (duplicated across repos)

Fail Fast

Good: Quick feedback on failures

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - name: Quick syntax check
        run: |
          if ! php -l src/*.php; then
            echo "::error::PHP syntax errors found"
            exit 1
          fi

  test:
    needs: validate  # Only run if validation passes

Bad: Slow feedback

jobs:
  everything:
    steps:
      - name: Run all tests (30 minutes)
      - name: Then check syntax  # Should be first!

Common Anti-Patterns

Anti-Pattern 1: Monolithic Workflows

Problem: One huge workflow that does everything

Solution: Break into focused, composable workflows

Anti-Pattern 2: Hardcoded Values

Problem: Hardcoded configuration in workflow files

Solution: Use inputs and variables

Anti-Pattern 3: Insufficient Error Handling

Problem: Workflows fail silently or with unclear errors

Solution: Add error handling and clear error messages

Anti-Pattern 4: Overly Broad Permissions

Problem: Workflows request more permissions than needed

Solution: Follow principle of least privilege

Anti-Pattern 5: No Testing

Problem: Workflows deployed without testing

Solution: Test in feature branches first

References

Metadata

  • Document: .github/WORKFLOW_ARCHITECTURE.md
  • Repository: MokoStandards
  • Owner: Moko Consulting Engineering Team
  • Scope: Workflow architecture and design patterns
  • Lifecycle: Active
  • Audience: All engineers and workflow authors

Revision History

Version Date Author Notes
01.00.00 2026-01-13 GitHub Copilot Initial workflow architecture documentation