{"id":26883953,"url":"https://github.com/colin-b/keepachangelog","last_synced_at":"2025-04-07T18:11:40.564Z","repository":{"id":40298261,"uuid":"240946215","full_name":"Colin-b/keepachangelog","owner":"Colin-b","description":"Convert keep a changelog markdown file into python dict","archived":false,"fork":false,"pushed_at":"2025-01-14T16:27:20.000Z","size":150,"stargazers_count":48,"open_issues_count":6,"forks_count":17,"subscribers_count":2,"default_branch":"develop","last_synced_at":"2025-03-30T13:36:47.750Z","etag":null,"topics":["changelog","changelog-parser","markdown"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Colin-b.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-02-16T18:49:31.000Z","updated_at":"2025-02-16T08:45:57.000Z","dependencies_parsed_at":"2024-03-31T06:32:53.138Z","dependency_job_id":"215fa69f-d182-4020-b2e6-47b499f34448","html_url":"https://github.com/Colin-b/keepachangelog","commit_stats":{"total_commits":77,"total_committers":6,"mean_commits":"12.833333333333334","dds":"0.23376623376623373","last_synced_commit":"da7e1f60261557ea65d121df0d6adc1cb23c6dbd"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Colin-b%2Fkeepachangelog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Colin-b%2Fkeepachangelog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Colin-b%2Fkeepachangelog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Colin-b%2Fkeepachangelog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Colin-b","download_url":"https://codeload.github.com/Colin-b/keepachangelog/tar.gz/refs/heads/develop","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247704571,"owners_count":20982298,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["changelog","changelog-parser","markdown"],"created_at":"2025-03-31T17:37:51.704Z","updated_at":"2025-04-07T18:11:40.543Z","avatar_url":"https://github.com/Colin-b.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch2 align=\"center\"\u003eManipulate keep a changelog files\u003c/h2\u003e\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://pypi.org/project/keepachangelog/\"\u003e\u003cimg alt=\"pypi version\" src=\"https://img.shields.io/pypi/v/keepachangelog\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/Colin-b/keepachangelog/actions\"\u003e\u003cimg alt=\"Build status\" src=\"https://github.com/Colin-b/keepachangelog/workflows/Release/badge.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/Colin-b/keepachangelog/actions\"\u003e\u003cimg alt=\"Coverage\" src=\"https://img.shields.io/badge/coverage-100%25-brightgreen\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/psf/black\"\u003e\u003cimg alt=\"Code style: black\" src=\"https://img.shields.io/badge/code%20style-black-000000.svg\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/Colin-b/keepachangelog/actions\"\u003e\u003cimg alt=\"Number of tests\" src=\"https://img.shields.io/badge/tests-48 passed-blue\"\u003e\u003c/a\u003e\n\u003ca href=\"https://pypi.org/project/keepachangelog/\"\u003e\u003cimg alt=\"Number of downloads\" src=\"https://img.shields.io/pypi/dm/keepachangelog\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n* [Command line utility](#usage-from-command-line)\n* [Convert to dict](#convert-changelog-to-dict)\n* [Convert from dict](#convert-dict-to-changelog)\n* [Release a new version](#release)\n* [Add changelog retrieval REST API endpoint](#endpoint)\n  * [Starlette](#starlette)\n  * [Flask-RestX](#flask-restx)\n\n## Convert changelog to dict\n\nConvert changelog markdown file following [keep a changelog](https://keepachangelog.com/en/1.1.0/) format into python dict.\n\n```python\nimport keepachangelog\n\nchanges = keepachangelog.to_dict(\"path/to/CHANGELOG.md\")\n```\n\n`changes` would look like:\n\n```python\nchanges = {\n    \"1.1.0\": {\n        \"changed\": [\n            \"Enhancement 1 (1.1.0)\",\n            \"sub enhancement 1\",\n            \"sub enhancement 2\",\n            \"Enhancement 2 (1.1.0)\",\n        ],\n        \"metadata\": {\n            \"release_date\": \"2018-05-31\",\n            \"version\": \"1.1.0\",\n            \"semantic_version\": {\n                \"major\": 1,\n                \"minor\": 1,\n                \"patch\": 0,\n                \"prerelease\": None,\n                \"buildmetadata\": None,\n            },\n            \"url\": \"https://github.test_url/test_project/compare/v1.0.1...v1.1.0\",\n        },\n    },\n    \"1.0.1\": {\n        \"fixed\": [\n            \"Bug fix 1 (1.0.1)\",\n            \"sub bug 1\",\n            \"sub bug 2\",\n            \"Bug fix 2 (1.0.1)\",\n        ],\n        \"metadata\": {\n            \"release_date\": \"2018-05-31\",\n            \"version\": \"1.0.1\",\n            \"semantic_version\": {\n                \"major\": 1,\n                \"minor\": 0,\n                \"patch\": 1,\n                \"prerelease\": None,\n                \"buildmetadata\": None,\n            },\n            \"url\": \"https://github.test_url/test_project/compare/v1.0.0...v1.0.1\",\n        },\n    },\n    \"1.0.0\": {\n        \"deprecated\": [\"Known issue 1 (1.0.0)\", \"Known issue 2 (1.0.0)\"],\n        \"metadata\": {\n            \"release_date\": \"2017-04-10\",\n            \"version\": \"1.0.0\",\n            \"semantic_version\": {\n                \"major\": 1,\n                \"minor\": 0,\n                \"patch\": 0,\n                \"prerelease\": None,\n                \"buildmetadata\": None,\n            },\n            \"url\": \"https://github.test_url/test_project/releases/tag/v1.0.0\",\n        },\n    },\n}\n```\n\nFor a markdown file with the following content:\n\n```markdown\n# Changelog\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),\nand this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n\n## [Unreleased]\n### Changed\n- Release note 1.\n- Release note 2.\n\n### Added\n- Enhancement 1\n - sub enhancement 1\n - sub enhancement 2\n- Enhancement 2\n\n### Fixed\n- Bug fix 1\n - sub bug 1\n - sub bug 2\n- Bug fix 2\n\n### Security\n- Known issue 1\n- Known issue 2\n\n### Deprecated\n- Deprecated feature 1\n- Future removal 2\n\n### Removed\n- Deprecated feature 2\n- Future removal 1\n\n## [1.1.0] - 2018-05-31\n### Changed\n- Enhancement 1 (1.1.0)\n - sub enhancement 1\n - sub enhancement 2\n- Enhancement 2 (1.1.0)\n\n## [1.0.1] - 2018-05-31\n### Fixed\n- Bug fix 1 (1.0.1)\n - sub bug 1\n - sub bug 2\n- Bug fix 2 (1.0.1)\n\n## [1.0.0] - 2017-04-10\n### Deprecated\n- Known issue 1 (1.0.0)\n- Known issue 2 (1.0.0)\n\n[Unreleased]: https://github.test_url/test_project/compare/v1.1.0...HEAD\n[1.1.0]: https://github.test_url/test_project/compare/v1.0.1...v1.1.0\n[1.0.1]: https://github.test_url/test_project/compare/v1.0.0...v1.0.1\n[1.0.0]: https://github.test_url/test_project/releases/tag/v1.0.0\n```\n\n`show_unreleased` parameter can be specified in order to include `Unreleased` section information.\nNote that `release_date` metadata will be set to None in such as case.\n\n### Retrieving the raw content\n\n#### Using CLI\n\n```shell\nkeepachangelog show 1.0.0\n```\n\nFor details on what is actually performed, refer to the section below as it is what is used underneath the hood.\n\n#### Using python module\n\nIf for some reason you would like to retrieve the raw content of a release you can use `to_raw_dict` instead.\n\n```python\nimport keepachangelog\n\nchanges = keepachangelog.to_raw_dict(\"path/to/CHANGELOG.md\")\n```\n\n`changes` would look like:\n\n```python\nchanges = {\n    \"1.1.0\": {\n        \"raw\": \"\"\"### Changed\n- Enhancement 1 (1.1.0)\n - sub enhancement 1\n - sub enhancement 2\n- Enhancement 2 (1.1.0)\"\"\",\n        \"metadata\": {\n            \"release_date\": \"2018-05-31\",\n            \"version\": \"1.1.0\",\n            \"semantic_version\": {\n                \"major\": 1,\n                \"minor\": 1,\n                \"patch\": 0,\n                \"prerelease\": None,\n                \"buildmetadata\": None,\n            },\n            \"url\": \"https://github.test_url/test_project/compare/v1.0.1...v1.1.0\",\n        },\n    },\n    \"1.0.1\": {\n        \"raw\": \"\"\"### Fixed\n- Bug fix 1 (1.0.1)\n - sub bug 1\n - sub bug 2\n- Bug fix 2 (1.0.1)\"\"\",\n        \"metadata\": {\n            \"release_date\": \"2018-05-31\",\n            \"version\": \"1.0.1\",\n            \"semantic_version\": {\n                \"major\": 1,\n                \"minor\": 0,\n                \"patch\": 1,\n                \"prerelease\": None,\n                \"buildmetadata\": None,\n            },\n            \"url\": \"https://github.test_url/test_project/compare/v1.0.0...v1.0.1\",\n        },\n    },\n    \"1.0.0\": {\n        \"raw\": \"\"\"### Deprecated\n- Known issue 1 (1.0.0)\n- Known issue 2 (1.0.0)\"\"\",\n        \"metadata\": {\n            \"release_date\": \"2017-04-10\",\n            \"version\": \"1.0.0\",\n            \"semantic_version\": {\n                \"major\": 1,\n                \"minor\": 0,\n                \"patch\": 0,\n                \"prerelease\": None,\n                \"buildmetadata\": None,\n            },\n            \"url\": \"https://github.test_url/test_project/releases/tag/v1.0.0\",\n        },\n    },\n}\n```\n\n## Convert dict to changelog\n\nConvert a python dict (resulting from [`keepachangelog.to_dict`](#convert-changelog-to-dict)) to a changelog markdown content following [keep a changelog](https://keepachangelog.com/en/1.1.0/) format.\n\n```python\nimport keepachangelog\n\nchanges = keepachangelog.to_dict(\"path/to/CHANGELOG.md\")\ncontent = keepachangelog.from_dict(changes)\n```\n\n## Release\n\n### Using CLI\n\n```shell\nkeepachangelog release\n```\n\nFor details on what is actually performed, refer to the section below as it is what is used underneath the hood.\n\n### Using python module\n\nYou can create a new release by using `keepachangelog.release` function.\n\n```python\nimport keepachangelog\n\nnew_version = keepachangelog.release(\"path/to/CHANGELOG.md\")\n```\n\nThis will:\n* If `new_version` parameter is not provided, guess the new version number and return it:\n  * `Removed` or `Changed` sections will be considered as breaking changes, thus incrementing the major version.\n  * If the only section is `Fixed`, only patch will be incremented.\n  * Otherwise, minor will be incremented.\n* Update changelog.\n  * Unreleased section content will be moved into a new section.\n  * `[Unreleased]` link will be updated.\n  * New link will be created corresponding to the new section (based on the format of the Unreleased link).\n\n## Usage from command line\n\n`keepachangelog` can be used directly via command line.\n\nThe main usage is within your CI to be able to [Release a new version](#release) and then [Create the appropriate release body](#retrieving-the-raw-content).\nAs in the following sample:\n```shell\nNEW_VERSION=$(keepachangelog release)\nGITHUB_RELEASE_BODY=$(keepachangelog show ${NEW_VERSION})\n```\n\nYou can use it as a python module:\n```sh\npython -m keepachangelog --help\n```\n\nOr as a shell command:\n```sh\nkeepachangelog --help\n```\n\n```sh\n# usage: keepachangelog [-h] [-v] {show,release} ...\n#\n# Manipulate keep a changelog files\n#\n# options:\n#   -h, --help      show this help message and exit\n#   -v, --version   show program's version number and exit\n#\n# commands:\n#   {show,release}\n#     show          Show the content of a release from the changelog\n#     release       Create a new release in the changelog\n#\n# Examples:\n#\n#     keepachangelog show 1.0.0\n#     keepachangelog show 1.0.0 path/to/CHANGELOG.md\n#\n#     keepachangelog release\n#     keepachangelog release 1.0.1\n#     keepachangelog release 1.0.1 -f path/to/CHANGELOG.md\n```\n\n## Endpoint\n\n### Starlette\n\nA helper function is available to create a [starlette](https://www.starlette.io) endpoint to retrieve changelog as JSON.\n\n```python\nfrom starlette.applications import Starlette\nfrom starlette.routing import Route\nfrom keepachangelog.starlette import changelog_endpoint\n\n# /changelog endpoint will return the dict extracted from the changelog as JSON.\nchangelog_route = Route(\"/changelog\", endpoint=changelog_endpoint(\"path/to/CHANGELOG.md\"))\napp = Starlette(routes=[changelog_route])\n```\n\nNote: [starlette](https://pypi.python.org/pypi/starlette) module must be installed.\n\n### Flask-RestX\n\nA helper function is available to create a [Flask-RestX](https://flask-restx.readthedocs.io/en/latest/) endpoint to retrieve changelog as JSON.\n\n```python\nimport flask\nimport flask_restx\nfrom keepachangelog.flask_restx import add_changelog_endpoint\n\n\napp = flask.Flask(__name__)\napi = flask_restx.Api(app)\n# /changelog endpoint will return the dict extracted from the changelog as JSON.\nadd_changelog_endpoint(api, \"path/to/CHANGELOG.md\")\n```\n\nNote: [flask-restx](https://pypi.python.org/pypi/flask-restx) module must be installed.\n\n## How to install\n1. [python 3.7+](https://www.python.org/downloads/) must be installed\n2. Use pip to install module:\n```sh\npython -m pip install keepachangelog\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcolin-b%2Fkeepachangelog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcolin-b%2Fkeepachangelog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcolin-b%2Fkeepachangelog/lists"}