Skip to content

Tools in python - #248

Open
quarckster wants to merge 19 commits into
openssl:masterfrom
quarckster:release-tools-python
Open

Tools in python#248
quarckster wants to merge 19 commits into
openssl:masterfrom
quarckster:release-tools-python

Conversation

@quarckster

@quarckster quarckster commented Aug 25, 2026

Copy link
Copy Markdown
Member

The tooling was split across bash, Perl and Python and had almost no tests — the logic lived in shell functions passing eighteen globals, and stage-release.sh called ./Configure and make from the middle of its own control flow, so testing the branch decisions meant building OpenSSL. One language now, and 491 tests covering release staging end to end.

  • stage-release.sh, the release-aux/*-fn.sh helpers and the twelve fixup-*.pl scripts: stage-release + lib/openssl_tools/stagerelease/
  • addrev, cherry-checker: thin entry points over lib/openssl_tools/reviewtools/
  • The OpenSSL::Query REST backend: a urllib client; nothing here needs the Perl module any more
  • ghmerge, pick-to-branch, opensslbuild, opensslpull and ghlink stay as they are

Python 3.10+, standard library only. Verified against the shell across 230 state/transition combinations: all 216 OpenSSL 3.0+ cases match byte for byte, and the 14 pre-3.0 differences are shell bugs that are now tested. Clean under ruff and mypy on 3.10 through 3.14.

Also fixes some latent bugs — notably gitaddrev --commit=<id> blanking the message of every other commit in the range, and reviewers never being checked for commit access.

Supersedes #240; the OpenPGP key-lifecycle tooling from it is a separate PR.

Replaces stage-release.sh, the release-aux/*-fn.sh helpers and the twelve
fixup-*.pl scripts.  Verified against the shell across 230 state and
transition combinations; the 14 that differ are shell bugs, now tested.

Assisted-by: Claude:claude-opus-5
Replaces the OpenSSL-Query REST backend with a urllib client, and fixes
several latent bugs: --commit blanked other commits' messages, --web was
silently ignored, and a blank message looped forever.

Assisted-by: Claude:claude-opus-5
stagerelease and reviewtools become subpackages, so the cross-package call
is a relative import rather than sys.path surgery at runtime.

Assisted-by: Claude:claude-opus-5
addrev --list already filtered by the commit group but nothing enforced it,
including for a name that happened to be the commit author.  stage-release
validates up front now, before the copyright commit and make update.

Assisted-by: Claude:claude-opus-5
The rule set is pinned because ruff's default varies between releases.
Notable fixes: a bare `except Exception: pass`, and an assert used for type
narrowing that vanishes under python -O.

Assisted-by: Claude:claude-opus-5
Every seam this code exists to be testable through was typed as the concrete
class it injects, so a fake was a type error.  Six protocols replace them,
which then caught three test doubles that had drifted.

Assisted-by: Claude:claude-opus-5
PATH and symlinks work; a copy cannot find ../lib.  It now says so instead
of raising ModuleNotFoundError.

Assisted-by: Claude:claude-opus-5
One zipapp per entry point, or one busybox-style archive dispatching on
argv[0].  Each is ~60 KiB, needs only a Python 3.10 interpreter, and is
named like the script it replaces so it drops over an existing install.

Assisted-by: Claude:claude-opus-5
Verified on the latest patch of 3.10 through 3.14, plus a 5x5 build/run
matrix for the archives and the 3.9 refusal path.

Assisted-by: Claude:claude-opus-5
Assisted-by: Claude:claude-opus-5
They described a manual process that is now pipeline-driven, and contradicted
each other about it.  Names no internal hosts.

Assisted-by: Claude:claude-opus-5
review-tools/README.md is rewritten: it documented a deleted script and
omitted four that exist.  Also drops review-tools/gitlabutil.

Assisted-by: Claude:claude-opus-5
Removes the web policy entry, ghmerge's --web selector and the two tests
that covered it.

Assisted-by: Claude:claude-opus-5
Follows upstream: Merge-date: and Merged-from: replace MergeDate: and the
prose "(Merged from ...)" line, and the trailer block is placed by
git interpret-trailers --if-exists addIfDifferent rather than by hand.
cherry-checker recognises the new trailer when extracting PR numbers.

Assisted-by: Claude:claude-opus-5
Comment thread lib/openssl_tools/reviewtools/gitaddrev_cli.py Outdated
Removes gitaddrev: the message is computed in process now, so there is no
msg-filter subprocess and no PYTHONPATH plumbing.  Rewritten tags still
follow, keeping their tagger and message.

Assisted-by: Claude:claude-opus-5
A reviewer named on the command line who authored one of the commits cannot
be credited on it, which the bare "Too few reviewers" did not explain.

Assisted-by: Claude:claude-opus-5
The tag pass cost one subprocess for every tag in the repository -- 443 in an
openssl clone -- to move at most one.  500 tags: 590ms of fixed overhead, now
5ms.

Assisted-by: Claude:claude-opus-5
@quarckster

Copy link
Copy Markdown
Member Author

Here is some addrev benchmarking with two authors and two reviewers.

Perl addrev (filter-branch + one gitaddrev process per commit)

commits total per commit
10 9.5 s 946 ms
20 17.9 s 896 ms
50 47.9 s 957 ms
100 91.7 s 917 ms

Python addrev (commit-tree/update-ref, in process)

commits total per commit
10 1.36 s 135 ms
20 1.41 s 70 ms
50 1.50 s 29 ms
100 1.77 s 17 ms

@t8m

t8m commented Aug 26, 2026

Copy link
Copy Markdown
Member

Nice

@t8m t8m left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that I thoroughly reviewed, but in general this looks like a beneficial change to me.

@t8m
t8m requested review from a team, levitte and mattcaswell August 26, 2026 14:47
@quarckster

Copy link
Copy Markdown
Member Author

Not that I thoroughly reviewed, but in general this looks like a beneficial change to me.

I understand that there is a lot of to review and I guess the best you can do is really to try it out.

Comment thread lib/openssl_tools/reviewtools/rewrite.py Outdated
Comment thread lib/openssl_tools/stagerelease/cli.py
Comment thread HOWTO-release.md

The key lifecycle itself — generating the primary and subkey, issuing and
rotating the certificate, issuing revocation certificates — is documented
separately in [`openpgp-tools/README.md`](openpgp-tools/README.md), which is

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this still exist?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it will exist when #249 will be merged.

Comment thread README.md
| --- | --- |
| [`release-tools/`](release-tools/README.md) | staging an OpenSSL release |
| [`review-tools/`](review-tools/README.md) | reviewing and merging pull requests |
| [`openpgp-tools/`](openpgp-tools/README.md) | the release signing key's lifecycle |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Ordering by commit date, git log's default, can emit a commit before its own
parent when two lines of history have skewed dates; the replay then re-parents
onto the original, leaving the shared parent forked.  filter-branch used
--topo-order for this.

Assisted-by: Claude:claude-opus-5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rewrite openssl/tools on python

3 participants