Skip to content

Reject datetime bounds in dates() with InvalidArgument#4768

Merged
Liam-DeVoe merged 1 commit into
HypothesisWorks:masterfrom
Zac-HD:claude/lucid-wozniak-cyr7v6
Jun 18, 2026
Merged

Reject datetime bounds in dates() with InvalidArgument#4768
Liam-DeVoe merged 1 commit into
HypothesisWorks:masterfrom
Zac-HD:claude/lucid-wozniak-cyr7v6

Conversation

@Zac-HD

@Zac-HD Zac-HD commented Jun 16, 2026

Copy link
Copy Markdown
Member

A datetime passed as min_value/max_value to dates() previously slipped past check_type() (datetime subclasses date) and then failed with a bare TypeError while generating examples. Validate explicitly and raise InvalidArgument instead.

A datetime passed as min_value/max_value to dates() previously slipped
past check_type() (datetime subclasses date) and then failed with a bare
TypeError while generating examples. Validate explicitly and raise
InvalidArgument instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RZQPx4c5KUdyvvny8Aqpz5
@Zac-HD Zac-HD requested a review from Liam-DeVoe June 16, 2026 21:53
@Zac-HD Zac-HD added the legibility make errors helpful and Hypothesis grokable label Jun 16, 2026
@Liam-DeVoe

Copy link
Copy Markdown
Member

Looks like deploy failed: https://github.com/HypothesisWorks/hypothesis/actions/runs/27638393001/job/81775560973. I've never seen this before. I'll investigate when claude stops being down :)

@Liam-DeVoe

Liam-DeVoe commented Jun 18, 2026

Copy link
Copy Markdown
Member

Here's Claude's analysis, which I agree with:

Details
⏺ I've fully diagnosed this. Here's what happened.

  Diagnosis: orphaned v6.155.4 tag from a deploy push-race

  The failing job (27638393001, deploy step) died here:

  Creating tag v6.155.4
    ...
    assert tagname not in tags()
  AssertionError

  create_tag() in tooling/src/hypothesistooling/__init__.py:100 asserts the tag doesn't already exist — and v6.155.4 already exists on the remote, even
  though it was never released. Current master is still at version 6.155.3, the hypothesis/RELEASE.rst is still pending, and PyPI's latest is 6.155.3. So
  6.155.4 is a phantom.

  Root cause — two deploys racing, tag pushed before the commit

  push_tag() (__init__.py:105) pushes the tag first, then HEAD:master:

  def push_tag(tagname):
      assert_can_release()
      subprocess.check_call(["git", "push", "origin", shlex.quote(tagname)])
      subprocess.check_call(["git", "push", "origin", "HEAD:master"])

  Timeline:

  1. 18:07 — PR #4766 merges → master = ecbef50bd. Triggers deploy run A (27637996942).
  2. 18:14 — PR #4763 ("Update pinned dependencies") merges → master advances to 5f3f6ae65. Triggers deploy run B (the one you linked).
  3. 18:22 — Run A, built on the now-stale ecbef50bd, bumps to 6.155.4 (commit 4204ba8a0) and runs push_tag. Its log shows:
  * [new tag]   v6.155.4 -> v6.155.4        ← tag push SUCCEEDS
  ! [rejected]  HEAD -> master (non-fast-forward)   ← commit push FAILS
  3. Master had moved, so the bump commit was rejected — but the tag had already landed. Run A fails, leaving v6.155.4 pointing at 4204ba8a0, a commit
  that's not on master.
  4. 22:06 — Run B recomputes the same next version 6.155.4 (RELEASE.rst is still pending), tries to tag, and trips the assert tagname not in tags() guard.
  This is the failure you're looking at.

  So nothing is wrong with the code in the merged commits — it's a deploy-infrastructure race that left a stray tag.

  Fix

  Immediate (unblock the release): delete the orphaned remote tag, then re-run deploy:

  git push origin :refs/tags/v6.155.4    # delete the stray remote tag
  # then re-trigger the deploy job (re-run 27638393001, or push a trivial commit to master)

  The next deploy will recreate v6.155.4 on the real master tip, push both commit and tag, and publish to PyPI normally. (This needs upstream push rights —
  I haven't touched the remote.)

  Preventing recurrence — the ordering in push_tag is the real bug: an atomic, fail-as-a-unit push would avoid orphaning the tag. Options:
  - Push commit and tag in one atomic call: git push --atomic origin HEAD:master "$tagname" — if the branch is non-fast-forward, neither ref updates, so no
  orphan tag.
  - Or push HEAD:master first and the tag second, so a lost race fails before any tag exists.

  Want me to open a PR hardening push_tag() (atomic push) so this can't recur? I can't delete the upstream tag myself, but I can prep that change.

❯ making the push atomic won't fix the underlying issue though, right? concisely, what's the underlying problem?                                            

⏺ Right. Atomic push only prevents the orphaned tag — Run A would still fail the non-fast-forward push. The underlying problem is that deploy operates on a
  stale checkout with no concurrency control: Run A bumped/tagged/pushed against ecbef50bd while master had already advanced to 5f3f6ae65. Two deploys ran
  concurrently against different bases, and the loser pushes nothing useful (or, today, a stray tag).

  The real fix is one of:
  - A concurrency guard on the deploy job (serialize deploys; cancel/queue so only one runs at a time), and/or
  - Have deploy fetch + rebase onto the current remote master before computing the version and tagging, so it's always building on the live tip.

  Atomic push is just damage-control on the symptom.

I disagree with its proposed solutions though. I think the right answer here is merge queues.

I've fixed the stuck release by deleting the orphaned tag and re-running the deploy job

@Liam-DeVoe Liam-DeVoe closed this Jun 18, 2026
@Liam-DeVoe Liam-DeVoe reopened this Jun 18, 2026
@Liam-DeVoe Liam-DeVoe enabled auto-merge June 18, 2026 18:33
@Liam-DeVoe Liam-DeVoe merged commit c2f6e7f into HypothesisWorks:master Jun 18, 2026
77 checks passed
@Zac-HD

Zac-HD commented Jun 18, 2026

Copy link
Copy Markdown
Member Author

Yeah, #3577 isn't even recent 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

legibility make errors helpful and Hypothesis grokable

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants