DEV Community

kanta13jp1
kanta13jp1

Posted on

GitHub Actions Beyond the Basics: Reusable Workflows, Matrix, and Cache

GitHub Actions Beyond the Basics: Reusable Workflows, Matrix, and Cache

Using GitHub Actions for "just running CI" misses half its value. Here are the advanced patterns I actually use in production.

1. Reusable Workflows — Share Common Steps

If multiple workflows repeat the same steps, extract them:

# .github/workflows/reusable-flutter-setup.yml
on:
  workflow_call:
    inputs:
      flutter-version:
        required: false
        type: string
        default: '3.27.0'

jobs:
  setup:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: subosito/flutter-action@v2
        with:
          flutter-version: ${{ inputs.flutter-version }}
          cache: true
      - run: flutter pub get
Enter fullscreen mode Exit fullscreen mode

Caller:

# .github/workflows/ci.yml
jobs:
  test:
    uses: ./.github/workflows/reusable-flutter-setup.yml
    with:
      flutter-version: '3.27.0'
Enter fullscreen mode Exit fullscreen mode

Before: flutter pub get duplicated across 5 workflows.
After: one file to update.

2. Matrix Strategy — Parallel Test Runs

jobs:
  test:
    strategy:
      matrix:
        platform: [vm, chrome]
        flutter-version: ['3.24.0', '3.27.0']
      fail-fast: false  # don't stop on first failure

    runs-on: ubuntu-latest
    steps:
      - run: |
          if [ "${{ matrix.platform }}" = "chrome" ]; then
            flutter test --platform chrome
          else
            flutter test
          fi
Enter fullscreen mode Exit fullscreen mode

4 combinations (2 platforms × 2 versions) run in parallel. fail-fast: false gives you the full result picture.

3. Cache — Speed Up Dependencies

- name: Cache Flutter packages
  uses: actions/cache@v4
  with:
    path: |
      ~/.pub-cache
      .dart_tool
    key: flutter-${{ runner.os }}-${{ hashFiles('pubspec.lock') }}
    restore-keys: |
      flutter-${{ runner.os }}-

- name: Cache Deno dependencies
  uses: actions/cache@v4
  with:
    path: ~/.deno
    key: deno-${{ hashFiles('supabase/functions/**/deps.ts') }}
Enter fullscreen mode Exit fullscreen mode

If pubspec.lock doesn't change, the cache is reused. CI time: 4min → 1.5min.

4. Conditional Steps — Run Only What Changed

- name: Get changed files
  id: changes
  uses: dorny/paths-filter@v3
  with:
    filters: |
      flutter:
        - 'lib/**'
        - 'pubspec.yaml'
      supabase:
        - 'supabase/**'

- name: Run Flutter tests
  if: steps.changes.outputs.flutter == 'true'
  run: flutter test

- name: Deploy Edge Functions
  if: steps.changes.outputs.supabase == 'true'
  run: supabase functions deploy
Enter fullscreen mode Exit fullscreen mode

Skip Flutter tests when only Supabase files changed. Cut unnecessary CI minutes.

5. Scheduled Tasks — $0 Recurring Jobs

on:
  schedule:
    - cron: '0 */4 * * *'  # every 4 hours
  workflow_dispatch:         # also triggerable manually

jobs:
  digest:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run digest
        env:
          SUPABASE_SERVICE_KEY: ${{ secrets.SUPABASE_SERVICE_KEY }}
        run: |
          curl -sf "$SUPABASE_DIGEST_URL" \
            -H "Authorization: Bearer $SUPABASE_SERVICE_KEY"
Enter fullscreen mode Exit fullscreen mode

GitHub Actions free tier (2000 min/month) covers it. No external cron service needed.

6. Concurrency Control

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: false  # don't cancel running deploys
Enter fullscreen mode Exit fullscreen mode
  • cancel-in-progress: true → for PR checks (cancel old commit's CI when new push arrives)
  • cancel-in-progress: false → for production deploys (don't leave a half-deployed state)

My Workflow Inventory

ci.yml              - flutter test + analyze (push/PR)
deploy-prod.yml     - firebase hosting deploy (main push)
blog-publish.yml    - dev.to/Qiita auto-publish (workflow_dispatch)
cs-check.yml        - support ticket check (every 4h)
daily-report.yml    - daily report generation (every morning)
claude-agent-review.yml  - PR review (PR open)
health-monitor.yml  - infra health check (every 30min)
Enter fullscreen mode Exit fullscreen mode

7 workflows automate dev, ops, and content publishing.

Summary

Introduce GitHub Actions features in this order: Reusable → Matrix → Cache → Conditional → Schedule. Cache has the highest impact for the lowest implementation cost. Start there.

Top comments (0)