Repository navigation
Releases: simonvanlierde/project-templates
Releases · simonvanlierde/project-templates
Release list
v0.12.0
Immutable
release. Only release title and notes can be modified.
Upgrade steps:
- Breaking: in a
library,researchordata-pipelineproject, runjust citationafter the update and commit what it writes. Until you do, the newcitationhook fails, in CI too. Addemail:to the authors inCITATION.cfffirst, orcodemeta.jsonloses the email it has. - With
openssf_badge=silver: from this update on, sign off your own commits too (git commit -s, orgit rebase --signoff origin/mainfor a branch you already have). Runprek installagain so the new commit-msg hook is active. - If your README.md has the three-dot fair-software.eu badge and
fair.ymlscores under five of five, delete the badge line by hand.copier updatenever changes README.md.
Changed
- New citable public projects no longer get a fair-software.eu badge at three of five dots. Add it once
fair.ymlscores five of five: setFAIR_MIN: 5and paste the snippet howfairis prints in the job summary. - Breaking for
openssf_badge=silver: thedcocheck runs on every pull request, the maintainers' branches included, as the silver badge's DCO criterion asks of every developer. A commit-msg hook refuses an unsigned commit before the push. Commits Dependabot or Renovate write in their own pull requests are exempt; a human commit on a bot's branch is still checked. The commit-msg hook accepts only a fullSigned-off-by: Name <email>line, as the check does.just repo-settingsalso turns on GitHub's "require contributors to sign off on web-based commits", so a commit made in the web UI, such as "Commit suggestion", passes the check. Below silver, only pull requests from forks are checked, as before. - The copier-update workflow signs off its commit.
- Pull requests restore the CI caches main saved and save none of their own, in every workflow that caches: uv, Rust, the pnpm store, Go, the git hook environments and trivy's database. GitHub lets only the pull request read a cache it saves, and a repo holds 10 GB of caches before it evicts the oldest, so those caches pushed out main's and new pull requests built cold. The
pr titleworkflow, which runs on pull requests only, no longer caches uv. codemeta.jsondeclares CodeMeta 3.0 instead of 4.0, because Software Heritage's indexer reads only 2.0 and 3.0 and skipped the file. The fields are the same in both.- JSON files are checked by jsonvet 3.2.0, the new name of check-json5, in every project, not only TypeScript ones:
.vscode/and.github/rulesets/JSON ship with every stack. It reads.jsonfiles as JSON5, so comments and trailing commas still pass, and fails on syntax errors and duplicate keys.
Fixed
- The generated README had two blank lines before "Before the first release" (or before "License" in a project that publishes nothing), so the Markdown linter rewrote it on the first commit.
fair.ymlcalled GitHub's API anonymously, so on a runner whose IP had used up its 60 requests an hour, howfairis scored checks as missing without an error. It now passes the job's token asAPIKEY_GITHUB.fair.ymlscored the checklist as missing on every repo with an OpenSSF Best Practices badge, because the howfairis on PyPI (0.14.2) predates thewww.bestpractices.devbadge URL. It now runs howfairis 0.15.0 from its GitHub tag, which reads that URL; PyPI has no 0.15.0 yet.biome checkfailed on every new TypeScript project with biome 2.6, which formats Markdown and YAML too.biome.jsonnow leaves those files to rumdl and yamlfmt.just repo-settingsin a public Renovate repo stopped with a bare "Validation Failed" when the Renovate app was not installed yet, because GitHub refuses an app it can't see as a bypass actor. It now shows GitHub's reason and says to install the app first.
Added
just citationwrites.zenodo.jsonandcodemeta.jsonfromCITATION.cff, so you edit one file instead of three: title, description, authors with their ORCID iD, email and affiliation, licence and repository into both, and version, release date and DOI intocodemeta.jsononly. Zenodo takes the version and date from the release, and would take a DOI for the release's own and mint none. Other top-level fields you add to the JSON files stay; the author lists are rewritten whole. A name particle such asvanis kept in front of the family name. A git hook, which CI also runs, fails while the files disagree, andjust citation --checkruns the same check by hand.- docs/usage.md has a checklist for making a private repo public: a secret scan over the full history, the name on PyPI, crates.io and npm, a clean issue list and the README status sentence.
- A Rust or Go
binaryand a Pythondata-pipelinegetdocs/accessibility.md: how the program prints (colour is never the only signal,NO_COLORand--color neverare honoured, plain output off a terminal, errors asfile:line:colon standard error) and the author's email for problems. Check each claim holds for your program before you publish it. An existing project gets the file oncopier updateand keeps its own edits after that. - A public repo's
CONTRIBUTING.mdhas a "Scope and response" section: one maintainer, a reply within about two weeks, an issue before a large pull request, and out-of-scope pull requests closed with a link to it. - A new
statusquestion (experimental, the default,stable,maintenanceorarchived, undercustomise) puts one status sentence under the README's badges. A public repo's README also says where questions and bugs go. An existing project's README is its own, socopier updateadds neither: copy them from a fresh render. - A public repo gets issue forms in
.github/ISSUE_TEMPLATE/: one for bugs and one for feature requests. Blank issues are turned off, and a link sends questions toCONTRIBUTING.md. Vulnerabilities go to private reporting, as before. A private repo gets none. - The template itself has a Zenodo DOI, 10.5281/zenodo.23701980, which always points to the newest release.
CITATION.cffand the README carry it.
v0.11.0
Immutable
release. Only release title and notes can be modified.
Upgrade steps:
- With
publish_to_pypi: push the version tag and approvepypi; letpython-release.yml
create the GitHub release. It replacesrelease.ymland attaches the distributions
and their provenance before publishing. Do not create the GitHub release by hand.
If PyPI succeeds but the release job fails, delete any leftover draft and re-run
only thereleasejob (recovery steps). - Breaking: install Copier 9.19 or later (
uv tool upgrade copier) before you run
copier update. Renovate's copier manager installs the latest Copier. - Breaking: a web app made from an untagged main asks the new
user_dataquestion,
which has no default, socopier update --defaultsstops on it. Answer it, or pass it:
copier update --data user_data=nothing(orbrowser, oraccounts). Then add the
footer and the page routing from a fresh render'ssrc/App.tsxto yours, and
/accessibilityand/privacy(and/terms) totests/e2e/routes.ts: an update
leaves both files alone. Fill in the TODOs indocs/. An app on its own domain: pass
--data site_url=https://<your domain>, or the pages name thepages.devaddress.
The weekly copier-update workflow fails until you have run this update by hand once. - Breaking: a private repo: pass
--data public=false. The newpublicquestion
is yes by default, socopier update --defaults, Renovate's update PR and the
copier-updateworkflow add the public-repo files, including ascorecard.ymlthat
fails in a private repo. With no,.github/SECURITY.md,CONTRIBUTING.md,
CODE_OF_CONDUCT.md,pull_request_template.md,dco.ymlandscorecard.ymlgo.
Your license answer stays as it is. - A public repo: the update adds
.github/CONTRIBUTING.md,CODE_OF_CONDUCT.md,
pull_request_template.mdand adcocheck on pull requests from forks,
andSECURITY.mdgains a Scope section to fill in. GitHub shows.github/CONTRIBUTING.md
before a rootCONTRIBUTING.md, so if you have your own, keep one and delete the other. - With
dependency_bot=dependabot: create a fine-grained token with read and write access
to Contents, Pull requests and Workflows on the repo, and store it as the
COPIER_UPDATE_TOKENsecret. Without it, the new weeklycopier-updateworkflow opens
an issue instead of a PR for an update that changes a workflow
(Hearing about new releases). README.md,CHANGELOG.mdand the citation files (CITATION.cff,.zenodo.json,
codemeta.json) are now your project's, and this update already leaves them alone. So
this release's README changes don't arrive, such as the badges for the options you
turned on and the Releasing section. Diff your README against a fresh render with your
answers and copy the parts you want.- Breaking: if a ruleset or branch protection requires the
lint, types, testscheck
(lint, types, pipeline, testsin adata-pipelineproject), switch it to the new
name:python: lint, types, tests(python: lint, types, pipeline, tests) or
ts: lint, types, tests. A library runs one per Python version, named
python: lint, types, tests (3.12)and so on. Until then, pull requests wait on a
check that never reports. - Run
just repo-settingsonce after the update, and in a new project after the first
push. It protectsmainand thev*tags and, in a public repo, turns on private
vulnerability reporting, whichSECURITY.mdpoints to.mainthen requires thegit hooks,
pull request title,dependency reviewand, in a public repo,DCO sign-offchecks: if
you renamed any of those jobs, edit.github/rulesets/main.jsonfirst (in a public repo,
main-checks.json), or pull requests wait on a check that never reports. In a public
repo,mainalso requires an approval from now on; as the repo admin you can merge your
own pull requests by ticking the bypass box in the merge box. - Run
prek installagain in each clone, so the new commit-msg hook is installed. - The new
typosandlycheehooks run on every file in CI's git hooks job. After the
update, runprek run --all-files typos lychee, review what typos fixed, and fix the
dead links lychee lists, or that job fails. - After the update, refresh the lockfiles for your stacks and commit them:
uv lock,
pnpm install,just go-sync. This release bumps dev tools in every stack, and CI
installs with--lockedand--frozen-lockfile. - A TypeScript library with
publish_to_npm: after the update, runjust ts-apiand
commit<package>.api.md. The template's copy describes the sampleaddfunction, not
your exports, so CI fails until you do. - With
dependency_bot=renovate: turn Dependabot security updates off
(gh api -X DELETE repos/OWNER/REPO/automated-security-fixes), or each security fix
arrives as two PRs. Keep Dependabot alerts on: Renovate's security PRs need them. - Breaking: in a Go library made with v0.10.0 or earlier,
copier updatedeletes
<package>_test.gowithout asking, your changes to it included, and adds
add_test.go. Before you commit the update, rungit checkout HEAD -- <package>_test.go
(after committing it,git checkout HEAD~1 -- <package>_test.go). Then delete
add_test.go, or the twoTestAddfunctions stop the tests compiling. With
test_extras=[property], first copyFuzzAddfromadd_test.gointo your test file. - In a Python or TypeScript library, the new sample
addfunction arrives as a conflict
insrc/<module>/__init__.pyorsrc/index.ts: keep your own side. Then delete
tests/test_add.py, and theaddimport and test the update merged into
src/index.test.ts, or those tests fail. - In a
data-pipelineproject (see the two Breaking changes below):src/<module>/pipeline.pybecomes a short file that imports sourceledger. If you
added readers toparse, keep only your own branches, end it with
return sourceledger.parse_source(source, payload), and keep the imports your
branches need: the new file no longer importscsvorio.- Take the new
tests/test_pipeline.py, and keep any tests of your own readers. pyproject.tomlgains thesourceledgerdependency. Keep any dependencies of your
own next to it, wherecopier updatecan't merge the two lists.- In
sources.toml, renamereleasetovintage(the old key still works, with a
warning). Give each implemented source alicense(an SPDX id, or
LicenseRef-<name>) andredistribute = trueorfalse. Rename any source id with
a non-ASCII letter: only ASCII letters, digits,_and-are accepted. - Run
just pipeline.just validatereports a missingdatapackage.jsonuntil
just buildhas written one.
- Breaking:
python-release.ymlandts-release.ymlnow run when avX.Y.Ztag is
pushed, not when a GitHub release is published. Add the## [X.Y.Z]section to
CHANGELOG.mdbefore you tag. The release workflow reads that section and fails
when it is missing. Releases created byGITHUB_TOKENdon't start other
workflows, so the publish workflows could not follow the release.
Added
- Weekly Go property runs cache generated fuzz inputs so each run resumes the
coverage the previous runs found. - Copier and howfairis workflow pins follow template updates. Renovate tracks their
versions in the template, so they no longer need separate manual bumps. - The code of conduct tells readers that a report about the maintainer can go to GitHub
instead, through Report abuse. - An
openssf_badgequestion, asked in a public repo with a license, for the
OpenSSF Best Practices badge.passingadds a test
policy and each stack's coding standards to.github/CONTRIBUTING.md.silveralso
addsGOVERNANCE.md,docs/roadmap.mdanddocs/assurance-case.md, short skeletons
you fill in and then own. It defaults tonone, so an update changes nothing unless
you pass--data openssf_badge=passing(orsilver). - A
cold-install.ymlworkflow runs the shell blocks under the README's## Development
heading as written, in a Debian container with only the tools the README says you
need, so a setup step the README leaves out fails in CI. It runs weekly and on pull
requests that changeREADME.md. It skipsjust up,just pipeline,just ts-e2e
and the mutation and property recipes, which need Docker, a browser, live sources or hours.
Your README stays yours oncopier update, so the job runs whatever it says now. - Spelling and link checks. A
typosgit hook finds misspelt words and alycheehook
finds relative links to missing files in Markdown and HTML. The lychee hook runs
offline, so a new weeklylinks.ymlworkflow checks the web links too. List a word
typos must leave alone in_typos.toml(Spelling and link checks). - A short
AGENTS.mdin every project, for coding agents: thejust checkcommand, each
stack's test recipe and where the docs are. It names only recipes the project's
justfilehas. - Commit message rules in
committed.toml: Conventional Commits, an imperative summary,
no period. Acommittedcommit-msg hook checks each commit, skipping merge
commits, and a newpr-title.ymlworkflow checks the pull request title, which a squash
merge turns into the commit subject. Dependabot and Renovate now write PR titles in the
same form,chore(deps): .... - GPL-3.0-or-later and AGPL-3.0-or-later as
licenseanswers, with
the GNU texts inLICENSE. These texts have no copyright line, so they don't ask
copyright_year. - A
python_layoutquestion undercustomise,srcby default.flatis for adopting
the template in a repo whose package already sits at the root: it renders no
src/<module>stub ortests/test_add.py, and sets `mod...
v0.10.0
Immutable
release. Only release title and notes can be modified.
What's Changed
- fix(codecov): carry each stack's coverage forward until its report arrives by @simonvanlierde in #54
- feat: ask which dependency bot a project uses, dependabot by default by @simonvanlierde in #55
- fix(codecov): comment only on untested new lines by @simonvanlierde in #56
- fix(data-pipeline): per-source download cap and a pipeline-specific pyproject comment by @simonvanlierde in #57
- feat(data-pipeline): retry a failed fetch and record Last-Modified and ETag by @simonvanlierde in #58
Full Changelog: v0.9.1...v0.10.0
v0.9.0
Immutable
release. Only release title and notes can be modified.
Added
- A
codecovoption for the Python and TS stacks: CI uploads test coverage to Codecov, and acodecov.ymlfails a pull request only when total coverage drops by more than 2 points. Codecov comments only then. It needs aCODECOV_TOKENrepository secret (see the README).
v0.8.1
Immutable
release. Only release title and notes can be modified.
A fix for private repositories. Nothing breaks.
What changes in your project
- Dependency review skips private repositories. GitHub runs it there only with Advanced Security, so the job failed every pull request. The stack workflows' dependency audits still run.
Upgrading from v0.8.0
Run copier update.
v0.8.0
No more personal defaults, citation files for libraries, and libraries tested on every supported Python. Two changes are breaking.
What changes in your project
- No personal defaults. The GitHub user, author name, email and ORCID iD no longer default to the template author's. Copier asks for them, or reads them from the
defaults:in your Copier settings file (see the README). - Citation files.
library,researchanddata-pipelineprojects getCITATION.cff,.zenodo.jsonfor Zenodo, and a CodeMeta 4.0codemeta.json. - Libraries are tested on every supported Python. A new
python_minanswer, two minors belowpython_versionby default (after SPEC 0), setsrequires-python. CI tests every version from there up. - Breaking:
data-pipelinedrops thevintage_basiscolumn and the per-sourceencodingkey. A source can pin asha256, andfetchrefuses a download that doesn't match it. - Security: the Python workflow checks every package against OSV's malware advisories before it runs. The generated README installs golangci-lint with
go install, checked against the Go checksum database. Release workflows loseworkflow_dispatch. - The web service's API docs are off unless
API_DOCSis set, CI skips draft pull requests, and VS Code formats TOML with Tombi.
Upgrading from v0.7.1
- Run
copier update. Your saved answers carry over. A library is asked forpython_min. - In a library that added a dependency,
pyproject.tomlconflicts once atrequires-python: take the new floor and keep yourdependencies. - In a
data-pipelineproject, re-runjust pipeline. - Scripts that run
copier copy --defaultsmust now pass--data github_user=… --data author_name=… --data author_email=…, or set them in Copier's settings file.
The full list is in CHANGELOG.md.
v0.7.1
A small release: a Rust sync recipe, YAML formatting, and clearer docs. Nothing breaks.
What changes in your project
just rs-syncdownloads Rust dependencies and writesCargo.lock, like
just py-sync,just ts-syncandjust go-syncdo for their stacks.- A yamlfmt hook formats YAML files. yamllint now checks yamlfmt's output, and
flow mappings are written{key: value}. - Hook revs are commit SHAs, with a
# frozen:comment naming the tag, because
tags can move. Dependabot updates both together. - Comments and docstrings in generated files are shorter and plainer.
Upgrading from v0.7.0
- Run
copier update. - Run
prek run -aonce, so yamlfmt formats your existing YAML files.
The full list is in
CHANGELOG.md.
v0.7.0
A cleanup release: less duplication, less dead config, and nothing that breaks.
What changes in your project
hygiene.ymlis nowchecks.yml. Job names are unchanged, so required status
checks still match..tombi.tomlreplaces.taplo.toml, because tombi replaced taplo as the TOML
formatter.- Coverage recipes print a summary only.
just py-covandjust ts-covno longer
writecoverage.xmlorcoverage/lcov.info. - Removed: the pull request template, and the unused
knipscript
(pnpm run checkstill runs knip).
Upgrading from v0.6.0
- Run
copier update. - If something uploads coverage reports, add the reporter flag back to
just py-cov
orjust ts-cov.
The full list is in
CHANGELOG.md.
v0.6.0
Two new stacks, two new Python project kinds, and a lot of hardening.
Highlights
- Rust and Go stacks. Each comes as a library or a binary, with strict linting, tests, CI and
Dependabot. - Python
web-service: a FastAPI app in a container, with/healthand opt-in OpenTelemetry. - Python
data-pipeline: downloads third-party data, records a checksum for each file and
rebuilds a dataset from it. - Dependency audits in
just checkand CI for Python, TypeScript, Rust and Go. New releases
wait a week before uv or pnpm install them. - Safer answers. Copier rejects answers that used to produce a broken project, such as a name
that starts with a digit. - A
CHANGELOG.mdin every new project.
Breaking changes
- Secret scanning uses Betterleaks instead of gitleaks.
- Vale is gone. rumdl still lints Markdown.
- The web service's
config.pyandtelemetry.pyare gone. OpenTelemetry turns on only when
OTEL_EXPORTER_OTLP_ENDPOINTis set.
Upgrading from v0.5.0
- Run
copier update. If you added dependencies, you get one conflict inpyproject.toml. Keep
your dependencies and take the new comment below them. - Run
uv lockandpnpm install, then commit the lockfiles. - If a
SKIPlist namesgitleaks, change it tobetterleaks. - Delete the
.vale/folder.
The full list is in
CHANGELOG.md.