Skip to content

Commit 5ff8a17

Browse files
committed
feat: Add script for signing release tags.
1 parent 7cd2dcb commit 5ff8a17

File tree

3 files changed

+155
-68
lines changed

3 files changed

+155
-68
lines changed

.github/workflows/common-ci.yml

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ jobs:
1919

2020
restyled:
2121
runs-on: ubuntu-22.04
22+
if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target'
2223
steps:
2324
- uses: actions/checkout@v4
2425
with:

tools/lib/git.py

+84-68
Original file line numberDiff line numberDiff line change
@@ -87,28 +87,24 @@ def __enter__(self) -> None:
8787
if diff_exitcode():
8888
print("Stashing changes.")
8989
self.stashed = True
90-
subprocess.run( # nosec
90+
subprocess.check_call( # nosec
9191
[
9292
"git",
9393
"stash",
9494
"--quiet",
9595
"--include-untracked",
96-
],
97-
check=True,
98-
)
96+
])
9997

10098
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
10199
if self.stashed:
102100
print("Restoring stashed changes.")
103-
subprocess.run( # nosec
101+
subprocess.check_call( # nosec
104102
[
105103
"git",
106104
"stash",
107105
"pop",
108106
"--quiet",
109-
],
110-
check=True,
111-
)
107+
])
112108

113109

114110
class Checkout:
@@ -120,28 +116,24 @@ def __init__(self, branch: str) -> None:
120116
def __enter__(self) -> None:
121117
if self.branch != current_branch():
122118
print(f"Checking out {self.branch} (from {self.old_branch}).")
123-
subprocess.run( # nosec
119+
subprocess.check_call( # nosec
124120
[
125121
"git",
126122
"checkout",
127123
"--quiet",
128124
self.branch,
129-
],
130-
check=True,
131-
)
125+
])
132126

133127
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
134128
if self.old_branch != current_branch():
135129
print(f"Moving back to {self.old_branch}.")
136-
subprocess.run( # nosec
130+
subprocess.check_call( # nosec
137131
[
138132
"git",
139133
"checkout",
140134
"--quiet",
141135
self.old_branch,
142-
],
143-
check=True,
144-
)
136+
])
145137

146138

147139
class ResetOnExit:
@@ -153,15 +145,13 @@ def __enter__(self) -> None:
153145
pass
154146

155147
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
156-
subprocess.run( # nosec
148+
subprocess.check_call( # nosec
157149
[
158150
"git",
159151
"reset",
160152
"--quiet",
161153
"--hard",
162-
],
163-
check=True,
164-
)
154+
])
165155

166156

