1
1
#!/usr/bin/env python3
2
2
3
3
import argparse
4
- import os
5
4
import re
6
5
import subprocess
7
6
import sys
7
+ import tempfile
8
8
from pathlib import Path
9
9
10
10
11
- ROOT_DIR = Path (__file__ ).resolve ().parent .parent
12
- CARGO_TOML = ROOT_DIR / "Cargo.toml"
13
-
14
-
15
11
def parse_args (argv : list [str ]) -> argparse .Namespace :
16
12
parser = argparse .ArgumentParser (description = "Create a tagged Codex release." )
17
13
parser .add_argument (
@@ -22,99 +18,78 @@ def parse_args(argv: list[str]) -> argparse.Namespace:
22
18
23
19
24
20
def main (argv : list [str ]) -> int :
25
- os .chdir (ROOT_DIR )
26
21
args = parse_args (argv )
27
22
try :
28
- ensure_clean_worktree ()
29
- branch = current_branch ()
30
- ensure_on_main ( branch )
31
- ensure_on_origin_main ( )
32
- create_release (args .version , branch )
23
+ with tempfile . TemporaryDirectory () as temp_dir :
24
+ repo_dir = Path ( temp_dir ) / "codex"
25
+ clone_repository ( repo_dir )
26
+ branch = current_branch ( repo_dir )
27
+ create_release (args .version , branch , repo_dir )
33
28
except ReleaseError as error :
34
29
print (f"ERROR: { error } " , file = sys .stderr )
35
30
return 1
36
31
return 0
37
32
38
33
39
- def ensure_clean_worktree () -> None :
40
- commands = [
41
- ["diff" , "--quiet" ],
42
- ["diff" , "--cached" , "--quiet" ],
43
- ]
44
- for command in commands :
45
- result = run_git (command , check = False )
46
- if result .returncode != 0 :
47
- raise ReleaseError ("You have uncommitted changes." )
48
-
49
- untracked = run_git (["ls-files" , "--others" , "--exclude-standard" ], capture_output = True )
50
- if untracked .stdout .strip ():
51
- raise ReleaseError ("You have untracked files." )
52
-
53
-
54
- def ensure_on_main (branch : str ) -> None :
55
- if branch != "main" :
56
- raise ReleaseError (
57
- f"Releases must be created from the 'main' branch (current: '{ branch } ')."
58
- )
59
-
60
-
61
- def ensure_on_origin_main () -> None :
62
- try :
63
- run_git (["fetch" , "--quiet" , "origin" , "main" ])
64
- except ReleaseError as error :
65
- raise ReleaseError (
66
- "Failed to fetch 'origin/main'. Ensure the 'origin' remote is configured and reachable."
67
- ) from error
68
-
69
- result = run_git (["merge-base" , "--is-ancestor" , "HEAD" , "origin/main" ], check = False )
70
- if result .returncode != 0 :
71
- raise ReleaseError (
72
- "Your local 'main' HEAD commit is not present on 'origin/main'. "
73
- "Please push first (git push origin main) or check out a commit on 'origin/main'."
74
- )
75
-
76
-
77
- def current_branch () -> str :
78
- result = run_git (["symbolic-ref" , "--short" , "-q" , "HEAD" ], capture_output = True , check = False )
34
+ def current_branch (repo_dir : Path ) -> str :
35
+ result = run_git (
36
+ repo_dir ,
37
+ ["symbolic-ref" , "--short" , "-q" , "HEAD" ],
38
+ capture_output = True ,
39
+ check = False ,
40
+ )
79
41
branch = result .stdout .strip ()
80
42
if result .returncode != 0 or not branch :
81
43
raise ReleaseError ("Could not determine the current branch (detached HEAD?)." )
82
44
return branch
83
45
84
46
85
- def update_version (version : str ) -> None :
86
- content = CARGO_TOML .read_text (encoding = "utf-8" )
47
+ def update_version (version : str , cargo_toml : Path ) -> None :
48
+ content = cargo_toml .read_text (encoding = "utf-8" )
87
49
new_content , matches = re .subn (
88
50
r'^version = "[^"]+"' , f'version = "{ version } "' , content , count = 1 , flags = re .MULTILINE
89
51
)
90
52
if matches != 1 :
91
53
raise ReleaseError ("Unable to update version in Cargo.toml." )
92
- CARGO_TOML .write_text (new_content , encoding = "utf-8" )
54
+ cargo_toml .write_text (new_content , encoding = "utf-8" )
93
55
94
56
95
- def create_release (version : str , branch : str ) -> None :
57
+ def create_release (version : str , branch : str , repo_dir : Path ) -> None :
96
58
tag = f"rust-v{ version } "
97
- run_git (["checkout" , "-b" , tag ])
59
+ run_git (repo_dir , ["checkout" , "-b" , tag ])
98
60
try :
99
- update_version (version )
100
- run_git (["add" , "Cargo.toml" ])
101
- run_git (["commit" , "-m" , f"Release { version } " ])
102
- run_git (["tag" , "-a" , tag , "-m" , f"Release { version } " ])
103
- run_git (["push" , "origin" , f"refs/tags/{ tag } " ])
61
+ update_version (version , repo_dir / "codex-rs" / "Cargo.toml" )
62
+ run_git (repo_dir , ["add" , "codex-rs/ Cargo.toml" ])
63
+ run_git (repo_dir , ["commit" , "-m" , f"Release { version } " ])
64
+ run_git (repo_dir , ["tag" , "-a" , tag , "-m" , f"Release { version } " ])
65
+ run_git (repo_dir , ["push" , "origin" , f"refs/tags/{ tag } " ])
104
66
finally :
105
- run_git (["checkout" , branch ])
67
+ run_git (repo_dir , ["checkout" , branch ])
68
+
69
+
70
+ def clone_repository (destination : Path ) -> None :
71
+ result = subprocess .run (
72
+ ["gh" , "repo" , "clone" , "openai/codex" , str (destination ), "--" , "--depth" , "1" ],
73
+ text = True ,
74
+ )
75
+ if result .returncode != 0 :
76
+ raise ReleaseError ("Failed to clone openai/codex using gh." )
106
77
107
78
108
79
class ReleaseError (RuntimeError ):
109
80
pass
110
81
111
82
112
83
def run_git (
113
- args : list [str ], * , capture_output : bool = False , check : bool = True
84
+ repo_dir : Path ,
85
+ args : list [str ],
86
+ * ,
87
+ capture_output : bool = False ,
88
+ check : bool = True ,
114
89
) -> subprocess .CompletedProcess :
115
90
result = subprocess .run (
116
91
["git" , * args ],
117
- cwd = ROOT_DIR ,
92
+ cwd = repo_dir ,
118
93
text = True ,
119
94
capture_output = capture_output ,
120
95
)
0 commit comments