Brazil's biggest MU Online portal — since 2003
Tutorial Intermediate Infrastructure

How to create an automatic changelog from Git for your MU Online server

Set up a pipeline that automatically generates changelogs from your MU Online server's Git commits, using Conventional Commits, semantic-release, and automatic publishing to the website and Discord.

GA Gabriel · Updated on Jul 31, 2026 · ⏱ 14 min read
Quick answer

Every MU Online server that evolves frequently — fixing bugs, balancing items, adding events — runs into the same communication problem: how do you let the community know what changed without relying on someone remembering to manually write a "news" post for every update? The answer is to automate t

Every MU Online server that evolves frequently — fixing bugs, balancing items, adding events — runs into the same communication problem: how do you let the community know what changed without relying on someone remembering to manually write a "news" post for every update? The answer is to automate the changelog from the Git history itself, using a commit message convention that a computer can parse. This tutorial shows how to adopt Conventional Commits, generate changelogs automatically with semantic-release, and publish those release notes to the website and Discord without repetitive manual work.

Why generate a changelog from Git

Writing a changelog by hand has two recurring problems: either it gets forgotten (nobody remembers to update it) or it becomes generic ("various fixes"). When the changelog is born from the commit history, every change already documented in the code automatically becomes a changelog entry, categorized by type (new feature, fix, breaking change). The team only needs to write a good commit message once — everything else is automatic.

The Conventional Commits standard

Every commit message follows a fixed format that describes the type of change and the affected scope:

<type>(<scope>): <short description>

<optional body with more details>

<optional footer, e.g. BREAKING CHANGE>
TypeWhen to useAppears in the changelog as
featNew feature (e.g. new event, new item)"New Features" section
fixBug fix"Fixes" section
perfPerformance improvement"Performance" section
docsDocumentation-only changeUsually omitted from the public changelog
choreMaintenance tasks with no player impactOmitted from the public changelog
feat! or BREAKING CHANGE footerBreaking changeHighlighted "Important Changes" section

Prerequisites

  • The server's Git repository (setup scripts, database, web panel) already under version control.
  • Node.js 18+ installed on the build/CI machine.
  • Write access to the repository and permissions to create releases (tags).
  • A CI pipeline configured (GitHub Actions, GitLab CI, or Gitea Actions).

Step 1 — Standardize commit messages

Install commitlint to validate messages before accepting a commit:

npm install --save-dev @commitlint/cli @commitlint/config-conventional husky
npx husky init
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg

Create the commitlint.config.js file:

module.exports = { extends: ['@commitlint/config-conventional'] };

From this point on, a commit like fixed drop bug will be rejected; the team needs to write something like fix(drop): fix jewel drop rate in Devil Square.

Step 2 — Install and configure semantic-release

npm install --save-dev semantic-release @semantic-release/changelog @semantic-release/git

.releaserc.json file:

{
  "branches": ["main"],
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/changelog",
    "@semantic-release/git"
  ]
}

The commit-analyzer decides whether the next version is a patch, minor, or major bump based on the commit types since the last release. The release-notes-generator builds the text; @semantic-release/changelog writes it to CHANGELOG.md; @semantic-release/git commits the updated changelog back to the repository.

Step 3 — Configure the CI pipeline

Example GitHub Actions workflow (.github/workflows/release.yml):

name: Release
on:
  push:
    branches: [main]
jobs:
  release:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: 18
      - run: npm ci
      - run: npx semantic-release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Every time a merge lands on the main branch, the pipeline analyzes the new commits, decides the version, generates the changelog, and creates the tag and release automatically.

Step 4 — Publish the changelog to the server's website

Add an extra pipeline step that sends the generated content to the website's content repository (or triggers a rebuild webhook), turning each release into a post on the portal's "News" page. This closes the loop: the developer only has to write a good commit message, and the player sees the news published with no manual intervention.

Step 5 — Automatically notify Discord

An additional workflow step can send the generated changelog to a Discord webhook, formatted as an embed, as soon as the release is published:

      - name: Notify Discord
        if: success()
        run: |
          curl -H "Content-Type: application/json" \
            -d "{\"content\": \"📦 New version published! Check out the changelog on the website.\"}" \
            ${{ secrets.DISCORD_WEBHOOK_URL }}

Categorizing changes that matter to players

Not every technical change is relevant to the end player. Split the changelog into two audiences:

AudienceWhat appearsWhere to publish
PlayersNew events, items, balance fixes, drop changesWebsite + Discord (announcements channel)
Technical teamRefactors, infrastructure changes, dependency updatesRepository's internal CHANGELOG.md

Use commit scopes (feat(event), fix(drop), chore(deps)) to automate this split with a simple filter in the publishing script.

Semantic versioning applied to the server

Adopt versions in the MAJOR.MINOR.PATCH format. A fix bumps the PATCH (e.g. 2.4.1 → 2.4.2), a feat bumps the MINOR (2.4.2 → 2.5.0), and a BREAKING CHANGE bumps the MAJOR (2.5.0 → 3.0.0) — for example, a database migration that requires a character reset or an incompatible change to the web panel's API.

Common errors and fixes

SymptomLikely causeSolution
Changelog isn't generatedCommits don't follow Conventional CommitsEnable commitlint as a mandatory hook
Pipeline fails to create the tagCI token lacks write permissionSet permissions: contents: write in the workflow
Version doesn't change between releasesNo feat/fix commits since the last releaseConfirm new commits use the correct type
Changelog full of technical noiseMissing separation by scope/typeFilter by type before publishing to website/Discord
Duplicate Discord notificationWorkflow triggering on multiple eventsRestrict on: to push on the release branch only

Release checklist

  • Conventional Commits adopted and validated by commitlint.
  • semantic-release configured with the changelog and git plugins.
  • CI pipeline creating tags and releases automatically.
  • Public (player-facing) changelog separated from the internal technical changelog.
  • Automatic website publishing tested end to end.
  • Discord notification configured and validated.
  • Semantic versioning documented for the team.

With the changelog automated, every update to your server becomes traceable and communicated with no manual effort — the natural next step is to connect this pipeline to the deployment process of the MU Online server, so that every published release also triggers an update of the production environment.

Frequently asked questions

Do I need to rewrite the commit history that already exists?

No. The automatic changelog starts applying from the moment you adopt the message convention (Conventional Commits). Older commits can be added manually to a 'History' section in the changelog, with no need to rewrite anything.

My team doesn't follow any commit convention today, can we migrate gradually?

Yes. Start by requiring the convention only on release branches or only for the core team, and use a commit hook (commitlint) to validate messages before they even reach the remote repository.

Can the generated changelog be published automatically on the server's website?

Yes, with an extra pipeline step that sends the generated changelog (in Markdown or JSON) to your website's API or writes it directly to the content repository, triggering a rebuild of the news page.

Does this work without GitHub Actions, using GitLab or a self-hosted Git server?

Yes, the concept (Conventional Commits + semantic-release) is platform-agnostic. GitLab CI and Gitea Actions have their own pipeline syntax, but the same Node.js packages (semantic-release, conventional-changelog) run the same way.

Is it worth it for a small server with just one person working on the code?

Yes, mainly for the discipline the commit convention enforces and the transparency the changelog gives players. Even working alone, you gain a readable history of technical decisions and a ready-made channel for communicating changes.

GA
Guides & builds editor

Gabriel covers gameplay, class builds, PvP and progression. He tests every strategy on a live server before publishing.

Keep reading

Related articles