167157
@memoize
@@ -187,7 +177,7 @@ def fetch(*remotes: str) -> None:
187177
branches, tags, and prunes stale references. Overwrites local tags if they
188178
have been updated on the remote.
189179
"""
190-
subprocess.run( # nosec
180+
subprocess.check_call( # nosec
191181
[
192182
"git",
193183
"fetch",
@@ -197,24 +187,20 @@ def fetch(*remotes: str) -> None:
197187
"--force",
198188
"--multiple",
199189
*remotes,
200-
],
201-
check=True,
202-
)
190+
])
203191

204192

205193
def pull(remote: str) -> None:
206194
"""Pull changes from the current branch and remote."""
207-
subprocess.run( # nosec
195+
subprocess.check_call( # nosec
208196
[
209197
"git",
210198
"pull",
211199
"--rebase",
212200
"--quiet",
213201
remote,
214202
current_branch(),
215-
],
216-
check=True,
217-
)
203+
])
218204

219205

220206
def remote_slug(remote: str) -> types.RepoSlug:
@@ -307,7 +293,7 @@ def release_tag_exists(tag: str) -> bool:
307293

308294
def tag(tag: str, message: str, sign: bool) -> None:
309295
"""Create a signed tag with a message."""
310-
subprocess.run( # nosec
296+
subprocess.check_call( # nosec
311297
[
312298
"git",
313299
"tag",
@@ -316,9 +302,7 @@ def tag(tag: str, message: str, sign: bool) -> None:
316302
"--message",
317303
message,
318304
tag,
319-
],
320-
check=True,
321-
)
305+
])
322306

323307

324308
def release_branches() -> list[str]:
@@ -374,59 +358,101 @@ def current_tag() -> str:
374358
]).decode("utf-8").strip())
375359

376360

361+
def tag_has_signature(tag: str) -> bool:
362+
"""Check if a tag has a signature."""
363+
return b"-----BEGIN PGP SIGNATURE-----" in subprocess.check_output( # nosec
364+
[
365+
"git",
366+
"cat-file",
367+
"tag",
368+
tag,
369+
])
370+
371+
372+
def verify_tag(tag: str) -> bool:
373+
"""Verify the signature of a tag."""
374+
return (subprocess.run( # nosec
375+
[
376+
"git",
377+
"verify-tag",
378+
"--verbose",
379+
tag,
380+
],
381+
check=False,
382+
).returncode == 0)
383+
384+
385+
def sign_tag(tag: str) -> None:
386+
"""Sign a tag with its original message."""
387+
subprocess.check_call( # nosec
388+
[
389+
"git",
390+
"tag",
391+
"--sign",
392+
"--force",
393+
tag,
394+
f"{tag}^{{}}",
395+
])
396+
397+
398+
def push_tag(tag: str, remote: str) -> None:
399+
"""Push a tag to a remote."""
400+
subprocess.check_call( # nosec
401+
[
402+
"git",
403+
"push",
404+
"--quiet",
405+
"--force",
406+
remote,
407+
tag,
408+
])
409+
410+
377411
def checkout(branch: str) -> None:
378412
"""Checkout a branch."""
379-
subprocess.run( # nosec
413+
subprocess.check_call( # nosec
380414
[
381415
"git",
382416
"checkout",
383417
"--quiet",
384418
branch,
385-
],
386-
check=True,
387-
)
419+
])
388420

389421

390422
def revert(*files: str) -> None:
391423
"""Checkout files."""
392424
branch = current_branch()
393-
subprocess.run( # nosec
425+
subprocess.check_call( # nosec
394426
[
395427
"git",
396428
"checkout",
397429
"--quiet",
398430
branch,
399431
"--",
400432
*files,
401-
],
402-
check=True,
403-
)
433+
])
404434

405435

406436
def add(*files: str) -> None:
407437
"""Add files to the index."""
408-
subprocess.run( # nosec
438+
subprocess.check_call( # nosec
409439
[
410440
"git",
411441
"add",
412442
*files,
413-
],
414-
check=True,
415-
)
443+
])
416444

417445

418446
def reset(branch: str) -> None:
419447
"""Reset a branch to a specific commit."""
420-
subprocess.run( # nosec
448+
subprocess.check_call( # nosec
421449
[
422450
"git",
423451
"reset",
424452
"--quiet",
425453
"--hard",
426454
branch,
427-
],
428-
check=True,
429-
)
455+
])
430456

431457

432458
def rebase(onto: str, commits: int = 0) -> bool:
@@ -438,28 +464,24 @@ def rebase(onto: str, commits: int = 0) -> bool:
438464
"""
439465
old_sha = branch_sha("HEAD")
440466
if not commits:
441-
subprocess.run( # nosec
467+
subprocess.check_call( # nosec
442468
[
443469
"git",
444470
"rebase",
445471
"--quiet",
446472
onto,
447-
],
448-
check=True,
449-
)
473+
])
450474
else:
451475
branch = current_branch()
452-
subprocess.run( # nosec
476+
subprocess.check_call( # nosec
453477
[
454478
"git",
455479
"rebase",
456480
"--quiet",
457481
"--onto",
458482
onto,
459483
f"HEAD~{commits}",
460-
],
461-
check=True,
462-
)
484+
])
463485
new_sha = branch_sha("HEAD")
464486
checkout(branch)
465487
reset(new_sha)
@@ -468,23 +490,21 @@ def rebase(onto: str, commits: int = 0) -> bool:
468490

469491
def create_branch(branch: str, base: str) -> None:
470492
"""Create a branch from a base branch."""
471-
subprocess.run( # nosec
493+
subprocess.check_call( # nosec
472494
[
473495
"git",
474496
"checkout",
475497
"--quiet",
476498
"-b",
477499
branch,
478500
base,
479-
],
480-
check=True,
481-
)
501+
])
482502

483503

484504
def push(remote: str, branch: str, force: bool = False) -> None:
485505
"""Push the current branch to a remote."""
486506
force_flag = ["--force"] if force else []
487-
subprocess.run( # nosec
507+
subprocess.check_call( # nosec
488508
[
489509
"git",
490510
"push",
@@ -493,9 +513,7 @@ def push(remote: str, branch: str, force: bool = False) -> None:
493513
"--set-upstream",
494514
remote,
495515
branch,
496-
],
497-
check=True,
498-
)
516+
])
499517

500518

501519
def list_changed_files() -> list[str]:
@@ -553,7 +571,7 @@ def commit(title: str, body: str) -> None:
553571
"""
554572
amend = ["--amend"] if last_commit_message(
555573
current_branch()) == title else []
556-
subprocess.run( # nosec
574+
subprocess.check_call( # nosec
557575
[
558576
"git",
559577
"commit",
@@ -563,9 +581,7 @@ def commit(title: str, body: str) -> None:
563581
title,
564582
"--message",
565583
body,
566-
],
567-
check=True,
568-
)
584+
])
569585

570586

571587
def files_changed(commit: str) -> list[str]:

0 commit comments

Comments
 (0)