If you've ever updated a dependency and wondered "Wait, what changed?", you know the pain of packages without proper changelogs. Let's talk about why changelogs matter for Swift Package Manager (SPM) projects and how to write one that developers will actually appreciate.
The Problem
You're maintaining an iOS app that depends on several Swift packages. One releases version 2.0. Should you update? What changed? Will it break your code? You dig through commits, scan PRs, and eventually just... hope for the best.
This is exactly why changelogs exist.
What is a CHANGELOG?
A CHANGELOG is a file (CHANGELOG.md
) that documents all notable changes to your package in a human-readable format. It answers one crucial question: "What's different?"
Why It Matters
For Package Users:
- Decision Making: Should I update now or wait?
- Migration Planning: What do I need to change in my code?
- Feature Discovery: Oh, they added that feature I needed!
For Package Maintainers:
- Communication: Clear way to announce changes
- Documentation: Historical record of decisions
- Professionalism: Shows you care about your users
The Standard Format: Keep a Changelog
The iOS/Swift community uses the Keep a Changelog format:
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Dark mode support for all UI components
- New `fetchUserProfile()` async method
### Changed
- Updated minimum iOS version to 15.0
## [2.1.0] - 2025-03-15
### Added
- SwiftUI previews for all public views
- Comprehensive error handling
### Fixed
- Memory leak in image caching layer
- Crash when network request times out
### Security
- Updated dependencies to patch CVE-2025-1234
## [2.0.0] - 2025-02-20
### Changed
- **BREAKING**: Renamed `NetworkManager` to `APIClient`
- **BREAKING**: All completion handlers replaced with async/await
### Removed
- Deprecated iOS 13 support
### Added
- Full async/await support
- Improved error messages
The Six Categories
Added - New features, APIs, or capabilities
### Added
- New `Logger` class for debugging
Changed - Modifications to existing functionality
### Changed
- Improved performance of data parsing (2x faster)
Deprecated - Features that will be removed soon
### Deprecated
- `oldMethod()` - Use `newMethod()` instead. Will be removed in 3.0.0
Removed - Features that are gone
### Removed
- iOS 12 support
Fixed - Bug fixes
### Fixed
- Crash when array is empty
Security - Security patches
### Security
- Fixed potential XSS vulnerability
Practical Workflow
Step 1: Create the File
Add CHANGELOG.md
to your package root, next to Package.swift
.
Step 2: Add to Unreleased
Every time you make a change, add it under [Unreleased]
:
## [Unreleased]
### Fixed
- Fixed typo in error message
Step 3: Release Process
When ready to release:
- Move
[Unreleased]
changes to a new version section - Add the release date
- Create a git tag matching the version
## [Unreleased]
## [1.2.0] - 2025-03-20
### Fixed
- Fixed typo in error message
Semantic Versioning
Your changelog works with semantic versioning (SemVer):
Version Format: MAJOR.MINOR.PATCH
- MAJOR (2.0.0): Breaking changes
- MINOR (1.5.0): New features, backward compatible
- PATCH (1.4.1): Bug fixes, backward compatible
Common Mistakes to Avoid
❌ Don't Do This:
### Changed
- Bug fixes and improvements
- Various updates
✅ Do This Instead:
### Fixed
- Fixed crash when user profile image is missing
- Resolved memory leak in WebSocket connection
Be specific! Vague entries help nobody.
Pro Tips
Link to Issues and PRs:
### Fixed
- Fixed memory leak in image cache ([#123](link-to-issue))
Add Migration Guides for Breaking Changes:
## [2.0.0] - 2025-03-20
### Changed
- **BREAKING**: Replaced completion handlers with async/await
### Migration Guide
Before:
client.fetch { result in }
After:
let data = try await client.fetch()
Tag Your Releases:
git tag -a v1.2.0 -m "Release 1.2.0"
git push origin v1.2.0
Getting Started Today
Here's a minimal template:
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [1.0.0] - 2025-03-20
### Added
- Initial release
- Core networking functionality
- Authentication support
Copy this, replace the content, and you're done!
Take away
A good changelog takes just a few extra minutes per release, but saves hours of confusion for your users.
Top comments (1)
A CHANGELOG is a file (CHANGELOG.md) that documents all notable changes to your package in a human-readable format.