e12820f150
Release / release (push) Failing after 21s
Previous implementation silently assumed any missing 'id' in POST response meant "release already exists", then called an unguarded python3 on the fallback response — which crashes (exit 1) if the fallback also fails (e.g. release really doesn't exist). New logic: - Build JSON payload in Python (avoids shell escaping + CLI length limits) - Capture HTTP status explicitly - 201 → success - 409 or "already exists" message → reuse existing (with HTTP check on fetch) - Anything else → fail loudly with the response body printed This also unblocks diagnosis of the current v0.1.0 failure by surfacing the actual error the Gitea API is returning.
156 lines
5.6 KiB
YAML
156 lines
5.6 KiB
YAML
name: Release
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
|
|
env:
|
|
REGISTRY: git.dolgolyov-family.by
|
|
IMAGE_NAME: alexei.dolgolyov/notify-bridge
|
|
|
|
jobs:
|
|
release:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout repo
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Extract version from tag
|
|
id: version
|
|
run: |
|
|
TAG="${{ gitea.ref_name }}"
|
|
VERSION="${TAG#v}"
|
|
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
|
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
|
|
IS_PRE="false"
|
|
if echo "$TAG" | grep -qE '(alpha|beta|rc)'; then
|
|
IS_PRE="true"
|
|
fi
|
|
echo "is_pre=$IS_PRE" >> "$GITHUB_OUTPUT"
|
|
|
|
- name: Login to Gitea Container Registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ gitea.actor }}
|
|
password: ${{ secrets.DEPLOY_TOKEN }}
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Build and push Docker image
|
|
uses: docker/build-push-action@v5
|
|
with:
|
|
context: .
|
|
push: true
|
|
tags: |
|
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.tag }}
|
|
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}
|
|
${{ steps.version.outputs.is_pre == 'false' && format('{0}/{1}:latest', env.REGISTRY, env.IMAGE_NAME) || '' }}
|
|
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
|
|
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max
|
|
|
|
- name: Trigger redeploy webhook
|
|
if: steps.version.outputs.is_pre == 'false'
|
|
continue-on-error: true
|
|
run: |
|
|
if [ -n "${{ secrets.DOCKER_REDEPLOY_WEBHOOK_URL }}" ]; then
|
|
echo "Triggering redeploy webhook..."
|
|
curl -sf -X POST "${{ secrets.DOCKER_REDEPLOY_WEBHOOK_URL }}" \
|
|
--max-time 30 || echo "::warning::Redeploy webhook failed"
|
|
else
|
|
echo "DOCKER_REDEPLOY_WEBHOOK_URL not set — skipping auto-deploy"
|
|
fi
|
|
|
|
- name: Generate changelog
|
|
id: changelog
|
|
run: |
|
|
PREV_TAG=$(git tag --sort=-v:refname | head -2 | tail -1)
|
|
if [ -z "$PREV_TAG" ] || [ "$PREV_TAG" = "${{ gitea.ref_name }}" ]; then
|
|
CHANGELOG=$(git log --oneline --no-decorate -n 20)
|
|
else
|
|
CHANGELOG=$(git log --oneline --no-decorate ${PREV_TAG}..HEAD)
|
|
fi
|
|
echo "$CHANGELOG" > /tmp/changelog.txt
|
|
|
|
- name: Create Gitea Release
|
|
env:
|
|
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
|
|
run: |
|
|
TAG="${{ steps.version.outputs.tag }}"
|
|
VERSION="${{ steps.version.outputs.version }}"
|
|
IS_PRE="${{ steps.version.outputs.is_pre }}"
|
|
BASE_URL="https://${{ env.REGISTRY }}/api/v1/repos/${{ env.IMAGE_NAME }}"
|
|
|
|
if [ -f RELEASE_NOTES.md ]; then
|
|
export RELEASE_NOTES=$(cat RELEASE_NOTES.md)
|
|
echo "Found RELEASE_NOTES.md"
|
|
else
|
|
export RELEASE_NOTES=""
|
|
echo "No RELEASE_NOTES.md found"
|
|
fi
|
|
|
|
BODY=$(python3 -c "
|
|
import json, os
|
|
|
|
release_notes = os.environ.get('RELEASE_NOTES', '')
|
|
changelog = open('/tmp/changelog.txt').read().strip()
|
|
|
|
sections = []
|
|
if release_notes.strip():
|
|
sections.append(release_notes.strip())
|
|
if changelog:
|
|
sections.append('## Changelog\n\n' + changelog)
|
|
|
|
print(json.dumps('\n\n'.join(sections)))
|
|
")
|
|
|
|
# Send body via file to avoid CLI length limits / shell escaping
|
|
python3 -c "
|
|
import json, os
|
|
body = os.environ['BODY']
|
|
payload = {
|
|
'tag_name': os.environ['TAG'],
|
|
'name': f\"Notify Bridge {os.environ['VERSION']}\",
|
|
'body': json.loads(body),
|
|
'draft': False,
|
|
'prerelease': os.environ['IS_PRE'] == 'true',
|
|
}
|
|
open('/tmp/release-payload.json','w').write(json.dumps(payload))
|
|
" BODY="$BODY" TAG="$TAG" VERSION="$VERSION" IS_PRE="$IS_PRE"
|
|
|
|
HTTP=$(curl -s -o /tmp/release-resp.json -w "%{http_code}" \
|
|
-X POST "$BASE_URL/releases" \
|
|
-H "Authorization: token $DEPLOY_TOKEN" \
|
|
-H "Content-Type: application/json" \
|
|
--data-binary @/tmp/release-payload.json)
|
|
|
|
echo "POST /releases → HTTP $HTTP"
|
|
echo "--- response ---"
|
|
head -c 2000 /tmp/release-resp.json; echo
|
|
echo "----------------"
|
|
|
|
if [ "$HTTP" = "201" ]; then
|
|
RELEASE_ID=$(python3 -c "import json; print(json.load(open('/tmp/release-resp.json'))['id'])")
|
|
echo "Created release $RELEASE_ID for $TAG"
|
|
elif [ "$HTTP" = "409" ] || grep -q "already exists" /tmp/release-resp.json; then
|
|
echo "::warning::Release already exists for tag $TAG — reusing"
|
|
HTTP2=$(curl -s -o /tmp/release-resp.json -w "%{http_code}" \
|
|
"$BASE_URL/releases/tags/$TAG" \
|
|
-H "Authorization: token $DEPLOY_TOKEN")
|
|
if [ "$HTTP2" != "200" ]; then
|
|
echo "::error::Failed to fetch existing release (HTTP $HTTP2)"
|
|
cat /tmp/release-resp.json
|
|
exit 1
|
|
fi
|
|
RELEASE_ID=$(python3 -c "import json; print(json.load(open('/tmp/release-resp.json'))['id'])")
|
|
echo "Reused release $RELEASE_ID for $TAG"
|
|
else
|
|
echo "::error::Failed to create release for $TAG (HTTP $HTTP)"
|
|
exit 1
|
|
fi
|