Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions .github/workflows/auto-tag.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: Auto Tag on Version Bump

on:
push:
branches: [main]
paths:
- 'library.json'
- 'library.properties'
- 'src/HttpCommon.h'

permissions:
contents: write

jobs:
check-and-tag:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history needed for tag comparison

- name: Extract version from library.json
id: version
run: |
VERSION=$(grep -m1 '"version"' library.json | sed -E 's/.*"version" *: *"([^"]+)".*/\1/')
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "Detected version: ${VERSION}"

- name: Verify version consistency across files
run: |
VERSION="${{ steps.version.outputs.version }}"
V_PROP=$(grep '^version=' library.properties | cut -d'=' -f2)
V_HDR=$(grep '#define ESP_ASYNC_WEB_CLIENT_VERSION' src/HttpCommon.h | sed -E 's/.*"([^"]+)".*/\1/')

MISMATCH=0
if [[ "${VERSION}" != "${V_PROP}" ]]; then
echo "::error::Version mismatch: library.json=${VERSION} vs library.properties=${V_PROP}"
MISMATCH=1
fi
if [[ "${VERSION}" != "${V_HDR}" ]]; then
echo "::error::Version mismatch: library.json=${VERSION} vs HttpCommon.h=${V_HDR}"
MISMATCH=1
fi
if [[ $MISMATCH -ne 0 ]]; then
echo "::error::Fix version mismatches before tagging. Use: scripts/sync-version.sh <version>"
exit 1
fi
echo "All 3 version sources agree: ${VERSION}"

- name: Check if tag already exists
id: tag_check
run: |
TAG="v${{ steps.version.outputs.version }}"
if git rev-parse "refs/tags/${TAG}" >/dev/null 2>&1; then
echo "exists=true" >> "$GITHUB_OUTPUT"
echo "Tag ${TAG} already exists — skipping."
else
echo "exists=false" >> "$GITHUB_OUTPUT"
echo "Tag ${TAG} does not exist — will create."
fi

- name: Create and push tag
if: steps.tag_check.outputs.exists == 'false'
run: |
TAG="v${{ steps.version.outputs.version }}"
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag -a "${TAG}" -m "Release ${TAG}"
git push origin "${TAG}"
echo "::notice::Created and pushed tag ${TAG}"
104 changes: 95 additions & 9 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ jobs:

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # full history for changelog generation

- name: Set up Python
uses: actions/setup-python@v5
Expand Down Expand Up @@ -59,16 +61,100 @@ jobs:
name: source-archive
path: ${{ env.ARCHIVE }}

- name: Extract changelog for this version
id: changelog
run: |
VERSION=$(grep '"version"' library.json | sed -E 's/.*"version" *: *"([^"]+)".*/\1/')
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"

Comment on lines +64 to +69
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the changelog extraction step, VERSION=$(grep '"version"' library.json | ...) will match multiple "version" keys in library.json (the top-level library version and dependency versions). This can produce a multi-line VERSION value and break release naming/notes. Use jq -r .version or at least grep -m1 with a stricter pattern targeting only the top-level version.

Copilot uses AI. Check for mistakes.
# Extract the section for this version from CHANGELOG.md
# Matches everything between "## [X.Y.Z]" and the next "## [" heading
NOTES=""
if [[ -f CHANGELOG.md ]]; then
NOTES=$(awk -v ver="${VERSION}" '
BEGIN { found=0 }
/^## \[/ {
if (found) exit
if ($0 ~ "\\[" ver "\\]") { found=1; next }
}
found { print }
' CHANGELOG.md)
fi

if [[ -z "${NOTES}" ]]; then
echo "No CHANGELOG entry found for ${VERSION}, generating from commits..."
# Get the previous tag
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
if [[ -n "${PREV_TAG}" ]]; then
NOTES=$(git log "${PREV_TAG}..HEAD" --pretty=format:"- %s (%h)" --no-merges)
else
NOTES=$(git log --pretty=format:"- %s (%h)" --no-merges -20)
fi
fi

# Write to file to preserve multiline
echo "${NOTES}" > /tmp/release_notes.md

- name: Generate AI-style release summary
id: summary
run: |
VERSION="${{ steps.changelog.outputs.version }}"
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")

