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
- System GitHub
- Step Link change to ticket
- Step Check reviewer and tests
- Step Record the evidence
- System Drata
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
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
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
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
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
Emergency changes are reviewed after the fact
Marked as emergency, allowed through, and reviewed by someone else within a set number of days.
- 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
Set up, then list the repositories in scope
The control covers what reaches production, so start there.
Headless skills
build-workflowUse 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
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-workflowtray-gotchasUse 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
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
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-workflowUse 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
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
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.
Jira
Read the ticket behind each change, and open exception and after-the-fact review tickets.
Reads and 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.
Related guides
Legal and compliance
How to build audit evidence collection
Map each control to the systems that prove it, collect the evidence on a schedule with its date and source, chase the gaps before the auditor does, and keep one place to look. The prompts.
IT and security
How to build vulnerability to ticket routing
Rank on exploitability and exposure rather than CVSS, group by fix instead of by finding, and route to whoever ships the patch. The prompts that build it.
IT and security
How to build incident to resolution
Declare fast, assemble the channel and the timeline automatically, keep customers informed on a cadence, and make the postmortem unavoidable. The prompts.
Last reviewed October 2026.