fix: prevent race conditions in release workflows

- Remove 'release: published' triggers from publish-docker, promote-floating-tags, and helm-pages workflows
- All these workflows now only run via workflow_dispatch, triggered by create-release.yml in sequence
- Add image availability check in promote-floating-tags to wait for Docker images
- create-release.yml now dispatches: publish-docker, promote-floating-tags, helm-pages, update-demo-server
- This prevents the race condition where workflows triggered by release event run before Docker images are ready
This commit is contained in:
rcourtman 2025-12-14 18:07:46 +00:00
parent 7b54326889
commit bc82c4a144
4 changed files with 70 additions and 23 deletions

View file

@ -493,6 +493,34 @@ jobs:
echo "✓ Docker publish workflow dispatched"
- name: Trigger floating tag promotion
if: ${{ github.event.inputs.draft_only != 'true' }}
continue-on-error: true # Non-fatal if dispatch fails
env:
GH_TOKEN: ${{ secrets.WORKFLOW_PAT }}
run: |
TAG="${{ needs.extract_version.outputs.tag }}"
IS_PRERELEASE="${{ needs.extract_version.outputs.is_prerelease }}"
echo "Triggering floating tag promotion for ${TAG} (prerelease: ${IS_PRERELEASE})..."
gh workflow run promote-floating-tags.yml -f tag="${TAG}" -f prerelease="${IS_PRERELEASE}"
echo "✓ Floating tag promotion workflow dispatched"
- name: Trigger Helm chart release
if: ${{ github.event.inputs.draft_only != 'true' }}
continue-on-error: true # Non-fatal if dispatch fails
env:
GH_TOKEN: ${{ secrets.WORKFLOW_PAT }}
run: |
TAG="${{ needs.extract_version.outputs.tag }}"
VERSION="${TAG#v}"
echo "Triggering Helm chart release for ${VERSION}..."
gh workflow run helm-pages.yml -f chart_version="${VERSION}"
echo "✓ Helm chart release workflow dispatched"
- name: Trigger demo server update
if: ${{ github.event.inputs.draft_only != 'true' }}
continue-on-error: true # Non-fatal if dispatch fails

View file

@ -1,8 +1,8 @@
name: Release Helm Chart to GitHub Pages
# Only triggered manually or by create-release.yml
# Removing release: published trigger prevents race conditions
on:
release:
types: [published]
workflow_dispatch:
inputs:
chart_version:
@ -45,26 +45,19 @@ jobs:
helm-docs
# Commit if README changed
if [ "${GITHUB_EVENT_NAME}" != "release" ] && ! git diff --quiet README.md; then
if ! git diff --quiet README.md; then
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
git add README.md
git commit -m "Auto-update Helm chart documentation"
git push
elif [ "${GITHUB_EVENT_NAME}" = "release" ] && ! git diff --quiet README.md; then
echo "README.md updated by helm-docs but skipping commit because release workflows checkout a detached HEAD."
fi
cd ../../..
- name: Determine chart version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ inputs.chart_version }}"
else
VERSION="${{ github.event.release.tag_name }}"
VERSION="${VERSION#v}"
fi
VERSION="${{ inputs.chart_version }}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Update Chart.yaml version
@ -73,15 +66,13 @@ jobs:
sed -i "s/^version: .*/version: $VERSION/" deploy/helm/pulse/Chart.yaml
sed -i "s/^appVersion: .*/appVersion: \"$VERSION\"/" deploy/helm/pulse/Chart.yaml
# Commit only on workflow_dispatch (release runs are detached HEAD)
if [ "${GITHUB_EVENT_NAME}" != "release" ] && ! git diff --quiet deploy/helm/pulse/Chart.yaml; then
# Commit if Chart.yaml changed
if ! git diff --quiet deploy/helm/pulse/Chart.yaml; then
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
git add deploy/helm/pulse/Chart.yaml
git commit -m "Auto-update Helm chart version to $VERSION"
git push
elif [ "${GITHUB_EVENT_NAME}" = "release" ] && ! git diff --quiet deploy/helm/pulse/Chart.yaml; then
echo "Chart.yaml updated for packaging, skipping commit (detached HEAD on release event)."
fi
- name: Validate Helm chart

View file

@ -1,8 +1,19 @@
name: Promote Floating Tags
# Only triggered by create-release.yml after Docker images are published
# This prevents race conditions with release: published event
on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: 'Release tag (e.g., v5.0.0)'
required: true
type: string
prerelease:
description: 'Is this a prerelease?'
required: true
type: boolean
default: false
jobs:
promote-images:
@ -12,8 +23,8 @@ jobs:
packages: write
env:
OWNER: ${{ github.repository_owner }}
TAG: ${{ github.event.release.tag_name }}
PRERELEASE: ${{ github.event.release.prerelease }}
TAG: ${{ inputs.tag }}
PRERELEASE: ${{ inputs.prerelease }}
steps:
- name: Log in to Docker Hub
@ -29,6 +40,23 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Wait for Docker image to be available
run: |
echo "Waiting for rcourtman/pulse:${TAG} to be available..."
MAX_ATTEMPTS=30
ATTEMPT=0
while [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
if docker manifest inspect rcourtman/pulse:${TAG} > /dev/null 2>&1; then
echo "Image rcourtman/pulse:${TAG} is available!"
exit 0
fi
ATTEMPT=$((ATTEMPT + 1))
echo "Attempt $ATTEMPT/$MAX_ATTEMPTS - Image not yet available, waiting 10s..."
sleep 10
done
echo "Timeout waiting for Docker image"
exit 1
- name: Promote Pulse server image tags
run: |
set -euo pipefail

View file

@ -1,8 +1,8 @@
name: Publish Docker Images
# Only triggered by create-release.yml after staging images are built
# Removing release: published trigger prevents race conditions
on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
@ -11,7 +11,7 @@ on:
type: string
concurrency:
group: docker-publish-${{ github.event.release.tag_name || inputs.tag }}
group: docker-publish-${{ inputs.tag }}
cancel-in-progress: false
jobs:
@ -26,7 +26,7 @@ jobs:
- name: Extract version from release tag
id: version
run: |
TAG="${{ github.event.release.tag_name || inputs.tag }}"
TAG="${{ inputs.tag }}"
VERSION="${TAG#v}"
# Detect if this is a prerelease (RC, alpha, beta)