# Build a structured release body
{
echo "# ESPAsyncWebClient v${VERSION}"
echo ""

# Changelog section
echo "## What's Changed"
cat /tmp/release_notes.md
echo ""

# Auto-generated commit summary by category
if [[ -n "${PREV_TAG}" ]]; then
echo "## Commit Summary"
echo ""

# Fixes
FIXES=$(git log "${PREV_TAG}..HEAD" --pretty=format:"- %s (%h)" --no-merges --grep="^[Ff]ix" || true)
if [[ -n "${FIXES}" ]]; then
echo "### Bug Fixes"
echo "${FIXES}"
echo ""
fi

# Features
FEATURES=$(git log "${PREV_TAG}..HEAD" --pretty=format:"- %s (%h)" --no-merges --grep="^[Ff]eat" || true)
if [[ -n "${FEATURES}" ]]; then
echo "### New Features"
echo "${FEATURES}"
echo ""
fi

# Other commits
OTHER=$(git log "${PREV_TAG}..HEAD" --pretty=format:"- %s (%h)" --no-merges --invert-grep --grep="^[Ff]ix" --grep="^[Ff]eat" || true)
if [[ -n "${OTHER}" ]]; then
echo "### Other Changes"
echo "${OTHER}"
echo ""
fi

echo "**Full diff**: https://github.com/${{ github.repository }}/compare/${PREV_TAG}...v${VERSION}"
echo ""
fi

# Stats
echo "## Verification"
echo "- :white_check_mark: All examples built successfully"
echo "- :white_check_mark: Version metadata consistent across library.json, library.properties, and HttpCommon.h"
echo "- :package: Source archive attached"
} > /tmp/full_release_notes.md

- name: Create Release
uses: softprops/action-gh-release@v2
with:
files: ${{ env.ARCHIVE }}
name: Release ${{ github.ref }}
body: |
## Changes in this release
See the Git diff for this tag or the Releases page for details.

## Verification
- Examples built successfully
- Version metadata consistent
- Source archive attached
name: "v${{ steps.changelog.outputs.version }}"
body_path: /tmp/full_release_notes.md
generate_release_notes: true
2 changes: 1 addition & 1 deletion library.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ESPAsyncWebClient",
"version": "2.1.0",
"version": "2.1.1",
"description": "Asynchronous HTTP client library for ESP32 ",
"keywords": [
"http",
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=ESPAsyncWebClient
version=2.1.0
version=2.1.1
author=playmiel
maintainer=playmiel
sentence=Asynchronous HTTP client library for ESP32 microcontrollers
Expand Down
53 changes: 53 additions & 0 deletions scripts/sync-version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/usr/bin/env bash
# sync-version.sh — Update version in all 3 source-of-truth files at once.
# Usage: ./scripts/sync-version.sh 2.2.0
set -euo pipefail

if [[ $# -ne 1 ]]; then
echo "Usage: $0 <version>"
echo "Example: $0 2.2.0"
exit 1
fi

NEW_VERSION="$1"

# Validate semver format
if [[ ! "${NEW_VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error: '${NEW_VERSION}' is not a valid semver (expected X.Y.Z)"
exit 1
fi

echo "Syncing version to ${NEW_VERSION} across all files..."

# 1. library.json
if [[ -f library.json ]]; then
sed -i -E "s/\"version\" *: *\"[^\"]+\"/\"version\": \"${NEW_VERSION}\"/" library.json

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict version sync to top-level library.json version

The sed replacement matches every "version" key in library.json, not just the package’s top-level version field. In this repo that also rewrites dependencies[].version (e.g., AsyncTCP), so running scripts/sync-version.sh 2.2.0 would silently change the dependency constraint to 2.2.0 and can break dependency resolution/builds in subsequent releases.

Useful? React with 👍 / 👎.

echo " ✓ library.json"
else
Comment on lines +22 to +26
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sed replacement for library.json matches any line containing a "version" key, which will also rewrite dependency versions (e.g. the AsyncTCP dependency’s "version": "^3.4.8"). This will corrupt library.json when syncing versions. Update the script to only modify the top-level .version field (e.g., parse JSON with jq/Python, or restrict the match to the first occurrence / an anchored top-level key).

Copilot uses AI. Check for mistakes.
echo " ✗ library.json not found"
fi

# 2. library.properties
if [[ -f library.properties ]]; then
sed -i -E "s/^version=.*/version=${NEW_VERSION}/" library.properties
echo " ✓ library.properties"
else
echo " ✗ library.properties not found"
fi

# 3. src/HttpCommon.h
if [[ -f src/HttpCommon.h ]]; then
sed -i -E "s/#define ESP_ASYNC_WEB_CLIENT_VERSION \"[^\"]+\"/#define ESP_ASYNC_WEB_CLIENT_VERSION \"${NEW_VERSION}\"/" src/HttpCommon.h
echo " ✓ src/HttpCommon.h"
Comment on lines +23 to +41
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sed -i behaves differently between GNU sed (Linux) and BSD sed (macOS requires -i ''). Since this script is meant to be run locally, consider making the in-place edit portable (e.g., detect BSD vs GNU sed, or use a small Python/JQ snippet for replacements) to avoid breaking contributors on macOS.

Copilot uses AI. Check for mistakes.
else
echo " ✗ src/HttpCommon.h not found"
fi

echo ""
echo "Done! Version is now ${NEW_VERSION} everywhere."
echo ""
echo "Next steps:"
echo " 1. Update CHANGELOG.md with your changes under [${NEW_VERSION}]"
echo " 2. Commit and push to main"
echo " 3. The auto-tag workflow will create the tag v${NEW_VERSION} automatically"
echo " 4. The release workflow will generate the release with auto-generated notes"
Loading
Loading