common-python-tasks 0.8.0__tar.gz → 0.10.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.
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/PKG-INFO +35 -25
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/README.md +34 -24
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/pyproject.toml +0 -8
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/scripts/add_common_python_tasks.py +8 -41
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/scripts/update_readme_tasks_table.py +0 -2
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/scripts/utils.py +2 -1
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/__init__.py +7 -3
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/data/fastapi/compose-base.yml.j2 +1 -2
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/data/fastapi/compose-db.yml.j2 +1 -2
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/data/fastapi/compose-debug.yml.j2 +1 -1
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/data/generic/.dockerignore +1 -1
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/data/generic/Dockerfile.deps.j2 +6 -1
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/data/generic/Dockerfile.j2 +13 -39
- common_python_tasks-0.10.0/src/common_python_tasks/data/generic/ruff.toml +2 -0
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/docker.py +7 -24
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/docker_compose.py +17 -20
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/env.py +89 -2
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/git.py +2 -2
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/github.py +20 -1
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/project.py +127 -297
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/tasks.py +28 -18
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/utils.py +14 -6
- common_python_tasks-0.8.0/src/common_python_tasks/data/generic/ruff.toml +0 -2
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/.gitignore +0 -0
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/.poetry/plugins/poetry_dynamic_versioning-1.10.0.dist-info/licenses/LICENSE +0 -0
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/.poetry/plugins/poetry_plugin_export-1.10.0.dist-info/licenses/LICENSE +0 -0
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/LICENSE +0 -0
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/scripts/__init__.py +0 -0
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/scripts/readme_tasks_table.py +0 -0
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/scripts/release_script.py +0 -0
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/__main__.py +0 -0
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/data/dockerfile_extensions/.gitkeep +0 -0
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/data/fastapi/alembic.ini.j2 +0 -0
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/data/fastapi/compose-db-debug.yml.j2 +0 -0
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/data/generic/.coveragerc +0 -0
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/data/generic/cliff.toml +0 -0
- {common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/data/generic/pytest.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: common-python-tasks
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.0
|
|
4
4
|
Summary: Opinionated Poe the Poet tasks for Python package development.
|
|
5
5
|
Project-URL: Homepage, http://github.com/ci-sourcerer/common-python-tasks
|
|
6
6
|
Project-URL: Source, http://github.com/ci-sourcerer/common-python-tasks.git
|
|
@@ -43,9 +43,7 @@ It supplies sensible defaults for formatting, linting, testing, packaging, relea
|
|
|
43
43
|
Add `common-python-tasks` as a development dependency from your project root.
|
|
44
44
|
|
|
45
45
|
```shell
|
|
46
|
-
uv add --dev common-python-tasks==0.
|
|
47
|
-
# or, for Poetry projects
|
|
48
|
-
poetry add --group dev common-python-tasks==0.8.0
|
|
46
|
+
uv add --dev common-python-tasks==0.10.0
|
|
49
47
|
```
|
|
50
48
|
|
|
51
49
|
Configure Poe the Poet to expose the default `common` task set.
|
|
@@ -70,7 +68,7 @@ The helper script performs the same development-dependency installation and Poe
|
|
|
70
68
|
```shell
|
|
71
69
|
curl --fail --silent --show-error --location \
|
|
72
70
|
--output /tmp/add_common_python_tasks.py \
|
|
73
|
-
https://raw.githubusercontent.com/ci-sourcerer/common-python-tasks/v0.
|
|
71
|
+
https://raw.githubusercontent.com/ci-sourcerer/common-python-tasks/v0.10.0/scripts/add_common_python_tasks.py
|
|
74
72
|
```
|
|
75
73
|
|
|
76
74
|
Review the downloaded script before executing it.
|
|
@@ -82,10 +80,10 @@ less /tmp/add_common_python_tasks.py
|
|
|
82
80
|
Run the reviewed script with the same pinned package version.
|
|
83
81
|
|
|
84
82
|
```shell
|
|
85
|
-
COMMON_PYTHON_TASKS_VERSION=0.
|
|
83
|
+
COMMON_PYTHON_TASKS_VERSION=0.10.0 python3 /tmp/add_common_python_tasks.py
|
|
86
84
|
```
|
|
87
85
|
|
|
88
|
-
To install another release, replace both occurrences of `0.
|
|
86
|
+
To install another release, replace both occurrences of `0.10.0` with that release's version.
|
|
89
87
|
|
|
90
88
|
## Available tasks
|
|
91
89
|
|
|
@@ -108,7 +106,7 @@ The generated tables below list public tasks only. Tags identify which tasks are
|
|
|
108
106
|
| --- | --- | --- |
|
|
109
107
|
| `publish-package` | Publish the package to the PyPI server. | common, packaging |
|
|
110
108
|
| `publish-github-release` | Publish or update a GitHub Release for the current repository. | common, packaging, release |
|
|
111
|
-
| `update-dependencies` | Update project dependencies with
|
|
109
|
+
| `update-dependencies` | Update project dependencies with uv. | common, packaging |
|
|
112
110
|
| `build-package` | Build the package (wheel and sdist). | build, common, packaging |
|
|
113
111
|
| `bump-version` | Bump the project version. | common, packaging |
|
|
114
112
|
| `changelog` | Print the changelog for the current version based on git history and git-cliff. | common, packaging, release |
|
|
@@ -143,7 +141,7 @@ The generated tables below list public tasks only. Tags identify which tasks are
|
|
|
143
141
|
|
|
144
142
|
Every project needs a `pyproject.toml` file at its root and Poe the Poet available in its development environment.
|
|
145
143
|
|
|
146
|
-
Tasks that install, build, publish, or update dependencies
|
|
144
|
+
Tasks that install, build, publish, or update dependencies require uv. Package and release tasks need a resolvable project version from `project.version` or Git tags. Dynamic versioning is supported but is not a baseline requirement.
|
|
147
145
|
|
|
148
146
|
### Task selection
|
|
149
147
|
|
|
@@ -163,18 +161,27 @@ include_script = "common_python_tasks:tasks(include_tags=['common', 'containers'
|
|
|
163
161
|
|
|
164
162
|
The `containers` tag also includes container-based development-stack tasks. Use the tags in the task tables to tailor a smaller task set.
|
|
165
163
|
|
|
166
|
-
### Package
|
|
164
|
+
### Package management
|
|
167
165
|
|
|
168
|
-
Packaging-related tasks, including `build-package`, `publish-package`, release version resolution, and container build metadata,
|
|
166
|
+
Packaging-related tasks, including `build-package`, `publish-package`, dependency updates, release version resolution, and container build metadata, use uv exclusively. The `uv` executable must be available on `PATH`.
|
|
169
167
|
|
|
170
|
-
|
|
168
|
+
### Publish target selection
|
|
171
169
|
|
|
172
|
-
|
|
173
|
-
2. `COMMON_PYTHON_TASKS_BUILD_TOOL`
|
|
174
|
-
3. `PACKAGE_MANAGER`
|
|
175
|
-
4. Auto-discovery (`auto`) based on installed tools and project metadata
|
|
170
|
+
The `publish-package` task resolves publish targets with this precedence.
|
|
176
171
|
|
|
177
|
-
|
|
172
|
+
1. Explicit task arguments (`repository` or `repository_url`)
|
|
173
|
+
2. Environment-variable fallback
|
|
174
|
+
3. uv project configuration fallback from `[[tool.uv.index]]`
|
|
175
|
+
4. The `uv publish` default
|
|
176
|
+
|
|
177
|
+
uv prefers named publish indexes.
|
|
178
|
+
|
|
179
|
+
- `COMMON_PYTHON_TASKS_PUBLISH_REPOSITORY`
|
|
180
|
+
- `UV_PUBLISH_INDEX`
|
|
181
|
+
- `COMMON_PYTHON_TASKS_PUBLISH_URL`
|
|
182
|
+
- `UV_PUBLISH_URL`
|
|
183
|
+
|
|
184
|
+
When using uv project configuration fallback, `[[tool.uv.index]]` must include both `name` and `publish-url` for publish selection. If multiple publishable indexes exist, set exactly one `default = true` or pass an explicit repository.
|
|
178
185
|
|
|
179
186
|
### Configuration precedence
|
|
180
187
|
|
|
@@ -196,7 +203,7 @@ After installing the package, a minimal project configuration looks like this.
|
|
|
196
203
|
```toml
|
|
197
204
|
[project]
|
|
198
205
|
name = "simple-cli-tool"
|
|
199
|
-
version = "0.
|
|
206
|
+
version = "0.10.0"
|
|
200
207
|
|
|
201
208
|
[tool.poe]
|
|
202
209
|
include_script = "common_python_tasks:tasks()"
|
|
@@ -232,14 +239,16 @@ addopts = "-ra"
|
|
|
232
239
|
#### Project and package settings
|
|
233
240
|
|
|
234
241
|
- `PACKAGE_NAME`: Overrides the package name inferred from `pyproject.toml`
|
|
235
|
-
- `
|
|
236
|
-
- `
|
|
237
|
-
- `
|
|
242
|
+
- `COMMON_PYTHON_TASKS_PUBLISH_REPOSITORY`: Preferred publish repository/index name for `publish-package`
|
|
243
|
+
- `COMMON_PYTHON_TASKS_PUBLISH_URL`: Preferred uv publish upload URL for `publish-package` when no repository/index is selected
|
|
244
|
+
- `UV_PUBLISH_INDEX`: uv publish-index fallback for `publish-package`
|
|
245
|
+
- `UV_PUBLISH_URL`: uv publish upload-url fallback for `publish-package`
|
|
238
246
|
|
|
239
247
|
#### Container image settings
|
|
240
248
|
|
|
241
249
|
- `CONTAINER_REGISTRY_USERNAME`: Container-registry username for image tagging; the default is the current local user
|
|
242
250
|
- `CONTAINER_REGISTRY_URL`: Registry URL with a default of `docker.io/{username}`
|
|
251
|
+
- `CONTAINER_PYTHON_VARIANT`: Python base-image variant such as `slim`, `alpine`, etc. See <https://hub.docker.com/_/python> for available options. Defaults to `slim`; set to empty string for no variant (e.g., `FROM python:3.11`). The value is passed as the `PYTHON_VARIANT` Docker build argument and recorded in the `org.opencontainers.image.python.variant` image label.
|
|
243
252
|
- `CONTAINER_DOCKER_BUILD_ARGS`: Additional arguments passed directly to `docker build`, parsed using shell quoting rules. Free arguments provided to the task after `--` take precedence.
|
|
244
253
|
- `CONTAINER_DOCKERFILE_HOOK_PATH`: Optional host path to an executable hook script that receives the generated Dockerfile path and can modify the file before `docker build` runs.
|
|
245
254
|
- `CONTAINER_APT_PACKAGES`: Space-delimited system packages installed in the generated image
|
|
@@ -255,6 +264,7 @@ addopts = "-ra"
|
|
|
255
264
|
- `CONTAINER_DEPS_MAPPINGS`: Space-delimited `name:/target/path` entries for copying items from `/tmp/deps`. It is used only when no dependency move script is set.
|
|
256
265
|
- `CONTAINER_DEPS_MOVE_SCRIPT`: Raw executable script to run after `/tmp/deps` is copied into the image
|
|
257
266
|
- `CONTAINER_DEPS_MOVE_SCRIPT_PATH`: Host path to a dependency move script. This takes precedence over `CONTAINER_DEPS_MOVE_SCRIPT`.
|
|
267
|
+
- `UV_INDEX_{name}_USERNAME` and `UV_INDEX_{name}_PASSWORD`: Private Python index credentials consumed by uv during the Docker build. When any of these are set, the task automatically passes them as BuildKit secrets (`--secret id=uv_index_{name}_username,env=...`) and renders matching `--mount=type=secret` directives in the builder stage so uv can authenticate without baking credentials into the image. Multiple indices are supported; replace `{name}` with the uppercase index name (hyphens as underscores). These can be set in `tool.poe.env` for CI/CD or in the local environment for development.
|
|
258
268
|
|
|
259
269
|
#### Release settings
|
|
260
270
|
|
|
@@ -386,7 +396,7 @@ GITHUB_RELEASE_ASSETS="dist/*.whl:dist/*.tar.gz" poe publish-github-release
|
|
|
386
396
|
|
|
387
397
|
### Container build fails with "unable to find package"
|
|
388
398
|
|
|
389
|
-
Check that `pyproject.toml` has a correct package name and the package-discovery settings required by its build backend. For
|
|
399
|
+
Check that `pyproject.toml` has a correct package name and the package-discovery settings required by its build backend. For a `src` layout built with Hatch, configure `[tool.hatch.build.targets.wheel] packages = ["src/your_package"]`.
|
|
390
400
|
|
|
391
401
|
### Stack fails to start or services cannot connect
|
|
392
402
|
|
|
@@ -411,9 +421,9 @@ Ensure the project-root `.env` file is writable and inspect its permissions with
|
|
|
411
421
|
|
|
412
422
|
See the [standard Dockerfile template](src/common_python_tasks/data/generic/Dockerfile.j2) for the implementation.
|
|
413
423
|
|
|
414
|
-
- Multi-stage build: The build stage installs
|
|
415
|
-
- Cache mounts: Pip and
|
|
416
|
-
- Explicit build metadata: `PYTHON_VERSION`, `
|
|
424
|
+
- Multi-stage build: The build stage installs uv and builds a wheel. The runtime stage installs only the wheel to keep the final image slim and reproducible.
|
|
425
|
+
- Cache mounts: Pip and uv cache mounts speed up iterative builds without bloating the final image.
|
|
426
|
+
- Explicit build metadata: `PYTHON_VERSION`, `UV_VERSION`, `PACKAGE_VERSION`, `PACKAGE_NAME`, `AUTHORS`, and `GIT_COMMIT` make image metadata predictable and auditable.
|
|
417
427
|
- Project-level build settings: `CONTAINER_APT_PACKAGES`, `CONTAINER_CUSTOM_ENTRYPOINT`, and `CONTAINER_DEPS_IMAGE` configure generated image behavior without being encoded as generic Docker arguments.
|
|
418
428
|
- Optional debug stage: The image exports and installs the `debug` dependency group only when present and does not include it in the default final image.
|
|
419
429
|
- Stable package path: Symlinks give entrypoints and consumers consistent `/pkg` and `/_$PACKAGE_NAME` paths regardless of wheel layout.
|
|
@@ -11,9 +11,7 @@ It supplies sensible defaults for formatting, linting, testing, packaging, relea
|
|
|
11
11
|
Add `common-python-tasks` as a development dependency from your project root.
|
|
12
12
|
|
|
13
13
|
```shell
|
|
14
|
-
uv add --dev common-python-tasks==0.
|
|
15
|
-
# or, for Poetry projects
|
|
16
|
-
poetry add --group dev common-python-tasks==0.8.0
|
|
14
|
+
uv add --dev common-python-tasks==0.10.0
|
|
17
15
|
```
|
|
18
16
|
|
|
19
17
|
Configure Poe the Poet to expose the default `common` task set.
|
|
@@ -38,7 +36,7 @@ The helper script performs the same development-dependency installation and Poe
|
|
|
38
36
|
```shell
|
|
39
37
|
curl --fail --silent --show-error --location \
|
|
40
38
|
--output /tmp/add_common_python_tasks.py \
|
|
41
|
-
https://raw.githubusercontent.com/ci-sourcerer/common-python-tasks/v0.
|
|
39
|
+
https://raw.githubusercontent.com/ci-sourcerer/common-python-tasks/v0.10.0/scripts/add_common_python_tasks.py
|
|
42
40
|
```
|
|
43
41
|
|
|
44
42
|
Review the downloaded script before executing it.
|
|
@@ -50,10 +48,10 @@ less /tmp/add_common_python_tasks.py
|
|
|
50
48
|
Run the reviewed script with the same pinned package version.
|
|
51
49
|
|
|
52
50
|
```shell
|
|
53
|
-
COMMON_PYTHON_TASKS_VERSION=0.
|
|
51
|
+
COMMON_PYTHON_TASKS_VERSION=0.10.0 python3 /tmp/add_common_python_tasks.py
|
|
54
52
|
```
|
|
55
53
|
|
|
56
|
-
To install another release, replace both occurrences of `0.
|
|
54
|
+
To install another release, replace both occurrences of `0.10.0` with that release's version.
|
|
57
55
|
|
|
58
56
|
## Available tasks
|
|
59
57
|
|
|
@@ -76,7 +74,7 @@ The generated tables below list public tasks only. Tags identify which tasks are
|
|
|
76
74
|
| --- | --- | --- |
|
|
77
75
|
| `publish-package` | Publish the package to the PyPI server. | common, packaging |
|
|
78
76
|
| `publish-github-release` | Publish or update a GitHub Release for the current repository. | common, packaging, release |
|
|
79
|
-
| `update-dependencies` | Update project dependencies with
|
|
77
|
+
| `update-dependencies` | Update project dependencies with uv. | common, packaging |
|
|
80
78
|
| `build-package` | Build the package (wheel and sdist). | build, common, packaging |
|
|
81
79
|
| `bump-version` | Bump the project version. | common, packaging |
|
|
82
80
|
| `changelog` | Print the changelog for the current version based on git history and git-cliff. | common, packaging, release |
|
|
@@ -111,7 +109,7 @@ The generated tables below list public tasks only. Tags identify which tasks are
|
|
|
111
109
|
|
|
112
110
|
Every project needs a `pyproject.toml` file at its root and Poe the Poet available in its development environment.
|
|
113
111
|
|
|
114
|
-
Tasks that install, build, publish, or update dependencies
|
|
112
|
+
Tasks that install, build, publish, or update dependencies require uv. Package and release tasks need a resolvable project version from `project.version` or Git tags. Dynamic versioning is supported but is not a baseline requirement.
|
|
115
113
|
|
|
116
114
|
### Task selection
|
|
117
115
|
|
|
@@ -131,18 +129,27 @@ include_script = "common_python_tasks:tasks(include_tags=['common', 'containers'
|
|
|
131
129
|
|
|
132
130
|
The `containers` tag also includes container-based development-stack tasks. Use the tags in the task tables to tailor a smaller task set.
|
|
133
131
|
|
|
134
|
-
### Package
|
|
132
|
+
### Package management
|
|
135
133
|
|
|
136
|
-
Packaging-related tasks, including `build-package`, `publish-package`, release version resolution, and container build metadata,
|
|
134
|
+
Packaging-related tasks, including `build-package`, `publish-package`, dependency updates, release version resolution, and container build metadata, use uv exclusively. The `uv` executable must be available on `PATH`.
|
|
137
135
|
|
|
138
|
-
|
|
136
|
+
### Publish target selection
|
|
139
137
|
|
|
140
|
-
|
|
141
|
-
2. `COMMON_PYTHON_TASKS_BUILD_TOOL`
|
|
142
|
-
3. `PACKAGE_MANAGER`
|
|
143
|
-
4. Auto-discovery (`auto`) based on installed tools and project metadata
|
|
138
|
+
The `publish-package` task resolves publish targets with this precedence.
|
|
144
139
|
|
|
145
|
-
|
|
140
|
+
1. Explicit task arguments (`repository` or `repository_url`)
|
|
141
|
+
2. Environment-variable fallback
|
|
142
|
+
3. uv project configuration fallback from `[[tool.uv.index]]`
|
|
143
|
+
4. The `uv publish` default
|
|
144
|
+
|
|
145
|
+
uv prefers named publish indexes.
|
|
146
|
+
|
|
147
|
+
- `COMMON_PYTHON_TASKS_PUBLISH_REPOSITORY`
|
|
148
|
+
- `UV_PUBLISH_INDEX`
|
|
149
|
+
- `COMMON_PYTHON_TASKS_PUBLISH_URL`
|
|
150
|
+
- `UV_PUBLISH_URL`
|
|
151
|
+
|
|
152
|
+
When using uv project configuration fallback, `[[tool.uv.index]]` must include both `name` and `publish-url` for publish selection. If multiple publishable indexes exist, set exactly one `default = true` or pass an explicit repository.
|
|
146
153
|
|
|
147
154
|
### Configuration precedence
|
|
148
155
|
|
|
@@ -164,7 +171,7 @@ After installing the package, a minimal project configuration looks like this.
|
|
|
164
171
|
```toml
|
|
165
172
|
[project]
|
|
166
173
|
name = "simple-cli-tool"
|
|
167
|
-
version = "0.
|
|
174
|
+
version = "0.10.0"
|
|
168
175
|
|
|
169
176
|
[tool.poe]
|
|
170
177
|
include_script = "common_python_tasks:tasks()"
|
|
@@ -200,14 +207,16 @@ addopts = "-ra"
|
|
|
200
207
|
#### Project and package settings
|
|
201
208
|
|
|
202
209
|
- `PACKAGE_NAME`: Overrides the package name inferred from `pyproject.toml`
|
|
203
|
-
- `
|
|
204
|
-
- `
|
|
205
|
-
- `
|
|
210
|
+
- `COMMON_PYTHON_TASKS_PUBLISH_REPOSITORY`: Preferred publish repository/index name for `publish-package`
|
|
211
|
+
- `COMMON_PYTHON_TASKS_PUBLISH_URL`: Preferred uv publish upload URL for `publish-package` when no repository/index is selected
|
|
212
|
+
- `UV_PUBLISH_INDEX`: uv publish-index fallback for `publish-package`
|
|
213
|
+
- `UV_PUBLISH_URL`: uv publish upload-url fallback for `publish-package`
|
|
206
214
|
|
|
207
215
|
#### Container image settings
|
|
208
216
|
|
|
209
217
|
- `CONTAINER_REGISTRY_USERNAME`: Container-registry username for image tagging; the default is the current local user
|
|
210
218
|
- `CONTAINER_REGISTRY_URL`: Registry URL with a default of `docker.io/{username}`
|
|
219
|
+
- `CONTAINER_PYTHON_VARIANT`: Python base-image variant such as `slim`, `alpine`, etc. See <https://hub.docker.com/_/python> for available options. Defaults to `slim`; set to empty string for no variant (e.g., `FROM python:3.11`). The value is passed as the `PYTHON_VARIANT` Docker build argument and recorded in the `org.opencontainers.image.python.variant` image label.
|
|
211
220
|
- `CONTAINER_DOCKER_BUILD_ARGS`: Additional arguments passed directly to `docker build`, parsed using shell quoting rules. Free arguments provided to the task after `--` take precedence.
|
|
212
221
|
- `CONTAINER_DOCKERFILE_HOOK_PATH`: Optional host path to an executable hook script that receives the generated Dockerfile path and can modify the file before `docker build` runs.
|
|
213
222
|
- `CONTAINER_APT_PACKAGES`: Space-delimited system packages installed in the generated image
|
|
@@ -223,6 +232,7 @@ addopts = "-ra"
|
|
|
223
232
|
- `CONTAINER_DEPS_MAPPINGS`: Space-delimited `name:/target/path` entries for copying items from `/tmp/deps`. It is used only when no dependency move script is set.
|
|
224
233
|
- `CONTAINER_DEPS_MOVE_SCRIPT`: Raw executable script to run after `/tmp/deps` is copied into the image
|
|
225
234
|
- `CONTAINER_DEPS_MOVE_SCRIPT_PATH`: Host path to a dependency move script. This takes precedence over `CONTAINER_DEPS_MOVE_SCRIPT`.
|
|
235
|
+
- `UV_INDEX_{name}_USERNAME` and `UV_INDEX_{name}_PASSWORD`: Private Python index credentials consumed by uv during the Docker build. When any of these are set, the task automatically passes them as BuildKit secrets (`--secret id=uv_index_{name}_username,env=...`) and renders matching `--mount=type=secret` directives in the builder stage so uv can authenticate without baking credentials into the image. Multiple indices are supported; replace `{name}` with the uppercase index name (hyphens as underscores). These can be set in `tool.poe.env` for CI/CD or in the local environment for development.
|
|
226
236
|
|
|
227
237
|
#### Release settings
|
|
228
238
|
|
|
@@ -354,7 +364,7 @@ GITHUB_RELEASE_ASSETS="dist/*.whl:dist/*.tar.gz" poe publish-github-release
|
|
|
354
364
|
|
|
355
365
|
### Container build fails with "unable to find package"
|
|
356
366
|
|
|
357
|
-
Check that `pyproject.toml` has a correct package name and the package-discovery settings required by its build backend. For
|
|
367
|
+
Check that `pyproject.toml` has a correct package name and the package-discovery settings required by its build backend. For a `src` layout built with Hatch, configure `[tool.hatch.build.targets.wheel] packages = ["src/your_package"]`.
|
|
358
368
|
|
|
359
369
|
### Stack fails to start or services cannot connect
|
|
360
370
|
|
|
@@ -379,9 +389,9 @@ Ensure the project-root `.env` file is writable and inspect its permissions with
|
|
|
379
389
|
|
|
380
390
|
See the [standard Dockerfile template](src/common_python_tasks/data/generic/Dockerfile.j2) for the implementation.
|
|
381
391
|
|
|
382
|
-
- Multi-stage build: The build stage installs
|
|
383
|
-
- Cache mounts: Pip and
|
|
384
|
-
- Explicit build metadata: `PYTHON_VERSION`, `
|
|
392
|
+
- Multi-stage build: The build stage installs uv and builds a wheel. The runtime stage installs only the wheel to keep the final image slim and reproducible.
|
|
393
|
+
- Cache mounts: Pip and uv cache mounts speed up iterative builds without bloating the final image.
|
|
394
|
+
- Explicit build metadata: `PYTHON_VERSION`, `UV_VERSION`, `PACKAGE_VERSION`, `PACKAGE_NAME`, `AUTHORS`, and `GIT_COMMIT` make image metadata predictable and auditable.
|
|
385
395
|
- Project-level build settings: `CONTAINER_APT_PACKAGES`, `CONTAINER_CUSTOM_ENTRYPOINT`, and `CONTAINER_DEPS_IMAGE` configure generated image behavior without being encoded as generic Docker arguments.
|
|
386
396
|
- Optional debug stage: The image exports and installs the `debug` dependency group only when present and does not include it in the default final image.
|
|
387
397
|
- Stable package path: Symlinks give entrypoints and consumers consistent `/pkg` and `/_$PACKAGE_NAME` paths regardless of wheel layout.
|
|
@@ -10,11 +10,6 @@ import tomllib
|
|
|
10
10
|
from pathlib import Path
|
|
11
11
|
|
|
12
12
|
PACKAGE_NAME = "common-python-tasks"
|
|
13
|
-
PACKAGE_MANAGER_ENV_VARS = (
|
|
14
|
-
"COMMON_PYTHON_TASKS_PACKAGE_MANAGER",
|
|
15
|
-
"COMMON_PYTHON_TASKS_BUILD_TOOL",
|
|
16
|
-
"PACKAGE_MANAGER",
|
|
17
|
-
)
|
|
18
13
|
PYPROJECT_PATH = Path("pyproject.toml")
|
|
19
14
|
TOOL_POE_PATTERN = re.compile(r"^\s*\[tool\.poe\]\s*(?:#.*)?$")
|
|
20
15
|
TABLE_PATTERN = re.compile(r"^\s*\[")
|
|
@@ -26,47 +21,18 @@ def _require_command(command: str) -> None:
|
|
|
26
21
|
sys.exit(f"Required command not found: {command}")
|
|
27
22
|
|
|
28
23
|
|
|
29
|
-
def _get_requested_package_manager() -> str:
|
|
30
|
-
for env_var in PACKAGE_MANAGER_ENV_VARS:
|
|
31
|
-
if os.getenv(env_var, "").strip():
|
|
32
|
-
return os.environ[env_var].strip().lower()
|
|
33
|
-
return "auto"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def _select_package_manager() -> str:
|
|
37
|
-
requested_manager = _get_requested_package_manager()
|
|
38
|
-
if requested_manager in {"poetry", "uv"}:
|
|
39
|
-
_require_command(requested_manager)
|
|
40
|
-
return requested_manager
|
|
41
|
-
if requested_manager != "auto":
|
|
42
|
-
sys.exit(f"Unsupported package manager: {requested_manager}")
|
|
43
|
-
|
|
44
|
-
for lock_file, package_manager in (
|
|
45
|
-
(Path("uv.lock"), "uv"),
|
|
46
|
-
(Path("poetry.lock"), "poetry"),
|
|
47
|
-
):
|
|
48
|
-
if lock_file.is_file() and shutil.which(package_manager) is not None:
|
|
49
|
-
return package_manager
|
|
50
|
-
|
|
51
|
-
for package_manager in ("uv", "poetry"):
|
|
52
|
-
if shutil.which(package_manager) is not None:
|
|
53
|
-
return package_manager
|
|
54
|
-
|
|
55
|
-
sys.exit("Neither uv nor Poetry is installed.")
|
|
56
|
-
|
|
57
|
-
|
|
58
24
|
def _get_package_requirement() -> str:
|
|
59
25
|
if os.getenv("COMMON_PYTHON_TASKS_VERSION", "").strip():
|
|
60
26
|
return f"{PACKAGE_NAME}=={os.environ['COMMON_PYTHON_TASKS_VERSION'].strip()}"
|
|
61
27
|
return PACKAGE_NAME
|
|
62
28
|
|
|
63
29
|
|
|
64
|
-
def _install_package(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
30
|
+
def _install_package() -> None:
|
|
31
|
+
subprocess.run(
|
|
32
|
+
["uv", "add", "--dev", _get_package_requirement()],
|
|
33
|
+
check=True,
|
|
34
|
+
shell=False,
|
|
35
|
+
)
|
|
70
36
|
|
|
71
37
|
|
|
72
38
|
def _get_include_script() -> str:
|
|
@@ -132,7 +98,8 @@ def _print_available_tasks() -> None:
|
|
|
132
98
|
|
|
133
99
|
def main() -> None:
|
|
134
100
|
"""Install common tasks and configure Poe in the current project."""
|
|
135
|
-
|
|
101
|
+
_require_command("uv")
|
|
102
|
+
_install_package()
|
|
136
103
|
_configure_poe()
|
|
137
104
|
print("\n\033[1;32mCommon Python tasks added to project.\033[0m")
|
|
138
105
|
print("\n\033[1mAvailable tasks:\033[0m")
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import subprocess
|
|
3
|
+
from typing import ClassVar
|
|
3
4
|
|
|
4
5
|
|
|
5
6
|
class ColoredFormatter(logging.Formatter):
|
|
6
7
|
"""Format warning and error log levels with ANSI color codes."""
|
|
7
8
|
|
|
8
|
-
COLORS = {
|
|
9
|
+
COLORS: ClassVar = {
|
|
9
10
|
"WARNING": "\033[93m",
|
|
10
11
|
"ERROR": "\033[91m",
|
|
11
12
|
"CRITICAL": "\033[91m",
|
{common_python_tasks-0.8.0 → common_python_tasks-0.10.0}/src/common_python_tasks/__init__.py
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
3
|
if TYPE_CHECKING:
|
|
4
|
-
from
|
|
4
|
+
from collections.abc import Sequence
|
|
5
5
|
|
|
6
6
|
from poethepoet_tasks import TaskCollection
|
|
7
7
|
|
|
@@ -9,7 +9,8 @@ __all__ = ["TaskCollection"]
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def tasks(
|
|
12
|
-
include_tags: "Sequence[str] | None" = None,
|
|
12
|
+
include_tags: "Sequence[str] | None" = None,
|
|
13
|
+
exclude_tags: "Sequence[str] | None" = None,
|
|
13
14
|
) -> dict:
|
|
14
15
|
"""Return the task collection filtered by the requested tags.
|
|
15
16
|
|
|
@@ -25,6 +26,9 @@ def tasks(
|
|
|
25
26
|
if include_tags is None and not exclude_tags:
|
|
26
27
|
include_tags = ("common",)
|
|
27
28
|
elif include_tags is None:
|
|
28
|
-
include_tags =
|
|
29
|
+
include_tags = ()
|
|
30
|
+
|
|
31
|
+
if exclude_tags is None:
|
|
32
|
+
exclude_tags = ()
|
|
29
33
|
|
|
30
34
|
return task_collection(include_tags=include_tags, exclude_tags=exclude_tags)
|
|
@@ -9,8 +9,7 @@ x-common-environment: &common-environment
|
|
|
9
9
|
x-common-build-args: &common-build-args
|
|
10
10
|
PACKAGE_NAME: ${PACKAGE_NAME}
|
|
11
11
|
PYTHON_VERSION: ${PYTHON_VERSION}
|
|
12
|
-
|
|
13
|
-
PACKAGE_MANAGER_VERSION: ${PACKAGE_MANAGER_VERSION}
|
|
12
|
+
UV_VERSION: ${UV_VERSION}
|
|
14
13
|
|
|
15
14
|
services:
|
|
16
15
|
api:
|
|
@@ -8,8 +8,7 @@ x-common-environment: &common-environment
|
|
|
8
8
|
x-common-build-args: &common-build-args
|
|
9
9
|
PACKAGE_NAME: ${PACKAGE_NAME}
|
|
10
10
|
PYTHON_VERSION: ${PYTHON_VERSION}
|
|
11
|
-
|
|
12
|
-
PACKAGE_MANAGER_VERSION: ${PACKAGE_MANAGER_VERSION}
|
|
11
|
+
UV_VERSION: ${UV_VERSION}
|
|
13
12
|
WORKDIR_PATH: ${WORKDIR_PATH}
|
|
14
13
|
|
|
15
14
|
services:
|
|
@@ -5,7 +5,12 @@
|
|
|
5
5
|
ARG PYTHON_VERSION=3
|
|
6
6
|
ARG PYTHON_VARIANT=slim
|
|
7
7
|
|
|
8
|
-
FROM python:${PYTHON_VERSION}
|
|
8
|
+
FROM python:${PYTHON_VERSION}${PYTHON_VARIANT:+-${PYTHON_VARIANT}} AS deps
|
|
9
|
+
ARG PYTHON_VERSION
|
|
10
|
+
ARG PYTHON_VARIANT
|
|
11
|
+
|
|
12
|
+
LABEL org.opencontainers.image.base.name="python:${PYTHON_VERSION}${PYTHON_VARIANT:+-${PYTHON_VARIANT}}" \
|
|
13
|
+
org.opencontainers.image.python.variant="${PYTHON_VARIANT}"
|
|
9
14
|
|
|
10
15
|
ARG CACHE_ID_SUFFIX
|
|
11
16
|
RUN printf '%s' "$CACHE_ID_SUFFIX" >/tmp/.cache_id_suffix
|
|
@@ -4,36 +4,12 @@
|
|
|
4
4
|
# the latest. The `build-image` task passes the version properly here
|
|
5
5
|
ARG PYTHON_VERSION=3
|
|
6
6
|
# Variant for the runtime image, e.g. slim, alpine, etc.
|
|
7
|
-
# See https://hub.docker.com/_/python for available variants
|
|
7
|
+
# See https://hub.docker.com/_/python for available variants. Leave empty for no variant.
|
|
8
8
|
ARG PYTHON_VARIANT=slim
|
|
9
|
-
ARG WORKDIR_PATH=/workspace
|
|
10
|
-
{% set package_manager = PACKAGE_MANAGER|default('poetry') %}
|
|
11
9
|
|
|
12
10
|
FROM python:${PYTHON_VERSION} AS builder
|
|
13
11
|
|
|
14
12
|
ARG PACKAGE_VERSION
|
|
15
|
-
|
|
16
|
-
{% if package_manager == 'poetry' %}
|
|
17
|
-
ARG POETRY_VERSION
|
|
18
|
-
ARG POETRY_DYNAMIC_VERSIONING_PLUGIN_VERSION
|
|
19
|
-
ARG POETRY_PLUGIN_EXPORT_VERSION
|
|
20
|
-
|
|
21
|
-
# Bypass VCS-based version detection: use the host-computed version directly.
|
|
22
|
-
# This avoids requiring a .git directory in the build context and prevents
|
|
23
|
-
# false dirty-version detection from a partial working tree.
|
|
24
|
-
ENV POETRY_DYNAMIC_VERSIONING_BYPASS=${PACKAGE_VERSION}
|
|
25
|
-
|
|
26
|
-
# Install Poetry and required Poetry plugins for package build
|
|
27
|
-
RUN --mount=type=cache,target=/root/.cache/pip,id=pip-cache{{ CACHE_ID_SUFFIX }} \
|
|
28
|
-
sh -c 'set -eu; \
|
|
29
|
-
poetry_spec="poetry"; \
|
|
30
|
-
if [ -n "${POETRY_VERSION:-}" ]; then poetry_spec="poetry==$POETRY_VERSION"; fi; \
|
|
31
|
-
dynamic_spec="poetry-dynamic-versioning[plugin]"; \
|
|
32
|
-
if [ -n "${POETRY_DYNAMIC_VERSIONING_PLUGIN_VERSION:-}" ]; then dynamic_spec="poetry-dynamic-versioning[plugin]==$POETRY_DYNAMIC_VERSIONING_PLUGIN_VERSION"; fi; \
|
|
33
|
-
export_spec="poetry-plugin-export"; \
|
|
34
|
-
if [ -n "${POETRY_PLUGIN_EXPORT_VERSION:-}" ]; then export_spec="poetry-plugin-export==$POETRY_PLUGIN_EXPORT_VERSION"; fi; \
|
|
35
|
-
pip install --root-user-action=ignore "$poetry_spec" "$dynamic_spec" "$export_spec"'
|
|
36
|
-
{% else %}
|
|
37
13
|
ARG UV_VERSION
|
|
38
14
|
|
|
39
15
|
# Bypass VCS-based version detection: use the host-computed version directly.
|
|
@@ -48,7 +24,6 @@ RUN --mount=type=cache,target=/root/.cache/pip,id=pip-cache{{ CACHE_ID_SUFFIX }}
|
|
|
48
24
|
else \
|
|
49
25
|
pip install --root-user-action=ignore uv; \
|
|
50
26
|
fi'
|
|
51
|
-
{% endif %}
|
|
52
27
|
|
|
53
28
|
# Build package
|
|
54
29
|
WORKDIR /tmp/build
|
|
@@ -56,28 +31,27 @@ COPY . /tmp/build/
|
|
|
56
31
|
|
|
57
32
|
{% if HAS_DEBUG_DEPS %}
|
|
58
33
|
# Export debug requirements when the project defines a debug dependency group
|
|
59
|
-
{%
|
|
60
|
-
|
|
61
|
-
poetry export --only debug --without-hashes -f requirements.txt --output requirements-debug.txt
|
|
62
|
-
{% else %}
|
|
63
|
-
RUN --mount=type=cache,target=/root/.cache/uv,id=uv-cache{{ CACHE_ID_SUFFIX }} \
|
|
34
|
+
RUN --mount=type=cache,target=/root/.cache/uv,id=uv-cache{{ CACHE_ID_SUFFIX }}{% for mount in UV_INDEX_SECRET_MOUNTS %} \
|
|
35
|
+
--mount={{ mount }}{% endfor %} \
|
|
64
36
|
uv export --group debug --no-hashes --format requirements-txt --output-file requirements-debug.txt
|
|
65
37
|
{% endif %}
|
|
66
|
-
{% endif %}
|
|
67
38
|
|
|
68
|
-
# Build the wheel, caching the
|
|
39
|
+
# Build the wheel, caching the uv cache directory to speed up subsequent builds.
|
|
69
40
|
# If running this in a CI system, you must be using a persistent builder to take
|
|
70
41
|
# advantage of the cache mount, and you should configure your CI to persist the
|
|
71
42
|
# cache directory between builds
|
|
72
|
-
{%
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
RUN --mount=type=cache,target=/root/.cache/uv,id=uv-cache{{ CACHE_ID_SUFFIX }} uv build --wheel
|
|
76
|
-
{% endif %}
|
|
43
|
+
RUN --mount=type=cache,target=/root/.cache/uv,id=uv-cache{{ CACHE_ID_SUFFIX }}{% for mount in UV_INDEX_SECRET_MOUNTS %} \
|
|
44
|
+
--mount={{ mount }}{% endfor %} \
|
|
45
|
+
uv build --wheel
|
|
77
46
|
|
|
78
|
-
FROM python:${PYTHON_VERSION}
|
|
47
|
+
FROM python:${PYTHON_VERSION}${PYTHON_VARIANT:+-${PYTHON_VARIANT}} AS runtime
|
|
48
|
+
ARG PYTHON_VERSION
|
|
49
|
+
ARG PYTHON_VARIANT
|
|
79
50
|
ARG WORKDIR_PATH=/workspace
|
|
80
51
|
|
|
52
|
+
LABEL org.opencontainers.image.base.name="python:${PYTHON_VERSION}${PYTHON_VARIANT:+-${PYTHON_VARIANT}}" \
|
|
53
|
+
org.opencontainers.image.python.variant="${PYTHON_VARIANT}"
|
|
54
|
+
|
|
81
55
|
ENV PYTHONUNBUFFERED=1
|
|
82
56
|
ENV PYTHONDONTWRITEBYTECODE=1
|
|
83
57
|
|