Skip to content

Conversation

@auricom
Copy link
Contributor

@auricom auricom commented Jan 19, 2026

Overview

@github-actions
Copy link
Contributor

github-actions bot commented Jan 19, 2026

The latest Buf updates on your PR. Results from workflow CI / buf-check (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed⏩ skipped✅ passed❌ failed (1)Jan 22, 2026, 5:48 PM

@claude
Copy link
Contributor

claude bot commented Jan 19, 2026

Claude finished @auricom's task in 2m 28s —— View job


Code Review Complete

I've completed a comprehensive review of this release process implementation. Here's my detailed feedback:


Security Issues (Critical)

1. Unpinned GitHub Actions - .github/workflows/release.yml

GitHub Advanced Security has flagged several unpinned actions. This is a legitimate security concern:

Lines with unpinned actions:

  • Line 355: softprops/action-gh-release@v2
  • Line 22, 224, 269, 300: actions/checkout@v6 (first-party action, less critical)

Recommendation: Pin third-party actions to commit SHAs instead of version tags:

# Instead of:
- uses: softprops/action-gh-release@v2

# Use:
- uses: softprops/action-gh-release@c062e08bd532815e2082a85e87e3ef29c3e6d191 # v2

Why this matters: Version tags are mutable and can be changed by attackers. Pinning to SHAs prevents supply chain attacks.

Fix unpinned actions →

2. Potentially Unsafe Checkout - Line 305

GitHub Advanced Security flagged line 305 for potentially unsafe checkout:

- name: Checkout code
  uses: actions/checkout@v6
  with:
    ref: ${{ needs.create-release-branch.outputs.release-branch }}
    fetch-depth: 0

Issue: Checking out code from a branch created by the workflow itself using outputs from a previous job. While this appears safe in this specific case (the branch name is controlled by the workflow), the scanner flags it as a potential vector for code injection.

Analysis: This appears to be a false positive because:

  1. The release-branch output comes from a controlled job that creates the branch name deterministically
  2. The branch name is derived from github.ref_name which is controlled by GitHub
  3. There's no user input that could manipulate the branch name

Recommendation: Add a validation step to explicitly sanitize the branch name before checkout, or add a comment explaining why this is safe:

- name: Validate release branch name
  run: |
    BRANCH="${{ needs.create-release-branch.outputs.release-branch }}"
    if [[ ! "$BRANCH" =~ ^release/[a-zA-Z0-9/_.-]+/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
      echo "::error::Invalid release branch name: $BRANCH"
      exit 1
    fi

- name: Checkout code
  uses: actions/checkout@v6
  with:
    ref: ${{ needs.create-release-branch.outputs.release-branch }}
    fetch-depth: 0

Code Quality & Architecture

3. Shell Script Complexity - Lines 28-172

The create-release-branch job contains extensive bash scripting logic (144 lines) embedded in the workflow. This reduces:

  • Testability: Cannot unit test bash logic in workflow files
  • Maintainability: Hard to debug and modify
  • Reusability: Cannot reuse logic across workflows

Recommendation: Extract the changelog generation logic into a dedicated script:

# In workflow:
- name: Generate changelog
  run: |
    ./scripts/generate-changelog.sh "${{ github.ref_name }}" "${{ steps.get-prev-tag.outputs.prev-tag }}"

# Move lines 83-161 to scripts/generate-changelog.sh

Benefits:

  • Can be tested locally with shellcheck and unit tests
  • Easier to debug and iterate
  • Can be reused in other workflows or locally
  • Better separation of concerns

Refactor to separate script →

4. Error Handling in Shell Scripts - Multiple locations

The bash scripts lack comprehensive error handling:

Issues:

  • No set -euo pipefail at the beginning of script blocks
  • Some commands use || true which silently swallows errors (lines 111, 120, 129, 138)
  • No validation of critical variables before use

Recommendation: Add defensive programming patterns:

# At the start of each bash script block:
set -euo pipefail

# For optional matches, be explicit:
FEATURES=$(git log --oneline "$PREV_TAG"..HEAD | grep -i "^[a-f0-9]* feat" || echo "")
if [ -n "$FEATURES" ]; then
  # ... process features
fi

5. Tag Validation - Lines 40-43

Good security practice with regex validation, but the regex could be more restrictive:

if [[ ! "$CURRENT_TAG" =~ ^[a-zA-Z0-9/_.-]+$ ]]; then

Issue: This allows characters that may not be valid in Git tags (like consecutive slashes).

Recommendation: Use a more specific pattern matching your tag format:

# Should match: evm/v0.2.0, testapp/v1.0.0, apps/grpc/v2.1.3
if [[ ! "$CURRENT_TAG" =~ ^[a-zA-Z0-9][a-zA-Z0-9/_.-]*/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
  echo "::error::Invalid tag format: $CURRENT_TAG (expected: {app}/v{major}.{minor}.{patch})"
  exit 1
fi

6. Race Condition Risk - Job Dependencies

The workflow has three parallel jobs after create-release-branch:

  • parse-tag
  • build-and-push (depends on parse-tag)
  • create-github-release (depends on all three)

Potential issue: If build-and-push fails, create-github-release will still run and create a draft release referencing Docker images that don't exist.

Current mitigation: The needs declaration ensures failure propagation.

Recommendation: Consider adding an explicit verification step in create-github-release:

- name: Verify Docker image exists
  run: |
    IMAGE="ghcr.io/${{ github.repository_owner }}/${{ needs.parse-tag.outputs.image-name }}:${{ needs.parse-tag.outputs.version }}"
    docker pull "$IMAGE"

Performance & Resource Efficiency

7. Full Git History Fetches - Lines 24, 303

Multiple jobs fetch full git history with fetch-depth: 0. While necessary for changelog generation, this can be expensive for large repositories.

Current implementation:

- uses: actions/checkout@v6
  with:
    fetch-depth: 0

Recommendation: Consider using shallow clones with increased depth for better performance:

- uses: actions/checkout@v6
  with:
    fetch-depth: 100  # Usually sufficient for recent tag
    # Only use fetch-depth: 0 if tag is older than 100 commits

Or optimize by fetching only the necessary tags:

- name: Fetch tags only
  run: |
    git fetch --depth=1 origin +refs/tags/*:refs/tags/*

8. Multi-platform Docker Builds - Line 287

Building for both linux/amd64 and linux/arm64 is excellent for compatibility but can be time-consuming.

Current implementation:

platforms: linux/amd64,linux/arm64

Recommendation: Consider using build cache to speed up subsequent builds:

- name: Build and push Docker image
  uses: docker/build-push-action@v6
  with:
    context: .
    file: ${{ needs.parse-tag.outputs.dockerfile }}
    push: true
    platforms: linux/amd64,linux/arm64
    cache-from: type=gha
    cache-to: type=gha,mode=max
    tags: |
      ghcr.io/${{ github.repository_owner }}/${{ needs.parse-tag.outputs.image-name }}:${{ needs.parse-tag.outputs.version }}
      ghcr.io/${{ github.repository_owner }}/${{ needs.parse-tag.outputs.image-name }}:latest

Documentation & Developer Experience

9. RELEASE.md - Excellent Documentation

The documentation is comprehensive and well-structured. A few suggestions for improvement:

Strengths:

  • Clear distinction between automated and manual steps
  • Excellent examples and scenarios
  • Good use of visual formatting (emojis, code blocks)
  • Comprehensive troubleshooting section
  • Clear support policy

Minor improvements:

a. Ambiguity in Release Branch Lifecycle (Lines 65-122)

Gemini Code Assist correctly identified this issue. The document explains the release branch lifecycle well but could be clearer about what happens to the changelog in the branch vs. the GitHub Release.

Current issue: Lines 376-382 mention "Replace the changelog in apps/.../CHANGELOG.md" but it's unclear if this refers to:

  1. The file in the release branch
  2. The content in the GitHub Release draft
  3. Both

Recommendation: Add a clarifying note:

**To enhance the changelog with Claude AI:**
1. Open your IDE with Claude integration
2. Copy the prompt below and send it to Claude
3. Claude will generate an enhanced changelog
4. **Update both:**
   - Replace content in `apps/${{ ... }}/CHANGELOG.md` on the release branch
   - Copy the enhanced changelog to the GitHub Release draft
5. Commit and push changes to the release branch: `${{ ... }}`

b. Tag Format Distinction Needs More Prominence (Lines 831-833)

The distinction between Docker release tags (without apps/) and Go module tags (with apps/) is mentioned at the very end. This is confusing and should be highlighted earlier.

Recommendation: Add a clear callout box near the top of the Docker section (around line 406):

### Tag Format

> ⚠️ **Important:** Docker release tags do NOT include the "apps/" prefix, even though app directories are in `./apps/`. Go module release tags DO include "apps/".
>
> - Docker: `evm/v0.2.0` → releases `./apps/evm/`
> - Go Module: `apps/evm/v0.3.0` → releases module `github.com/evstack/ev-node/apps/evm`

Use the tag format: `{app-name}/v{major}.{minor}.{patch}`

c. Tested Upgrade Paths - Excellent Addition

The emphasis on documenting tested upgrade paths (lines 237-272) is excellent and shows maturity in release management. This is a best practice that many projects overlook.

Suggestion: Add a note about automating this:

### Automating Upgrade Path Documentation

Consider adding upgrade path detection to your E2E tests:

\```go
// In E2E test output:
fmt.Printf("✅ Upgrade tested: %s → %s\n", fromVersion, toVersion)
\```

This output can be parsed and automatically added to CHANGELOG.md.

10. Claude Prompt Generation - Lines 305-352

The Claude prompt generation is creative and useful, but the prompt itself could be more specific:

Current prompt (lines 316-345):

  • Generic instructions about changelog format
  • No specific context about ev-node architecture
  • Could benefit from examples

Recommendation: Enhance the prompt with project-specific context:

cat > claude-prompt.txt << 'EOF_PROMPT'
You are a technical writer for ev-node, a sovereign rollup framework built in Go.

Context about ev-node:
- Modular architecture with pluggable DA layers, executors, and sequencers
- Components: core (interfaces), block (management), pkg/p2p (networking), sequencers
- Built on libp2p with GossipSub and Kademlia DHT

Generate a changelog for this release with:

1. Brief summary highlighting impact on:
   - Node operators (deployment, configuration changes)
   - Developers (API changes, new features)
   - End users (performance, reliability improvements)

2. Categorize changes:
   - 🎯 Breaking Changes (with migration guide)
   - ✨ Features (with use cases)
   - 🐛 Bug Fixes (with impact assessment)
   - ⚡ Performance (with benchmarks if available)
   - 📚 Documentation
   - 🔧 Internal (refactoring, testing)

3. For breaking changes, include:
   - What changed
   - Why it changed
   - How to migrate

Analyze these git changes:
EOF_PROMPT

Testing & Reliability

11. No Workflow Tests

The workflow itself has no tests. Consider adding:

  1. Validation workflow that runs on PR to test workflow syntax
  2. Mock release test that validates workflow logic without actually releasing
  3. Integration test using act to test locally

Recommendation: Create .github/workflows/test-release.yml:

name: Test Release Workflow

on:
  pull_request:
    paths:
      - '.github/workflows/release.yml'
      - 'scripts/generate-changelog.sh'

jobs:
  validate-workflow:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - name: Validate workflow syntax
        run: |
          # Use actionlint to validate workflow
          wget https://github.com/rhysd/actionlint/releases/latest/download/actionlint_linux_amd64.tar.gz
          tar -xzf actionlint_linux_amd64.tar.gz
          ./actionlint .github/workflows/release.yml

  test-changelog-generation:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 0
      - name: Test changelog script
        run: |
          # Test with mock data
          git tag test/v0.1.0 HEAD~10
          git tag test/v0.2.0
          # Run changelog generation
          # Validate output format

12. Missing Rollback Documentation

The documentation mentions rollback briefly (line 817-819) but doesn't provide a complete rollback procedure.

Recommendation: Add a comprehensive rollback section:

## Emergency Rollback Procedure

### If You Need to Rollback a Release

#### Docker Image Release

1. **Revert the tag:**
   ```bash
   git tag -d evm/v0.2.0
   git push origin :refs/tags/evm/v0.2.0
  1. Delete the GitHub Release:

    • Go to GitHub → Releases
    • Edit the release
    • Delete the release
  2. Delete or hide Docker images:

    # Images in GHCR can be deleted via UI:
    # GitHub → Packages → ev-node-evm → Package settings → Delete
    
    # Or use GitHub API to delete specific version
  3. Clean up release branch:

    git push origin --delete release/evm/v0.2.0
  4. Create corrected release with new version:

    # Fix issues, then create new patch version
    git tag evm/v0.2.1
    git push origin evm/v0.2.1

Go Module Release

⚠️ NEVER DELETE Go module tags - Go proxy caches are immutable.

Instead:

  1. Create a new patch version with fixes
  2. Document the issue in CHANGELOG.md
  3. Mark the problematic version as deprecated in release notes
# DO NOT DO THIS:
# git tag -d core/v0.3.0  # ❌ Bad

# DO THIS INSTEAD:
git tag core/v0.3.1  # ✅ Good

---

## Additional Recommendations

### 13. **Permissions Follow Least Privilege** ✅

Good job following least privilege principle:
- Root level: `permissions: {}`
- Job level: Only required permissions granted
- Examples: `contents: write`, `packages: write`, `pull-requests: write`

This is security best practice.

### 14. **Consider Adding Notification Step**

The documentation mentions Slack/Telegram announcements but doesn't automate them. Consider adding a notification job:

```yaml
notify-release:
  name: Notify Release
  needs: create-github-release
  if: ${{ !github.event.release.draft }}
  runs-on: ubuntu-latest
  steps:
    - name: Notify Slack
      env:
        SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
      run: |
        curl -X POST "$SLACK_WEBHOOK" -H 'Content-Type: application/json' -d '{
          "text": "🚀 New release: ${{ github.ref_name }}",
          "blocks": [...]
        }'

15. Consider Adding Release Analytics

Track release metrics:

  • Time from tag to published release
  • Number of commits per release
  • Breaking change frequency
  • Upgrade path coverage

Could be implemented as a simple GitHub Action that posts metrics to a dashboard.


Summary

Critical Issues (Must Fix)

  1. Security: Pin third-party GitHub Actions to commit SHAs (line 355)
  2. ⚠️ Security: Add branch name validation before checkout (line 305) - likely false positive but good defense-in-depth

High Priority (Should Fix)

  1. Maintainability: Extract changelog generation to separate script (lines 83-161)
  2. Reliability: Add set -euo pipefail to all bash blocks
  3. Documentation: Clarify changelog update process in RELEASE.md

Medium Priority (Consider)

  1. Performance: Add Docker build cache
  2. Testing: Add workflow validation tests
  3. DX: Add rollback procedure documentation
  4. Validation: Improve tag format regex

Low Priority (Nice to Have)

  1. Automation: Add Slack/Telegram notification step
  2. Analytics: Track release metrics
  3. Documentation: Add project context to Claude prompt

Overall Assessment

This is a well-thought-out release process with excellent documentation. The automation is comprehensive and the manual steps are clearly documented. The main areas for improvement are:

  1. Security hardening (pin actions, validate inputs)
  2. Maintainability (extract complex bash to scripts)
  3. Testing (add workflow tests)

The release process shows maturity with features like:

  • ✅ Tested upgrade path documentation
  • ✅ Multi-platform Docker builds
  • ✅ Automated changelog generation with AI enhancement option
  • ✅ Comprehensive troubleshooting guide
  • ✅ Clear support policy

Great work! The suggested improvements are primarily about hardening and maintainability rather than fundamental issues.


@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @auricom, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly overhauls the project's release documentation by introducing a structured and comprehensive release process. It defines clear version support policies, details both automated and manual steps for creating and publishing releases, and establishes robust guidelines for changelog management and external communication. The changes aim to standardize release procedures, enhance transparency, and provide a clearer understanding of release content and upgrade compatibility for users and contributors.

Highlights

  • Support Policy Definition: A new section clearly outlines the version support policy, specifying support for the current and previous major versions with security and critical bug fixes.
  • Comprehensive Release Workflow: Detailed automated and manual steps for the release process are introduced, covering everything from tag pushes and automated changelog generation to manual review, GitHub Release publication, and public announcements.
  • Structured Changelog Management: New guidelines for maintaining CHANGELOG.md are added, including a specific format, content categories (e.g., Added, Changed, Fixed, Security, Tested Upgrades), and the use of git-cliff for automated generation.
  • Clear Communication Protocols: Templates and instructions are provided for consistent release announcements on GitHub, Slack, and Telegram, ensuring stakeholders are well-informed.
  • Enhanced Release Scenarios & Checklists: The document now includes updated examples for various release scenarios (single app, multiple apps, Go modules, hotfixes) and a comprehensive checklist template to ensure all release steps are followed.
  • Tested Upgrade Paths Emphasis: A new requirement and dedicated section highlight the importance of documenting tested upgrade paths within the changelog, improving clarity for users.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/release.yml
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

contents: write
steps:
- name: Create GitHub Release
uses: softprops/action-gh-release@v2

Check warning

Code scanning / CodeQL

Unpinned tag for a non-immutable Action in workflow Medium

Unpinned 3rd party Action 'Release' step
Uses Step
uses 'softprops/action-gh-release' with ref 'v2', not a pinned commit hash
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a comprehensive and well-documented release process, including changelog management and automated workflows. The changes are primarily in RELEASE.md and provide detailed steps for both Docker image and Go module releases. My review focuses on improving the clarity of the new process. I've suggested clarifying the manual steps required before tagging a release and detailing the lifecycle of the temporary release branches created by the automation. Overall, this is a great step towards standardizing the release workflow.

RELEASE.md Outdated
Comment on lines 42 to 47
1. 📝 Review the release branch `release/<tag-name>`
2. 📝 Edit and refine the generated changelog if needed
3. 📝 Add **recommended upgrade priority** (Critical/High/Medium/Low)
4. 📝 Add **general description** of the release
5. 📝 Ensure **tested upgrade paths** are documented (1-2 lines in changelog)
6. ✅ Merge the release branch or update the GitHub Release directly
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The process for refining the changelog could be clarified. The 'Quick Steps' (lines 254-258) show editing and pushing to the release/<tag-name> branch. However, it's not clear how these committed changes are then reflected in the final GitHub Release. Does the developer need to manually copy the refined changelog from the branch to the GitHub Release draft?

Additionally, step 6 here says 'Merge the release branch...'. It would be helpful to specify the merge target for this branch (e.g., a version branch like v0.3), or confirm if it should be discarded after the release is published (as suggested on line 666). Clarifying the lifecycle and purpose of the release/<tag-name> branch would prevent confusion.

RELEASE.md Outdated

### Changelog Workflow

The release workflow automatically generates changelogs from `./CHANGELOG.md`:
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

To improve clarity, it would be helpful to explicitly state that CHANGELOG.md needs to be manually updated before the automated workflow is triggered by a tag push. This involves moving changes from [Unreleased] to a new version section. While this is mentioned in other parts of the document (e.g., line 246), adding it here would make the Changelog Workflow section self-contained and easier to follow.

Suggested change
The release workflow automatically generates changelogs from `./CHANGELOG.md`:
The release workflow starts with a manual update to `./CHANGELOG.md`, after which automation takes over:

@codecov
Copy link

codecov bot commented Jan 22, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 57.96%. Comparing base (66ac65a) to head (f91abaa).
⚠️ Report is 12 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2998      +/-   ##
==========================================
- Coverage   59.25%   57.96%   -1.30%     
==========================================
  Files         106      110       +4     
  Lines       10023    10526     +503     
==========================================
+ Hits         5939     6101     +162     
- Misses       3456     3774     +318     
- Partials      628      651      +23     
Flag Coverage Δ
combined 57.96% <ø> (-1.30%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment on lines +299 to +305
- name: Checkout code
uses: actions/checkout@v6
with:
ref: ${{ needs.create-release-branch.outputs.release-branch }}
fetch-depth: 0

- name: Generate changelog prompt

Check warning

Code scanning / CodeQL

Checkout of untrusted code in trusted context Medium

Potential unsafe checkout of untrusted pull request on privileged workflow.

Copilot Autofix

AI about 24 hours ago

Copilot could not generate an autofix suggestion

Copilot could not generate an autofix suggestion for this alert. Try pushing a new commit or if the problem persists contact support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants