From 26cad2f826580caa3cbd1065342abfce309c74f6 Mon Sep 17 00:00:00 2001 From: auricom <27022259+auricom@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:49:20 +0100 Subject: [PATCH 1/3] wip --- .../{release.yml => release-apps.yml} | 2 +- .github/workflows/release-github.yml | 186 ++++++++++++++++++ 2 files changed, 187 insertions(+), 1 deletion(-) rename .github/workflows/{release.yml => release-apps.yml} (99%) create mode 100644 .github/workflows/release-github.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release-apps.yml similarity index 99% rename from .github/workflows/release.yml rename to .github/workflows/release-apps.yml index 020e51787..7b1fe024c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release-apps.yml @@ -1,4 +1,4 @@ -name: Release +name: Apps release on: push: tags: diff --git a/.github/workflows/release-github.yml b/.github/workflows/release-github.yml new file mode 100644 index 000000000..f85f72eb1 --- /dev/null +++ b/.github/workflows/release-github.yml @@ -0,0 +1,186 @@ +name: Github Release +on: + workflow_dispatch: + inputs: + tag: + description: "Release tag (e.g., v1.2.3)" + required: true + type: string + +permissions: + contents: write + id-token: write + +jobs: + create-draft-release: + name: Create Draft Release + runs-on: ubuntu-latest + steps: + - name: Validate semver tag + run: | + TAG="${{ github.event.inputs.tag }}" + + # Check if tag matches semver pattern (v followed by MAJOR.MINOR.PATCH with optional pre-release and build metadata) + # Supports: v1.2.3, v1.2.3-rc.4, v1.2.3-beta.1, v1.2.3-alpha.1+build.123 + if ! echo "$TAG" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$'; then + echo "::error::Invalid tag format: $TAG" + echo "::error::Tag must be in semver format: v..[-PRERELEASE][+BUILD]" + echo "::error::Examples: v1.2.3, v1.2.3-rc.4, v1.2.3-beta.1, v1.2.3-alpha.1+build.123" + exit 1 + fi + + echo "::notice::Tag validation passed: $TAG" + + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Extract version from tag + id: extract-version + run: | + TAG="${{ github.event.inputs.tag }}" + VERSION="${TAG#v}" + echo "tag=$TAG" >> $GITHUB_OUTPUT + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "::notice::Tag: $TAG" + echo "::notice::Version: $VERSION" + + - name: Find previous tag + id: prev-tag + run: | + TAG="${{ steps.extract-version.outputs.tag }}" + PREV_TAG=$(git tag -l "v*.*.*" --sort=-version:refname | grep -v "^${TAG}$" | head -n1) + + if [ -z "$PREV_TAG" ]; then + echo "::notice::No previous tag found, using initial commit" + PREV_TAG=$(git rev-list --max-parents=0 HEAD) + fi + + echo "prev-tag=$PREV_TAG" >> $GITHUB_OUTPUT + echo "::notice::Previous tag: $PREV_TAG" + + - name: Get list of Docker images + id: get-images + run: | + # Find all apps with Dockerfiles + IMAGES="" + for app_dir in apps/*/; do + if [ -f "${app_dir}Dockerfile" ]; then + APP_NAME=$(basename "$app_dir") + IMAGE_NAME="ev-node-${APP_NAME}" + IMAGES="${IMAGES}ghcr.io/${{ github.repository_owner }}/${IMAGE_NAME}:${{ steps.extract-version.outputs.tag }}\n" + fi + done + + # Remove trailing newline + IMAGES=$(echo -e "$IMAGES" | sed '/^$/d') + + # Escape for GitHub Actions output + IMAGES="${IMAGES//'%'/'%25'}" + IMAGES="${IMAGES//$'\n'/'%0A'}" + IMAGES="${IMAGES//$'\r'/'%0D'}" + + echo "images=$IMAGES" >> $GITHUB_OUTPUT + echo "::notice::Found Docker images" + + - name: Generate changelog prompt + id: changelog-prompt + run: | + PREV_TAG="${{ steps.prev-tag.outputs.prev-tag }}" + TAG="${{ steps.extract-version.outputs.tag }}" + VERSION="${{ steps.extract-version.outputs.version }}" + + cat > claude-prompt.txt << 'EOF_PROMPT' + Read the file CHANGELOG.md and find the section for version $VERSION (tag $TAG). + + Generate professional release notes for GitHub based on the changes listed for this specific version. + + Create release notes with the following structure: + + ev-node VERSION + + ⚠️ This is a draft release. Please verify its content before publishing + + [Brief summary paragraph about this release - what type of release it is (feature/bugfix/maintenance), upgrade recommendations] + + **Tested upgrade paths** + - [List version upgrade paths that were tested, or state "TBD - to be tested before publishing"] + + **Changelog** + + **Added** + - BREAKING: [Feature description with context about what users need to do] + - [Other new features] + + **Changed** + - BREAKING: [Change description with migration instructions] + - [Other changes] + + **Removed** + - BREAKING: [Removed feature with alternatives or migration path] + - [Other removals] + + **Fixed** + - [Bug fixes] + + **Images** + EOF_PROMPT + + # Replace placeholders with actual values + sed -i "s/\$VERSION/${VERSION}/g" claude-prompt.txt + sed -i "s/\$TAG/${TAG}/g" claude-prompt.txt + + # Add the images list + echo "${{ steps.get-images.outputs.images }}" | while IFS= read -r image; do + echo "- $image" >> claude-prompt.txt + done + + cat >> claude-prompt.txt << 'EOF_PROMPT' + + Guidelines: + - Replace VERSION with the actual version number + - Replace YYYY-MM-DD with the actual release date + - Focus on BREAKING changes - clearly mark them and explain what users need to do + - For breaking changes, include specific migration steps or configuration changes needed + - Use clear, professional language + - Include technical details and PR numbers if available in the changelog + - Group related changes together + - Omit empty sections + - Format as clean markdown + + Output the release notes as your response. + EOF_PROMPT + + { + echo 'prompt<> $GITHUB_OUTPUT + + - name: Generate release notes with Claude + id: claude-release + uses: anthropics/claude-code-action@v1 + with: + claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + prompt: ${{ steps.changelog-prompt.outputs.prompt }} + trusted_bots: "*" + allowed_tools: "Read(CHANGELOG.md)" + claude_args: | + --json-schema '{"type":"object","properties":{"release_notes":{"type":"string"},"release_date":{"type":"string","description":"Release date in YYYY-MM-DD format"}},"required":["release_notes","release_date"]}' + + - name: Create Draft GitHub Release + id: create-release + uses: softprops/action-gh-release@v2 + with: + draft: true + name: ${{ steps.extract-version.outputs.tag }} (${{ fromJSON(steps.claude-release.outputs.structured_output).release_date }}) + tag_name: ${{ steps.extract-version.outputs.tag }} + body: ${{ fromJSON(steps.claude-release.outputs.structured_output).release_notes }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Output release URL + run: | + RELEASE_URL="https://github.com/${{ github.repository }}/releases/tag/${{ steps.extract-version.outputs.tag }}" + echo "::notice::Draft release created: $RELEASE_URL" From f9b5f826dc95af4e8c33bcc1d11260349963b482 Mon Sep 17 00:00:00 2001 From: auricom <27022259+auricom@users.noreply.github.com> Date: Tue, 3 Feb 2026 18:42:02 +0100 Subject: [PATCH 2/3] release.md --- RELEASE.md | 117 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 4 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index e269b6680..2ef79aa73 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -2,11 +2,80 @@ This document covers the release process for ev-node components: +- **GitHub Releases** - Manual workflow to create draft releases with AI-generated release notes - **Docker Image Releases** - Automated via GitHub workflows (for deployable applications) - **Go Module Releases** - Manual process for library packages and dependencies --- +## GitHub Releases (Manual Workflow) + +### When to Use + +Create official GitHub releases with professionally formatted release notes for version tags. + +### Quick Steps + +```bash +# 1. Ensure CHANGELOG.md is updated for the version +# 2. Navigate to GitHub Actions +# 3. Run "Github Release" workflow +# 4. Enter tag (e.g., v1.2.3) +# 5. Review and publish the draft release +``` + +### How It Works + +The GitHub Release workflow (`.github/workflows/release-github.yml`) automates release note generation: + +1. **Validates Tag Format** - Ensures tag follows semantic versioning (e.g., `v1.2.3`, `v1.2.3-rc.4`) +2. **Extracts Version Info** - Parses version from tag and finds previous release +3. **Discovers Docker Images** - Lists all Docker images that will be included in the release +4. **Generates Release Notes** - Uses Claude AI to read CHANGELOG.md and create professional release notes +5. **Creates Draft Release** - Publishes a draft GitHub release for review + +### Release Notes Structure + +The workflow generates release notes with: + +- **Summary** - Overview of the release type and upgrade recommendations +- **Tested Upgrade Paths** - Version compatibility information +- **Changelog Sections**: + - Added (new features, with BREAKING changes highlighted) + - Changed (modifications, with BREAKING changes highlighted) + - Removed (deprecated features, with BREAKING changes highlighted) + - Fixed (bug fixes) +- **Docker Images** - List of all available Docker images for this release + +### Requirements + +- Tag must follow semantic versioning: `v..[-PRERELEASE][+BUILD]` + - Valid: `v1.2.3`, `v1.2.3-rc.4`, `v1.2.3-beta.1`, `v1.2.3-alpha.1+build.123` +- CHANGELOG.md must contain a section for the version being released +- `CLAUDE_CODE_OAUTH_TOKEN` secret must be configured in repository settings + +### Workflow Dispatch + +To trigger the workflow: + +1. Go to **GitHub → Actions → Github Release** +2. Click **Run workflow** +3. Enter the release tag (e.g., `v1.2.3`) +4. Click **Run workflow** + +The workflow will create a **draft release** that you can review and edit before publishing. + +### Best Practices + +- ✅ Update CHANGELOG.md before running the workflow +- ✅ Use clear, descriptive changelog entries +- ✅ Mark breaking changes explicitly in CHANGELOG.md +- ✅ Review the draft release before publishing +- ✅ Test upgrade paths and update release notes accordingly +- ✅ Ensure all Docker images are built and available + +--- + ## Docker Image Releases (Automated) ### When to Use @@ -182,7 +251,21 @@ go list -m github.com/evstack/ev-node/apps/evm@v0.3.0 ## Common Release Scenarios -### Scenario 1: Release Single App (Docker Only) +### Scenario 1: Create GitHub Release + +```bash +# 1. Update CHANGELOG.md with version changes +# 2. Commit and push changes +git add CHANGELOG.md +git commit -m "Update changelog for v1.2.3" +git push origin main + +# 3. Go to GitHub Actions → Github Release → Run workflow +# 4. Enter tag: v1.2.3 +# 5. Review draft release and publish +``` + +### Scenario 2: Release Single App (Docker Only) ```bash # Tag and push - automation handles the rest @@ -190,7 +273,7 @@ git tag evm/v0.2.0 git push origin evm/v0.2.0 ``` -### Scenario 2: Release Multiple Apps +### Scenario 3: Release Multiple Apps ```bash # Release apps independently @@ -201,7 +284,7 @@ git push origin evm/single/v0.2.0 testapp/v1.0.0 # Each triggers its own workflow ``` -### Scenario 3: Full Go Module Release +### Scenario 4: Full Go Module Release ```bash # 1. Core @@ -216,7 +299,7 @@ git tag execution/evm/v0.3.0 && git push origin execution/evm/v0.3.0 git tag apps/evm/v0.3.0 && git push origin apps/evm/v0.3.0 ``` -### Scenario 4: Hotfix/Patch Release +### Scenario 5: Hotfix/Patch Release ```bash # For Docker images - delete and recreate @@ -263,6 +346,32 @@ go get github.com/evstack/ev-node/core@v0.3.0 ## Troubleshooting +### GitHub Releases + +**"Invalid tag format" error** + +- Ensure tag follows semantic versioning: `v1.2.3` +- Check for typos or incorrect format +- Valid examples: `v1.2.3`, `v1.2.3-rc.4`, `v1.2.3-beta.1` + +**"Version not found in CHANGELOG.md"** + +- Verify CHANGELOG.md contains a section for the version +- Check version format matches exactly (e.g., `v1.2.3` vs `1.2.3`) +- Ensure CHANGELOG.md is committed and pushed + +**"Claude API error"** + +- Verify `CLAUDE_CODE_OAUTH_TOKEN` secret is configured +- Check repository permissions for GitHub Actions +- Review workflow logs for specific error messages + +**Empty or incomplete release notes** + +- Ensure CHANGELOG.md has detailed entries for the version +- Check that changelog sections (Added, Changed, Fixed, etc.) are properly formatted +- Review the draft release and manually edit if needed + ### Docker Releases **"App directory does not exist"** From 21fe60721538144d936fc4d1a7c5c8dedabb277d Mon Sep 17 00:00:00 2001 From: auricom <27022259+auricom@users.noreply.github.com> Date: Tue, 3 Feb 2026 18:56:13 +0100 Subject: [PATCH 3/3] tweak release --- .github/workflows/release-github.yml | 41 ++++++++++++++++------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/.github/workflows/release-github.yml b/.github/workflows/release-github.yml index f85f72eb1..1c3040443 100644 --- a/.github/workflows/release-github.yml +++ b/.github/workflows/release-github.yml @@ -107,22 +107,25 @@ jobs: **Tested upgrade paths** - [List version upgrade paths that were tested, or state "TBD - to be tested before publishing"] - **Changelog** + ## ⚠️ Breaking Changes - **Added** - - BREAKING: [Feature description with context about what users need to do] - - [Other new features] + [If there are breaking changes, list each one with clear operational steps. If no breaking changes, state "None"] - **Changed** - - BREAKING: [Change description with migration instructions] - - [Other changes] + ### [Breaking Change Title] + **What changed:** [Clear description of what was changed/added/removed] - **Removed** - - BREAKING: [Removed feature with alternatives or migration path] - - [Other removals] + **Action required:** + 1. [Step-by-step instructions on what operators need to do] + 2. [Include configuration changes, file modifications, etc.] + 3. [Provide examples where helpful] - **Fixed** - - [Bug fixes] + **Reference:** [PR number if available] + + --- + + ## Full Changelog + + For a complete list of all changes including new features, improvements, and bug fixes, see [CHANGELOG.md](https://github.com/${{ github.repository }}/blob/$TAG/CHANGELOG.md#$VERSION). **Images** EOF_PROMPT @@ -141,12 +144,14 @@ jobs: Guidelines: - Replace VERSION with the actual version number - Replace YYYY-MM-DD with the actual release date - - Focus on BREAKING changes - clearly mark them and explain what users need to do - - For breaking changes, include specific migration steps or configuration changes needed - - Use clear, professional language - - Include technical details and PR numbers if available in the changelog - - Group related changes together - - Omit empty sections + - ONLY include BREAKING changes in the "Breaking Changes" section + - For each breaking change, provide clear operational steps that operators must follow + - Include specific configuration file changes, command modifications, or migration steps + - Use numbered lists for action steps to make them easy to follow + - Do NOT duplicate the full changelog content - just reference CHANGELOG.md + - If there are no breaking changes, clearly state "None" in that section + - Use clear, professional language focused on operational impact + - Include PR numbers for breaking changes when available - Format as clean markdown Output the release notes as your response.