Reporting Cicd Delivery Pipelines

Running Food-Cost Diffs as GitHub Actions Gates

This page walks a food-tech developer through wiring the food-cost diff into a GitHub Actions workflow so that a pull request touching recipe or mapping data cannot merge until the margin impact has been computed and reviewed. It is the platform-specific implementation of food-cost diff checks in CI/CD; read that for the basket, baseline, and tolerance design, then follow the steps here to make the check a required status on your default branch.

The goal is a gate that runs in seconds, comments the per-item deltas directly on the pull request, and returns a non-zero exit code when a regression exceeds tolerance — which, once configured as a required check, blocks the merge button.

Prerequisites and Data Contract

  • A GitHub repository holding recipe data (recipes/, baselines/basket_costs.csv) and the costing package.
  • Python 3.11+ with the costing dependencies installable via pip install -e ..
  • A scripts/food_cost_diff.py entry point that computes failures and exits 0/1, reusing the shared diff logic.
  • Permission to configure branch protection and a GITHUB_TOKEN with pull-requests: write for commenting.

The workflow’s contract: trigger only on changes to cost-relevant paths, produce a machine-readable diff artifact, and surface a pass/fail status the branch protection rule can require.

Food-cost diff as a GitHub Actions required check A pull request that changes files under the recipe paths triggers the workflow. The workflow checks out the branch, installs the costing package, runs the diff script which exits zero or one, posts a summary comment to the pull request, and reports a status check. A branch protection rule requires that status, so a failing diff blocks the merge. PR on recipe path paths filter Install + run diff exit 0 / 1 Comment on PR per-item deltas Required check gates merge

Step-by-Step Implementation

Step 1 — Trigger only on cost-relevant paths

Scope the workflow to recipe and mapping data so unrelated pull requests do not pay for the check.

# .github/workflows/food-cost-diff.yml
name: food-cost-diff
on:
  pull_request:
    paths:
      - "recipes/**"
      - "mappings/**"
      - "baselines/**"
permissions:
  contents: read
  pull-requests: write

Step 2 — Run the diff and capture its output

jobs:
  diff:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - run: pip install -e .
      - name: Run food-cost diff
        id: diff
        run: |
          python scripts/food_cost_diff.py --format markdown > diff.md || echo "failed=true" >> "$GITHUB_OUTPUT"
      - name: Upload diff artifact
        uses: actions/upload-artifact@v4
        with:
          name: food-cost-diff
          path: diff.md

Step 3 — Comment the diff on the pull request

Post the per-item deltas so a reviewer sees the margin impact inline.

      - name: Comment diff
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const body = fs.readFileSync('diff.md', 'utf8');
            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: "### Food-cost diff\n\n" + body,
            });

Step 4 — Fail the job so the status blocks merge

Re-assert the exit code after commenting, so the comment always posts but a regression still fails the check.

      - name: Enforce verdict
        if: steps.diff.outputs.failed == 'true'
        run: |
          echo "::error::food-cost regression exceeds tolerance"
          exit 1

Step 5 — Make the check required

In branch protection for the default branch, add food-cost-diff / diff to the required status checks. Now a failing diff greys out the merge button until the baseline is updated or the recipe change is corrected.

Verification and Validation

  • Path filter works. Open a PR editing only a README; the workflow should not run. Edit a file under recipes/; it should.
  • Comment posts on both outcomes. A passing PR shows a “all within tolerance” comment; a regressing PR shows the delta table. The comment must appear even when the job ultimately fails.
  • Required check blocks. With branch protection on, confirm a regressing PR shows a red required check and a disabled merge button; approving reviewers cannot override without an audited admin bypass.
  • Determinism. Re-run the workflow on the same commit; the diff artifact must be identical, confirming the check is a pure function of committed data.

Gotchas and Edge Cases

  • github-script needs the comment step before the failure. If you exit 1 in the same step that computes the diff, the comment step is skipped and reviewers see a red X with no explanation. Separate compute, comment, then enforce.
  • Forked-PR token scope. Pull requests from forks receive a read-only GITHUB_TOKEN, so the comment step fails. Use pull_request_target cautiously, or post the diff as a check-run summary instead of a comment.
  • Path filter false-negatives. A change to the costing code (not data) can move margin but not match the paths filter. Include the costing package path, or run the gate on all PRs and keep it fast.
  • Baseline updates in the same PR. When a margin change is intentional, the contributor updates baselines/basket_costs.csv in the same PR; the diff then shows a sanctioned change and passes. Do not widen tolerance to force a merge.

For platform specifics, see the official GitHub Actions documentation.