Skip to main content

Overview

HelixCommit integrates seamlessly with CI/CD platforms to automate release note generation. Whether you’re using GitHub Actions, GitLab CI, Jenkins, or another platform, you can generate release notes automatically on every release.

GitHub Actions

Native integration with GitHub’s CI/CD platform

GitLab CI

Automated pipelines for GitLab repositories

Jenkins

Flexible integration with Jenkins pipelines

CircleCI

Cloud-based CI/CD automation

GitHub Actions

Basic workflow

Automatically generate release notes when creating a release:
.github/workflows/release-notes.yml
name: Generate Release Notes

on:
  release:
    types: [created]

jobs:
  generate-notes:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # Full history for tags
      
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      
      - name: Install HelixCommit
        run: pip install helixcommit
      
      - name: Generate release notes
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          helixcommit generate \
            --unreleased \
            --format markdown \
            --out RELEASE_NOTES.md
      
      - name: Update release
        uses: softprops/action-gh-release@v1
        with:
          body_path: RELEASE_NOTES.md
GitHub Actions automatically provides GITHUB_TOKEN with appropriate permissions. No need to create a separate token!

With AI summarization

Add AI-powered summaries to your release notes:
.github/workflows/release-notes-ai.yml
name: Generate AI Release Notes

on:
  release:
    types: [created]

jobs:
  generate-notes:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      
      - name: Install HelixCommit
        run: pip install helixcommit
      
      - name: Generate AI-powered release notes
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          helixcommit generate \
            --unreleased \
            --use-llm \
            --openai-model gpt-4o-mini \
            --format markdown \
            --out RELEASE_NOTES.md
      
      - name: Update release
        uses: softprops/action-gh-release@v1
        with:
          body_path: RELEASE_NOTES.md
Add OPENAI_API_KEY to your repository secrets at Settings → Secrets and variables → Actions

With caching

Speed up subsequent runs with caching:
.github/workflows/release-notes-cached.yml
name: Generate Release Notes (Cached)

on:
  release:
    types: [created]

jobs:
  generate-notes:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      
      - name: Cache HelixCommit data
        uses: actions/cache@v3
        with:
          path: .helixcommit-cache
          key: helixcommit-${{ github.sha }}
          restore-keys: |
            helixcommit-
      
      - name: Install HelixCommit
        run: pip install helixcommit
      
      - name: Generate release notes
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          HELIXCOMMIT_GH_CACHE: 1
        run: |
          helixcommit generate \
            --unreleased \
            --format markdown \
            --out RELEASE_NOTES.md
      
      - name: Update release
        uses: softprops/action-gh-release@v1
        with:
          body_path: RELEASE_NOTES.md

On tag push

Generate notes when pushing a new tag:
.github/workflows/release-on-tag.yml
name: Release on Tag

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'
      
      - name: Install HelixCommit
        run: pip install helixcommit
      
      - name: Get previous tag
        id: previoustag
        run: echo "tag=$(git describe --tags --abbrev=0 HEAD^)" >> $GITHUB_OUTPUT
      
      - name: Generate release notes
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          helixcommit generate \
            --since-tag ${{ steps.previoustag.outputs.tag }} \
            --until-tag ${{ github.ref_name }} \
            --format markdown \
            --out RELEASE_NOTES.md
      
      - name: Create GitHub Release
        uses: softprops/action-gh-release@v1
        with:
          tag_name: ${{ github.ref_name }}
          name: Release ${{ github.ref_name }}
          body_path: RELEASE_NOTES.md

GitLab CI

Basic pipeline

.gitlab-ci.yml
generate_release_notes:
  stage: release
  image: python:3.11
  only:
    - tags
  script:
    - pip install helixcommit
    - |
      helixcommit generate \
        --since-tag $(git describe --tags --abbrev=0 HEAD^) \
        --until-tag $CI_COMMIT_TAG \
        --format markdown \
        --out RELEASE_NOTES.md
  artifacts:
    paths:
      - RELEASE_NOTES.md
    expire_in: 1 week

With GitHub integration

.gitlab-ci.yml
generate_release_notes:
  stage: release
  image: python:3.11
  only:
    - tags
  variables:
    GITHUB_TOKEN: $GITHUB_TOKEN
  script:
    - pip install helixcommit
    - |
      helixcommit generate \
        --since-tag $(git describe --tags --abbrev=0 HEAD^) \
        --until-tag $CI_COMMIT_TAG \
        --format markdown \
        --format html \
        --out RELEASE_NOTES.md
    - |
      helixcommit generate \
        --since-tag $(git describe --tags --abbrev=0 HEAD^) \
        --until-tag $CI_COMMIT_TAG \
        --format html \
        --out RELEASE_NOTES.html
  artifacts:
    paths:
      - RELEASE_NOTES.md
      - RELEASE_NOTES.html

