mex-release 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mex_release-0.2.0/LICENSE +21 -0
- mex_release-0.2.0/PKG-INFO +135 -0
- mex_release-0.2.0/README.md +99 -0
- mex_release-0.2.0/pyproject.toml +178 -0
- mex_release-0.2.0/release.py +147 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Robert Koch-Institut
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: mex-release
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Create new release with `pdm release VERSION`
|
|
5
|
+
Author-Email: MEx Team <mex@rki.de>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2024 Robert Koch-Institut
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Repository, https://github.com/robert-koch-institut/mex-release
|
|
29
|
+
Requires-Python: <3.13,>=3.11
|
|
30
|
+
Requires-Dist: pdm<3.0,>=2.13.2
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: ipdb<1,>=0.13.13; extra == "dev"
|
|
33
|
+
Requires-Dist: mypy<2,>=1.11.0; extra == "dev"
|
|
34
|
+
Requires-Dist: ruff<1,>=0.5.4; extra == "dev"
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# MEx release
|
|
38
|
+
|
|
39
|
+
Create new release with `pdm release VERSION`
|
|
40
|
+
|
|
41
|
+
[](https://github.com/robert-koch-institut/mex-template)
|
|
42
|
+
[](https://github.com/robert-koch-institut/mex-release/actions/workflows/cve-scan.yml)
|
|
43
|
+
[](https://github.com/robert-koch-institut/mex-release/actions/workflows/linting.yml)
|
|
44
|
+
[](https://gitlab.opencode.de/robert-koch-institut/mex/mex-release)
|
|
45
|
+
|
|
46
|
+
## project
|
|
47
|
+
|
|
48
|
+
The Metadata Exchange (MEx) project is committed to improve the retrieval of RKI
|
|
49
|
+
research data and projects. How? By focusing on metadata: instead of providing the
|
|
50
|
+
actual research data directly, the MEx metadata catalog captures descriptive information
|
|
51
|
+
about research data and activities. On this basis, we want to make the data FAIR[^1] so
|
|
52
|
+
that it can be shared with others.
|
|
53
|
+
|
|
54
|
+
Via MEx, metadata will be made findable, accessible and shareable, as well as available
|
|
55
|
+
for further research. The goal is to get an overview of what research data is available,
|
|
56
|
+
understand its context, and know what needs to be considered for subsequent use.
|
|
57
|
+
|
|
58
|
+
RKI cooperated with D4L data4life gGmbH for a pilot phase where the vision of a
|
|
59
|
+
FAIR metadata catalog was explored and concepts and prototypes were developed.
|
|
60
|
+
The partnership has ended with the successful conclusion of the pilot phase.
|
|
61
|
+
|
|
62
|
+
After an internal launch, the metadata will also be made publicly available and thus be
|
|
63
|
+
available to external researchers as well as the interested (professional) public to
|
|
64
|
+
find research data from the RKI.
|
|
65
|
+
|
|
66
|
+
For further details, please consult our
|
|
67
|
+
[project page](https://www.rki.de/DE/Content/Forsch/MEx/MEx_node.html).
|
|
68
|
+
|
|
69
|
+
[^1]: FAIR is referencing the so-called
|
|
70
|
+
[FAIR data principles](https://www.go-fair.org/fair-principles/) – guidelines to make
|
|
71
|
+
data Findable, Accessible, Interoperable and Reusable.
|
|
72
|
+
|
|
73
|
+
**Contact** \
|
|
74
|
+
For more information, please feel free to email us at [mex@rki.de](mailto:mex@rki.de).
|
|
75
|
+
|
|
76
|
+
### Publisher of this document
|
|
77
|
+
**Robert Koch-Institut** \
|
|
78
|
+
Nordufer 20 \
|
|
79
|
+
13353 Berlin \
|
|
80
|
+
Germany
|
|
81
|
+
|
|
82
|
+
## package
|
|
83
|
+
|
|
84
|
+
Create a new release, including changelog rollover, project version bump, commit, tag
|
|
85
|
+
and push.
|
|
86
|
+
|
|
87
|
+
## license
|
|
88
|
+
|
|
89
|
+
This package is licensed under the [MIT license](/LICENSE). All other software
|
|
90
|
+
components of the MEx project are open-sourced under the same license as well.
|
|
91
|
+
|
|
92
|
+
## development
|
|
93
|
+
|
|
94
|
+
### installation
|
|
95
|
+
|
|
96
|
+
- on unix, consider using pyenv https://github.com/pyenv/pyenv
|
|
97
|
+
- get pyenv `curl https://pyenv.run | bash`
|
|
98
|
+
- install 3.11 `pyenv install 3.11`
|
|
99
|
+
- switch version `pyenv global 3.11`
|
|
100
|
+
- run `make install`
|
|
101
|
+
- on windows, consider using pyenv-win https://pyenv-win.github.io/pyenv-win/
|
|
102
|
+
- follow https://pyenv-win.github.io/pyenv-win/#quick-start
|
|
103
|
+
- install 3.11 `pyenv install 3.11`
|
|
104
|
+
- switch version `pyenv global 3.11`
|
|
105
|
+
- run `.\mex.bat install`
|
|
106
|
+
|
|
107
|
+
### linting and testing
|
|
108
|
+
|
|
109
|
+
- run all linters with `pdm lint`
|
|
110
|
+
- run only unit tests with `pdm unit`
|
|
111
|
+
- run unit and integration tests with `pdm test`
|
|
112
|
+
|
|
113
|
+
### updating dependencies
|
|
114
|
+
|
|
115
|
+
- update boilerplate files with `cruft update`
|
|
116
|
+
- update global requirements in `requirements.txt` manually
|
|
117
|
+
- update git hooks with `pre-commit autoupdate`
|
|
118
|
+
- update package dependencies using `pdm update-all`
|
|
119
|
+
- update github actions in `.github/workflows/*.yml` manually
|
|
120
|
+
|
|
121
|
+
### creating release
|
|
122
|
+
|
|
123
|
+
- run `pdm release RULE` to release a new version where RULE determines which part of
|
|
124
|
+
the version to update and is one of `major`, `minor`, `patch`.
|
|
125
|
+
|
|
126
|
+
### container workflow
|
|
127
|
+
|
|
128
|
+
- build image with `make image`
|
|
129
|
+
- run directly using docker `make run`
|
|
130
|
+
- start with docker compose `make start`
|
|
131
|
+
|
|
132
|
+
## commands
|
|
133
|
+
|
|
134
|
+
- run `pdm release VERSION` to release a new version where VERSION matches the regular
|
|
135
|
+
expression: `\d{1,4}\.\d{1,4}\.\d{1,4}`.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# MEx release
|
|
2
|
+
|
|
3
|
+
Create new release with `pdm release VERSION`
|
|
4
|
+
|
|
5
|
+
[](https://github.com/robert-koch-institut/mex-template)
|
|
6
|
+
[](https://github.com/robert-koch-institut/mex-release/actions/workflows/cve-scan.yml)
|
|
7
|
+
[](https://github.com/robert-koch-institut/mex-release/actions/workflows/linting.yml)
|
|
8
|
+
[](https://gitlab.opencode.de/robert-koch-institut/mex/mex-release)
|
|
9
|
+
|
|
10
|
+
## project
|
|
11
|
+
|
|
12
|
+
The Metadata Exchange (MEx) project is committed to improve the retrieval of RKI
|
|
13
|
+
research data and projects. How? By focusing on metadata: instead of providing the
|
|
14
|
+
actual research data directly, the MEx metadata catalog captures descriptive information
|
|
15
|
+
about research data and activities. On this basis, we want to make the data FAIR[^1] so
|
|
16
|
+
that it can be shared with others.
|
|
17
|
+
|
|
18
|
+
Via MEx, metadata will be made findable, accessible and shareable, as well as available
|
|
19
|
+
for further research. The goal is to get an overview of what research data is available,
|
|
20
|
+
understand its context, and know what needs to be considered for subsequent use.
|
|
21
|
+
|
|
22
|
+
RKI cooperated with D4L data4life gGmbH for a pilot phase where the vision of a
|
|
23
|
+
FAIR metadata catalog was explored and concepts and prototypes were developed.
|
|
24
|
+
The partnership has ended with the successful conclusion of the pilot phase.
|
|
25
|
+
|
|
26
|
+
After an internal launch, the metadata will also be made publicly available and thus be
|
|
27
|
+
available to external researchers as well as the interested (professional) public to
|
|
28
|
+
find research data from the RKI.
|
|
29
|
+
|
|
30
|
+
For further details, please consult our
|
|
31
|
+
[project page](https://www.rki.de/DE/Content/Forsch/MEx/MEx_node.html).
|
|
32
|
+
|
|
33
|
+
[^1]: FAIR is referencing the so-called
|
|
34
|
+
[FAIR data principles](https://www.go-fair.org/fair-principles/) – guidelines to make
|
|
35
|
+
data Findable, Accessible, Interoperable and Reusable.
|
|
36
|
+
|
|
37
|
+
**Contact** \
|
|
38
|
+
For more information, please feel free to email us at [mex@rki.de](mailto:mex@rki.de).
|
|
39
|
+
|
|
40
|
+
### Publisher of this document
|
|
41
|
+
**Robert Koch-Institut** \
|
|
42
|
+
Nordufer 20 \
|
|
43
|
+
13353 Berlin \
|
|
44
|
+
Germany
|
|
45
|
+
|
|
46
|
+
## package
|
|
47
|
+
|
|
48
|
+
Create a new release, including changelog rollover, project version bump, commit, tag
|
|
49
|
+
and push.
|
|
50
|
+
|
|
51
|
+
## license
|
|
52
|
+
|
|
53
|
+
This package is licensed under the [MIT license](/LICENSE). All other software
|
|
54
|
+
components of the MEx project are open-sourced under the same license as well.
|
|
55
|
+
|
|
56
|
+
## development
|
|
57
|
+
|
|
58
|
+
### installation
|
|
59
|
+
|
|
60
|
+
- on unix, consider using pyenv https://github.com/pyenv/pyenv
|
|
61
|
+
- get pyenv `curl https://pyenv.run | bash`
|
|
62
|
+
- install 3.11 `pyenv install 3.11`
|
|
63
|
+
- switch version `pyenv global 3.11`
|
|
64
|
+
- run `make install`
|
|
65
|
+
- on windows, consider using pyenv-win https://pyenv-win.github.io/pyenv-win/
|
|
66
|
+
- follow https://pyenv-win.github.io/pyenv-win/#quick-start
|
|
67
|
+
- install 3.11 `pyenv install 3.11`
|
|
68
|
+
- switch version `pyenv global 3.11`
|
|
69
|
+
- run `.\mex.bat install`
|
|
70
|
+
|
|
71
|
+
### linting and testing
|
|
72
|
+
|
|
73
|
+
- run all linters with `pdm lint`
|
|
74
|
+
- run only unit tests with `pdm unit`
|
|
75
|
+
- run unit and integration tests with `pdm test`
|
|
76
|
+
|
|
77
|
+
### updating dependencies
|
|
78
|
+
|
|
79
|
+
- update boilerplate files with `cruft update`
|
|
80
|
+
- update global requirements in `requirements.txt` manually
|
|
81
|
+
- update git hooks with `pre-commit autoupdate`
|
|
82
|
+
- update package dependencies using `pdm update-all`
|
|
83
|
+
- update github actions in `.github/workflows/*.yml` manually
|
|
84
|
+
|
|
85
|
+
### creating release
|
|
86
|
+
|
|
87
|
+
- run `pdm release RULE` to release a new version where RULE determines which part of
|
|
88
|
+
the version to update and is one of `major`, `minor`, `patch`.
|
|
89
|
+
|
|
90
|
+
### container workflow
|
|
91
|
+
|
|
92
|
+
- build image with `make image`
|
|
93
|
+
- run directly using docker `make run`
|
|
94
|
+
- start with docker compose `make start`
|
|
95
|
+
|
|
96
|
+
## commands
|
|
97
|
+
|
|
98
|
+
- run `pdm release VERSION` to release a new version where VERSION matches the regular
|
|
99
|
+
expression: `\d{1,4}\.\d{1,4}\.\d{1,4}`.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "mex-release"
|
|
3
|
+
version = "0.2.0"
|
|
4
|
+
description = "Create new release with `pdm release VERSION`"
|
|
5
|
+
authors = [
|
|
6
|
+
{ name = "MEx Team", email = "mex@rki.de" },
|
|
7
|
+
]
|
|
8
|
+
requires-python = "<3.13,>=3.11"
|
|
9
|
+
dependencies = [
|
|
10
|
+
"pdm>=2.13.2,<3.0",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
[project.readme]
|
|
14
|
+
file = "README.md"
|
|
15
|
+
content-type = "text/markdown"
|
|
16
|
+
|
|
17
|
+
[project.license]
|
|
18
|
+
file = "LICENSE"
|
|
19
|
+
|
|
20
|
+
[project.urls]
|
|
21
|
+
Repository = "https://github.com/robert-koch-institut/mex-release"
|
|
22
|
+
|
|
23
|
+
[project.optional-dependencies]
|
|
24
|
+
dev = [
|
|
25
|
+
"ipdb>=0.13.13,<1",
|
|
26
|
+
"mypy>=1.11.0,<2",
|
|
27
|
+
"ruff>=0.5.4,<1",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.entry-points.pdm]
|
|
31
|
+
release = "release:release"
|
|
32
|
+
|
|
33
|
+
[tool.cruft]
|
|
34
|
+
template = "https://github.com/robert-koch-institut/mex-template"
|
|
35
|
+
skip = [
|
|
36
|
+
"CHANGELOG.md",
|
|
37
|
+
"mex",
|
|
38
|
+
"tests",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[tool.ipdb]
|
|
42
|
+
context = 5
|
|
43
|
+
|
|
44
|
+
[tool.mypy]
|
|
45
|
+
python_version = "3.11"
|
|
46
|
+
show_error_codes = true
|
|
47
|
+
strict = true
|
|
48
|
+
plugins = [
|
|
49
|
+
"pydantic.mypy",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[tool.pdm]
|
|
53
|
+
distribution = true
|
|
54
|
+
|
|
55
|
+
[tool.pdm.scripts.update-all]
|
|
56
|
+
cmd = "pdm update --group :all --update-all --save-compatible"
|
|
57
|
+
|
|
58
|
+
[tool.pdm.scripts.lock-all]
|
|
59
|
+
cmd = "pdm lock --group :all --python='==3.11.*'"
|
|
60
|
+
|
|
61
|
+
[tool.pdm.scripts.install-all]
|
|
62
|
+
cmd = "pdm install --group :all --frozen-lockfile"
|
|
63
|
+
|
|
64
|
+
[tool.pdm.scripts.export-all]
|
|
65
|
+
cmd = "pdm export --group :all --no-hashes -f requirements"
|
|
66
|
+
|
|
67
|
+
[tool.pdm.scripts.apidoc]
|
|
68
|
+
cmd = "pdm run sphinx-apidoc -f -o docs/source mex"
|
|
69
|
+
|
|
70
|
+
[tool.pdm.scripts.sphinx]
|
|
71
|
+
cmd = "pdm run sphinx-build -aE -b dirhtml docs docs/dist"
|
|
72
|
+
|
|
73
|
+
[tool.pdm.scripts.doc]
|
|
74
|
+
composite = [
|
|
75
|
+
"apidoc",
|
|
76
|
+
"sphinx",
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
[tool.pdm.scripts.wheel]
|
|
80
|
+
cmd = "pdm build --no-sdist"
|
|
81
|
+
|
|
82
|
+
[tool.pdm.scripts.mypy-daemon]
|
|
83
|
+
cmd = "pdm run dmypy run --timeout 7200 -- mex"
|
|
84
|
+
|
|
85
|
+
[tool.pdm.scripts.lint]
|
|
86
|
+
cmd = "pre-commit run --all-files"
|
|
87
|
+
|
|
88
|
+
[tool.pdm.scripts.unit]
|
|
89
|
+
cmd = "pdm run pytest -m 'not integration'"
|
|
90
|
+
|
|
91
|
+
[tool.pdm.scripts.test]
|
|
92
|
+
cmd = "pdm run pytest --numprocesses=auto --dist=worksteal"
|
|
93
|
+
|
|
94
|
+
[tool.pdm.scripts.all]
|
|
95
|
+
composite = [
|
|
96
|
+
"install-all",
|
|
97
|
+
"lint",
|
|
98
|
+
"test",
|
|
99
|
+
"doc",
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
[tool.pydantic-mypy]
|
|
103
|
+
warn_untyped_fields = true
|
|
104
|
+
|
|
105
|
+
[tool.pytest.ini_options]
|
|
106
|
+
addopts = [
|
|
107
|
+
"--verbose",
|
|
108
|
+
"--cov",
|
|
109
|
+
"--no-cov-on-fail",
|
|
110
|
+
"--cov-report=term-missing:skip-covered",
|
|
111
|
+
"--cov-fail-under=95",
|
|
112
|
+
"--cov-branch",
|
|
113
|
+
"--pdbcls=IPython.terminal.debugger:TerminalPdb",
|
|
114
|
+
"--random-order-bucket=global",
|
|
115
|
+
]
|
|
116
|
+
markers = "integration: mark a test as integration test"
|
|
117
|
+
|
|
118
|
+
[tool.ruff]
|
|
119
|
+
fix = true
|
|
120
|
+
line-length = 88
|
|
121
|
+
show-fixes = true
|
|
122
|
+
|
|
123
|
+
[tool.ruff.format]
|
|
124
|
+
docstring-code-format = true
|
|
125
|
+
|
|
126
|
+
[tool.ruff.lint]
|
|
127
|
+
ignore = [
|
|
128
|
+
"D100",
|
|
129
|
+
"D104",
|
|
130
|
+
"D106",
|
|
131
|
+
"D203",
|
|
132
|
+
"D213",
|
|
133
|
+
"D406",
|
|
134
|
+
"D407",
|
|
135
|
+
"D413",
|
|
136
|
+
"N805",
|
|
137
|
+
"N815",
|
|
138
|
+
"RUF012",
|
|
139
|
+
]
|
|
140
|
+
select = [
|
|
141
|
+
"A",
|
|
142
|
+
"B",
|
|
143
|
+
"C90",
|
|
144
|
+
"D",
|
|
145
|
+
"E",
|
|
146
|
+
"ERA",
|
|
147
|
+
"F",
|
|
148
|
+
"I",
|
|
149
|
+
"N",
|
|
150
|
+
"PERF",
|
|
151
|
+
"RET",
|
|
152
|
+
"RUF",
|
|
153
|
+
"S",
|
|
154
|
+
"T10",
|
|
155
|
+
"T20",
|
|
156
|
+
"UP",
|
|
157
|
+
"W",
|
|
158
|
+
]
|
|
159
|
+
|
|
160
|
+
[tool.ruff.lint.per-file-ignores]
|
|
161
|
+
"tests/**" = [
|
|
162
|
+
"D101",
|
|
163
|
+
"D102",
|
|
164
|
+
"D103",
|
|
165
|
+
"D107",
|
|
166
|
+
"E501",
|
|
167
|
+
"N807",
|
|
168
|
+
"S101",
|
|
169
|
+
]
|
|
170
|
+
|
|
171
|
+
[tool.ruff.lint.pydocstyle]
|
|
172
|
+
convention = "google"
|
|
173
|
+
|
|
174
|
+
[build-system]
|
|
175
|
+
requires = [
|
|
176
|
+
"pdm-backend==2.4.1",
|
|
177
|
+
]
|
|
178
|
+
build-backend = "pdm.backend"
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import re
|
|
3
|
+
import subprocess
|
|
4
|
+
from datetime import date
|
|
5
|
+
|
|
6
|
+
from pdm import termui
|
|
7
|
+
from pdm.cli.commands.base import BaseCommand
|
|
8
|
+
from pdm.core import Core
|
|
9
|
+
from pdm.project import Project
|
|
10
|
+
from pdm.project.project_file import PyProject
|
|
11
|
+
|
|
12
|
+
CHANGELOG_TEMPLATE = """
|
|
13
|
+
## [Unreleased]
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
### Changes
|
|
18
|
+
|
|
19
|
+
### Deprecated
|
|
20
|
+
|
|
21
|
+
### Removed
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
### Security
|
|
26
|
+
|
|
27
|
+
## [{version}] - {date}
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ReleaseCommand(BaseCommand):
|
|
32
|
+
"""Set project version to the given version."""
|
|
33
|
+
|
|
34
|
+
def add_arguments(self, parser: argparse.ArgumentParser) -> None:
|
|
35
|
+
"""Manipulate the argument parser to add more arguments."""
|
|
36
|
+
parser.add_argument(
|
|
37
|
+
"bump",
|
|
38
|
+
choices=("major", "minor", "patch"),
|
|
39
|
+
default="patch",
|
|
40
|
+
help="part of the project version to update",
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
def handle(self, project: Project, options: argparse.Namespace) -> None:
|
|
44
|
+
"""Execute the release command."""
|
|
45
|
+
releaser = Releaser(project.pyproject, options.bump)
|
|
46
|
+
releaser.release()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class Releaser:
|
|
50
|
+
"""Wrap the release functionality in a single object."""
|
|
51
|
+
|
|
52
|
+
def __init__(self, pyproject: PyProject, bump: str) -> None:
|
|
53
|
+
"""Create a new releaser instance."""
|
|
54
|
+
self.bump = bump
|
|
55
|
+
self.pyproject = pyproject
|
|
56
|
+
|
|
57
|
+
def run(self, *args: str) -> str:
|
|
58
|
+
"""Run a command as subproccess, first print it, later print the output."""
|
|
59
|
+
self.pyproject.ui.echo(" ".join(args))
|
|
60
|
+
# use noqa because we check user input (bump) and all other args are hard
|
|
61
|
+
# coded
|
|
62
|
+
stdout = subprocess.check_output(args).decode("utf-8") # noqa: S603
|
|
63
|
+
self.pyproject.ui.echo(
|
|
64
|
+
stdout,
|
|
65
|
+
verbosity=termui.Verbosity.NORMAL,
|
|
66
|
+
)
|
|
67
|
+
return stdout.strip()
|
|
68
|
+
|
|
69
|
+
def check_working_tree(self) -> None:
|
|
70
|
+
"""Only continue if working tree is empty."""
|
|
71
|
+
if self.run("git", "status", "--short"):
|
|
72
|
+
raise RuntimeError(
|
|
73
|
+
"Working tree is dirty. Can only release clean working tree."
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
def check_default_branch(self) -> None:
|
|
77
|
+
"""Only continue if default branch is checked out."""
|
|
78
|
+
git_branch = self.run("git", "rev-parse", "--abbrev-ref", "HEAD")
|
|
79
|
+
git_origin_branches = self.run("git", "remote", "show", "origin")
|
|
80
|
+
git_default_branch = re.findall(
|
|
81
|
+
r"HEAD branch: (\S+)", str(git_origin_branches)
|
|
82
|
+
)[0]
|
|
83
|
+
if git_branch != git_default_branch:
|
|
84
|
+
raise RuntimeError(
|
|
85
|
+
"Not on default branch. Can only release on default branch."
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
def check_version_string(self) -> None:
|
|
89
|
+
"""Validate the version string to format `0.3.14`."""
|
|
90
|
+
if not re.match(
|
|
91
|
+
r"\d{1,4}\.\d{1,4}\.\d{1,4}", self.pyproject.metadata["version"]
|
|
92
|
+
):
|
|
93
|
+
raise RuntimeError("Current version string does not match expected format.")
|
|
94
|
+
|
|
95
|
+
def release(self) -> None:
|
|
96
|
+
"""Execute the release command."""
|
|
97
|
+
self.check_working_tree()
|
|
98
|
+
self.check_default_branch()
|
|
99
|
+
self.check_version_string()
|
|
100
|
+
|
|
101
|
+
# update project version in toml
|
|
102
|
+
major, minor, patch = self.pyproject.metadata["version"].split(".")
|
|
103
|
+
if self.bump == "major":
|
|
104
|
+
new_version = f"{int(major) + 1}.0.0"
|
|
105
|
+
elif self.bump == "minor":
|
|
106
|
+
new_version = f"{major}.{int(minor) + 1}.0"
|
|
107
|
+
elif self.bump == "patch":
|
|
108
|
+
new_version = f"{major}.{minor}.{int(patch) + 1}"
|
|
109
|
+
else:
|
|
110
|
+
raise Exception("Unexpected bump value.")
|
|
111
|
+
self.pyproject.metadata["version"] = new_version
|
|
112
|
+
self.pyproject.write()
|
|
113
|
+
|
|
114
|
+
# rollover changelog sections
|
|
115
|
+
with open("CHANGELOG.md") as fh:
|
|
116
|
+
changelog = fh.read()
|
|
117
|
+
# remove empty subsections
|
|
118
|
+
changelog = re.sub(r"^### [A-Za-z]+\s+(?=#)", "", changelog, flags=re.MULTILINE)
|
|
119
|
+
# add a new unreleased section
|
|
120
|
+
changelog = changelog.replace(
|
|
121
|
+
"\n## [Unreleased]\n",
|
|
122
|
+
CHANGELOG_TEMPLATE.format(version=new_version, date=date.today()),
|
|
123
|
+
)
|
|
124
|
+
with open("CHANGELOG.md", "w") as fh:
|
|
125
|
+
fh.write(changelog)
|
|
126
|
+
self.pyproject.ui.echo(
|
|
127
|
+
"Changes are written to [success]CHANGELOG.md[/].",
|
|
128
|
+
verbosity=termui.Verbosity.NORMAL,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# commit, tag and push
|
|
132
|
+
self.run(
|
|
133
|
+
"git",
|
|
134
|
+
"commit",
|
|
135
|
+
"-m",
|
|
136
|
+
f"bump version to {new_version}",
|
|
137
|
+
"CHANGELOG.md",
|
|
138
|
+
"pyproject.toml",
|
|
139
|
+
)
|
|
140
|
+
self.run("git", "tag", f"{new_version}")
|
|
141
|
+
self.run("git", "push")
|
|
142
|
+
self.run("git", "push", "--tags")
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def release(core: Core) -> None:
|
|
146
|
+
"""Register the release command as a pdm command."""
|
|
147
|
+
core.register_command(ReleaseCommand, "release")
|