Commit graph

11319 commits

Author SHA1 Message Date
Brad Warren
ac8ed3ba4e
move san_test to test dir (#10525)
fixes https://github.com/certbot/certbot/issues/10520

i personally don't think this PR requires a second review
2025-12-17 11:44:26 -08:00
Jacob Hoffman-Andrews
17a1f0e114
Merge pull request #10519 from jsha/dedupe-enforce-domain-sanity
De-duplicate enforce_domain_sanity
2025-12-16 10:31:25 -08:00
Brad Warren
fb3e95e372
make _DomainsAction an external attribute of _internal.cli.cli_utils (#10514)
as i mentioned at
https://github.com/certbot/certbot/pull/10509#discussion_r2601282033, i
didn't love how the tests were using `_DomainsAction` when i think the
leading underscore suggests the class is internal to the cli/cl_utils
module

this PR fixes that

also, i don't think this PR requires two reviews
2025-12-15 16:41:39 -08:00
Brad Warren
36ddada4b3
update pinned dependencies (#10516)
this fixes the dependabot alerts those with access can see at
https://github.com/certbot/certbot/security/dependabot

i don't think those alerts are particularly relevant to us, but i think
it's good for us to update anyway
2025-12-15 15:05:27 -08:00
Brad Warren
4b90db8d29
Merge pull request #10512 from certbot/candidate-5.2.2
Candidate 5.2.2
2025-12-10 10:18:37 -08:00
Will Greenberg
f0aa0c06c3 Bump version to 5.3.0 2025-12-10 09:08:44 -08:00
Will Greenberg
8874ae05e0 Remove built packages from git 2025-12-10 09:08:44 -08:00
Will Greenberg
2e499f5dff
Release 5.2.2 2025-12-10 09:08:43 -08:00
Will Greenberg
97761a1103 Update changelog for 5.2.2 release 2025-12-10 09:08:09 -08:00
Brad Warren
965ee86f3e
remove built packages from 5.2.x (#10511)
this just cherry picks 90507bd07f from
#10502 to this branch

i'll update the release instructions to stop us from dropping this
commit in the future
2025-12-10 09:06:06 -08:00
Will Greenberg
305ebe1c16
Fix --webroot-path action (#10509) (#10510)
Cherry-picks #10509 which fixes #10506. This will eventually make its
way into the 5.2.2 point release

Co-authored-by: Jacob Hoffman-Andrews <github@hoffman-andrews.com>
2025-12-10 08:35:35 -08:00
Jacob Hoffman-Andrews
f6d2ae377d
Fix --webroot-path action (#10509)
Fixes #10506.

When --webroot-path was specified multiple times, Certbot was erroring
with `DNSName SAN compared to non-SAN`. That's because, in the
_WebrootPathAction that builds `namespace.webroot_path`, we were passing
`domain` (type `san.DNSName`) as the keys. The other code that modifies
or accesses `namespace.webroot_path` expects the keys to be of type
`str`. In particular `webroot.Authenticator._set_webroots` does:

```python
            for achall in achalls:
                self.conf("map").setdefault(achall.domain, webroot_path)
```

Where `achall.domain` is a `str`.

Two existing unittests would have caught this: `test_multiwebroot` and
`test_webroot_map_partial_without_perform`. However, they faked out the
parsing of the `--domains` flag, and that faked out code was not updated
in #10468. Since this bug is caused by an interaction between the types
produced by the `--domains` flag and those produced by the
`--webroot-path` flag, the tests failed to catch the problem. I've
updated the tests and confirmed that they fail before the fix is
applied.
2025-12-09 15:37:20 -08:00
Brad Warren
d3c30cfb2d
fix finish_release.py on the 5.2.x point release branch (#10507)
this PR just cherry picks https://github.com/certbot/certbot/pull/10503
to the 5.2.x branch in case we need to do a point release to fix
https://github.com/certbot/certbot/issues/10506 or any other issues
2025-12-08 09:03:46 -08:00
Jacob Hoffman-Andrews
b1cf53ff6b
Add identifier field to AnnotatedChallenge subclasses (#10491)
This field is optional to maintain backwards compatibility. Note that
`AnnotatedChallenge` inherits from `jose.ImmutableMap`, which has a
[check in
__init__](4b74747670/src/josepy/util.py (L125-L131))
that all slots are provided. That check would not allow us to do a
backwards-compatible addition, so I implemented an `__init__` for each
of these subclasses that fills the fields without calling the parent
`__init__`, and so doesn't hit an error when `identifier` is absent.

I chose to use `acme.messages.Identifier` rather than
`certbot._internal.san.SAN` here because these are wrapped ACME types,
so they should use the ACME representation. Also, `AnnotatedChallenge`
is passed to plugins, so we need to pass a type that the plugins can
understand.

Additionally, `domain` is marked as deprecated.

Part of #10346

/cc @bmw, who noticed the issue with `AnnotatedChallenge`
[here](https://github.com/certbot/certbot/pull/10468#issuecomment-3403294394)
and provided additional feedback
[here](https://github.com/jsha/certbot/pull/2#issuecomment-3534895793).
Note that there's still some work to do to finish excising `domain`
assumptions from this portion of the code.

---------

Co-authored-by: ohemorange <ebportnoy@gmail.com>
2025-12-05 13:44:04 -08:00
Brad Warren
9e7a98f4cd
fix finish_release.py (#10503)
in https://github.com/canonical/snapcraft/pull/5720, snapcraft made a
change. `snapcraft status certbot` output changed from something like
this:
```
Track    Arch    Channel    Version     Revision    Progress
latest   amd64   stable     5.1.0       5057        -
                 candidate  ↑           ↑           -
                 beta       5.2.1       5214        -
                 edge       5.2.0.dev0  5210        -
         arm64   stable     5.1.0       5058        -
                 candidate  ↑           ↑           -
                 beta       5.2.1       5215        -
                 edge       5.2.0.dev0  5211        -
         armhf   stable     5.1.0       5056        -
                 candidate  ↑           ↑           -
                 beta       5.2.1       5213        -
                 edge       5.2.0.dev0  5212        -
```
to this:
```
Track    Arch    Channel    Version     Revision    Progress
latest   amd64   stable     5.1.0       5057        -
latest   amd64   candidate  ↑           ↑           -
latest   amd64   beta       5.2.1       5214        -
latest   amd64   edge       5.2.0.dev0  5210        -
latest   arm64   stable     5.1.0       5058        -
latest   arm64   candidate  ↑           ↑           -
latest   arm64   beta       5.2.1       5215        -
latest   arm64   edge       5.2.0.dev0  5211        -
latest   armhf   stable     5.1.0       5056        -
latest   armhf   candidate  ↑           ↑           -
latest   armhf   beta       5.2.1       5213        -
latest   armhf   edge       5.2.0.dev0  5212        -
```
when its output is captured like it is in finish_release.py in the lines
above the code i'm modifying here

not matching on the beginning of lines makes this pattern a little less
strict, but based on the rest of the pattern and the output here, i
personally think this is fine

after carefully verifying this works with the current state of things, i
went ahead and finished the release with this change and it worked just
fine. instead, this PR proposes a way to fix things going forward
2025-12-04 15:15:25 -08:00
ohemorange
8c4e3080dd
Merge pull request #10502 from certbot/candidate-5.2.1
update files from 5.2.1 release
2025-12-03 12:55:54 -08:00
Brad Warren
9a2e508348 Bump version to 5.3.0 2025-12-03 11:48:10 -08:00
Brad Warren
90507bd07f Remove built packages from git 2025-12-03 11:48:10 -08:00
Brad Warren
1127ac1cd7
Release 5.2.1 2025-12-03 11:48:09 -08:00
Brad Warren
65548e36c4 Update changelog for 5.2.1 release 2025-12-03 11:47:31 -08:00
Brad Warren
7f138ca073
add changelog entry about 5.2.1 (#10501)
see the thread at
https://opensource.eff.org/eff-open-source/pl/f5yx4a4q4j8zjyqpmath494jge
for details

since it's only the `v5.2.0` github tag that's borked, we could in
theory try and use like `v5.2.0-2` or something, but there are
[places](259dfadb43/.azure-pipelines/release.yml (L10))
in the release pipeline that use the GH tag as input to the assets they
build, so i think just skipping 5.2.0 altogether is simpler, easier, and
safer

with this change, here's the proposed changelog
```
$ towncrier build --draft --version 5.2.1
Loading template...
Finding news fragments...
Rendering news fragments...
Draft only -- nothing has been written.
What is seen below is what would be written.

## 5.2.1 - 2025-12-02

### Added

- Support for Python 3.14 was added.
  ([#10477](https://github.com/certbot/certbot/issues/10477))

### Changed

- While nothing significant should have changed from the user's perspective,
  we've been doing a lot of internal refactoring in preparation for soon adding
  support for IP address certificates to Certbot.
  ([#10468](https://github.com/certbot/certbot/issues/10468),
  [#10478](https://github.com/certbot/certbot/issues/10478))

### Fixed

- Removed `vhost_combined` and `vhost_common` log formats from included Apache
  configuration file. ([#9769](https://github.com/certbot/certbot/issues/9769))
- Due to a mistake on our end playing with GitHub's new [immutable
  releases](https://github.blog/changelog/2025-10-28-immutable-releases-are-now-generally-available/)
  feature that prevented our CI from uploading additional release assets,
  Certbot 5.2.0 was not and will not be uploaded to most platforms. Instead,
  that version number will be skipped and we'll go straight to 5.2.1.
  ([#10501](https://github.com/certbot/certbot/issues/10501))
2025-12-03 10:10:00 -08:00
Brad Warren
259dfadb43
add changelog entry about IP refactoring (#10498)
if you dislike the general idea of this PR, feel free to just close it,
but i'm scheduled to release the next version of certbot a week from
today and i personally didn't like how
[newsfragments](https://github.com/certbot/certbot/tree/main/newsfragments)
is so empty despite us having done a lot of work on certbot lately

this PR just adds a simple newsfragment highlighting/teasing the work
jsha has been leading on support for IP address certificates which i
imagine would be of interest to some people in the community

```
$ towncrier build --draft --version 5.2.0
Loading template...
Finding news fragments...
Rendering news fragments...
Draft only -- nothing has been written.
What is seen below is what would be written.

## 5.2.0 - 2025-11-25

### Added

- Support for Python 3.14 was added.
  ([#10477](https://github.com/certbot/certbot/issues/10477))

### Changed

- While nothing significant should have changed from the user's perspective,
  we've been doing a lot of internal refactoring in preparation for soon adding
  support for IP address certificates to Certbot.
  ([#10468](https://github.com/certbot/certbot/issues/10468),
  [#10478](https://github.com/certbot/certbot/issues/10478))
```
2025-11-26 13:11:06 -08:00
Jason Owen
6e489cdb74
Remove vhost_combined override from Apache conf (#10486)
The Apache configuration `Include`d in automatically created
`[sitename]-le-ssl.conf` files was redefining the `vhost_combined`
`LogFormat`, but contrary to the comment before the redefinition, did
not include the virtual host server name in the log format. This is
particularly confusing because this redefinition is hard to find when
debugging logging issues, as log formats are not related to SSL/TLS
configuration, and the included configuration file is outside of
`/etc/apache2`.

Additionally, a `vhost_common` `LogFormat` was defined, but not used
anywhere.

The `LogFormat` directives were introduced in commit
68f85d9f1a. Several other directives that
do not directly pertain to configuring SSL/TLS were added in that
commit, and have gradually been removed over the years. This should be
the last such removal.

Delete the `LogFormat` directives from the Apache configuration files
(both old and current), and update the `ALL_SSL_OPTIONS_HASHES`.

Fixes #9769 File 'options-ssl-apache.conf' included in autocreated
'[sitename]-le-ssl.conf' has potentially problematic vhost_combined
LogFormat
2025-11-26 09:03:31 -08:00
Leo Singer
1c3668fb64
Add certbot-pkcs12 to list of third-party plugins (#10488)
Closes #10348.

## Pull Request Checklist

- [ ] The Certbot team has recently expressed interest in reviewing a PR
for this. If not, this PR may be closed due our limited resources and
need to prioritize how we spend them.
- [ ] If the change being made is to a [distributed
component](https://certbot.eff.org/docs/contributing.html#code-components-and-layout),
add a description of your change to the `newsfragments` directory. This
should be a file called `<title>.<type>`, where `<title>` is either a
GitHub issue number or some other unique name starting with `+`, and
`<type>` is either `changed`, `fixed`, or `added`.
* For example, if you fixed a bug for issue number 42, create a file
called `42.fixed` and put a description of your change in that file.
- [ ] Add or update any documentation as needed to support the changes
in this PR.
- [ ] Include your name in `AUTHORS.md` if you like.
2025-11-25 15:31:11 -08:00
Brad Warren
e9050f1a3c
dynamically determine base branch name in mattermost notifications (#10496)
previously, if we merged a PR into one of our point release branches,
the mattermost notification would still say it was merged into main.
this PR fixes that

you can see me testing this change on my fork with this [workflow
file](https://github.com/bmw/letsencrypt/actions/runs/19588662936/workflow#L30)
and this
[output](https://github.com/bmw/letsencrypt/actions/runs/19588662936/job/56102625766#step:2:4)

if this PR is merged, i'll do the same thing in our josepy repo
2025-11-24 13:42:14 -08:00
Brad Warren
b02deb339a
update actions in response to pull_request_target concerns (#10490)
this pr is in response to https://words.filippo.io/compromise-survey/.
ohemorange and i read this late on a friday to (speaking for myself at
least) much panic as it has some very strong words to say about the
github actions trigger pull_request_target which we use. looking into
the issue more, i also found that the popular static analysis tool
[zizmor](https://github.com/zizmorcore/zizmor) flags any github actions
workflow that uses the pull_request_target trigger with the message:

```
error[dangerous-triggers]: use of fundamentally insecure workflow trigger
pull_request_target is almost always used insecurely
```

this only added to my concern

the general problem with pull_request_target is that it runs with
additional privileges (e.g. potential write access, access to secrets)
in an environment containing values that can be set by an attacker.
these values include things such as references to the arbitrary code
contained in the triggering pr and pr titles which have been used to
perform shell injection attacks. not carefully treating these values
like the untrusted data it is while executing code in the privileged
environment given to pull_request_target has resulted in many supply
chain attacks

that's not to say that pull_request_target CAN'T be used securely.
zizmor even has [an
issue](https://github.com/zizmorcore/zizmor/issues/1168) brainstorming
how to not warn about all uses of the trigger as some are clearly fine
and the only way to accomplish what the user wants. i'm going to argue
that our uses of the trigger are ok

looking through the links provided by filippo's blog and [zizmor's
docs](https://docs.zizmor.sh/audits/#dangerous-triggers), i think we can
break down attacks used against pull_request_target into roughly 2
categories:

1. shell injection: "Nx S1ingularity" and "Ultralytics" from filippo's
blog
2. checking out and running a PR's code: "Kong Ingress Controller" and
"Rspack" from filippo's blog and https://ptrpa.ws/nixpkgs-actions-abuse
from zizmor docs

i think none of our pull_request_target workflows have these problems.
none of them use a shell (the [zizmor
issue](https://github.com/zizmorcore/zizmor/issues/1168) i linked
earlier suggests that any pull_request_target workflow that uses a run
block should always be flagged as insecure). instead, our workflows just
call action-mattermost-notify which can be [pretty easily
audited](https://github.com/mattermost/action-mattermost-notify/blob/2.0.0/src/main.js)
(as all the other files in the repo are boilerplate). passing possible
attacker controlled values directly to an action written in another
language is one of the approaches for mitigating script injection
[recommended by
github](https://docs.github.com/en/actions/reference/security/secure-use#use-an-action-instead-of-an-inline-script).
our workflows also do not check out the triggering pr's code

despite all that, i took this opportunity to cleanup and harden things a
bit. i reduced the permissions for each workflow and confirmed they each
still work on my fork. i also pinned the mattermost action to an exact
version and added some inline documentation

with these changes, our github workflows trigger few to no
warnings/errors when checked with zizmor,
[octoscan](https://github.com/synacktiv/octoscan), and [openssf
scorecard](https://github.com/ossf/scorecard)

if this pr is approved, i'll make similar changes to our josepy repo
2025-11-20 15:09:06 -08:00
Jacob Hoffman-Andrews
d638200d12
Initial IP address support: use san.SAN types internally (#10468)
In #10478 we added a `san.SAN` class, with two subclasses `san.DNSName`
and `san.IPAddress`, so we can carry type information about identifiers
through the Certbot code. This PR plumbs through those types in most
Certbot-internal code. Note that this does not change the `acme` module,
which uses `messages.Identifier`. It also tries to leave alone the code
paths into plugins.

This does not add a CLI flag to request an IP address certificate. That
will be in a followup PR.

Part of #10346
2025-11-20 14:03:37 -08:00
Jacob Hoffman-Andrews
ada2c547cf
Add san module (#10478)
Contains san.DNSName, san.IPAddress, and a parent class san.SAN.

Split out from #10468 as a standalone PR. To see examples of how it's
intended to be used, please see that PR.

The constructor for DNSName incorporates the same validation done in
`enforce_domain_sanity`, and the tests from `enforce_domain_sanity` are
copied here as well. The goal is to delete `enforce_domain_sanity`
entirely as part of #10468.

In support of #10346.
2025-11-04 19:44:18 -08:00
ohemorange
2ec8320763
Add python 3.14 support (#10481)
fixes https://github.com/certbot/certbot/issues/10477. this is based on
the PR that did this for 3.13 at
https://github.com/certbot/certbot/pull/10164
2025-11-04 10:49:51 -08:00
ohemorange
4d5d5f7ae8
Merge pull request #10474 from certbot/util-openssl
Simplify loading code only used for PEM files
2025-10-09 13:43:01 -07:00
Brad Warren
d7ae612841
Release 5.1.0 (#10473) 2025-10-07 11:00:17 -07:00
Erica Portnoy
3683eb6cf4 Bump version to 5.2.0 2025-10-07 09:42:29 -07:00
Erica Portnoy
068203b1bd Remove built packages from git 2025-10-07 09:42:29 -07:00
Erica Portnoy
d97f2aefc3
Release 5.1.0 2025-10-07 09:42:28 -07:00
Erica Portnoy
1d32888ac4 Update changelog for 5.1.0 release 2025-10-07 09:42:00 -07:00
Brad Warren
33890ab7f3
deprecate make_self_signed_cert (#10466)
with https://github.com/certbot/certbot/pull/10465,
make_self_signed_cert is no longer used outside of our tests so let's
move it there and remove it from our public API
2025-09-30 07:16:03 -07:00
Brad Warren
513190afe0
don't use snakeoil certs in nginx (#10465)
this PR finally removes all uses of self-signed certificates from
certbot-nginx

i plan to create one last PR related to this deprecating
`acme.crypto_util.make_self_signed_cert` and moving the function to
certbot-compatibility-test which is the only place it's currently used

i think we could also do additional refactoring in certbot-nginx by
moving the _make_server_ssl call out of choose_or_make_vhost and make
deploy_cert responsible for calling it if the returned vhosts aren't
ssl. in this case, we could then skip updating cert and key directives a
second time as this is duplicate work if we just made the server ssl

i considered doing this, but it's a bigger refactor, breaks more tests,
and i'm not sure it really buys us much so i skipped it. i could take
this on or create an issue for it if you think it's important for us to
do for some reason tho ohemorange
2025-09-25 12:41:47 -07:00
Brad Warren
57d2429e4f
remove create_if_no_match (#10464)
this is another tiny piece of my nginx refactoring. with
https://github.com/certbot/certbot/pull/10455, this function is now
never called outside of tests with `create_if_no_match=False` so this PR
removes the unnecessary parameter

luckily, tests still Just Work™ with this change
2025-09-25 08:43:23 -07:00
ohemorange
dc2f3b9eb0
Show --deploy-hook help info in certonly and run info, and add note that it will be run again later. (#10463)
Fixes https://github.com/certbot/certbot/issues/6180.

New output:

```
  --deploy-hook DEPLOY_HOOK
                        Command to be run in a shell once for each successfully issued certificate, including on subsequent renewals. Unless --disable-hook-validation is
                        used, the command’s first word must be the absolute pathname of an executable or one found via the PATH environment variable. For this command, the
                        shell variable $RENEWED_LINEAGE will point to the config live subdirectory (for example, "/etc/letsencrypt/live/example.com") containing the new
                        certificates and keys; the shell variable $RENEWED_DOMAINS will contain a space-delimited list of renewed certificate domains (for example,
                        "example.com www.example.com") (default: None)
```

Pre and post hooks are still only shown in `renew` and `reconfigure`
help, though perhaps there is less confusion over those so it's not
necessary.
2025-09-23 12:23:11 -07:00
ohemorange
f8838fc949
Remove unnecessary time.sleep from certbot-ci (#10461)
Fixes https://github.com/certbot/certbot/issues/10450

Discussion when originally added is
[here](https://github.com/certbot/certbot/pull/6989/files#r283050165).
Further notes are "The problem is transient, only observed on Travis so
far, not locally. I not know how to recreate a reliable pattern and find
precisely what needs to be done." So it's possible we weren't even
hitting this anymore anyway. Regardless, I ran the test a few times in
CI just to make sure it's not breaking.

Runs:

https://dev.azure.com/certbot/certbot/_build/results?buildId=9686&view=results
(pass)

https://dev.azure.com/certbot/certbot/_build/results?buildId=9688&view=results
(pass)

https://dev.azure.com/certbot/certbot/_build/results?buildId=9689&view=results
(pass)

https://dev.azure.com/certbot/certbot/_build/results?buildId=9690&view=results
(pass)

https://dev.azure.com/certbot/certbot/_build/results?buildId=9691&view=results
(pass)
2025-09-18 12:40:53 -07:00
Alexis
90905de18f
[DOCS] Update documentation: Remove decommissioned server (#10460)
Deleted decommissioned server language

Fixes: #10459

Signed-off-by: zoracon <zoracon@pm.me>
2025-09-18 08:04:24 -07:00
Brad Warren
deb3d035e3
require ssl vhosts for HSTS and OCSP stapling (#10455)
this is the first part of the nginx refactoring work i wanted to do.
ohemorange, if this conflicts with your work on updating our nginx ssl
config, please feel free to either ignore this for now or point me to
your branch after merging this and i can fix up any merge conflicts
myself like i previously offered

the main thing this PR does is create a new choose_or_make_vhosts
function with the current choose_vhosts behavior and makes choose_vhosts
only return existing ssl vhosts which i think is the behavior we want
when setting up HSTS or OCSP stapling. [this is what we do in
apache](867b499f9b/certbot-apache/src/certbot_apache/_internal/configurator.py (L1795-L1829)),
enabling HSTS or OCSP stapling on an HTTP vhost seems wrong/dangerous,
and since we don't have cert and key information in these [enhance
calls](867b499f9b/certbot/src/certbot/interfaces.py (L255)),
any SSL vhost we create will be left with snakeoil certs which also
seems very wrong

of course, this simple change to certbot-nginx's prod code required many
changes to its tests. the config file for headers.com was introduced
[here](https://github.com/certbot/certbot/pull/6068) specifically for
testing HSTS so i added the SSL configuration it needs to make work with
the choose_vhost changes. that then broke the IP tests for headers.com
that were added in https://github.com/certbot/certbot/pull/10145/ so i
created a new no-listens.com vhost for testing that

if this is merged, my plan in the next PR or two is to:

1. since choose_or_make_vhosts is now always called with
create_if_no_match=True in prod code, i plan to remove that variable,
make that the default behavior of the function, and fix up tests
2. then, since choose_or_make_vhosts is only called in deploy_cert, i
plan to pass the cert and key to it so it can be used in
_make_server_ssl instead of the dummy certs currently being used there

i could do more of this in this PR if you want ohemorange, but i figured
it rarely hurts to break things up especially when the code is kind of
tricky like it is (to me) here
2025-09-17 14:23:32 -07:00
ohemorange
867b499f9b
Merge pull request #10451 from certbot/candidate-5.0.0
release 5.0.0
2025-09-02 12:09:12 -07:00
Brad Warren
8ecd7fc23d Bump version to 5.1.0 2025-09-02 08:47:05 -07:00
Brad Warren
95e65ac3a5 Remove built packages from git 2025-09-02 08:47:05 -07:00
Brad Warren
c307f62114
Release 5.0.0 2025-09-02 08:47:04 -07:00
Brad Warren
6f8a357147 Update changelog for 5.0.0 release 2025-09-02 08:46:14 -07:00
ldlb
8556a9c427
fix: Remove pyOpenSSL dependency with custom certificate text formatting (#10439)
fixed: #10434

---------

Co-authored-by: ohemorange <ebportnoy@gmail.com>
2025-08-29 14:39:48 -07:00
ohemorange
1c67e990f7
Merge pull request #10448 from certbot/no-openssl-ocsp
remove openssl-based ocsp checking
2025-08-28 10:22:17 -07:00
Brad Warren
9c1685638b fixup pytest.ini, out var, and add changelog 2025-08-28 09:33:37 -07:00