Skip to content

Automation  ·  Legal and compliance

How to build change approval evidence

The auditor picks 25 production releases and asks, for each one, who approved it, what ticket it served and whether the tests passed. The answers are in GitHub, Jira and the deploy tool, and someone spends a week joining them by hand. The model behind evidence that builds itself, the prompts that build it, and what it takes to keep it honest.

Built with Tray Headless

  1. System GitHub
  2. Step Link change to ticket
  3. Step Check reviewer and tests
  4. Step Record the evidence
  5. System Drata
Also Flag what skipped a step

Each deploy is matched to its pull request, its ticket and its reviewer as it happens, so a change that skipped a step is flagged the same day.

The short answer

What is change approval evidence?

Change approval evidence has four parts: every production deploy linked to the pull request and the ticket it came from, a check that someone other than the author approved it and the tests passed, a flag raised the same day for any change that skipped a step, with emergency changes reviewed after the fact, and one record per change an auditor can sample. The usual failure is checking at audit time. By then the people who could explain an unreviewed change have moved on, and a gap found a year late is a finding instead of a fix.

Stage 3 of 7: Change approval. Part of Compliance automation, end to end : every stage, the systems it runs on and the guide that builds it.

What matters here

  • Start from the deploy, not the ticket. A change that never had a ticket is the one you most need to see.
  • The approver must not be the author. A self-approved pull request has the shape of a review without the review.
  • Check as each change ships. A gap found the same day gets explained; one found at audit time gets written up.
  • Allow emergency changes, then review them within days. Blocking the fix is worse than reviewing it late.
  • Keep one record per change with links to the source. An auditor samples records; they do not read your process document.

Who this is for

You run engineering operations, security or compliance. Your audit tests change management every year, the evidence lives in three tools, and pulling a sample takes a week.

How it works in practice

What happens between a change reaching production and it being a record an auditor can sample.

  1. 1

    Each production deploy is picked up as it happens

    From the deploy tool or the merge to the release branch, for every repository in scope.

  2. 2

    The deploy is linked to its pull request and ticket

    By the ticket key in the branch, title or commit, and flagged when there is none.

  3. 3

    The review is checked

    At least one approval from someone other than the author, given after the last commit, with the required tests passed.

  4. 4

    Anything that skipped a step is flagged that day

    To the author and the team lead in Slack, with the step that was missed and a ticket to explain it.

  5. 5

    Emergency changes are reviewed after the fact

    Marked as emergency, allowed through, and reviewed by someone else within a set number of days.

  6. 6

    One record per change is kept

    Deploy, pull request, ticket, reviewer, tests and any exception, with links back to each source.

What change approval evidence is made of

Four parts. The second is the one auditors test hardest.

A link from deploy to ticket

Every production deploy traced to the pull request and the ticket that asked for it, starting from the deploy so untracked changes show up.

An independent review

An approval from someone other than the author, after the final commit, with the required checks passed.

Same-day exceptions

Anything that skipped a step flagged to its author and lead that day, and emergency changes reviewed within a set window.

A record per change

One row per change with every link and date, kept in the warehouse and attached to the control in the compliance tool.

The Tray Headless prompts

Paste these into Claude Code or Codex with the Tray Headless plugin installed. Each stage runs on its own. The systems named in them are the worked example rather than a requirement, and every prompt says so.

Once per project, run /tray-workflows:set-workspace to pick the workspace these build in. Point it at a sandbox first.

  1. 1

    Set up, then list the repositories in scope

    The control covers what reaches production, so start there.

    Headless skills build-workflow

    Use build-workflow. The systems in play are GitHub, Jira, Slack,
    Snowflake and Drata, or whatever we run in those seats. Before you plan
    anything, tell me which of them are already authenticated in the
    workspace, because I do not want a connector stubbed that I have not
    authenticated.
    
    Then build a table of the repositories in scope: repository, owning
    team, which branch deploys to production, how a deploy is recorded,
    and which checks must pass before a merge.
    
    Tell me for each one whether branch protection requires a review
    today. Where it does not, the control relies on this workflow alone,
    and I want to know that before anything else.
  2. 2

    Pick up each deploy and link it to its ticket

    Start from what shipped, so a change with no ticket still shows up.

    Headless skills build-workflow tray-gotchas

    Use build-workflow and tray-gotchas. For every merge to a production
    branch in GitHub, read the pull request, its commits, its reviews and
    its check results.
    
    Find the Jira ticket from the key in the branch name, the pull request
    title or the commit messages, in that order. Read its type, status and
    who requested it.
    
    If no ticket is found, do not guess one. Mark the change as having no
    ticket and carry on with the other checks.
  3. 3

    Check the review and the tests

    A self-approved change has the shape of a review without the review.

    For each change, record pass or fail on each of these:
    
      At least one approval from someone other than the author
      The approval was given after the last commit was pushed
      Every required check passed on the final commit
      The ticket exists and was in an approved state before the merge
    
    An approval followed by a new commit does not count, because the
    reviewer never saw the final change.
    
    A change labelled emergency passes for now, with a review due within
    three working days by someone other than the author.
  4. 4

    Flag what skipped a step, the same day

    A gap explained this week is a fix. One found at audit time is a finding.

    Headless skills build-workflow

    Use build-workflow. For any change that failed a check, message the
    author and their team lead in Slack with the pull request, the check
    that failed and a button to open a Jira ticket explaining it.
    
    For emergency changes, open the after-the-fact review ticket at merge
    time, assign it to a reviewer who is not the author, and remind on the
    due date. If it is still open two days later, tell the engineering
    manager.
    
    Never block or revert a deploy from this workflow. It records and
    flags; the deploy pipeline decides what ships.
  5. 5

    Keep one record per change

    The auditor samples records, so make the sample a query.

    Write one row per production change to Snowflake: repository, deploy
    time, pull request, author, approvers with times, check results,
    ticket, emergency flag, any exception ticket and its outcome, and a
    link to each source.
    
    Each month, attach a summary to the change management control in
    Drata: changes shipped, share fully passing, exceptions raised and
    closed, and emergency changes with their review dates.
    
    When the auditor sends a sample, the answer is the rows for those
    changes, exported with their links.
  6. 6

    Check it end to end, then hand the rules to compliance

    Because what counts as approved is a policy decision.

    Run the per-step checks and the whole-workflow audit before this
    touches production. Test with a self-approved pull request, a pull
    request with a commit after approval, and an emergency change, and
    confirm each is flagged correctly.
    
    Then open the same workflow in Tray Build so compliance and
    engineering operations can change the repositories in scope, the
    required checks and the emergency review window in the visual canvas.

What it connects to

The change lives in GitHub, the reason in Jira, and the evidence has to outlive both.

GitHub

Read merges to production branches, pull request reviews, commits and check results.

Reads

Jira

Read the ticket behind each change, and open exception and after-the-fact review tickets.

Reads and writes

Slack

Tell the author and lead the same day when a change skipped a step.

Writes

Snowflake

Keep one row per production change with every link and date, so an audit sample is a query.

Writes

Drata

Attach the monthly summary to the change management control, where the audit already looks.

Writes

Same build, other stacks

The design does not change if you run something else in one of these seats. The same prompts build it against Google BigQuery, Microsoft Teams, ServiceNow, Databricks, Google Chat or Jira Service Desk.

Connections in this build

Field mapping, templates and common problems for each pairing: GitHub + Jira, GitHub + Slack, Jira + Slack and Drata + GitHub.

Named systems are the ones most teams run, not the only ones that work. Each is an authentication in your Tray workspace, referenced by name, so the workflow never holds a credential. Where we have a connector page, the name links to it.

Running it in production

This produces the evidence for one of the most tested controls in any audit. It has to be complete, and it must never get in the way of a fix.

It runs on the platform, not on your laptop

Every merge is picked up and checked as it happens, with a full history of each run.

It records and flags, it never blocks

The deploy pipeline decides what ships. This workflow makes sure every change has its evidence and every gap has an owner.

Credentials are managed, never written into the build

Read access across every production repository is sensitive. It lives in your workspace as its own authentication, scoped to read.

Compliance owns the rules

Repositories in scope, required checks and the emergency window open in Tray Build, changed by the team that answers to the auditor.

Test with the awkward cases

A self-approval, a commit after approval and an emergency change. If those three are flagged correctly, the ordinary ones will be too.

Questions people ask

Why start from the deploy instead of the ticket?

Because a change that never had a ticket would never appear if you started from tickets. Starting from what reached production means every change is checked.

Why doesn't an approval count if there was a commit after it?

Because the reviewer approved an earlier version. The change that shipped was never reviewed.

How should emergency changes be handled?

Let them through, mark them as emergency, and have someone other than the author review them within a few working days. Blocking an urgent fix is worse than reviewing it late.

Should this workflow block deploys?

No. Branch protection and the deploy pipeline decide what ships. This workflow records the evidence and flags gaps the same day.

Does this make us compliant?

No workflow does that. It makes sure every change has its record and every gap has an owner. Your auditor still decides whether the control works.

Last reviewed October 2026.