-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcopier.yml
More file actions
269 lines (209 loc) · 8.47 KB
/
Copy pathcopier.yml
File metadata and controls
269 lines (209 loc) · 8.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
# =================================================================== #
# Copier template configuration #
# Docs: https://copier.readthedocs.io/en/stable/configuring/ #
# =================================================================== #
_subdirectory: template
_templates_suffix: .jinja
_answers_file: .copier-answers.yml
_exclude:
- "copier.yml"
- ".git"
- "__pycache__"
- "*.pyc"
- "*.pyo"
# Drop the publish workflow when it's not needed. Jinja-templated
# excludes are evaluated against the destination path (post-`.jinja`
# strip), so this matches `template/.github/workflows/publish.yml.jinja`'s
# output target and lets that file stay a single source of truth
# with internal `{% if use_testpypi %}` branching for its two shapes.
- "{% if not (is_library and release_automation == 'github-oidc') %}.github/workflows/publish.yml{% endif %}"
# =================================================================== #
# Questions #
# =================================================================== #
# ─── Project identity ───
project_name:
type: str
help: |
Display/PyPI name of the project (lowercase, hyphens allowed).
Example: my-awesome-lib
validator: >-
{% if not (project_name | regex_search('^[a-z][a-z0-9]*(-[a-z0-9]+)*$')) %}
Must be lowercase, start with a letter, and contain only letters, digits,
and single hyphens (PEP 503 normalized form).
{% endif %}
project_description:
type: str
help: One-line description of the project
default: ""
package_name:
type: str
help: |
Importable Python package name.
Defaults to a snake_case version of project_name; usually keep the default.
default: "{{ project_name | replace('-', '_') | lower }}"
validator: >-
{% if not (package_name | regex_search('^[a-z_][a-z0-9_]*$')) %}
Must be a valid Python identifier: lowercase letters, digits, and
underscores only; must not start with a digit.
{% endif %}
# ─── Author info ───
author_name:
type: str
help: Your full name (used in pyproject.toml and LICENSE)
default: "Jaewoo Park"
author_email:
type: str
help: Your email address
default: "kaparoo2001@gmail.com"
# ─── GitHub ───
github_username:
type: str
help: GitHub username or organization
default: "kaparoo"
repo_name:
type: str
help: GitHub repository name (usually same as project_name)
default: "{{ project_name }}"
# ─── Environment ───
python_version:
type: str
help: Target Python version (major.minor)
choices:
- "3.14"
- "3.13"
- "3.12"
default: "3.14"
# ─── License ───
license_year:
type: int
help: Copyright year for the LICENSE file
default: 2026
# ─── Project nature ───
is_library:
type: bool
help: |
Is this project a distributable library (wheel/sdist, possibly
publishable to PyPI)?
yes → include `[build-system]` (uv_build) + `[tool.uv.build-backend]`
and ship a `py.typed` marker so downstream consumers can use
its type hints (PEP 561).
no → application / CLI / script / service mode. No build system,
no py.typed; uv treats it as an application.
default: true
release_automation:
type: str
help: |
How releases get published to PyPI (libraries only).
manual → no CI publish workflow; you build and `uv publish`
by hand. The AGENTS.md "Releases" section documents
the flow with keyring tokens.
github-oidc → ship `.github/workflows/publish.yml`. Pushing a `v*`
tag runs CI, waits for approval on a `pypi` GitHub
environment, then publishes to PyPI via Trusted
Publishing (OIDC — no stored token). Needs a one-time
PyPI + GitHub setup, documented in the generated
AGENTS.md.
choices:
- manual
- github-oidc
default: manual
when: "{{ is_library }}"
use_testpypi:
type: bool
help: |
Stage releases on TestPyPI before pushing to real PyPI (libraries
only). PyPI uploads are permanent — yank is possible, replace is
not — so a TestPyPI rehearsal catches install-time issues
(dependency resolution, missing files in the wheel, entry points)
that `uvx twine check` doesn't.
When `release_automation = manual`:
- `pyproject.toml` ships both the `pypi` and `testpypi` named
`[[tool.uv.index]]` entries with `publish-url`.
- AGENTS.md "Releases" includes a `uv publish --index testpypi`
step before PyPI.
When `release_automation = github-oidc`:
- `publish.yml` becomes a 4-job pipeline
(ci → build → testpypi → pypi), promoting the same artifacts.
- You'll need a second Trusted Publisher for TestPyPI; the
AGENTS.md setup checklist covers this.
Disable if PyPI-only is fine (e.g. tiny personal libraries where
the `environment: pypi` approval gate is enough of a checkpoint).
default: true
when: "{{ is_library }}"
use_pytest:
type: bool
help: |
Configure a pytest test suite — `tests/` directory, the `pytest` dev
dependency, `[tool.pytest.ini_options]`, the ruff `PT` rule with
`[tool.ruff.lint.flake8-pytest-style]`, per-file-ignores for tests,
and the test-adapter VSCode extension.
Disable for ML/DL projects where deterministic pytest workflows are
impractical (CUDA non-determinism, GPU dependency, slow steps), or
for ad-hoc script collections without test suites.
default: true
coverage_fail_under:
type: int
help: |
Minimum branch-coverage percent that `pytest` enforces via
`pytest-cov`'s `fail_under` gate.
0 (default) disables the gate — coverage is still measured and
reported (`--cov-report=term-missing`), but the run never fails on
a low percentage. Raise it once the project has a test baseline
(e.g. 80); a fresh project with no tests yet would otherwise fail
`pytest` immediately.
Only used when use_pytest is enabled.
default: 0
when: "{{ use_pytest }}"
include_todo:
type: bool
help: |
Generate a `TODO.md` skeleton at the project root for tracking
open items that aren't yet captured in code or tests. The
generated `README.md` links to it from a 📋 TODO section.
Disable for tiny projects where a TODO file is overkill — the
`README.md` section is omitted in sync.
default: true
# =================================================================== #
# After-action messages #
# =================================================================== #
_message_after_copy: |
🎉 Your project '{{ project_name }}' has been created!
📁 Path: {{ _copier_conf.dst_path }}
📦 Package: {{ package_name }}
🐍 Python: {{ python_version }}
Next steps:
cd {{ _copier_conf.dst_path }}
code .
The initial commit is already on branch 'main'. Happy coding!
_message_after_update: |
✨ '{{ project_name }}' has been updated from the template.
Review the changes:
git diff
Re-lock dependencies if needed, then commit when ready.
# =================================================================== #
# Post-generation tasks (require --UNSAFE) #
# =================================================================== #
_tasks:
# Initialize a git repository with `main` as the default branch
- command: ["git", "init", "-b", "main"]
when: "{{ _copier_operation == 'copy' }}"
# Resolve and lock dependencies (creates uv.lock); also runs on update
- command: ["uv", "lock"]
# Sync the local virtual environment (creates .venv/)
- command: ["uv", "sync"]
# Stage all generated files and create the initial commit
- command: ["git", "add", "."]
when: "{{ _copier_operation == 'copy' }}"
- command: ["git", "commit", "-m", "🎉 Initial commit from copier template"]
when: "{{ _copier_operation == 'copy' }}"
# =================================================================== #
# Migrations (run when updating across template versions) #
# =================================================================== #
# Add entries here as breaking changes ship in tagged template releases.
# Example:
# _migrations:
# - version: v2.0.0
# before:
# - command: ["echo", "Migrating to v2.0.0"]
# after:
# - command: ["uv", "run", "ruff", "check", "--fix", "--unsafe-fixes", "."]