mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-01-19 03:40:59 +00:00
docs(core): use towncrier for generating CHANGELOG.md
This commit is contained in:
parent
2397afffd4
commit
f58c1634c6
4
.gitattributes
vendored
4
.gitattributes
vendored
@ -1,4 +0,0 @@
|
|||||||
core/CHANGELOG.md merge=union
|
|
||||||
python/CHANGELOG.md merge=union
|
|
||||||
legacy/firmware/CHANGELOG.md merge=union
|
|
||||||
legacy/bootloader/CHANGELOG.md merge=union
|
|
10
Makefile
10
Makefile
@ -11,7 +11,7 @@ C_FILES = $(shell find . -type f -name '*.[ch]' | grep -f ./tools/style.c.inclu
|
|||||||
|
|
||||||
style_check: pystyle_check cstyle_check changelog_check yaml_check editor_check ## run all style checks (C+Py)
|
style_check: pystyle_check cstyle_check changelog_check yaml_check editor_check ## run all style checks (C+Py)
|
||||||
|
|
||||||
style: pystyle cstyle changelog ## apply all code styles (C+Py)
|
style: pystyle cstyle ## apply all code styles (C+Py)
|
||||||
|
|
||||||
pystyle_check: ## run code style check on application sources and tests
|
pystyle_check: ## run code style check on application sources and tests
|
||||||
flake8 --version
|
flake8 --version
|
||||||
@ -40,7 +40,10 @@ pystyle: ## apply code style on application sources and tests
|
|||||||
make -C python style
|
make -C python style
|
||||||
|
|
||||||
changelog_check: ## check changelog format
|
changelog_check: ## check changelog format
|
||||||
./tools/linkify-changelogs.py --check
|
./tools/generate-changelog.py --check core
|
||||||
|
./tools/generate-changelog.py --check python
|
||||||
|
./tools/generate-changelog.py --check legacy/firmware
|
||||||
|
./tools/generate-changelog.py --check legacy/bootloader
|
||||||
|
|
||||||
yaml_check: ## check yaml formatting
|
yaml_check: ## check yaml formatting
|
||||||
yamllint .
|
yamllint .
|
||||||
@ -48,9 +51,6 @@ yaml_check: ## check yaml formatting
|
|||||||
editor_check: ## check editorconfig formatting
|
editor_check: ## check editorconfig formatting
|
||||||
editorconfig-checker -exclude '.*\.(so|dat|toif|der)'
|
editorconfig-checker -exclude '.*\.(so|dat|toif|der)'
|
||||||
|
|
||||||
changelog: ## fill out issue links in changelog
|
|
||||||
./tools/linkify-changelogs.py
|
|
||||||
|
|
||||||
cstyle_check: ## run code style check on low-level C code
|
cstyle_check: ## run code style check on low-level C code
|
||||||
clang-format --version
|
clang-format --version
|
||||||
@echo [CLANG-FORMAT]
|
@echo [CLANG-FORMAT]
|
||||||
|
42
ci/check_changelog.sh
Executable file
42
ci/check_changelog.sh
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
base_branch=master
|
||||||
|
fail=0
|
||||||
|
subdirs="core python legacy/firmware legacy/bootloader"
|
||||||
|
|
||||||
|
git fetch origin "$base_branch"
|
||||||
|
|
||||||
|
check_feature_branch () {
|
||||||
|
for subdir in $subdirs
|
||||||
|
do
|
||||||
|
echo "Checking $subdir"
|
||||||
|
files=$(git diff --name-only "origin/$base_branch..." -- "$subdir")
|
||||||
|
|
||||||
|
if echo "$files" | grep . | grep -Fq -v .changelog.d; then
|
||||||
|
if ! echo "$files" | grep -Fq .changelog.d; then
|
||||||
|
fail=1
|
||||||
|
echo "FAILURE! No changelog entry for changes in $subdir."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
check_release_branch () {
|
||||||
|
if git diff --name-only "origin/$base_branch..." | grep -Fq .changelog.d; then
|
||||||
|
fail=1
|
||||||
|
echo "FAILURE! Changelog fragments not allowed in release branch:"
|
||||||
|
git diff --name-only "origin/$base_branch..." | grep -F .changelog.d
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if echo "$CI_COMMIT_BRANCH" | grep -q "^release/"; then
|
||||||
|
check_release_branch
|
||||||
|
else
|
||||||
|
check_feature_branch
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$fail" -ne 0 ]]; then
|
||||||
|
echo "Please see https://docs.trezor.io/trezor-firmware/misc/changelog.html for instructions."
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit $fail
|
@ -41,3 +41,12 @@ release commit messages prebuild:
|
|||||||
- $CI_PROJECT_PATH_SLUG == 'satoshilabs-trezor-trezor-firmware'
|
- $CI_PROJECT_PATH_SLUG == 'satoshilabs-trezor-trezor-firmware'
|
||||||
script:
|
script:
|
||||||
- nix-shell --run "ci/check_release_commit_messages.sh"
|
- nix-shell --run "ci/check_release_commit_messages.sh"
|
||||||
|
|
||||||
|
changelog prebuild:
|
||||||
|
stage: prebuild
|
||||||
|
before_script: [] # nothing needed
|
||||||
|
variables:
|
||||||
|
GIT_SUBMODULE_STRATEGY: "none"
|
||||||
|
GIT_STRATEGY: clone
|
||||||
|
script:
|
||||||
|
- nix-shell --run "ci/check_changelog.sh"
|
||||||
|
1
core/.changelog.d/.gitignore
vendored
Normal file
1
core/.changelog.d/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
!.gitignore
|
1
core/.changelog.d/1167.changed
Normal file
1
core/.changelog.d/1167.changed
Normal file
@ -0,0 +1 @@
|
|||||||
|
Support PIN of unlimited length.
|
1
core/.changelog.d/1249.added
Normal file
1
core/.changelog.d/1249.added
Normal file
@ -0,0 +1 @@
|
|||||||
|
Decred staking.
|
1
core/.changelog.d/1404.added
Normal file
1
core/.changelog.d/1404.added
Normal file
@ -0,0 +1 @@
|
|||||||
|
Locking the device by holding finger on the homescreen for 2.5 seconds.
|
1
core/.changelog.d/1491.changed
Normal file
1
core/.changelog.d/1491.changed
Normal file
@ -0,0 +1 @@
|
|||||||
|
Allow decreasing the output value in RBF transactions.
|
1
core/.changelog.d/1502.changed
Normal file
1
core/.changelog.d/1502.changed
Normal file
@ -0,0 +1 @@
|
|||||||
|
Cardano: Allow stake pool registrations with zero margin.
|
1
core/.changelog.d/1510.changed
Normal file
1
core/.changelog.d/1510.changed
Normal file
@ -0,0 +1 @@
|
|||||||
|
Cardano: Assets are now shown as CIP-0014.
|
1
core/.changelog.d/1518.added
Normal file
1
core/.changelog.d/1518.added
Normal file
@ -0,0 +1 @@
|
|||||||
|
Public key to ECDHSessionKey.
|
1
core/.towncrier.template.md
Symbolic link
1
core/.towncrier.template.md
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../tools/towncrier.template.md
|
@ -4,27 +4,6 @@ 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/).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
|
|
||||||
## 2.4.0 [unreleased]
|
|
||||||
|
|
||||||
### Added
|
|
||||||
- Locking the device by holding finger on the homescreen for 2.5 seconds. [#1404]
|
|
||||||
- Public key to ECDHSessionKey. [#1518]
|
|
||||||
- Decred staking. [#1249]
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Allow decreasing the output value in RBF transactions. [#1491]
|
|
||||||
- Cardano: Allow stake pool registrations with zero margin. [#1502]
|
|
||||||
- Cardano: Assets are now shown as CIP-0014. [#1510]
|
|
||||||
- Support PIN of unlimited length. [#1167]
|
|
||||||
|
|
||||||
### Deprecated
|
|
||||||
|
|
||||||
### Removed
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
### Security
|
|
||||||
|
|
||||||
## 2.3.6 [15th February 2021]
|
## 2.3.6 [15th February 2021]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
@ -359,7 +338,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
[#1139]: https://github.com/trezor/trezor-firmware/issues/1139
|
[#1139]: https://github.com/trezor/trezor-firmware/issues/1139
|
||||||
[#1159]: https://github.com/trezor/trezor-firmware/issues/1159
|
[#1159]: https://github.com/trezor/trezor-firmware/issues/1159
|
||||||
[#1165]: https://github.com/trezor/trezor-firmware/pull/1165
|
[#1165]: https://github.com/trezor/trezor-firmware/pull/1165
|
||||||
[#1167]: https://github.com/trezor/trezor-firmware/issues/1167
|
|
||||||
[#1173]: https://github.com/trezor/trezor-firmware/pull/1173
|
[#1173]: https://github.com/trezor/trezor-firmware/pull/1173
|
||||||
[#1184]: https://github.com/trezor/trezor-firmware/issues/1184
|
[#1184]: https://github.com/trezor/trezor-firmware/issues/1184
|
||||||
[#1188]: https://github.com/trezor/trezor-firmware/issues/1188
|
[#1188]: https://github.com/trezor/trezor-firmware/issues/1188
|
||||||
@ -367,7 +345,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
[#1193]: https://github.com/trezor/trezor-firmware/issues/1193
|
[#1193]: https://github.com/trezor/trezor-firmware/issues/1193
|
||||||
[#1206]: https://github.com/trezor/trezor-firmware/issues/1206
|
[#1206]: https://github.com/trezor/trezor-firmware/issues/1206
|
||||||
[#1246]: https://github.com/trezor/trezor-firmware/issues/1246
|
[#1246]: https://github.com/trezor/trezor-firmware/issues/1246
|
||||||
[#1249]: https://github.com/trezor/trezor-firmware/issues/1249
|
|
||||||
[#1271]: https://github.com/trezor/trezor-firmware/issues/1271
|
[#1271]: https://github.com/trezor/trezor-firmware/issues/1271
|
||||||
[#1292]: https://github.com/trezor/trezor-firmware/issues/1292
|
[#1292]: https://github.com/trezor/trezor-firmware/issues/1292
|
||||||
[#1322]: https://github.com/trezor/trezor-firmware/issues/1322
|
[#1322]: https://github.com/trezor/trezor-firmware/issues/1322
|
||||||
@ -378,10 +355,5 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
[#1384]: https://github.com/trezor/trezor-firmware/issues/1384
|
[#1384]: https://github.com/trezor/trezor-firmware/issues/1384
|
||||||
[#1399]: https://github.com/trezor/trezor-firmware/issues/1399
|
[#1399]: https://github.com/trezor/trezor-firmware/issues/1399
|
||||||
[#1402]: https://github.com/trezor/trezor-firmware/pull/1402
|
[#1402]: https://github.com/trezor/trezor-firmware/pull/1402
|
||||||
[#1404]: https://github.com/trezor/trezor-firmware/issues/1404
|
|
||||||
[#1415]: https://github.com/trezor/trezor-firmware/pull/1415
|
[#1415]: https://github.com/trezor/trezor-firmware/pull/1415
|
||||||
[#1467]: https://github.com/trezor/trezor-firmware/issues/1467
|
[#1467]: https://github.com/trezor/trezor-firmware/issues/1467
|
||||||
[#1491]: https://github.com/trezor/trezor-firmware/issues/1491
|
|
||||||
[#1502]: https://github.com/trezor/trezor-firmware/issues/1502
|
|
||||||
[#1510]: https://github.com/trezor/trezor-firmware/issues/1510
|
|
||||||
[#1518]: https://github.com/trezor/trezor-firmware/pull/1518
|
|
||||||
|
1
core/CHANGELOG.unreleased
Symbolic link
1
core/CHANGELOG.unreleased
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../tools/generate-changelog-unreleased.sh
|
1
core/towncrier.toml
Symbolic link
1
core/towncrier.toml
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../tools/towncrier.toml
|
@ -44,4 +44,5 @@
|
|||||||
- [Monorepo Notes](misc/monorepo.md)
|
- [Monorepo Notes](misc/monorepo.md)
|
||||||
- [Purpose48 derivation scheme](misc/purpose48.md)
|
- [Purpose48 derivation scheme](misc/purpose48.md)
|
||||||
- [Review Process](misc/review.md)
|
- [Review Process](misc/review.md)
|
||||||
|
- [Changelog](misc/changelog.md)
|
||||||
- [TOIF Image Format](misc/toif.md)
|
- [TOIF Image Format](misc/toif.md)
|
||||||
|
59
docs/misc/changelog.md
Normal file
59
docs/misc/changelog.md
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
Our releases are accompanied by changelogs based on the
|
||||||
|
[Keep a Changelog](https://keepachangelog.com/en/1.0.0/) format. We are using
|
||||||
|
the [towncrier](https://github.com/twisted/towncrier) utility to generate them
|
||||||
|
at the time a new version is released. There are currently four such changelogs
|
||||||
|
for different components of the repository:
|
||||||
|
|
||||||
|
* **[`core/CHANGELOG.md`](https://github.com/trezor/trezor-firmware/blob/master/core/CHANGELOG.md)** for Trezor T firmware
|
||||||
|
* **[`legacy/firmware/CHANGELOG.md`](https://github.com/trezor/trezor-firmware/blob/master/legacy/firmware/CHANGELOG.md)** for Trezor 1 firmware
|
||||||
|
* **[`legacy/bootloader/CHANGELOG.md`](https://github.com/trezor/trezor-firmware/blob/master/legacy/bootloader/CHANGELOG.md)** for Trezor 1 bootloader
|
||||||
|
* **[`python/CHANGELOG.md`](https://github.com/trezor/trezor-firmware/blob/master/python/CHANGELOG.md)** for Python client library
|
||||||
|
|
||||||
|
## Adding changelog entry
|
||||||
|
|
||||||
|
[`towncrier`](https://github.com/twisted/towncrier) aims to create changelogs
|
||||||
|
that are convenient to read, at the expense of being somewhat inconvenient to
|
||||||
|
create. Furthermore every changelog entry has to be linked to a GitHub issue or
|
||||||
|
pull request number. If you don't want to create an issue just to satisfy this
|
||||||
|
rule you can use self-reference to your change's pull request number by first
|
||||||
|
creating the PR and then adding the entry.
|
||||||
|
|
||||||
|
There are a few types of changelog entries, as described by the [Keep a
|
||||||
|
Changelog](https://keepachangelog.com/en/1.0.0/) format:
|
||||||
|
|
||||||
|
* `added`
|
||||||
|
* `changed`
|
||||||
|
* `deprecated`
|
||||||
|
* `removed`
|
||||||
|
* `fixed`
|
||||||
|
* `security`
|
||||||
|
* `incompatible` (for backwards incompatible changes)
|
||||||
|
|
||||||
|
Entries are added by creating files in the `.changelog.d` directory where the
|
||||||
|
file name is `<number>.<type>` and contains single line describing the change.
|
||||||
|
As an example, an entry describing bug fix for issue 1234 in Trezor T firmware
|
||||||
|
is added by creating file `core/.changelog.d/1234.fixed`. The file can be
|
||||||
|
formatted with markdown. If more entries are desired for single issue number and
|
||||||
|
type you can add numeral suffix, e.g. `1234.fixed.1`, `1234.fixed.2`, etc.
|
||||||
|
|
||||||
|
You can also add this entry using your `$VISUAL` editor by running `towncrier
|
||||||
|
create --edit 1234.fixed` in the `core` directory.
|
||||||
|
|
||||||
|
## Generating changelog at the time of release
|
||||||
|
|
||||||
|
When it's time to release new version of a repository component the formatted
|
||||||
|
changelog needs to be generated using the `tools/generate-changelog.py` script.
|
||||||
|
It accepts repo subdirectory and the version number as arguments and you can
|
||||||
|
specify the release date if it's different from today's date:
|
||||||
|
|
||||||
|
```
|
||||||
|
tools/generate-changelog.py --date "20th April 2021" legacy/firmware 1.10.0
|
||||||
|
```
|
||||||
|
|
||||||
|
## Cherry-picking changes to release branch
|
||||||
|
|
||||||
|
Branches named `release/YY.MM` already have their corresponding `CHANGELOG.md`
|
||||||
|
section generated. When cherry-picking bug fix to such branch you need to
|
||||||
|
bypass towncrier and edit `CHANGELOG.md` directly.
|
@ -12,5 +12,6 @@ Your Pull Request should follow these criteria:
|
|||||||
- The generated files are up-to-date. Use `make gen` in repository root to make
|
- The generated files are up-to-date. Use `make gen` in repository root to make
|
||||||
it happen.
|
it happen.
|
||||||
- Commits must have concise commit messages, we endorse [Conventional Commits](https://www.conventionalcommits.org).
|
- Commits must have concise commit messages, we endorse [Conventional Commits](https://www.conventionalcommits.org).
|
||||||
|
- A [changelog entry](changelog.md) must be part of the pull request.
|
||||||
|
|
||||||
### Please read and follow our [review procedure](review.md).
|
### Please read and follow our [review procedure](review.md).
|
||||||
|
1
legacy/bootloader/CHANGELOG.unreleased
Symbolic link
1
legacy/bootloader/CHANGELOG.unreleased
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../tools/generate-changelog-unreleased.sh
|
1
legacy/firmware/CHANGELOG.unreleased
Symbolic link
1
legacy/firmware/CHANGELOG.unreleased
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../tools/generate-changelog-unreleased.sh
|
90
poetry.lock
generated
90
poetry.lock
generated
@ -97,6 +97,17 @@ category = "main"
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "click-default-group"
|
||||||
|
version = "1.2.2"
|
||||||
|
description = "Extends click.Group to invoke a command without explicit subcommand name"
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
click = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorama"
|
name = "colorama"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
@ -344,6 +355,17 @@ zipp = {version = ">=0.4", markers = "python_version < \"3.8\""}
|
|||||||
docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
|
docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
|
||||||
testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "pytest-black (>=0.3.7)", "pytest-mypy"]
|
testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "pytest-black (>=0.3.7)", "pytest-mypy"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "incremental"
|
||||||
|
version = "21.3.0"
|
||||||
|
description = "A small library that versions your Python projects."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
scripts = ["click (>=6.0)", "twisted (>=16.4.0)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iniconfig"
|
name = "iniconfig"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
@ -377,6 +399,20 @@ pyproject = ["toml"]
|
|||||||
requirements = ["pipreqs", "pip-api"]
|
requirements = ["pipreqs", "pip-api"]
|
||||||
xdg_home = ["appdirs (>=1.4.0)"]
|
xdg_home = ["appdirs (>=1.4.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jinja2"
|
||||||
|
version = "2.11.3"
|
||||||
|
description = "A very fast and expressive template engine."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
MarkupSafe = ">=0.23"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
i18n = ["Babel (>=0.8)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libusb1"
|
name = "libusb1"
|
||||||
version = "1.9.1"
|
version = "1.9.1"
|
||||||
@ -773,6 +809,24 @@ category = "main"
|
|||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "towncrier"
|
||||||
|
version = "21.3.0"
|
||||||
|
description = "Building newsfiles for your project."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
click = "*"
|
||||||
|
click-default-group = "*"
|
||||||
|
incremental = "*"
|
||||||
|
jinja2 = "*"
|
||||||
|
toml = "*"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["packaging"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tox"
|
name = "tox"
|
||||||
version = "3.21.4"
|
version = "3.21.4"
|
||||||
@ -910,7 +964,7 @@ testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "1.1"
|
lock-version = "1.1"
|
||||||
python-versions = "^3.6"
|
python-versions = "^3.6"
|
||||||
content-hash = "1182233da1c699fa3f6fc47c397c064f05f14c02582a71e00983f2a05c8fdc92"
|
content-hash = "f731bd62e9c130760c8b619cf8ef9eb102ac26dcff99834d26e0e356475ab6be"
|
||||||
|
|
||||||
[metadata.files]
|
[metadata.files]
|
||||||
appdirs = [
|
appdirs = [
|
||||||
@ -982,6 +1036,9 @@ click = [
|
|||||||
{file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"},
|
{file = "click-7.1.2-py2.py3-none-any.whl", hash = "sha256:dacca89f4bfadd5de3d7489b7c8a566eee0d3676333fbb50030263894c38c0dc"},
|
||||||
{file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
|
{file = "click-7.1.2.tar.gz", hash = "sha256:d2b5255c7c6349bc1bd1e59e08cd12acbbd63ce649f2588755783aa94dfb6b1a"},
|
||||||
]
|
]
|
||||||
|
click-default-group = [
|
||||||
|
{file = "click-default-group-1.2.2.tar.gz", hash = "sha256:d9560e8e8dfa44b3562fbc9425042a0fd6d21956fcc2db0077f63f34253ab904"},
|
||||||
|
]
|
||||||
colorama = [
|
colorama = [
|
||||||
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
{file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
|
||||||
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
|
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
|
||||||
@ -1102,6 +1159,10 @@ importlib-resources = [
|
|||||||
{file = "importlib_resources-5.1.0-py3-none-any.whl", hash = "sha256:885b8eae589179f661c909d699a546cf10d83692553e34dca1bf5eb06f7f6217"},
|
{file = "importlib_resources-5.1.0-py3-none-any.whl", hash = "sha256:885b8eae589179f661c909d699a546cf10d83692553e34dca1bf5eb06f7f6217"},
|
||||||
{file = "importlib_resources-5.1.0.tar.gz", hash = "sha256:bfdad047bce441405a49cf8eb48ddce5e56c696e185f59147a8b79e75e9e6380"},
|
{file = "importlib_resources-5.1.0.tar.gz", hash = "sha256:bfdad047bce441405a49cf8eb48ddce5e56c696e185f59147a8b79e75e9e6380"},
|
||||||
]
|
]
|
||||||
|
incremental = [
|
||||||
|
{file = "incremental-21.3.0-py2.py3-none-any.whl", hash = "sha256:92014aebc6a20b78a8084cdd5645eeaa7f74b8933f70fa3ada2cfbd1e3b54321"},
|
||||||
|
{file = "incremental-21.3.0.tar.gz", hash = "sha256:02f5de5aff48f6b9f665d99d48bfc7ec03b6e3943210de7cfc88856d755d6f57"},
|
||||||
|
]
|
||||||
iniconfig = [
|
iniconfig = [
|
||||||
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
{file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
|
||||||
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
|
{file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
|
||||||
@ -1114,6 +1175,10 @@ isort = [
|
|||||||
{file = "isort-4.3.21-py2.py3-none-any.whl", hash = "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"},
|
{file = "isort-4.3.21-py2.py3-none-any.whl", hash = "sha256:6e811fcb295968434526407adb8796944f1988c5b65e8139058f2014cbe100fd"},
|
||||||
{file = "isort-4.3.21.tar.gz", hash = "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1"},
|
{file = "isort-4.3.21.tar.gz", hash = "sha256:54da7e92468955c4fceacd0c86bd0ec997b0e1ee80d97f67c35a78b719dccab1"},
|
||||||
]
|
]
|
||||||
|
jinja2 = [
|
||||||
|
{file = "Jinja2-2.11.3-py2.py3-none-any.whl", hash = "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419"},
|
||||||
|
{file = "Jinja2-2.11.3.tar.gz", hash = "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6"},
|
||||||
|
]
|
||||||
libusb1 = [
|
libusb1 = [
|
||||||
{file = "libusb1-1.9.1-py2-none-any.whl", hash = "sha256:4a024fffe195c49f3e7eadd2266087b4be065982f0cb41ef4b7e2c5053e7e65c"},
|
{file = "libusb1-1.9.1-py2-none-any.whl", hash = "sha256:4a024fffe195c49f3e7eadd2266087b4be065982f0cb41ef4b7e2c5053e7e65c"},
|
||||||
{file = "libusb1-1.9.1-py2-none-win32.whl", hash = "sha256:16203d77a1f623b6f8f4e6c9d6bac79c1293b8d3e11de5f2f3c30d91380ae478"},
|
{file = "libusb1-1.9.1-py2-none-win32.whl", hash = "sha256:16203d77a1f623b6f8f4e6c9d6bac79c1293b8d3e11de5f2f3c30d91380ae478"},
|
||||||
@ -1145,39 +1210,20 @@ markupsafe = [
|
|||||||
{file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"},
|
{file = "MarkupSafe-1.1.1-cp35-cp35m-win32.whl", hash = "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1"},
|
||||||
{file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"},
|
{file = "MarkupSafe-1.1.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d"},
|
||||||
{file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"},
|
{file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff"},
|
||||||
{file = "MarkupSafe-1.1.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d53bc011414228441014aa71dbec320c66468c1030aae3a6e29778a3382d96e5"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"},
|
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473"},
|
||||||
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"},
|
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e"},
|
||||||
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:3b8a6499709d29c2e2399569d96719a1b21dcd94410a586a18526b143ec8470f"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:84dee80c15f1b560d55bcfe6d47b27d070b4681c699c572af2e3c7cc90a3b8e0"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:b1dba4527182c95a0db8b6060cc98ac49b9e2f5e64320e2b56e47cb2831978c7"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"},
|
{file = "MarkupSafe-1.1.1-cp36-cp36m-win32.whl", hash = "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66"},
|
||||||
{file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"},
|
{file = "MarkupSafe-1.1.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5"},
|
||||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"},
|
{file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d"},
|
||||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:bf5aa3cbcfdf57fa2ee9cd1822c862ef23037f5c832ad09cfea57fa846dec193"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"},
|
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e"},
|
||||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"},
|
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6"},
|
||||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:6fffc775d90dcc9aed1b89219549b329a9250d918fd0b8fa8d93d154918422e1"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:a6a744282b7718a2a62d2ed9d993cad6f5f585605ad352c11de459f4108df0a1"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:195d7d2c4fbb0ee8139a6cf67194f3973a6b3042d742ebe0a9ed36d8b6f0c07f"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"},
|
{file = "MarkupSafe-1.1.1-cp37-cp37m-win32.whl", hash = "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2"},
|
||||||
{file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"},
|
{file = "MarkupSafe-1.1.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c"},
|
||||||
{file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"},
|
{file = "MarkupSafe-1.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15"},
|
||||||
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"},
|
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2"},
|
||||||
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"},
|
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42"},
|
||||||
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:acf08ac40292838b3cbbb06cfe9b2cb9ec78fce8baca31ddb87aaac2e2dc3bc2"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:d9be0ba6c527163cbed5e0857c451fcd092ce83947944d6c14bc95441203f032"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:caabedc8323f1e93231b52fc32bdcde6db817623d33e100708d9a68e1f53b26b"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"},
|
{file = "MarkupSafe-1.1.1-cp38-cp38-win32.whl", hash = "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b"},
|
||||||
{file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"},
|
{file = "MarkupSafe-1.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be"},
|
||||||
{file = "MarkupSafe-1.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d73a845f227b0bfe8a7455ee623525ee656a9e2e749e4742706d80a6065d5e2c"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:98bae9582248d6cf62321dcb52aaf5d9adf0bad3b40582925ef7c7f0ed85fceb"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:2beec1e0de6924ea551859edb9e7679da6e4870d32cb766240ce17e0a0ba2014"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:7fed13866cf14bba33e7176717346713881f56d9d2bcebab207f7a036f41b850"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:6f1e273a344928347c1290119b493a1f0303c52f5a5eae5f16d74f48c15d4a85"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:feb7b34d6325451ef96bc0e36e1a6c0c1c64bc1fbec4b854f4529e51887b1621"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp39-cp39-win32.whl", hash = "sha256:22c178a091fc6630d0d045bdb5992d2dfe14e3259760e713c490da5323866c39"},
|
|
||||||
{file = "MarkupSafe-1.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7d644ddb4dbd407d31ffb699f1d140bc35478da613b441c582aeb7c43838dd8"},
|
|
||||||
{file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"},
|
{file = "MarkupSafe-1.1.1.tar.gz", hash = "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b"},
|
||||||
]
|
]
|
||||||
mccabe = [
|
mccabe = [
|
||||||
@ -1466,6 +1512,10 @@ toml = [
|
|||||||
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
|
||||||
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
|
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
|
||||||
]
|
]
|
||||||
|
towncrier = [
|
||||||
|
{file = "towncrier-21.3.0-py2.py3-none-any.whl", hash = "sha256:e6ccec65418bbcb8de5c908003e130e37fe0e9d6396cb77c1338241071edc082"},
|
||||||
|
{file = "towncrier-21.3.0.tar.gz", hash = "sha256:6eed0bc924d72c98c000cb8a64de3bd566e5cb0d11032b73fcccf8a8f956ddfe"},
|
||||||
|
]
|
||||||
tox = [
|
tox = [
|
||||||
{file = "tox-3.21.4-py2.py3-none-any.whl", hash = "sha256:65d0e90ceb816638a50d64f4b47b11da767b284c0addda2294cb3cd69bd72425"},
|
{file = "tox-3.21.4-py2.py3-none-any.whl", hash = "sha256:65d0e90ceb816638a50d64f4b47b11da767b284c0addda2294cb3cd69bd72425"},
|
||||||
{file = "tox-3.21.4.tar.gz", hash = "sha256:cf7fef81a3a2434df4d7af2a6d1bf606d2970220addfbe7dea2615bd4bb2c252"},
|
{file = "tox-3.21.4.tar.gz", hash = "sha256:cf7fef81a3a2434df4d7af2a6d1bf606d2970220addfbe7dea2615bd4bb2c252"},
|
||||||
|
@ -72,6 +72,7 @@ yamllint = "^1.25.0"
|
|||||||
|
|
||||||
[tool.poetry.dev-dependencies]
|
[tool.poetry.dev-dependencies]
|
||||||
scan-build = "*"
|
scan-build = "*"
|
||||||
|
towncrier = "^21.3.0"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry>=1;<1.1", "pip>=20"]
|
requires = ["poetry>=1;<1.1", "pip>=20"]
|
||||||
|
1
python/CHANGELOG.unreleased
Symbolic link
1
python/CHANGELOG.unreleased
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../tools/generate-changelog-unreleased.sh
|
4
tools/generate-changelog-unreleased.sh
Executable file
4
tools/generate-changelog-unreleased.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
cd $(dirname "$0") || exit
|
||||||
|
towncrier build --draft --version unreleased
|
147
tools/generate-changelog.py
Executable file
147
tools/generate-changelog.py
Executable file
@ -0,0 +1,147 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
import click
|
||||||
|
|
||||||
|
LINK_RE = re.compile(r"\[#(\d+)\]")
|
||||||
|
ISSUE_URL = "https://github.com/trezor/trezor-firmware/issues/{issue}"
|
||||||
|
|
||||||
|
VERSION_HEADER_RE = re.compile(r"## \[([.0-9]+)\]")
|
||||||
|
DIFF_LINK = "[{new}]: https://github.com/trezor/trezor-firmware/compare/{tag_prefix}{old}...{tag_prefix}{new}\n"
|
||||||
|
|
||||||
|
|
||||||
|
def linkify_changelog(changelog_file, only_check=False):
|
||||||
|
links = {}
|
||||||
|
orig_links = {}
|
||||||
|
result_lines = []
|
||||||
|
|
||||||
|
with open(changelog_file, "r+") as changelog:
|
||||||
|
for line in changelog:
|
||||||
|
m = LINK_RE.match(line)
|
||||||
|
if m: # line *starts with* issue identifier
|
||||||
|
# keep existing links as-is
|
||||||
|
orig_links[int(m[1])] = line.replace(m[0] + ": ", "").strip()
|
||||||
|
else:
|
||||||
|
for issue in LINK_RE.findall(line):
|
||||||
|
links[int(issue)] = ISSUE_URL.format(issue=issue)
|
||||||
|
result_lines.append(line)
|
||||||
|
|
||||||
|
if only_check:
|
||||||
|
missing_links = set(links.keys()) - set(orig_links.keys())
|
||||||
|
if missing_links:
|
||||||
|
click.echo(f"missing links: {missing_links}")
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
links.update(orig_links)
|
||||||
|
|
||||||
|
changelog.seek(0)
|
||||||
|
changelog.truncate(0)
|
||||||
|
for line in result_lines:
|
||||||
|
changelog.write(line)
|
||||||
|
for marker, url in sorted(links.items()):
|
||||||
|
changelog.write(f"[#{marker}]: {url}\n")
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def linkify_gh_diff(changelog_file, tag_prefix):
|
||||||
|
linkified = False
|
||||||
|
versions = []
|
||||||
|
result_lines = []
|
||||||
|
|
||||||
|
with open(changelog_file, "r+") as changelog:
|
||||||
|
for line in changelog:
|
||||||
|
m = VERSION_HEADER_RE.match(line)
|
||||||
|
if m:
|
||||||
|
versions.append(m[1])
|
||||||
|
result_lines.append(line)
|
||||||
|
|
||||||
|
changelog.seek(0)
|
||||||
|
changelog.truncate(0)
|
||||||
|
for line in result_lines:
|
||||||
|
changelog.write(line)
|
||||||
|
if not linkified and VERSION_HEADER_RE.match(line):
|
||||||
|
changelog.write(
|
||||||
|
DIFF_LINK.format(
|
||||||
|
tag_prefix=tag_prefix, new=versions[0], old=versions[1]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
linkified = True
|
||||||
|
|
||||||
|
|
||||||
|
def current_date(project):
|
||||||
|
parts = project.parts
|
||||||
|
today = datetime.datetime.now()
|
||||||
|
|
||||||
|
if parts[-2:] == ("legacy", "bootloader"):
|
||||||
|
return today.strftime("%B %Y")
|
||||||
|
elif parts[-1] == "python":
|
||||||
|
return today.strftime("%Y-%m-%d")
|
||||||
|
else:
|
||||||
|
daysuffix = {1: "st", 2: "nd", 3: "rd"}.get(today.day % 10, "th")
|
||||||
|
return today.strftime(f"%d{daysuffix} %B %Y")
|
||||||
|
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.argument(
|
||||||
|
"project",
|
||||||
|
type=click.Path(exists=True, dir_okay=True, file_okay=False, resolve_path=True),
|
||||||
|
)
|
||||||
|
@click.argument(
|
||||||
|
"version",
|
||||||
|
type=str,
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
@click.option("--date", help="Specify release date (default: today).")
|
||||||
|
@click.option(
|
||||||
|
"--check", is_flag=True, help="Dry run, do not actually create changelog."
|
||||||
|
)
|
||||||
|
def cli(project, version, date, check):
|
||||||
|
"""Generate changelog for given project (core, python, legacy/firmware,
|
||||||
|
legacy/bootloader).
|
||||||
|
|
||||||
|
- Run towncrier to assemble changelog from fragments in .changelog.d/.
|
||||||
|
|
||||||
|
- Find all occurences of "[#123]" in text, and add a Markdown link to the
|
||||||
|
referenced issue.
|
||||||
|
|
||||||
|
- Tell git to stage changed files.
|
||||||
|
"""
|
||||||
|
project = Path(project)
|
||||||
|
changelog = project / "CHANGELOG.md"
|
||||||
|
|
||||||
|
if not changelog.exists():
|
||||||
|
raise click.ClickException("{} not found".format(changelog))
|
||||||
|
|
||||||
|
if version is None:
|
||||||
|
if not check:
|
||||||
|
raise click.ClickException("Version argument is required.")
|
||||||
|
version = "unreleased"
|
||||||
|
|
||||||
|
if date is None:
|
||||||
|
date = current_date(project)
|
||||||
|
|
||||||
|
args = ["towncrier", "build", "--yes", "--version", version, "--date", date]
|
||||||
|
if check:
|
||||||
|
args.append("--draft")
|
||||||
|
subprocess.run(args, cwd=project, check=True)
|
||||||
|
|
||||||
|
if not check:
|
||||||
|
linkify_changelog(changelog)
|
||||||
|
|
||||||
|
# python changelog has links to github diffs
|
||||||
|
if project.parts[-1] == "python":
|
||||||
|
linkify_gh_diff(changelog, tag_prefix="python/v")
|
||||||
|
|
||||||
|
# towncrier calls git add before we do linkification, stage the changes too
|
||||||
|
subprocess.run(["git", "add", changelog], check=True)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
cli()
|
@ -1,87 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
|
||||||
import re
|
|
||||||
|
|
||||||
import click
|
|
||||||
|
|
||||||
LINK_RE = re.compile(r"\[#(\d+)\]")
|
|
||||||
ISSUE_URL = "https://github.com/trezor/trezor-firmware/issues/{issue}"
|
|
||||||
|
|
||||||
ROOT = Path(__file__).parent.resolve().parent
|
|
||||||
|
|
||||||
DEFAULT_CHANGELOGS = ( # TODO replace with a wildcard?
|
|
||||||
ROOT / "core" / "CHANGELOG.md",
|
|
||||||
ROOT / "legacy" / "firmware" / "CHANGELOG.md",
|
|
||||||
ROOT / "legacy" / "bootloader" / "CHANGELOG.md",
|
|
||||||
ROOT / "python" / "CHANGELOG.md",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def process_changelog(changelog_file, only_check=False):
|
|
||||||
links = {}
|
|
||||||
orig_links = {}
|
|
||||||
result_lines = []
|
|
||||||
|
|
||||||
with open(changelog_file, "r+") as changelog:
|
|
||||||
for line in changelog:
|
|
||||||
m = LINK_RE.match(line)
|
|
||||||
if m: # line *starts with* issue identifier
|
|
||||||
# keep existing links as-is
|
|
||||||
orig_links[int(m[1])] = line.replace(m[0] + ": ", "").strip()
|
|
||||||
else:
|
|
||||||
for issue in LINK_RE.findall(line):
|
|
||||||
links[int(issue)] = ISSUE_URL.format(issue=issue)
|
|
||||||
result_lines.append(line)
|
|
||||||
|
|
||||||
if only_check:
|
|
||||||
missing_links = set(links.keys()) - set(orig_links.keys())
|
|
||||||
if missing_links:
|
|
||||||
click.echo(f"missing links: {missing_links}")
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
links.update(orig_links)
|
|
||||||
|
|
||||||
changelog.seek(0)
|
|
||||||
changelog.truncate(0)
|
|
||||||
for line in result_lines:
|
|
||||||
changelog.write(line)
|
|
||||||
for marker, url in sorted(links.items()):
|
|
||||||
changelog.write(f"[#{marker}]: {url}\n")
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
@click.command()
|
|
||||||
@click.argument(
|
|
||||||
"changelogs",
|
|
||||||
nargs=-1,
|
|
||||||
type=click.Path(exists=True, dir_okay=False, writable=True),
|
|
||||||
)
|
|
||||||
@click.option("--check", is_flag=True, help="Check for missing links, do not modify.")
|
|
||||||
def cli(changelogs, check):
|
|
||||||
"""Linkify changelog.
|
|
||||||
|
|
||||||
Find all occurences of "[#123]" in text, and add a Markdown link to the referenced
|
|
||||||
issue.
|
|
||||||
|
|
||||||
If no arguments are provided, runs on all known changelogs.
|
|
||||||
"""
|
|
||||||
if not changelogs:
|
|
||||||
changelogs = DEFAULT_CHANGELOGS
|
|
||||||
|
|
||||||
all_ok = True
|
|
||||||
for changelog in changelogs:
|
|
||||||
click.echo(changelog)
|
|
||||||
if not process_changelog(changelog, check):
|
|
||||||
all_ok = False
|
|
||||||
|
|
||||||
if not all_ok:
|
|
||||||
raise click.ClickException("Some links are missing. Run `make style` to fix.")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
cli()
|
|
16
tools/towncrier.template.md
Normal file
16
tools/towncrier.template.md
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{% for section, _ in sections.items() %}
|
||||||
|
{% if section %}{{section}}{% endif -%}
|
||||||
|
|
||||||
|
{% if sections[section] %}
|
||||||
|
|
||||||
|
{% for category, val in definitions.items() if category in sections[section] %}
|
||||||
|
|
||||||
|
### {{ definitions[category]['name'] }}
|
||||||
|
{% if definitions[category]['showcontent'] %}
|
||||||
|
{% for text, values in sections[section][category].items() %}
|
||||||
|
- {{ text }} {{ values|join(', ') }}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
43
tools/towncrier.toml
Normal file
43
tools/towncrier.toml
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
[tool.towncrier]
|
||||||
|
directory = ".changelog.d"
|
||||||
|
filename = "CHANGELOG.md"
|
||||||
|
template = ".towncrier.template.md"
|
||||||
|
start_string = "The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)."
|
||||||
|
title_format = "\n## {version} [{project_date}]"
|
||||||
|
issue_format = "[#{issue}]"
|
||||||
|
underlines = ["", ""]
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "added"
|
||||||
|
name = "Added"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "changed"
|
||||||
|
name = "Changed"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "deprecated"
|
||||||
|
name = "Deprecated"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "removed"
|
||||||
|
name = "Removed"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "fixed"
|
||||||
|
name = "Fixed"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "security"
|
||||||
|
name = "Security"
|
||||||
|
showcontent = true
|
||||||
|
|
||||||
|
[[tool.towncrier.type]]
|
||||||
|
directory = "incompatible"
|
||||||
|
name = "Incompatible changes"
|
||||||
|
showcontent = true
|
Loading…
Reference in New Issue
Block a user