<!-- Canonical: https://nitrozen.io/blog/automate-changelog-github-releases -->


# How to Automate Your Changelog from GitHub Releases

The hardest part of keeping a changelog isn't writing it; it's remembering to. If your team already publishes GitHub Releases, you have everything you need to keep a public changelog up to date without anyone opening another dashboard.

This guide walks through connecting GitHub Releases to a hosted changelog with the [Nitrozen GitHub Action](https://nitrozen.io/docs/github-action), plus tips for making automated entries read well.

## How it works

1. You publish a release in GitHub (manually, or from your release tooling).
2. GitHub fires the `release` event.
3. A workflow runs the Nitrozen action, which creates a changelog entry from the release's name and body.
4. The entry appears on your public changelog page and in-app widget.

GitHub documents the `release` event and its activity types, including `published`, in [Events that trigger workflows](https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#release).

## What you need

- A GitHub repository where you publish releases.
- A [Nitrozen](https://nitrozen.io) account and project (the free plan works for trying this).
- A Nitrozen API key and your project ID, from the dashboard.

## Step 1: store your API key as a secret

Never paste API keys into workflow files. In your repository, go to **Settings → Secrets and variables → Actions** and add a repository secret named `NITROZEN_API_KEY`. GitHub explains the options in [Using secrets in GitHub Actions](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions).

## Step 2: add the workflow

Create `.github/workflows/changelog.yml`:

```yaml
name: Publish changelog

on:
  release:
    types: [published]

jobs:
  changelog:
    runs-on: ubuntu-latest
    steps:
      - uses: nitrozenio/changelog-action@v1
        with:
          api-key: ${{ secrets.NITROZEN_API_KEY }}
          project-id: '123'
```

Replace `123` with your project ID. That's the whole integration: the entry's title and content default to the release's name (or tag) and body. The action is a composite action, so there's no build step or dependency install. See the [action's documentation](https://nitrozen.io/docs/github-action) for optional inputs, and the source on [GitHub](https://github.com/nitrozenio/changelog-action).

## Step 3: publish a release

Create a release from **Releases → Draft a new release**, write the notes and click **Publish release**. Watch the workflow run in the **Actions** tab, then check your changelog page.

Using `published` (rather than `created`) means drafts don't trigger the workflow, so you can prepare notes in a draft and publish when ready.

## Make automated entries read well

Automation moves text; it doesn't make it customer-friendly. The release body becomes your public entry, so write it for users:

- **Title the release by benefit**, e.g. "v2.4: Scheduled exports" rather than just "v2.4.0".
- **Open with one or two plain sentences** describing what users can do now.
- **Group the rest** under headings like New, Improvement and Fix.
- **Remove internal noise** such as PR numbers, contributor handles and dependency bumps that users don't care about.

GitHub's [automatically generated release notes](https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes) list merged pull requests and contributors. They're a good starting draft; you can also configure categories with a `.github/release.yml` file and exclude labels such as `dependencies`. Edit the summary at the top before publishing.

For a deeper guide on wording, see [how to write a changelog users actually read](https://nitrozen.io/blog/how-to-write-a-changelog).

## Internal releases you don't want public

Not every release deserves a public entry. Options:

- Only publish releases for your customer-facing repository.
- Skip pre-releases with a condition on the job, for example `if: github.event.release.prerelease == false`. (`prerelease` is part of the release event payload GitHub sends.)
- Keep internal tooling releases in separate repositories without the workflow.

## Other ways to automate

GitHub Releases aren't the only trigger. Nitrozen also offers:

- A [REST API](https://nitrozen.io/docs/api) for any CI system (GitLab CI, Bitbucket Pipelines, Jenkins).
- SDKs for [Node.js](https://nitrozen.io/docs/node-sdk), [Python](https://nitrozen.io/docs/python-sdk) and [Go](https://nitrozen.io/docs/go-sdk) if you want to post entries from your own deploy scripts.
- A [Terraform provider](https://nitrozen.io/docs/terraform) for managing projects as code.
- An [MCP server](https://nitrozen.io/docs/mcp) so assistants like Claude or Cursor can draft and publish entries from a conversation, which is handy for turning a list of merged PRs into a readable summary.

## Troubleshooting

- **Workflow didn't run:** check the trigger is `release` with `types: [published]`, and that the workflow file is on the default branch.
- **Authentication error:** confirm the secret name matches exactly and the key hasn't been revoked.
- **Entry went to the wrong project:** double-check the `project-id` value.
- **Duplicate entries:** make sure only one workflow listens for releases.

## FAQ

**Does this work with semantic-release or release-please?** Yes, if those tools publish a GitHub Release, the `release` event fires and the workflow runs.

**Can I edit an entry after it's published?** Yes, in the Nitrozen dashboard or through the API.

## Set it up in five minutes

Create a free [Nitrozen](https://nitrozen.io) project, add the secret and workflow above, and your next GitHub Release becomes a public changelog entry automatically.
