All checks were successful
Update README with ADR Index / update-readme (push) Successful in 6s
- Add Gitea Action to auto-update README badges and ADR table on push - Standardize 8 ADRs from heading-style to inline metadata format - Add shields.io badges for ADR counts (total/accepted/proposed) - Replace static directory listing with linked ADR table in README - Accept ADR-0030 (MFA/YubiKey strategy)
4.4 KiB
4.4 KiB
CI Notifications and Semantic Versioning
- Status: accepted
- Date: 2026-02-02
- Deciders: Billy
- Technical Story: Add pipeline notifications and automated versioning to Gitea Actions CI
Context
With Gitea Actions now handling CI/CD for our repositories (ADR-0013), we need:
- Visibility - Notifications when pipelines pass or fail
- Versioning - Consistent, automated semantic versioning for releases
- Traceability - Clear version tags linked to commits
We already have ntfy deployed for push notifications (used by alertmanager and Gatus).
Decision
1. CI Notifications via ntfy
All CI workflows send notifications to ntfy on pipeline completion:
env:
NTFY_URL: http://ntfy.observability.svc.cluster.local:80
notify:
name: Notify
runs-on: ubuntu-latest
needs: [lint, test]
if: always()
steps:
- name: Notify on success
if: needs.lint.result == 'success' && needs.test.result == 'success'
run: |
curl -s \
-H "Title: ✅ CI Passed: ${{ gitea.repository }}" \
-H "Priority: default" \
-H "Tags: white_check_mark,github" \
-H "Click: ${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_id }}" \
-d "Branch: ${{ gitea.ref_name }}" \
${{ env.NTFY_URL }}/gitea-ci
- name: Notify on failure
if: needs.lint.result == 'failure' || needs.test.result == 'failure'
run: |
curl -s \
-H "Title: ❌ CI Failed: ${{ gitea.repository }}" \
-H "Priority: high" \
-H "Tags: x,github" \
-d "..." \
${{ env.NTFY_URL }}/gitea-ci
Topic: gitea-ci (subscribe at ntfy.daviestechlabs.io/gitea-ci)
2. Semantic Versioning
Version bumps are determined by commit message keywords:
| Keyword in Commit | Version Bump | Example |
|---|---|---|
major: or BREAKING CHANGE |
Major (1.0.0 → 2.0.0) | major: redesign API |
minor: or feat: |
Minor (1.0.0 → 1.1.0) | feat: add streaming |
fix:, patch:, or other |
Patch (1.0.0 → 1.0.1) | fix: null pointer |
Implementation in workflow:
release:
name: Release
runs-on: ubuntu-latest
needs: [lint, test]
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Determine version bump
id: version
run: |
# Get latest tag or default to v0.0.0
LATEST=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
VERSION=${LATEST#v}
IFS='.' read -r MAJOR MINOR PATCH <<< "$VERSION"
# Check commit message for keywords
MSG="${{ github.event.head_commit.message }}"
if echo "$MSG" | grep -qiE "^major:|BREAKING CHANGE"; then
MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0
elif echo "$MSG" | grep -qiE "^(minor:|feat:)"; then
MINOR=$((MINOR + 1)); PATCH=0
else
PATCH=$((PATCH + 1))
fi
NEW_VERSION="v${MAJOR}.${MINOR}.${PATCH}"
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "Bumping $LATEST → $NEW_VERSION"
- name: Create tag
run: |
git config user.name "gitea-actions[bot]"
git config user.email "actions@git.daviestechlabs.io"
git tag -a ${{ steps.version.outputs.version }} -m "Release ${{ steps.version.outputs.version }}"
git push origin ${{ steps.version.outputs.version }}
- name: Create release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.version.outputs.version }}
generate_release_notes: true
3. Topic Structure
| Topic | Purpose |
|---|---|
gitea-ci |
All CI pipeline notifications |
gitea-releases |
New version releases (optional) |
Consequences
Positive
- Immediate visibility - Know instantly when builds fail
- Consistent versioning - No manual version management
- Audit trail - Git tags link versions to commits
- Low friction - Developers just use conventional commit prefixes
Negative
- Commit message discipline - Requires consistent prefixes
- ntfy dependency - Notifications require ntfy to be running
- Tag pollution - Every main push creates a tag (can skip with
[skip ci])