Use GitHub Releases API

This commit is contained in:
WasserEsser
2026-07-14 08:00:19 +02:00
parent a12b1c00b5
commit 342d60f8d5
+50 -37
View File
@@ -2,10 +2,9 @@ name: Auto-tag new Mattermost releases
on: on:
schedule: schedule:
# Check every 6 hours # Check daily at 2am UTC
- cron: '0 2 * * *' - cron: '0 2 * * *'
workflow_dispatch: workflow_dispatch:
# Allow manual trigger with a specific tag
inputs: inputs:
mattermost_tag: mattermost_tag:
description: 'Specific Mattermost image tag to test (e.g. 11.8.2)' description: 'Specific Mattermost image tag to test (e.g. 11.8.2)'
@@ -34,10 +33,15 @@ jobs:
- name: Discover new Mattermost tags - name: Discover new Mattermost tags
id: discover id: discover
# Uses the GitHub Releases API (authenticated via GITHUB_TOKEN) instead
# of the Docker Hub web API, which is shared across all GitHub Actions
# runners and frequently returns 429s during nightly runs.
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: | run: |
set -euo pipefail set -euo pipefail
# If a specific tag was provided, use only that # If a specific tag was provided manually, use only that
if [ -n "${{ inputs.mattermost_tag }}" ]; then if [ -n "${{ inputs.mattermost_tag }}" ]; then
echo "new_tags=${{ inputs.mattermost_tag }}" >> "$GITHUB_OUTPUT" echo "new_tags=${{ inputs.mattermost_tag }}" >> "$GITHUB_OUTPUT"
exit 0 exit 0
@@ -45,37 +49,31 @@ jobs:
EXISTING="${{ steps.existing.outputs.tags }}" EXISTING="${{ steps.existing.outputs.tags }}"
# Fetch all tags from Docker Hub, paginated # Fetch stable releases from GitHub API. This is authenticated via
PAGE=1 # GITHUB_TOKEN so it gets 5,000 req/hr — never rate limited from
ALL_TAGS="" # within GitHub Actions. Fetches enough pages to cover many releases.
while true; do ALL_TAGS=$(curl -sf \
for ATTEMPT in 1 2 3; do -H "Authorization: Bearer ${GH_TOKEN}" \
RESPONSE=$(curl -sf "https://hub.docker.com/v2/repositories/mattermost/mattermost-enterprise-edition/tags/?page_size=100&page=${PAGE}" && break) || { -H "Accept: application/vnd.github+json" \
if [ "$ATTEMPT" -eq 3 ]; then "https://api.github.com/repos/mattermost/mattermost/releases?per_page=50" \
echo "Failed to fetch Docker Hub tags after 3 attempts" | python3 -c "
exit 1
fi
echo "Docker Hub API error (attempt $ATTEMPT/3), retrying in $((ATTEMPT * 5))s..."
sleep $((ATTEMPT * 5))
}
done
TAGS=$(echo "$RESPONSE" | python3 -c "
import sys, json import sys, json
data = json.load(sys.stdin) releases = json.load(sys.stdin)
for t in data.get('results', []): for r in releases:
name = t['name'] # Skip prereleases and drafts
# Filter: semantic version tags only (e.g. 11.8.1, not rc, att, sig, sha256) if r.get('prerelease') or r.get('draft'):
parts = name.split('.') continue
tag = r['tag_name'].lstrip('v')
# Stable semver only: X.Y.Z with all numeric parts
parts = tag.split('.')
if len(parts) == 3 and all(p.isdigit() for p in parts): if len(parts) == 3 and all(p.isdigit() for p in parts):
print(name) print(tag)
") ")
ALL_TAGS="${ALL_TAGS}${ALL_TAGS:+$'\n'}${TAGS}"
NEXT=$(echo "$RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin).get('next','') or '')") if [ -z "$ALL_TAGS" ]; then
if [ -z "$NEXT" ]; then echo "No stable Mattermost releases found from GitHub API"
break exit 1
fi fi
PAGE=$((PAGE + 1))
done
# Find tags that don't exist in our repo yet # Find tags that don't exist in our repo yet
NEW_TAGS="" NEW_TAGS=""
@@ -104,12 +102,13 @@ jobs:
for TAG in "${TAGS[@]}"; do for TAG in "${TAGS[@]}"; do
echo "=== Testing Mattermost ${TAG} ===" echo "=== Testing Mattermost ${TAG} ==="
# Check if the image tag exists on Docker Hub # Verify the image tag exists on Docker Hub before attempting build.
HTTP_CODE=$(curl -sf -o /dev/null -w "%{http_code}" \ # This is a single targeted call (not paginated) so it's fine to use
"https://hub.docker.com/v2/repositories/mattermost/mattermost-enterprise-edition/tags/${TAG}" \ # the Hub web API here — it only runs when a new release is found.
|| echo "$?") HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
"https://hub.docker.com/v2/repositories/mattermost/mattermost-enterprise-edition/tags/${TAG}")
if [ "$HTTP_CODE" != "200" ]; then if [ "$HTTP_CODE" != "200" ]; then
echo "Tag ${TAG} does not exist on Docker Hub, skipping" echo "Tag ${TAG} does not exist on Docker Hub yet (HTTP ${HTTP_CODE}), skipping"
SKIPPED="${SKIPPED}${SKIPPED:+', '}${TAG}" SKIPPED="${SKIPPED}${SKIPPED:+', '}${TAG}"
continue continue
fi fi
@@ -136,7 +135,21 @@ jobs:
echo "failed=${FAILED}" >> "$GITHUB_OUTPUT" echo "failed=${FAILED}" >> "$GITHUB_OUTPUT"
echo "skipped=${SKIPPED}" >> "$GITHUB_OUTPUT" echo "skipped=${SKIPPED}" >> "$GITHUB_OUTPUT"
- name: Notify on failure - name: Notify on discover failure
# Fires when the discover step itself fails — previously silent
if: failure() && steps.discover.outcome == 'failure'
env:
PUSHOVER_TOKEN: ${{ secrets.PUSHOVER_TOKEN }}
PUSHOVER_USER: ${{ secrets.PUSHOVER_USER }}
run: |
curl -sf -X POST "https://api.pushover.net/1/messages.json" \
-d "token=${PUSHOVER_TOKEN}" \
-d "user=${PUSHOVER_USER}" \
-d "title=Mattermost tagger: discovery failed" \
-d "message=Failed to discover new Mattermost releases. Check the Actions log: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
-d "priority=0"
- name: Notify on build failure
if: steps.build.outputs.failed != '' if: steps.build.outputs.failed != ''
env: env:
PUSHOVER_TOKEN: ${{ secrets.PUSHOVER_TOKEN }} PUSHOVER_TOKEN: ${{ secrets.PUSHOVER_TOKEN }}