OK, so we live in a world of automation and GitHub Actions, because nobody wants to deploy things themselves, right?
Sometimes you have multiple repositories, because code separation is fun and we need to be able trigger downstream builds in a different repository using github actions.
Easy, you say? Comes out of the box with GitHub Actions...
Repository A:
...
- name: Trigger my downstream workflow
run: |
curl -XPOST -u "${{ secrets.GIT_CREDENTIALS }}" -H "Accept:application/vnd.github" -H "Content-Type:application/json" https://api.github.com/repos/path/to/workflow.yml/dispatches --data '{"ref": "main" }'
...
Repository X:
name: Deploy Repo X
on:
workflow_dispatch:
inputs:
source:
description: 'Source of event'
required: false
default: 'No source specified'
...
...and off we go. Easy peasy.
But there's a downside here. Let's say we've got multiple repositories that all need to do the same thing. If any of Repos A, B, C & D change they need to trigger a build of Repo X.
Great. No problemo.
However, if all 4 repos change at once, we get 4 builds. That'll tie up the build system for an hour. Horrible log jam. Angry developers. The works. And GitHub don't provide any kind of build throttling (are you listening GitHub? ARE YOU???)
What we need is a way to prevent multiple repos from submitting a new pending job if one of its siblings had recently done the same thing.
Sounds like a job for Redis (he said with the benefit of hindsight).
SET buildlock 1 NX EX 180
enables us to set a buildlock key in Redis with an expiry of 3 minutes. The important thing here is that if the key is successfully set, Redis returns "OK", otherwise "(nil)".
So, without further ado, here's a way of only firing workflows on an upstream repo if something else hasn't recently done so:
name: Update components
on:
push:
branches:
- main
jobs:
TriggerPlatformDeploy:
runs-on: ubuntu-latest
timeout-minutes: 20
env:
ENVIRONMENT: "dev"
steps:
- name: Install redis CLI
run: |
sudo apt-get install redis-tools -y
- name: Check for recent push lock
run: |
didSet=$(redis-cli -a ${{ secrets.REDIS_TOKEN }} -h ${{ secrets.REDIS_URL }} -p$ {{ secrets.REDIS_PORT }} --no-auth-warning SET buildlock 1 NX EX 180)
echo "didSet=$(echo $didSet)" >> $GITHUB_ENV
- name: Trigger workflow if not locked
if: env.didSet == 'OK'
run: |
curl -XPOST -u "${{ secrets.GIT_CREDENTIALS }}" -H "Accept:application/vnd.github" -H "Content-Type:application/json" https://api.github.com/repos/path/to/workflow.yml/dispatches --data '{"ref": "main" }'
- name: Workflow is locked
if: env.didSet != 'OK'
run: |
echo Suppressing build trigger because another repo has triggered within 3 minutes
Top comments (0)