With AI features

.gitlab-ci.yml
generate_ai_release_notes:
  stage: release
  image: python:3.11
  only:
    - tags
  variables:
    OPENAI_API_KEY: $OPENAI_API_KEY
    GITHUB_TOKEN: $GITHUB_TOKEN
  script:
    - pip install helixcommit
    - |
      helixcommit generate \
        --unreleased \
        --use-llm \
        --openai-model gpt-4o-mini \
        --format markdown \
        --out RELEASE_NOTES.md
  artifacts:
    paths:
      - RELEASE_NOTES.md
  cache:
    key: helixcommit-cache
    paths:
      - .helixcommit-cache/

Jenkins

Declarative pipeline

Jenkinsfile
pipeline {
    agent any
    
    environment {
        GITHUB_TOKEN = credentials('github-token')
        OPENAI_API_KEY = credentials('openai-api-key')
    }
    
    stages {
        stage('Setup') {
            steps {
                sh 'pip install helixcommit'
            }
        }
        
        stage('Generate Release Notes') {
            when {
                tag pattern: "v\\d+\\.\\d+\\.\\d+", comparator: "REGEXP"
            }
            steps {
                script {
                    def previousTag = sh(
                        script: 'git describe --tags --abbrev=0 HEAD^',
                        returnStdout: true
                    ).trim()
                    
                    sh """
                        helixcommit generate \
                            --since-tag ${previousTag} \
                            --until-tag ${env.TAG_NAME} \
                            --format markdown \
                            --out RELEASE_NOTES.md
                    """
                }
            }
        }
        
        stage('Publish') {
            steps {
                archiveArtifacts artifacts: 'RELEASE_NOTES.md'
            }
        }
    }
}

Scripted pipeline

Jenkinsfile
node {
    checkout scm
    
    stage('Install') {
        sh 'pip install helixcommit'
    }
    
    stage('Generate Notes') {
        withCredentials([string(credentialsId: 'github-token', variable: 'GITHUB_TOKEN')]) {
            sh '''
                helixcommit generate \
                    --unreleased \
                    --format markdown \
                    --out RELEASE_NOTES.md
            '''
        }
    }
    
    stage('Archive') {
        archiveArtifacts 'RELEASE_NOTES.md'
    }
}

CircleCI

.circleci/config.yml
version: 2.1

jobs:
  generate-release-notes:
    docker:
      - image: python:3.11
    steps:
      - checkout
      - run:
          name: Install HelixCommit
          command: pip install helixcommit
      - run:
          name: Generate release notes
          command: |
            helixcommit generate \
              --unreleased \
              --format markdown \
              --out RELEASE_NOTES.md
      - store_artifacts:
          path: RELEASE_NOTES.md

workflows:
  release:
    jobs:
      - generate-release-notes:
          filters:
            tags:
              only: /^v.*/
            branches:
              ignore: /.*/

Travis CI

.travis.yml
language: python
python:
  - "3.11"

install:
  - pip install helixcommit

script:
  - |
    if [ -n "$TRAVIS_TAG" ]; then
      helixcommit generate \
        --since-tag $(git describe --tags --abbrev=0 HEAD^) \
        --until-tag $TRAVIS_TAG \
        --format markdown \
        --out RELEASE_NOTES.md
    fi

deploy:
  provider: releases
  api_key: $GITHUB_TOKEN
  file: RELEASE_NOTES.md
  skip_cleanup: true
  on:
    tags: true

Bitbucket Pipelines

bitbucket-pipelines.yml
pipelines:
  tags:
    v*:
      - step:
          name: Generate Release Notes
          image: python:3.11
          script:
            - pip install helixcommit
            - export PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^)
            - |
              helixcommit generate \
                --since-tag $PREVIOUS_TAG \
                --until-tag $BITBUCKET_TAG \
                --format markdown \
                --out RELEASE_NOTES.md
          artifacts:
            - RELEASE_NOTES.md

Best practices

Cache AI-generated summaries to reduce costs:
- name: Cache summaries
  uses: actions/cache@v3
  with:
    path: .helixcommit-cache
    key: summaries-${{ github.sha }}
    restore-keys: summaries-
