towncrier

repository·trunk·Indexed 21 days ago

https://github.com/twisted/towncrier

A utility for generating user-facing changelogs by aggregating small, individual news fragments instead of parsing raw Git history. It supports reStructuredText and Markdown formats, custom fragment types, and monorepo configurations. Key commands include `build` for aggregating fragments into a news file, `create` for generating new fragments, and `check` for verifying fragments in feature branches.

Tokens
9.2K
Snippets
32
Records
41
Agent score
71%

What's inside towncrier

  1. What is towncrier?

    trunk

    towncrier is a utility designed to produce summarized news files (changelogs) for your project. Instead of parsing Git history or maintaining a single monolithic changelog file that causes merge conflicts, it aggregates information from individual "news fragments" (also known as "topfiles" or "newsfiles").

    These fragments are small files created by developers that contain only the information useful to end users, effectively separating the technical developer log from the user-facing news digest.

  2. How to split news into multiple sections

    trunk

    You can split news fragments into different sections (e.g., 'Main Platform' and 'Secondary') using the [[tool.towncrier.section]] array of tables. Each section requires a name and a path (relative to the configured directory).

    Path Behavior:

    • If directory is not set: The section path is appended to newsfragments. Example: path = "secondary" becomes ./newsfragments/secondary.
    • If directory is set: The section path is appended to that directory. Example: directory = "changes" and path = "secondary" becomes ./changes/secondary.
    [[tool.towncrier.section]]
    name = "Main Platform"
    path = ""
    
    [[tool.towncrier.section]]
    name = "Secondary"
    path = "secondary"
  3. Provide a version to towncrier

    trunk

    Towncrier requires a version number to generate news files. You can provide it using the following methods (in order of precedence):

    1. CLI Flag: Pass --version=<version> directly to the command.
    2. Config File: Set the version option in your configuration file.
    3. Python Metadata: For projects with a package key configured, towncrier can use the installed package's metadata or a __version__ string/tuple/Incremental object in the top-level package.
    towncrier build --version=1.2.3post4
  4. Define custom fragment types

    trunk

    Towncrier provides default types: feature, bugfix, doc, removal, and misc. You can define custom types using two methods:

    Method 1: TOML Tables (Alphabetical Order)

    Use [tool.towncrier.fragment.<type>]. Types are rendered in alphabetical order.

    • name: Description used in the news file (defaults to capitalized type).
    • showcontent: Boolean, whether to include fragment content (default true).
    • check: Boolean, whether towncrier check validates this type (default true).

    Method 2: TOML Array (Defined Order)

    Use [[tool.towncrier.type]]. This allows you to control the order of types. Do not use this method if you are also using the fragment table method.

    • name (Required): The description used in the news file.
    • directory: The directory/category of the fragment (defaults to name.lower()).
    • showcontent: Boolean, whether to include content (default true).
    • check: Boolean, whether towncrier check validates this type (default true).
    # Example using Tables (Alphabetical)
    [tool.towncrier.fragment.feat]
    [tool.towncrier.fragment.fix]
    
    [tool.towncrier.fragment.chore]
    name = "Other Tasks"
    showcontent = false
    
    # Example using Array (Ordered)
    [[tool.towncrier.type]]
    name = "Deprecations"
    
    [[tool.towncrier.type]]
    directory = "chore"
    name = "Other Tasks"
    showcontent = false
  5. Use towncrier with any project type

    trunk
    While the towncrier command line tool requires Python to run, it is platform-agnostic and can be used with any project type. To ensure compatibility with non-Python projects, avoid using Python-specific features such as the automatic detection of the project version.
  6. Add content above the towncrier news file output

    trunk

    By default, towncrier appends or manages content within the news file. If you want to include static content (such as links to issue trackers or project descriptions) at the top of your news file, you can use a special marker comment. towncrier will only update content that appears after this marker, leaving everything above it untouched.

    Depending on your news file format, use the appropriate marker syntax:

    ### For reStructuredText (.rst)
    
    .. towncrier release notes start
    
    ### For Markdown (.md)
    
    <!-- towncrier release notes start -->
  7. Integrate towncrier with pre-commit

    trunk

    You can use towncrier within a pre-commit configuration (.pre-commit-config.yaml) to automate checking or updating news fragments during commits or CI processes. The hook automatically detects your existing towncrier configuration files; no additional setup is required within towncrier itself.

    repos:
      - repo: https://github.com/twisted/towncrier
        rev: 23.11.0
        hooks:
          - id: towncrier-check
  8. Create news fragments

    trunk

    News fragments are categorized by 'type'. The default types are:

    • feature: New features.
    • bugfix: Bug fixes.
    • doc: Documentation improvements.
    • removal: Deprecation or removal of public API.
    • misc: Closed issues not of interest to users.

    Fragment Naming

    Fragments are identified by a filename containing a unique ID (like an issue number) and the type (e.g., 1234.bugfix). The file extension is ignored.

    Orphan Fragments: To create a fragment without an issue ID, prefix the filename with + (e.g., +random.bugfix.rst). These appear at the end of their category.

    Commands

    • Manual creation: Create a file in your fragments directory.
    • towncrier create: Use this command to generate fragments.
    • towncrier create --edit: Opens your editor to write the fragment content.
    # Create a bugfix fragment manually
    echo 'Fixed a thing!' > src/myproject/newsfragments/1234.bugfix
    
    # Create a doc fragment using the CLI
    towncrier create --content 'Can also be rst as well!' 3456.doc.rst
    
    # Create an orphan fragment
    echo 'Fixed an unreported thing!' > src/myproject/newsfragments/+anything.bugfix
    
    # Create and edit a fragment
    towncrier create --edit 2.misc.rst
  9. Configure towncrier for a monorepo with multiple projects

    trunk

    When managing multiple independent projects within a single repository (a monorepo), you can use a single towncrier.toml file to manage all of them.

    To achieve this, you must leave the package and name configuration fields empty in towncrier.toml. This is because these fields can only hold one value, and in a monorepo, each project has its own package name and identity. Instead of relying on the config file for project identity, you must specify the project directory using the --dir flag during CLI operations.

    Example Directory Structure:

    repo
    ├── project_a
    │   ├── newsfragments
    │   │   └── 123.added
    │   ├── project_a
    │   │   └── __init__.py
    │   └── NEWS.rst
    ├── project_b
    │   ├── newsfragments
    │   │   └── 120.bugfix
    │   ├── project_b
    │   │   └── __init__.py
    │   └── NEWS.rst
    └── towncrier.toml

    towncrier.toml configuration:

    [tool.towncrier]
    # It's important to keep these config fields empty
    # because we have more than one package/name to manage.
    package = ""
    name = ""
    [tool.towncrier]
    package = ""
    name = ""
  10. Create and build Markdown news fragments

    trunk

    Follow these steps to manage a Markdown changelog:

    1. Initialize the fragment directory: Create the directory specified in your configuration (e.g., mkdir changelog.d).
    2. Initialize the changelog file: Create CHANGELOG.md with an explanatory header and include the start_string marker defined in your config.
    3. Create news fragments: Use the towncrier create command to add individual changes. The filename suffix (e.g., .added.md, .fixed.md) determines which section the fragment will appear under.
    4. Build the changelog: Run towncrier build with the --version flag to aggregate all fragments into the main changelog file.

    Example Workflow:

    # Create fragments
    towncrier create -c "Added a cool feature!" 1.added.md
    towncrier create -c "Fixed a bug!" 5.fixed.md
    
    # Build the changelog for version 1.0.0
    towncrier build --yes --version 1.0.0
    towncrier create -c "Added a cool feature!" 1.added.md
    towncrier create -c "Changed a behavior!" 2.changed.md
    towncrier create -c "Deprecated a module!" 3.deprecated.md
    towncrier create -c "Removed a square feature!" 4.removed.md
    towncrier create -c "Fixed a bug!" 5.fixed.md
    towncrier create -c "Fixed a security issue!" 6.security.md
    towncrier create -c "Fixed a security issue!" 7.security.md
    towncrier create -c "A fix without an issue number!" +something-unique.fixed.md
    
    towncrier build --yes --version 1.0.0
  11. Generate news files for production

    trunk

    To generate the actual news file, run the towncrier command. This command:

    1. Removes old news files using git rm.
    2. Appends the new news to the configured filename.
    3. Stages the changes using git add.

    Adding persistent header content

    If you want to keep text (like links to issue trackers) at the top of your news file, place it above a specific comment marker. Towncrier will preserve everything above this marker.

    • For reStructuredText (.rst): Use .. towncrier release notes start
    • For Markdown (.md): Use <!-- towncrier release notes start -->
    towncrier