Skip to content

feat(changelog): Add changelog.output_dir configuration option#1406

Open
bilelomrani1 wants to merge 4 commits intopython-semantic-release:masterfrom
bilelomrani1:feat/changelog-output-dir
Open

feat(changelog): Add changelog.output_dir configuration option#1406
bilelomrani1 wants to merge 4 commits intopython-semantic-release:masterfrom
bilelomrani1:feat/changelog-output-dir

Conversation

@bilelomrani1
Copy link

@bilelomrani1 bilelomrani1 commented Jan 2, 2026

Purpose

This PR adds a new changelog.output_dir configuration option that allows users to specify the destination directory for changelog output.

This feature is particularly valuable for monorepo setups where PSR runs from a package subdirectory but needs to write changelogs to a consolidated documentation directory, and also when users use shared remote templates (see #1404) across multiple projects but still want fine grained control over where the changelog is written.

Rationale

In monorepo environments, users often want to:

  • Run PSR from a package directory (e.g., packages/pkg1/)
  • Write changelogs to a centralized docs folder (e.g., docs/source/pkg1/changelog.md)

Before this PR, achieving this required complex shell scripts to copy/move changelog files. The previous monorepo documentation reflected this complexity, requiring users to understand intricate template customization just to place changelogs in a different directory.

The new output_dir option provides a simple way to specify the changelog destination:

# packages/pkg1/pyproject.toml
[tool.semantic_release.changelog]
output_dir = "../../docs/source/pkg1"

This single line replaces what previously required custom templates and shell scripts. The Advanced Example in the monorepo documentation has been completely rewritten to use output_dir, reducing complexity significantly while enabling the same (and more) functionality.

Bug Fix: Custom Templates Now Render to CWD

This PR also fixes an inconsistency when using custom template directories from a subdirectory.

Before:

# changelog_writer.py
project_dir = Path(runtime_ctx.repo_dir)  # Always repo root
...
destination_dir=project_dir  # Hardcoded to repo root

After:

# changelog_writer.py
output_dir = runtime_ctx.output_dir  # Resolved from "." relative to CWD
...
destination_dir=output_dir  # Respects CWD

The old behavior was inconsistent: when running from a subdirectory (e.g., packages/pkg1/), template_dir was resolved relative to CWD, but destination_dir was always hardcoded to the repository root. This caused templates to be read from the subdirectory but output to be written to the repo root.

With this fix, both template reading and output writing are consistent: relative to CWD when output_dir="." (default), or to the explicitly configured output_dir. I'm expecting this to be related to #845, and could potentially fix it.

How did you test?

Unit Tests (tests/unit/semantic_release/cli/test_config.py)

  • test_output_dir_default_resolves_to_repo_root - Default behavior
  • test_output_dir_inside_repo_accepted - Valid paths accepted
  • test_output_dir_outside_repo_rejected - Security: paths outside repo rejected
  • test_output_dir_with_parent_traversal_rejected - Security: path traversal blocked
  • test_output_dir_and_changelog_file_with_dir_rejected - Ambiguous config rejected
  • test_output_dir_with_bare_changelog_filename_from_subdirectory_accepted - Monorepo scenario works

End-to-End Tests (tests/e2e/cmd_changelog/test_changelog.py)

  • test_changelog_generated_in_output_dir - Changelog written to specified directory
  • test_changelog_update_mode_reads_from_output_dir - Update mode reads existing changelog from correct location
  • test_changelog_file_with_directory_component_backward_compatibility - Existing changelog_file with directory component still works

Backward Compatibility

  • Existing configurations with changelog_file = "docs/CHANGELOG.md" (directory component) continue to work unchanged
  • The validation only triggers when output_dir is explicitly set alongside a changelog_file with directory component

How to Verify

  1. Basic usage: Set output_dir in config and run semantic-release changelog

    [tool.semantic_release.changelog]
    output_dir = "docs"

    Verify changelog is written to docs/CHANGELOG.md

  2. Monorepo scenario: From a package subdirectory with:

    [tool.semantic_release.changelog]
    output_dir = "../../docs/source/pkg1"

    Run semantic-release changelog and verify output location

  3. Update mode: Create an existing changelog in output_dir, run with mode = "update", verify it reads and updates the correct file

  4. Backward compatibility: Existing config with changelog_file = "docs/CHANGELOG.md" (no output_dir) should continue working


PR Completion Checklist

  • Reviewed & followed the Contributor Guidelines

  • Changes Implemented & Validation pipeline succeeds

  • Commits follow the Conventional Commits standard
    and are separated into the proper commit type and scope (recommended order: test, build, feat/fix, docs)

  • Appropriate Unit tests added/updated

  • Appropriate End-to-End tests added/updated

  • Appropriate Documentation added/updated and syntax validated for sphinx build (see Contributor Guidelines)

@bilelomrani1 bilelomrani1 force-pushed the feat/changelog-output-dir branch from 13cba46 to c23985e Compare January 2, 2026 03:46
@bilelomrani1 bilelomrani1 changed the title Add changelog.output_dir configuration option feat(changelog): Add changelog.output_dir configuration option Jan 2, 2026
@bilelomrani1
Copy link
Author

Just a note: this adds a changelog.output_dir configuration option, which is useful for monorepos where changelogs need to be written at the package root rather than the repository root.

It's a small, self-contained feature that shouldn't conflict with the v11 refactoring. See #1407 for the broader context on my use case. No rush on the review.

@bilelomrani1 bilelomrani1 force-pushed the feat/changelog-output-dir branch from c23985e to 9387cab Compare January 10, 2026 09:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant