Skip to content

⬆️ Update ghcr.io/hassio-addons/base Docker tag to v21.0.5 #105

⬆️ Update ghcr.io/hassio-addons/base Docker tag to v21.0.5

⬆️ Update ghcr.io/hassio-addons/base Docker tag to v21.0.5 #105

---
name: Update Changelog
on:
pull_request:
types: [opened, synchronize]
paths:
- 'netbird/Dockerfile'
- 'netbird/config.yaml'
jobs:
update-changelog:
name: Update changelog for NetBird releases
runs-on: ubuntu-latest
# SECURITY: This workflow has write permissions to push commits.
# Multiple safeguards prevent misuse:
# 1. Actor must be 'renovate[bot]' (GitHub-verified bot identity)
# 2. PR title must contain 'netbirdio/netbird' OR have 'netbird-update' label
# 3. PR must be from same repo (not a fork) - validated in first step
# 4. Branch name must match Renovate's pattern - validated in first step
# 5. Only modifies CHANGELOG.md, not arbitrary files
if: |
github.actor == 'renovate[bot]' &&
(
contains(github.event.pull_request.title, 'netbirdio/netbird') ||
contains(join(github.event.pull_request.labels.*.name, ','), 'netbird-update')
)
permissions:
contents: write
steps:
- name: Validate PR source and branch
env:
PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
PR_BASE_REPO: ${{ github.repository }}
PR_BRANCH: ${{ github.event.pull_request.head.ref }}
run: |
# Security check 1: Ensure PR is from same repository (not a fork)
if [ "$PR_HEAD_REPO" != "$PR_BASE_REPO" ]; then
echo "Error: This workflow only supports PRs from the same repository, not forks."
echo "Fork PRs cannot be updated because GITHUB_TOKEN lacks push access to external repos."
exit 1
fi
# Security check 2: Ensure branch name matches Renovate's naming pattern
# Renovate creates branches like: renovate/netbirdio-netbird-0.x
if ! echo "$PR_BRANCH" | grep -qE '^renovate/'; then
echo "Error: Branch name '$PR_BRANCH' does not match expected Renovate pattern (renovate/*)."
echo "This workflow only processes branches created by Renovate."
exit 1
fi
echo "Security checks passed: same-repo PR from Renovate branch"
- name: Checkout PR branch
uses: actions/checkout@v7.0.1
with:
# Use event payload ref which works reliably for same-repo PRs
ref: ${{ github.event.pull_request.head.ref }}
fetch-depth: 1
token: ${{ secrets.GITHUB_TOKEN }}
- name: Extract new version from PR
id: version
run: |
# Extract version from config.yaml
# Strip leading 'v' characters since config.yaml may contain "v0.64.1" but we add 'v' explicitly later
VERSION=$(grep -m 1 -E '^[[:space:]]*version:' netbird/config.yaml | sed -E 's/^[[:space:]]*version:[[:space:]]*//' | tr -d '"' | tr -d "'" | sed -E 's/^v+//')
if [ -z "$VERSION" ]; then
echo "Failed to extract NetBird version from netbird/config.yaml" >&2
exit 1
fi
# Validate that the extracted version looks like a semantic version (e.g., 0.64.1)
if ! printf '%s\n' "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "Invalid NetBird version '$VERSION' extracted from netbird/config.yaml; expected semantic version (e.g., 0.64.1)" >&2
exit 1
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "Detected NetBird version: ${VERSION}"
- name: Fetch upstream release notes
id: release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.version.outputs.version }}
run: |
# Fetch release notes from upstream repo
RELEASE_BODY=$(gh api "repos/netbirdio/netbird/releases/tags/v${VERSION}" --jq '.body // empty' 2>/dev/null || echo "")
# NOTE: We use the upstream release date (published_at), not the integration date.
# This makes it easier to track which upstream version corresponds to which release,
# and aligns the addon changelog with upstream NetBird release timeline.
# If you prefer integration dates, replace this with: RELEASE_DATE=$(date +%Y-%m-%d)
RELEASE_DATE=$(gh api "repos/netbirdio/netbird/releases/tags/v${VERSION}" --jq '.published_at // empty' 2>/dev/null | cut -d'T' -f1 || echo "")
if [ -z "$RELEASE_DATE" ]; then
echo "Error: Unable to fetch release date for NetBird v${VERSION}. Failing workflow to avoid using an incorrect date in the changelog."
exit 1
fi
echo "release_date=${RELEASE_DATE}" >> "$GITHUB_OUTPUT"
# Save release body to file for multiline handling
if [ -n "$RELEASE_BODY" ]; then
echo "$RELEASE_BODY" > /tmp/release_notes.md
echo "has_notes=true" >> "$GITHUB_OUTPUT"
else
echo "has_notes=false" >> "$GITHUB_OUTPUT"
fi
- name: Update CHANGELOG.md
env:
VERSION: ${{ steps.version.outputs.version }}
RELEASE_DATE: ${{ steps.release.outputs.release_date }}
HAS_NOTES: ${{ steps.release.outputs.has_notes }}
run: |
CHANGELOG_FILE="netbird/CHANGELOG.md"
# Create fresh changelog with only the latest version
# (previous version history is not preserved)
{
echo "# Changelog"
echo ""
echo "## [v${VERSION}] - ${RELEASE_DATE}"
echo ""
echo "### Changed"
echo "- Updated to NetBird v${VERSION}"
# Add upstream release notes if available
if [ "$HAS_NOTES" = "true" ]; then
echo ""
echo "### Upstream Release Notes"
# Process release notes - skip leading empty lines
started=""
while IFS= read -r line; do
if [ -z "$line" ] && [ -z "$started" ]; then
continue
fi
started=true
echo "$line"
done < /tmp/release_notes.md
fi
} > "$CHANGELOG_FILE"
echo "Updated changelog with v${VERSION} entry (previous versions removed)"
- name: Commit changes
env:
VERSION: ${{ steps.version.outputs.version }}
PR_HEAD_REF: ${{ github.event.pull_request.head.ref }}
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if git diff --quiet netbird/CHANGELOG.md; then
echo "No changelog changes to commit"
exit 0
fi
git add netbird/CHANGELOG.md
git commit -m "📝 Update CHANGELOG.md for NetBird v${VERSION}"
# Push with retry logic to handle race conditions (e.g., Renovate force-push while running)
MAX_RETRIES=3
for attempt in $(seq 1 $MAX_RETRIES); do
if git push; then
echo "Push succeeded on attempt $attempt"
exit 0
fi
if [ "$attempt" -lt "$MAX_RETRIES" ]; then
echo "Push failed (attempt $attempt/$MAX_RETRIES), rebasing and retrying..."
git pull --rebase origin "$PR_HEAD_REF"
fi
done
echo "Error: git push failed after $MAX_RETRIES attempts. The PR branch may have conflicts." >&2
exit 1