Motivation
Metadelta’s main function is to compute differences between different Hasura versions. The most natural place to compute such a difference is, if you use GitHub, during a Pull Request (PR): You compare the permission changes that a PR seeks to introduce.
This, then, is what we will implement in what follows: We will set up an action that comments with a link to the Metadelta UI, showing the diff of that particular PR. A new link will be provided each time the PR branch is updated.
The setup
The essential requirement is that you have in your repo somewhere a hasura
folder with something like the following structure:
./hasura/metadata
- actions.graphql
- actions.yaml
...
databases/
...
- version.yaml
If you’d like to follow along with our repo instead of your own, you can start with our demo-database which has everything you need.
The details
So, the set up is pretty straightfoward. If you just want to view the finished GitHub workflow file you can; but otherwise, we’ll go through all the steps.
The header
We start with a simple workflow that runs on pull requests. We require two
kinds of permissions: we need to write contents
as we’re going to upload an
artifact later, and we want to write to the pull-request to comment on it.
name: Compute permission diff on PR
on:
pull_request:
jobs:
compute-diff:
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-latest
steps:
The first steps:
1. Check out the two versions of the code
Pretty simple; we just check out the respective versions to an /old
and
/new
path.
- name: Checkout the PR as the 'new' source
uses: actions/checkout@v4
with:
path: ./new
ref: ${{ github.event.pull_request.head.sha }}
- name: Checkout `main` as the 'old' source
uses: actions/checkout@v4
with:
path: ./old
ref: main
2. Run Metadelta to produce a diff.json
file
The juicy part; we run Metadelta, from our
docker image, referring to the ./old
and ./new
paths we checked out
earlier.
A few detalis:
- We set some labels so that it displays nicely in the UI and is clear what commits it is referencing,
- We compute a small check to test whether we actually found a difference, In subsequent steps this will be used to check if we upload an artifact and post a comment on GitHub.
- name: Run metadelta comparing old and new
id: metadelta
run: |
docker run -i \
-v $PWD:/work \
ghcr.io/invariantclub/metadelta \
diff \
-o /work/old/hasura/metadata/ \
--oldLabel 'main' \
-n /work/new/hasura/metadata/ \
--newLabel '${{ github.event.pull_request.head.label }} @ ${{ github.event.pull_request.head.sha }}' \
--newLink '${{ github.event.pull_request.html_url }}' \
>diff.json || true echo "anythingDifferent=$(test -s diff.json || echo 'true')" >> "$GITHUB_OUTPUT"
3. Upload the diff.json
file as a GitHub artifact
Pretty straightforward: We are going to upload it so that it can be downloaded by the UI later on. The only thing to note is that we only do the upload if the previous step found a difference. In reality, it’s probably far more common for PRs to not be changing permissions; so it’s important to skip any extra work in those cases.
- name: Uploading the diff as an artifact
uses: actions/upload-artifact@v4
id: artifact
if:
# Only run if we detected changes.
${{ steps.metadelta.outputs.anythingDifferent != 'true' }}
with:
name: metadelta-diff
path: diff.json
retention-days: 5
4. Comment on the PR with a link
This is the final step. The Metadelta UI can load a GitHub artifact completely client-side, (supposing you have configured the UI, in the settings tab, with a GitHub access token, which is, unfortunately, a requirement for querying GitHub artifacts, even public ones); so all we need to do is prepare an appropriate URL, and post that as a comment on the PR.
As the above step was run conditionally, so too we want to run this one on the condition that the previous step was completed.
- name: Comment with Metadelta link
uses: peter-evans/create-or-update-comment@v4.0.0
if:
# Only run if we uploaded an artifact
${{ steps.artifact.outcome == 'success' }}
with:
token: ${{ secrets.GITHUB_TOKEN }}
issue-number: ${{ github.event.pull_request.number }}
body: |
[View the permission diff in Metadelta :eyes:](https://metadelta.invariant.club/explorer?githubArtifact=${{ steps.artifact.outputs.artifact-id }}/${{ github.repository_owner }}/${{ github.event.repository.name }})
This is was triggered from GitHub Actions [run ${{ github.run_number }}](https://github.com/${{ github.repository_owner }}/${{ github.event.repository.name }}/actions/runs/${{ github.run_id }}/).
That’s it!
Putting that all together in a single workflow file, perhaps called
compute-permission-diff.yaml
does the job!
You are now computing diffs on all PRs, and you will be notified when the permissions have changed in any way, and if so, you will receive a link to review those diffs in the Metadelta UI!
Hopefully this has been useful :)