Skip to content
Latchkey

Docs Feature Drift Check workflow (PatterAI/Patter)

The Docs Feature Drift Check workflow from PatterAI/Patter, explained and optimized by Latchkey.

C

CI health: C - fair

Point runs-on at Latchkey and get caching, job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.

Grade your own workflow free or run it on Latchkey →
Source: PatterAI/Patter.github/workflows/docs-feature-drift.ymlLicense MITView source

What it does

This is the Docs Feature Drift Check workflow from the PatterAI/Patter repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.

Below, Latchkey shows a faster, safer version produced by its optimization engine.

The workflow

workflow (.yml)
name: Docs Feature Drift Check

# Daily consistency check between:
#   - the canonical feature inventory (patter_sdk_features.xlsx, stored in the
#     patter-assets sibling repo)
#   - the Mintlify documentation under docs/
#   - the public SDK surface (libraries/python/getpatter/__init__.py + libraries/typescript/src/index.ts)
#
# Opens or updates a single issue labelled `docs-drift` listing every mismatch.
# If there is nothing to report, closes the issue (if open).

on:
  schedule:
    # 03:00 UTC every day
    - cron: '0 3 * * *'
  workflow_dispatch: {}

permissions:
  contents: read
  issues: write

jobs:
  drift-check:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Patter repo
        uses: actions/checkout@v5

      - name: Checkout patter-assets (private, xlsx lives here)
        uses: actions/checkout@v5
        with:
          repository: PatterAI/patter-assets
          token: ${{ secrets.PATTER_ASSETS_TOKEN }}
          path: patter-assets
          # Soft-fail if the repo/secret isn't configured yet: the job falls
          # back to a file path check and emits a warning.
          continue-on-error: true

      - name: Set up Python
        uses: actions/setup-python@v6
        with:
          python-version: '3.12'

      - name: Install deps
        run: pip install openpyxl==3.1.5

      - name: Run drift check
        id: drift
        run: |
          python scripts/check_feature_docs_drift.py \
            --xlsx patter-assets/patter_sdk_features.xlsx \
            --docs docs/ \
            --py-init libraries/python/getpatter/__init__.py \
            --ts-index libraries/typescript/src/index.ts \
            --output drift-report.md
        continue-on-error: true

      - name: Open or update docs-drift issue
        if: steps.drift.outcome == 'failure'
        uses: actions/github-script@v8
        with:
          script: |
            const fs = require('fs');
            const body = fs.readFileSync('drift-report.md', 'utf8');
            const { data: issues } = await github.rest.issues.listForRepo({
              owner: context.repo.owner,
              repo: context.repo.repo,
              labels: 'docs-drift',
              state: 'open',
            });
            if (issues.length > 0) {
              await github.rest.issues.update({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: issues[0].number,
                body,
              });
            } else {
              await github.rest.issues.create({
                owner: context.repo.owner,
                repo: context.repo.repo,
                title: 'docs-drift: feature inventory ↔ docs mismatch',
                body,
                labels: ['docs-drift', 'documentation'],
              });
            }

      - name: Close docs-drift issue if clean
        if: steps.drift.outcome == 'success'
        uses: actions/github-script@v8
        with:
          script: |
            const { data: issues } = await github.rest.issues.listForRepo({
              owner: context.repo.owner,
              repo: context.repo.repo,
              labels: 'docs-drift',
              state: 'open',
            });
            for (const issue of issues) {
              await github.rest.issues.createComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: issue.number,
                body: 'Drift resolved - closing automatically.',
              });
              await github.rest.issues.update({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: issue.number,
                state: 'closed',
              });
            }

The same workflow, on Latchkey

Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.

name: Docs Feature Drift Check
 
# Daily consistency check between:
#   - the canonical feature inventory (patter_sdk_features.xlsx, stored in the
#     patter-assets sibling repo)
#   - the Mintlify documentation under docs/
#   - the public SDK surface (libraries/python/getpatter/__init__.py + libraries/typescript/src/index.ts)
#
# Opens or updates a single issue labelled `docs-drift` listing every mismatch.
# If there is nothing to report, closes the issue (if open).
 
on:
  schedule:
    # 03:00 UTC every day
    - cron: '0 3 * * *'
  workflow_dispatch: {}
 
permissions:
  contents: read
  issues: write
 
jobs:
  drift-check:
    timeout-minutes: 30
    runs-on: latchkey-small
    steps:
      - name: Checkout Patter repo
        uses: actions/checkout@v5
 
      - name: Checkout patter-assets (private, xlsx lives here)
        uses: actions/checkout@v5
        with:
          repository: PatterAI/patter-assets
          token: ${{ secrets.PATTER_ASSETS_TOKEN }}
          path: patter-assets
          # Soft-fail if the repo/secret isn't configured yet: the job falls
          # back to a file path check and emits a warning.
          continue-on-error: true
 
      - name: Set up Python
        uses: actions/setup-python@v6
        with:
          cache: 'pip'
          python-version: '3.12'
 
      - name: Install deps
        run: pip install openpyxl==3.1.5
 
      - name: Run drift check
        id: drift
        run: |
          python scripts/check_feature_docs_drift.py \
            --xlsx patter-assets/patter_sdk_features.xlsx \
            --docs docs/ \
            --py-init libraries/python/getpatter/__init__.py \
            --ts-index libraries/typescript/src/index.ts \
            --output drift-report.md
        continue-on-error: true
 
      - name: Open or update docs-drift issue
        if: steps.drift.outcome == 'failure'
        uses: actions/github-script@v8
        with:
          script: |
            const fs = require('fs');
            const body = fs.readFileSync('drift-report.md', 'utf8');
            const { data: issues } = await github.rest.issues.listForRepo({
              owner: context.repo.owner,
              repo: context.repo.repo,
              labels: 'docs-drift',
              state: 'open',
            });
            if (issues.length > 0) {
              await github.rest.issues.update({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: issues[0].number,
                body,
              });
            } else {
              await github.rest.issues.create({
                owner: context.repo.owner,
                repo: context.repo.repo,
                title: 'docs-drift: feature inventory ↔ docs mismatch',
                body,
                labels: ['docs-drift', 'documentation'],
              });
            }
 
      - name: Close docs-drift issue if clean
        if: steps.drift.outcome == 'success'
        uses: actions/github-script@v8
        with:
          script: |
            const { data: issues } = await github.rest.issues.listForRepo({
              owner: context.repo.owner,
              repo: context.repo.repo,
              labels: 'docs-drift',
              state: 'open',
            });
            for (const issue of issues) {
              await github.rest.issues.createComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: issue.number,
                body: 'Drift resolved - closing automatically.',
              });
              await github.rest.issues.update({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: issue.number,
                state: 'closed',
              });
            }
 

What changed

What Latchkey heals here

This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:

This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow