project-toolbox 0.1.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.
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: project-toolbox
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Author: Farid Smaï
|
|
6
|
+
Author-email: Farid Smaï <f.smai@brgm.fr>
|
|
7
|
+
Requires-Dist: click>=8.3.1
|
|
8
|
+
Requires-Python: >=3.11
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# project-toolbox
|
|
12
|
+
|
|
13
|
+
```shell
|
|
14
|
+
uv add --dev project-toolbox
|
|
15
|
+
uv run project-toolbox
|
|
16
|
+
uv run release-tag
|
|
17
|
+
```
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "project-toolbox"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Add your description here"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Farid Smaï", email = "f.smai@brgm.fr" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.11"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"click>=8.3.1",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[project.scripts]
|
|
15
|
+
release-tag = "project_toolbox.release_tag:main"
|
|
16
|
+
project-toolbox = "project_toolbox:main"
|
|
17
|
+
|
|
18
|
+
[build-system]
|
|
19
|
+
requires = ["uv_build>=0.9.26,<0.10.0"]
|
|
20
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""project-toolbox -- a collection of tools to help you manage coding projects.
|
|
2
|
+
|
|
3
|
+
Philosophy:
|
|
4
|
+
- projects use git and uv
|
|
5
|
+
- tools automate repetitive tasks
|
|
6
|
+
- tools reduce the number of command to remember
|
|
7
|
+
- tools avoid mistakes by checking project sanity
|
|
8
|
+
|
|
9
|
+
Available tools:
|
|
10
|
+
release-tag Add and push git tag for project release.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main():
|
|
15
|
+
print(__doc__)
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# /// script
|
|
2
|
+
# requires-python = ">=3.11"
|
|
3
|
+
# dependencies = [
|
|
4
|
+
# "click>=8.3.1",
|
|
5
|
+
# ]
|
|
6
|
+
# ///
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
import pathlib
|
|
10
|
+
import tomllib
|
|
11
|
+
import subprocess
|
|
12
|
+
import click
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
DEFAULT_BRANCH = "main"
|
|
16
|
+
PROJECT_FILE = "pyproject.toml"
|
|
17
|
+
INDENT = " " * 4
|
|
18
|
+
BAR = "=" * 80
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_project_file(cwd='.'):
|
|
22
|
+
directory = pathlib.Path(cwd).resolve()
|
|
23
|
+
if not directory.exists():
|
|
24
|
+
return None
|
|
25
|
+
child = None
|
|
26
|
+
while directory != child:
|
|
27
|
+
file = directory / PROJECT_FILE
|
|
28
|
+
if file.exists():
|
|
29
|
+
return file
|
|
30
|
+
child, directory = directory, directory.parent
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def shell(args, **kwds):
|
|
35
|
+
out = subprocess.run(args, encoding="utf8", capture_output=True, **kwds)
|
|
36
|
+
out.stdout = out.stdout.strip()
|
|
37
|
+
out.stderr = out.stderr.strip()
|
|
38
|
+
return out
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@click.command(context_settings={"help_option_names": ['-h', '--help']})
|
|
42
|
+
def main() -> None:
|
|
43
|
+
""" Add and push git tag for project release.
|
|
44
|
+
|
|
45
|
+
It will look for project version, check repo sanity, create tag and push it.
|
|
46
|
+
|
|
47
|
+
\b
|
|
48
|
+
Project version is found in the 'project.version' entry of pyproject.toml.
|
|
49
|
+
A good way to handle that is with `uv version` command:
|
|
50
|
+
Start branch with:
|
|
51
|
+
uv version --bump dev --bump patch
|
|
52
|
+
Close branch with:
|
|
53
|
+
uv version --bump stable
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
# get project file
|
|
57
|
+
project_file = get_project_file()
|
|
58
|
+
if project_file is None:
|
|
59
|
+
click.echo(f"error: unable to find project file ({PROJECT_FILE})", err=True)
|
|
60
|
+
exit(1)
|
|
61
|
+
click.echo(f"Found project file: {project_file}")
|
|
62
|
+
|
|
63
|
+
# get version from project file
|
|
64
|
+
config = tomllib.load(project_file.open("rb"))
|
|
65
|
+
version = config.get("project", {}).get("version", None)
|
|
66
|
+
if version is None:
|
|
67
|
+
click.echo("error: unable to find '[project.version]' key in project file.", err=True)
|
|
68
|
+
exit(1)
|
|
69
|
+
version = version.strip()
|
|
70
|
+
version_tag = f"v{version}"
|
|
71
|
+
click.echo(f"Found version: {version}")
|
|
72
|
+
|
|
73
|
+
# get active branch
|
|
74
|
+
branch = shell(["git", "branch", "--show-current"]).stdout
|
|
75
|
+
if branch != DEFAULT_BRANCH:
|
|
76
|
+
click.echo(f"warning: current branch is '{branch}', should be '{DEFAULT_BRANCH}'")
|
|
77
|
+
if not click.confirm(f"Do you want to release from '{branch}' instead ?"):
|
|
78
|
+
exit(1)
|
|
79
|
+
|
|
80
|
+
# check if repo is clean
|
|
81
|
+
repo_not_clean = shell(["git", "diff-index", "--quiet", "HEAD"]).returncode
|
|
82
|
+
if repo_not_clean:
|
|
83
|
+
click.echo("warning: git repo is not clean, current changes won't be released", err=True)
|
|
84
|
+
if not click.confirm(f"Continue with not clean repo ?"):
|
|
85
|
+
exit(1)
|
|
86
|
+
|
|
87
|
+
# check if new tag already exists
|
|
88
|
+
tags = shell(["git", "tag", "--list"]).stdout.splitlines()
|
|
89
|
+
if version_tag in tags:
|
|
90
|
+
click.echo("error: git tag already exists [{version_tag}]", err=True)
|
|
91
|
+
exit(1)
|
|
92
|
+
|
|
93
|
+
# show commit to be released
|
|
94
|
+
click.echo("Commit to be released:")
|
|
95
|
+
click.echo(BAR)
|
|
96
|
+
subprocess.run(["git", "log", "HEAD^..HEAD"])
|
|
97
|
+
click.echo(BAR)
|
|
98
|
+
|
|
99
|
+
# prepare commands modifying repo
|
|
100
|
+
cmd_git = [
|
|
101
|
+
["git", "tag", "-a", version_tag, "-m", f"\"release of {version_tag}\""],
|
|
102
|
+
["git", "push", "origin", version_tag],
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
# ask confirmation for commands
|
|
106
|
+
click.echo("The following commands will be executed:")
|
|
107
|
+
click.echo("\n".join(INDENT + " ".join(cmd) for cmd in cmd_git))
|
|
108
|
+
if not click.confirm("Confirm execution ?"):
|
|
109
|
+
exit(1)
|
|
110
|
+
|
|
111
|
+
# run commands
|
|
112
|
+
for cmd in cmd_git:
|
|
113
|
+
click.echo(f"running: {' '.join(cmd)}")
|
|
114
|
+
subprocess.run(cmd)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
if __name__ == "__main__":
|
|
118
|
+
main()
|