Handle cases with no changes:
helixcommit generate \
  --unreleased \
  --fail-on-empty || echo "No changes to release"
Create notes in multiple formats for different uses:
- name: Generate all formats
  run: |
    helixcommit generate --unreleased --format markdown --out notes.md
    helixcommit generate --unreleased --format html --out notes.html
    helixcommit generate --unreleased --format text --out notes.txt
- name: Generate release notes
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    HELIXCOMMIT_GH_CACHE: 1
    HELIXCOMMIT_GH_MAX_RETRIES: 5
  run: |
    helixcommit generate --unreleased --out RELEASE_NOTES.md
# Generate notes
helixcommit generate --unreleased --out RELEASE_NOTES.md

# Validate content exists
if [ ! -s RELEASE_NOTES.md ]; then
  echo "Error: Release notes are empty"
  exit 1
fi

# Check for required sections
if ! grep -q "## Release" RELEASE_NOTES.md; then
  echo "Error: Invalid release notes format"
  exit 1
fi

Secrets management

GitHub Actions

Add secrets at: Repository Settings → Secrets and variables → Actions
env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}  # Provided automatically
  OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}  # Add manually
  OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}  # Add manually

GitLab CI

Add variables at: Project Settings → CI/CD → Variables
variables:
  GITHUB_TOKEN: $GITHUB_TOKEN
  OPENAI_API_KEY: $OPENAI_API_KEY

Jenkins

Use Jenkins credentials:
withCredentials([
  string(credentialsId: 'github-token', variable: 'GITHUB_TOKEN'),
  string(credentialsId: 'openai-key', variable: 'OPENAI_API_KEY')
]) {
  // Your script here
}

Troubleshooting

Ensure you fetch full history:
- uses: actions/checkout@v4
  with:
    fetch-depth: 0  # Important: fetch all history and tags
Install Python in your CI environment:
- name: Set up Python
  uses: actions/setup-python@v5
  with:
    python-version: '3.11'
Add required permissions:
jobs:
  release:
    permissions:
      contents: write  # Required to update releases
Enable caching and use authentication:
env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  HELIXCOMMIT_GH_CACHE: 1

Complete example

Here’s a production-ready workflow with all best practices:
.github/workflows/release.yml
name: Generate and Publish Release Notes

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      
    steps:
      - name: Checkout code
        uses: actions/checkout@v4
        with:
          fetch-depth: 0
      
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'
          cache: 'pip'
      
      - name: Cache HelixCommit data
        uses: actions/cache@v3
        with:
          path: .helixcommit-cache
          key: helixcommit-${{ github.sha }}
          restore-keys: gitrelease-
      
      - name: Install GitReleaseGen
        run: pip install gitreleasegen
      
      - name: Get previous tag
        id: previoustag
        run: |
          PREVIOUS=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
          echo "tag=${PREVIOUS}" >> $GITHUB_OUTPUT
      
      - name: Generate release notes
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
          GITRELEASEGEN_GH_CACHE: 1
        run: |
          if [ -n "${{ steps.previoustag.outputs.tag }}" ]; then
            SINCE_FLAG="--since-tag ${{ steps.previoustag.outputs.tag }}"
          else
            SINCE_FLAG=""
          fi
          
          if [ -n "$OPENAI_API_KEY" ]; then
            gitreleasegen generate \
              $SINCE_FLAG \
              --until-tag ${{ github.ref_name }} \
              --use-llm \
              --openai-model gpt-4o-mini \
              --format markdown \
              --out RELEASE_NOTES.md
          else
            gitreleasegen generate \
              $SINCE_FLAG \
              --until-tag ${{ github.ref_name }} \
              --format markdown \
              --out RELEASE_NOTES.md
          fi
      
      - name: Validate release notes
        run: |
          if [ ! -s RELEASE_NOTES.md ]; then
            echo "Error: Release notes are empty"
            exit 1
          fi
      
      - name: Create GitHub Release
        uses: softprops/action-gh-release@v1
        with:
          tag_name: ${{ github.ref_name }}
          name: Release ${{ github.ref_name }}
          body_path: RELEASE_NOTES.md
          draft: false
          prerelease: false
      
      - name: Upload release notes
        uses: actions/upload-artifact@v4
        with:
          name: release-notes-${{ github.ref_name }}
          path: RELEASE_NOTES.md

Next steps

Examples

See more CI/CD integration examples

Configuration

Advanced configuration options

GitHub integration

Set up GitHub API authentication

AI features

Add AI-powered summaries