Repository navigation
v0.11.0
·
107 commits
to main
since this release
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 setsmodule-root = ""for uv_build.
Adopting the template in an existing Python package
covers the rest, including a ruff and ty baseline for code written without them. - A
docs/decisions/folder in every project, for recording why you chose what you
did. It holds a short record template,0000-template.md(status, date, context,
decision, consequences), and an index,README.md. The index is yours once written,
socopier updateleaves it alone. - README badges for the options you turn on: Codecov coverage (
codecov), CodSpeed
(codspeed), PyPI version and supported Python versions (publish_to_pypi), npm version
(publish_to_npm) and OpenSSF Scorecard (public). - A weekly dependency audit,
advisories.yml, on every Monday with a job per stack:
uv audit,pnpm audit,cargo deny check advisoriesandgovulncheck. Before, a repo
with no new commits never heard of a new advisory. A failed run shows on the Actions page
and in the failed-run email. - With
public, an OpenSSF Scorecard workflow (scorecard.yml): it runs on pushes to
main, weekly and when branch protection changes, publishes the score for the README
badge and uploads the findings to code scanning. A private repo gets none. After the
update, the first run on main publishes the score. - The release workflows and
.github/scripts/release-notes.sh: a pushedvX.Y.Ztag becomes a
GitHub release whose notes are that version'sCHANGELOG.mdsection, so the two never
differ. just repo-settingsprotects the default branch with a GitHub ruleset (no deletion, no force-push, linear history, PRs squash-merged once the checks every PR runs have passed) from.github/rulesets/main.json, lets only a repo admin create, move or delete av*tag (.github/rulesets/tags.json), since pushing one publishes a release, and in a public repo turns on private vulnerability reporting, whichSECURITY.mdpoints to. Rerun it any time; it updates the ruleset instead of adding a second.just repo-aboutsets the GitHub About box from your answers withgh repo edit: the description fromproject_description(skipped when empty), the homepage fromsite_urlin a web app, and a topic per stack. It only adds topics, so ones you set by hand stay. Rerun it any time.- With
mutationintest_extras, a weekly CI run of mutation testing:
.github/workflows/mutation.yml, one job per library stack, also startable by hand
and never run on a pull request. Each job runs the stack'sjust <stack>-mutation
recipe. The Rust job fails when a mutant survives; the others print the survivors and
pass. - With
propertyintest_extras, a weekly CI run of the property tests at length:
.github/workflows/property.yml, one job per library stack, also startable by hand
and never run on a pull request. Each job runs a new recipe you can also run by hand:
just py-property(Hypothesis, 10,000 examples a property),just ts-property
(fast-check, 10,000 runs),just rs-property(proptest, 10,000 cases) or
just go-property(fuzzesFuzzAddfor 10 minutes). A failing input fails the job. A Python
library gainstests/conftest.py, which registers the Hypothesis profile. - A
publicquestion, yes by default. No leaves out.github/SECURITY.md,
CONTRIBUTING.md,CODE_OF_CONDUCT.md,pull_request_template.mdanddco.yml, and makes
nonethe license default. See Public repos. CONTRIBUTING.mdsays where to report a bug, states the commit, pull request and
changelog conventions, asks for a DCO sign-off on every commit and says who maintains the
project.CODE_OF_CONDUCT.mdis the Contributor Covenant 3.0, with the author email as
the contact. Adco.ymlworkflow fails a pull request from a fork with a commit that isn't signed off.SECURITY.mdsays what to include in a report, promises an answer within 14 days, says
how a fix is disclosed, and has a scope section to fill in.- A
customisequestion, no by default, ahead of the advanced questions: license,
directories, versions, module names, Codecov, CodSpeed, the dependency bot,
publishing, test extras, the port and the site URL. A new Python library, TypeScript web app or data pipeline now
asks 10 questions, or 11 for a web app, down from 18, 14 and 15. Every question says what it changes.
The questions lists them with their defaults. copier copysays where your details can be saved before it asks, and lists the
justcommands to run after it.- A
codspeedoption for the Python and Rust stacks: abenchmarks.ymlworkflow runs
benchmarks on CodSpeed for every pull request and every push to main, with a starter
benchmark per stack (pytest-codspeed, and divan throughcodspeed-divan-compat). Import
the repository on codspeed.io and set Pull Request comments to "On Change" there; see
usage. - A
web-appTypeScript kind: a Vite single-page app with React or Preact (the new
web_frameworkquestion), deployed by Cloudflare Pages' Git integration. The docker
stack builds no image for it, since it is static files.- Playwright specs run against the production build, in
ts.yml'se2ejob and with
just ts-e2e. They check every route with axe in light and dark mode (WCAG 2.2 AA
and axe's best-practice rules) and at 320 px wide (reflow), and check that the app
runs under the Content-Security-Policy inpublic/_headers, which allows no inline
script. Removing any security header from that file fails the check. just checkand CI enforce a bundle budget, set inscripts/checkBundleBudget.mjs,
and a pre-push hook runs the unit tests.- The e2e run always starts its own preview server, on port 4173, and fails if the
port is taken, so it can't test another app's server instead. - Adopting the template in an existing web app
lists the files a firstcopier copy --overwriteadds or replaces, and how to
install a lockfile resolved before the one-week release wait. - The starter files (
src/App.tsx,src/App.test.tsx,src/main.tsx,src/app.css,
index.htmlandtests/e2e/routes.ts) belong to the project once written:
copier updatenever touches them again.
- Playwright specs run against the production build, in
- A
test_extrasquestion for the library kinds, empty by default.propertyadds a
property test of the sampleaddfunction: Hypothesis, fast-check, proptest, or a
native GoFuzzAdd.mutationadds ajust <stack>-mutationrecipe to run by hand:
mutmut, Stryker, cargo-mutants or gremlins. See Test extras.
Python and TypeScript libraries now ship the sampleadd, as Rust and Go already did. - With the
dockerstack,docker.ymlscans each built image with Trivy for HIGH and
CRITICAL vulnerabilities that have a fix, and rebuilds and scans the image every Monday
without pushing it. Pull requests and pushes show the findings in the job log; only the
weekly run fails on them. The job that pushes to GHCR runs no scan, so it reads no
cache on a tag. - In a
data-pipelineproject:data/fetches.jsonlis committed and gets a line each time a source serves bytes it
has not served before: the history of every version, as checksums, not values.- The weekly CI run comments on an open "Source data revised upstream" issue when a
source in that file serves new bytes, with the old and new checksums. Only that job
may write issues.uv run <slug> revisions <older log>prints the same list locally. just statuslists every source with its vintage, last fetch and licence, and
just attributionprints the sources and their reuse terms as a Markdown table for
ATTRIBUTION.md.
just fmtruns each stack's fix-and-format recipe, the counterpart ofjust check.- Dependabot groups npm security updates into one pull request instead of one per
advisory. - VS Code formats
.tsx,.jsxand.cssfiles with Biome, and the Biome hook also
checks HTML. - The README says how to lock a security fix that is less than a week old, which
exclude-newerandminimumReleaseAgeotherwise hold back. - API-break checks for libraries that publish. With
publish_to_pypi, a newapijob
inpython.ymlruns griffe, which fails when a public function, class or argument was
removed or changed since the last git tag, and passes while there is no tag. It stays
out ofjust py-check, so a deliberate break leaves local checks green. Withpublish_to_npm,ts.ymlandjust ts-checkrun API Extractor, which
fails when the built types differ from the committed<package>.api.md.just ts-api
rewrites that report after a deliberate change, so the change shows in review. - A
web-apphas legal pages, linked from every page's footer: an accessibility
statement at/accessibility, a privacy statement at/privacyand, with
user_data=accounts, terms of use at/terms. Each is one Markdown file indocs/:
GitHub shows it, and the build turns it into HTML. Its HTML comments are notes for you,
and the build leaves them out. New e2e tests fail when a page still
holds a TODO, when the statement says "fully conformant" or goes 400 days without a
review, and when a first visit sets a cookie, stores anything in the browser or loads a
file from another site.docs/web-legal.mdin the template repository has tips for
filling the pages in, linked from each page's notes (Legal pages). - A
web-appgetsdocs/accessibility-assessment.mdbeside the accessibility statement: a
WCAG 2.2 self-assessment with one row for each of the 55 level A and AA criteria, and a
result and an evidence column to fill in. The app does not serve it. The statement links
it, and may say "partially conformant" only once every row has a result. An update
leaves your copy alone. - A public repo of a kind that has
CITATION.cff(library, research, data-pipeline) gets
fair.yml, which runshowfairisweekly and lists each fair-software.eu check in the job
summary, and a fair-software.eu badge in the README. The job fails belowFAIR_MINfilled
dots out of five. A new repo has three, so that is the starting floor: raise it as you
add a registry entry and the OpenSSF Best Practices badge, and edit the badge to match. - With
dependency_bot: dependabot, acopier-updateworkflow opens a weekly PR that
runscopier updateto the newest template tag, with conflicted files listed in the
PR body. It pushes with aCOPIER_UPDATE_TOKENsecret, a fine-grained token you create.
Without one it usesGITHUB_TOKEN, which GitHub stops from pushing workflow changes, so
such an update opens an issue asking you to run it locally, and other update PRs start
no CI. See
Hearing about new releases.
Changed
- A public repo's
mainruleset requires one approving review, given after the last push,
and a new push dismisses an earlier one. That lifts Scorecard's branch protection score
from at most 4 to 8. A repo admin can bypass the review from the merge box. The required
checks move to a second ruleset,main-checks, which only an admin can bypass, so a
bypass of the review still waits for them. Rerunjust repo-settingsafter the update to
apply both. A private repo's ruleset is unchanged. - With
dependency_bot=renovate, Renovate merges its own minor and patch updates of the
packages CI installs, and the weekly relock, once their checks pass. Its app may bypass
the review in a public repo, never the checks. Majors, copier template releases, and the
actions and hooks group still wait for you. Dependabot PRs still never merge themselves. - A web app with
user_data=accountsrefusescode@duinlab.nlasauthor_email: an app
that keeps personal data on a server needs its own contact address. Pass another
address tocopier updateif you hit this. copier copykeeps an existingREADME.md, andcopier updateno longer touches it.
Template changes to the README, this release's included, reach existing projects only
by hand.- A ty rule set to
"warn"reports without failingty check, the hook and
just py-check. ty exits 1 on warnings by default;pyproject.tomlnow sets
[tool.ty.terminal] error-on-warning = false. - In a Python project, the git hooks skip
data/, so the whitespace, end-of-file and
nbstripout hooks no longer rewrite input data and archived notebooks. pnpm audit --fix=updatelocks a security fix that is under a week old: it adds the
patched version tominimumReleaseAgeExclude, and the new
minimumReleaseAgeExcludePrunedrops the entry once the lockfile moves past it.- With
dependency_bot=renovate, Renovate refreshes the lockfiles every Monday. That is
how a security fix in a dependency of a dependency arrives, once it is a week old. - Breaking: the TypeScript and Python check jobs are now
ts: lint, types, testsand
python: lint, types, tests(python: lint, types, pipeline, testsin a
data-pipelineproject). Both used to belint, types, tests, so a ruleset could not
require one without the other. A ruleset that requires the old name needs the new one
(see the upgrade steps). - With the
codecovoption,just checkruns the TypeScript tests with coverage, as CI
does, so a coverage threshold in the Vitest config fails locally as well as in CI. - Dependabot and Renovate group minor and patch bumps of runtime dependencies into one
weekly PR, instead of one PR each. A major still gets its own PR. - GitHub Actions and pre-commit hook updates arrive as one weekly PR, instead of one
each: a Dependabot multi-ecosystem group, and one Renovate group. Fewer PRs means fewer
branches to bring up to date in turn where main requires it. - With the
codecovoption, Codecov no longer comments on pull requests. Any line left
untested drew a comment. A drop of over 2 points still fails thecodecov/project
check, which links to the report. - Breaking: a
data-pipelineproject gets its fetch, build, validate and revisions
stages from the sourceledger
package instead of about 400 copied lines inpipeline.py. Fixes now arrive as a
dependency bump, not acopier updatemerge.pipeline.pykeeps onlyparse.parsereads CSV, JSON and Excel sources, gzipped or not, by each source'sformat
or its URL's extension.just buildalso writes adatapackage.json.- A fetch asks the server whether the file changed (
If-None-Match,
If-Modified-Since) and keeps the record on a 304, unless the raw file was edited or
no longer matches its pinnedsha256. It waits at most 2 minutes for a
429'sRetry-After, and a fetch that fails after its retries names the source and
its URL. - The manifest names the edition
vintage, as the fetch record and the output column
already did.sources.tomlhas a schema line for editors, pinned to sourceledger
v0.2.0, and its comments cover every key. The example source is pinned to a
datasets/co2-ppm commit, so CI and the tripwire tests no longer follow a moving
branch.
- Breaking:
just validatein adata-pipelineproject needs each implemented source
to statelicense(an SPDX id) andredistribute(whether the raw file may be
republished), besideterms. The free-text terms stay for people; these two are for a
release step to check. go.modis written once and then belongs to the project, likeCHANGELOG.md. Before,
everycopier updateconflicted with whatgo mod tidyhad written there. To raise the
minimum Go version, rungo mod edit -go=<version>.copier updateno longer touchesCITATION.cff,.zenodo.jsonorcodemeta.jsononce
they exist, so a release that adds its version, date or DOI to them no longer conflicts
with every update. Template changes to these files, this release's included, reach
existing projects only by hand.- Web-service projects test with
httpx2, which Starlette's test client now prefers,
instead ofhttpx, and require Starlette 1.2.0 or later. The pytest filter that hid
Starlette's deprecation warning is gone. - A new Python release becomes the default
python_version90 days after it comes out,
once the packages projects install have wheels for it. - The generated README lists the tools the project needs (uv only where it's used), puts
just hooksnext tojust check, says thatjust checkdoesn't build the Docker
image, and, with a publish option, has a Releasing section on setting up the publishing
environment first. - The workflow linter hook runs jactionlint, a maintained fork of actionlint. It adds
checks for releases, caches and concurrency, so a workflow you wrote yourself may get new
findings. - A library's release workflow runs its wheel tests with the test tools from
uv.lock,
hash-checked, and turns on uv's malware check aspython.ymldoes. python-release.ymlandts-release.ymlrun one release per tag at a time.- The docker workflow cancels a superseded run only on a pull request, so a push to
main
or a tag is never stopped halfway through pushing an image. A tag build doesn't restore
the shared build cache, so a poisoned cache entry can't reach a release image; release
builds take longer as a result. When every image builds from a subdirectory, the
workflow runs only when a build context or the workflow changes, so a required build
check stays pending on a pull request that touches neither. - The Docker image of a
data-pipelineproject is documented as a stub: it has no
sources.tomlordata/, and it starts the/healthplaceholder. - Python projects accept
uv_build0.13 as their build backend. The 0.12.19 floor stays,
so older uv versions still build them. - With
dependency_bot: renovate, Renovate's copier manager opens a PR for each new
template release. Before, the one-week release age held those PRs back for good, because
template tags carry no release date. The docs say how Dependabot users hear about
releases.
Fixed
- The typos hook skips
.copier-answers.yml. The template commit id Copier writes there
could spell a word typos rejects and fail the hook after acopier update. - A project description with
""",*/or a line break is refused. It
broke the Python docstring or the Go and TypeScript comments it lands in. - With
dependency_bot: renovate, the comments inpyproject.toml,pnpm-workspace.yaml
and.pre-commit-config.yamlno longer say Dependabot waits the week or moves the hook
SHAs. - The README of a TypeScript project names Node.js among the tools you need.
- The weekly scheduled run and a push to
mainno longer cancel each other in
python.ymlanddocker.yml. A cancelled weekly run used to skip that week's tripwire
tests in adata-pipelineproject. - Copier refuses answers that rendered a broken project: a project name that is a Go,
Rust or Python keyword (such astype,genorlambda), an emptystackslist, an
empty*_dir, arust_versionbelow 1.85 (the template uses edition 2024), and an
app_portoutside 1 to 65535, or 65535 when two images publish ports. A Go binary no
longer needs a project name that can be a Go package name. - The
check-yamlhook no longer fails onpnpm-lock.yaml. pnpm 12 writes its own
version into the lockfile as a second YAML document, so every TS project failed its
checksworkflow once the lockfile was committed. - A name or email with a quote in it, such as
Ada "X" Lovelace, no longer breaks the
generatedpyproject.toml,package.jsonorCargo.toml. A leading space in the
author name no longer leaves the given name empty in the citation files. - The
tsand stdlib Python starter servers in the Docker image stop on SIGTERM. As PID 1
they ignored it, sodocker stopwaited 10 seconds and then killed them. - A Go library named
exampleno longer loses itsTestAdd: the unit test is now
add_test.go, which can't share a path withexample_test.go. - The image
.dockerignorefiles match.env,.venvandnode_modulesin any
directory, so another stack's secrets stay out of the build context when a package sits
at the repo root. .gitignorenames a Go binary without a trailing major version, asgo builddoes for
a module path ending in/v2.- With a Rust crate below the repo root,
.vscode/settings.jsonsets
rust-analyzer.linkedProjects, so the editor finds a crate two levels deep.
Security
- The weekly Copier updater renders in a read-only job. A fresh job applies only
the patch before pushing, so Copier's dependencies cannot alter the runner that
holds the update token. - With
publish_to_ghcr, the image push job runs in aghcrenvironment, as PyPI and npm
releases already do. Limit it tomainandv*tags with a required reviewer in the
repository's settings (see the README's Releasing section); until then GitHub creates it
unprotected and pushes as before. - A library's PyPI release signs a GitHub build-provenance attestation for each file in
dist/, so users can check where a wheel was built withgh attestation verify. It is
made in the publish job, which runs no project code. - The hooks job installs a set prek version, 0.5.5, instead of the newest one on each run,
and gives the read-only GitHub token to the zizmor hook only.