Sandpies Claude Opus 5 commited on
Commit ·
06ed23a
1
Parent(s): b2aeed4
The tag has to reach both sites too
Browse filesA tag on GitHub and not on HuggingFace is the same drift the mirror exists to
prevent, and it is worse than a missing branch push because the registry
listing points at a tag somebody will go looking for. --tag pushes it through
origin with the branch and then verifies it on both sites alongside the SHA.
Resolution goes through refs/tags/<tag>^{} first: this repo's tags are
annotated, so a bare ls-remote returns the tag object's own SHA, which never
equals the commit and would fail every comparison. Checked against v1.0.0 on
both remotes -- both resolve to abccaaef, which is what rev-parse v1.0.0^{commit}
gives locally.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PLXmbwfdXirQ5oFreXPcMi
- tools/push_release.py +31 -0
tools/push_release.py
CHANGED
|
@@ -24,6 +24,7 @@ handing off to check_lfs_urls.py, which fetches every published image.
|
|
| 24 |
|
| 25 |
python tools/push_release.py # current branch
|
| 26 |
python tools/push_release.py main
|
|
|
|
| 27 |
python tools/push_release.py main --dry-run
|
| 28 |
|
| 29 |
Terminal prompting is disabled: a missing credential fails in a second instead
|
|
@@ -72,6 +73,9 @@ def remote_sha(remote, branch):
|
|
| 72 |
def main():
|
| 73 |
ap = argparse.ArgumentParser()
|
| 74 |
ap.add_argument("branch", nargs="?", default=None)
|
|
|
|
|
|
|
|
|
|
| 75 |
ap.add_argument("--dry-run", action="store_true")
|
| 76 |
a = ap.parse_args()
|
| 77 |
|
|
@@ -99,6 +103,15 @@ def main():
|
|
| 99 |
dry=a.dry_run):
|
| 100 |
return 1
|
| 101 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
if a.dry_run:
|
| 103 |
print("\ndry run: nothing pushed, nothing verified")
|
| 104 |
return 0
|
|
@@ -111,6 +124,24 @@ def main():
|
|
| 111 |
bad = bad or not ok
|
| 112 |
print(" %-4s %-8s %s" % ("ok" if ok else "FAIL", name,
|
| 113 |
got[:10] if got else "no such branch"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 114 |
if bad:
|
| 115 |
print("\nthe sites disagree -- do not publish")
|
| 116 |
return 1
|
|
|
|
| 24 |
|
| 25 |
python tools/push_release.py # current branch
|
| 26 |
python tools/push_release.py main
|
| 27 |
+
python tools/push_release.py main --tag v2.0.0
|
| 28 |
python tools/push_release.py main --dry-run
|
| 29 |
|
| 30 |
Terminal prompting is disabled: a missing credential fails in a second instead
|
|
|
|
| 73 |
def main():
|
| 74 |
ap = argparse.ArgumentParser()
|
| 75 |
ap.add_argument("branch", nargs="?", default=None)
|
| 76 |
+
ap.add_argument("--tag", default=None,
|
| 77 |
+
help="also push this tag through origin, so both sites "
|
| 78 |
+
"carry it -- a tag on one site only is drift too")
|
| 79 |
ap.add_argument("--dry-run", action="store_true")
|
| 80 |
a = ap.parse_args()
|
| 81 |
|
|
|
|
| 103 |
dry=a.dry_run):
|
| 104 |
return 1
|
| 105 |
|
| 106 |
+
if a.tag:
|
| 107 |
+
if not a.dry_run and not git("rev-parse", a.tag).stdout.strip():
|
| 108 |
+
print()
|
| 109 |
+
print("no such tag: %s -- create it before pushing" % a.tag)
|
| 110 |
+
return 1
|
| 111 |
+
if not run("push tag", "push", "origin", "refs/tags/" + a.tag,
|
| 112 |
+
dry=a.dry_run):
|
| 113 |
+
return 1
|
| 114 |
+
|
| 115 |
if a.dry_run:
|
| 116 |
print("\ndry run: nothing pushed, nothing verified")
|
| 117 |
return 0
|
|
|
|
| 124 |
bad = bad or not ok
|
| 125 |
print(" %-4s %-8s %s" % ("ok" if ok else "FAIL", name,
|
| 126 |
got[:10] if got else "no such branch"))
|
| 127 |
+
# A tag on one site and not the other is drift too, and the registry
|
| 128 |
+
# listing points at a tag that has to exist wherever somebody looks.
|
| 129 |
+
if a.tag:
|
| 130 |
+
want = git("rev-parse", a.tag + "^{commit}").stdout.strip()
|
| 131 |
+
for name, remote in (("github", "origin"), ("hf", "hf")):
|
| 132 |
+
# An annotated tag lists as its own object, so prefer the ^{}
|
| 133 |
+
# line when the site reports one.
|
| 134 |
+
got = None
|
| 135 |
+
for ref in ("refs/tags/%s^{}" % a.tag, "refs/tags/" + a.tag):
|
| 136 |
+
out = git("ls-remote", remote, ref).stdout.strip()
|
| 137 |
+
if out:
|
| 138 |
+
got = out.splitlines()[0].split()[0]
|
| 139 |
+
break
|
| 140 |
+
ok = got == want
|
| 141 |
+
bad = bad or not ok
|
| 142 |
+
print(" %-4s %-8s %-10s %s" % ("ok" if ok else "FAIL", name,
|
| 143 |
+
a.tag, got[:10] if got else "absent"))
|
| 144 |
+
|
| 145 |
if bad:
|
| 146 |
print("\nthe sites disagree -- do not publish")
|
| 147 |
return 1
|