Setting the file. One moment.
Baseline · N8n:testmax Assistant UI · n8n-io/n8n · Skills Docs
ContentsBack to the top of the page scripts/baseline.py
scripts/ baseline.py
Python · 117 lines · 4 KB
15
16 import argparse
17 import fcntl
18 import json
19 import os
20 import subprocess
21 import sys
22 import time
23 from datetime import datetime, timezone
24
25 from common import CACHE , git
26
27 WORKTREE = CACHE / 'master'
28 STATE = CACHE / 'built.json'
29 BUILD_LOG = CACHE / 'build.log'
30
31
32 def built ():
33 try :
34 state = json.loads( STATE .read_text())
35 except ( OSError , ValueError ):
36 return None
37 cli = WORKTREE / 'packages' / 'cli' / 'dist'
38 editor = WORKTREE / 'packages' / 'frontend' / 'editor-ui' / 'dist' / 'index.html'
39 return state if cli.exists() and editor.exists() else None
40
41
42 def target (fetch = False ):
43 """The master commit to build: the merge base of HEAD and origin/master."""
44 if fetch:
45 git( 'fetch' , '--quiet' , 'origin' , 'master' )
46 try :
47 return git( 'merge-base' , 'HEAD' , 'origin/master' )
48 except subprocess.CalledProcessError:
49 return git( 'rev-parse' , 'origin/master' )
50
51
52 def status ():
53 state = built() or {}
54 try :
55 commit = target()
56 except subprocess.CalledProcessError:
57 commit = None
58 return { 'worktree' : str ( WORKTREE ), 'exists' : WORKTREE .exists(), 'builtCommit' : state.get( 'commit' ),
59 'builtAt' : state.get( 'builtAt' ), 'baseCommit' : commit,
60 'upToDate' : bool (commit) and state.get( 'commit' ) == commit, 'log' : str ( BUILD_LOG )}
61
62
63 def run_logged (cmd, log, env = None ):
64 log.write( f ' \n $ { " " .join(cmd) }\n ' )
65 log.flush()
66 code = subprocess.run(cmd, cwd = WORKTREE , stdout = log, stderr = subprocess. STDOUT , env = env).returncode
67 if code != 0 :
68 raise RuntimeError ( f ' { " " .join(cmd) } failed with exit code { code } . See { BUILD_LOG } ' )
69
70
71 def prepare (fetch = True , say = print ):
72 """Return {"root", "commit"} of a built merge base. Builds only when the merge base moved."""
73 CACHE .mkdir( parents = True , exist_ok = True )
74 with ( CACHE / 'build.lock' ).open( 'w' ) as lock:
75 # Two runs at the same time must not build into the same worktree.
76 fcntl.flock(lock, fcntl. LOCK_EX )
77 if fetch:
78 say( 'fetch origin/master' )
79 commit = target(fetch)
80 if not ( WORKTREE / '.git' ).exists():
81 say( f 'create the master worktree in { WORKTREE } ' )
82 git( 'worktree' , 'add' , '--detach' , str ( WORKTREE ), commit)
83 elif git( 'rev-parse' , 'HEAD' , cwd = WORKTREE ) != commit:
84 git( 'checkout' , '--detach' , '--force' , commit, cwd = WORKTREE )
85 state = built()
86 if state and state.get( 'commit' ) == commit:
87 say( f 'master { commit[: 11 ] } is built' )
88 return { 'root' : WORKTREE , 'commit' : commit}
89 started = time.time()
90 say( f 'build master { commit[: 11 ] } (the merge base). The first build takes 15 to 20 minutes. Log: { BUILD_LOG } ' )
91 with BUILD_LOG .open( 'w' ) as log:
92 # DOCKER_BUILD skips the git hook install of the prepare script, so the hooks of the
93 # main checkout stay as they are.
94 run_logged([ 'pnpm' , 'install' , '--frozen-lockfile' ], log, env = { ** os.environ, 'DOCKER_BUILD' : 'true' })
95 run_logged([ 'pnpm' , 'turbo' , 'run' , 'build' , '--filter=n8n...' ], log)
96 STATE .write_text(json.dumps({ 'commit' : commit, 'builtAt' : datetime.now(timezone.utc).isoformat()}, indent = 2 ))
97 say( f 'master { commit[: 11 ] } built in { time.time() - started :.0f} s' )
98 return { 'root' : WORKTREE , 'commit' : commit}
99
100
101 def main ():
102 ap = argparse.ArgumentParser()
103 ap.add_argument( 'action' , choices = [ 'status' , 'prepare' ])
104 ap.add_argument( '--no-fetch' , action = 'store_true' )
105 args = ap.parse_args()
106 if args.action == 'status' :
107 print (json.dumps(status(), indent = 2 ))
108 return
109 try :
110 result = prepare( fetch =not args.no_fetch, say =lambda m: print (m, flush = True ))
111 except ( RuntimeError , subprocess.CalledProcessError) as e:
112 sys.exit( str (e))
113 print (json.dumps({ 'root' : str (result[ 'root' ]), 'commit' : result[ 'commit' ]}, indent = 2 ))
114
115
116 if __name__ == '__main__' :
117 main()