From 44f3231a745ca5e39f7f0e784ac8ac60f2a7da48 Mon Sep 17 00:00:00 2001 From: Python1320 Date: Sun, 25 Oct 2020 19:56:00 +0200 Subject: [PATCH] Add Hammer CI WIP --- .gitignore | 4 + LAUNCH hammer.cmd | 8 ++ extras/flashcmd.exe | Bin 0 -> 8704 bytes test.cmd | 32 +++++ vbspautotest/install_icon_155236.ico | Bin 0 -> 67646 bytes vbspautotest/requirements.txt | 4 + vbspautotest/utils.py | 95 +++++++++++++ vbspautotest/vbspautotest.py | 197 +++++++++++++++++++++++++++ 8 files changed, 340 insertions(+) create mode 100644 extras/flashcmd.exe create mode 100644 test.cmd create mode 100644 vbspautotest/install_icon_155236.ico create mode 100644 vbspautotest/requirements.txt create mode 100644 vbspautotest/utils.py create mode 100644 vbspautotest/vbspautotest.py diff --git a/.gitignore b/.gitignore index 23b3f6d..dbb1382 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,7 @@ /game_compiling_ /setup/__pycache__ /setup/build/setup +/*.mdmp +*.pyc +/vbspautotest/build/setup +/vbspautotest/env diff --git a/LAUNCH hammer.cmd b/LAUNCH hammer.cmd index 0d2e086..f6d8742 100644 --- a/LAUNCH hammer.cmd +++ b/LAUNCH hammer.cmd @@ -3,6 +3,7 @@ @if defined NOHAMMERAUTOUPDATE @GOTO updated + @echo. @echo Modified mapfiles: @git -C "%mapfolder%" status --untracked-files=no -s @@ -10,6 +11,7 @@ @echo # Autoupdating mapfiles... + @git -C "%mapfolder%" pull @if ERRORLEVEL 1 @GOTO updatefail @@ -47,6 +49,12 @@ @rem @set VProject=%VProject_Hammer% @rem @echo Project: %VProject% + +@if not defined NOHAMMERCI ( + @cd vbspautotest + @start /low /min vbspautotest.exe +) + @TITLE "Hammer Repo Waiter" @echo # Waiting for hammer to close... @start /WAIT "Hammer" "%VProject_Hammer%\..\bin\hammer.exe" %HammerParams% %* diff --git a/extras/flashcmd.exe b/extras/flashcmd.exe new file mode 100644 index 0000000000000000000000000000000000000000..bb632d03cd7537b8930ca54fa5ece720a155138b GIT binary patch literal 8704 zcmeHMYiu0Xbv`pYyIhhc#U*KqekdHTWNTweE0TIxR>hbU9~Nzjq`509a+uJ=-QjZL z*`3wQEJdo7Kow2fxJeoViHjNzS{FrIqYYvME$p^7(zGyw1PHz(b7)@Ox z`Oy@K)bE^`eee-C4*I8Q?{dzZbM8Hld(ORg?!7$s=qD*cL>iu(H;G=to6Cs6cLtlN zZtwe>cKXZauiW*LGX0giva6P-mtCje8bv*4luC}TFPpksDd|>8AD_+WMJI2j+uB+V zgsSHzh^CbYefruzWvbTRAXRBqT8VnWi3i;F`|#HBjNoCQ83i}!*pAX?zy4huV3k*u4p29xQkNoHAd~)-ub;<+R5)g z6AN_J1P+OU+iLVS1xwVt_x*Rbsh_ZJXri&3+&(l;!L=CmK;;vG%9dEClInzq(yEU* zFXfn9;I^>VQWv-gfk;!9PTm(f^K8v{;LM-a=xxsAc5&vjY@p`MPlJHL88y|t!dl?i(4hO^%UK!aM?$p>Quc85vOM zJl;~=7ubNbb6=^Ufr$Iv8pHiz9sLWnCh_@54ShI7o5Rz5^G6eB*$VY48NA3TJ3L*_3cq3Da@_dJ%JvT#Anu%YG$d}HO%prs?;s< z!>#U*VB5O`+$*uxerke1*MLd}>|<^vNZl@>^|bb%?W7yGqFU{w*ZGyg64sL12XGZm zYn>Fi3O3%_RXB@x^eViS#!5)QY+@Xx)rB+(HpZo&(iJO`urrL(;Mx)FYdprTy@2OnDgaA!P<|R(S;Qf^a^> zFt!S~uvrFwVe{7n{*J)k6Zl60KL6CUw1*BI zV9}@O?-UOchU56Eq9Qt928@uZs+hTPz$mq0=qS{wc62DH?dVX!@95w*%)cGDN`1oN zT9#t|L6vm2!1%myURB;pKT$Sl5b)P&6z~a}68MO~ivkUSmcUB_Hw0c6_)&pR0{$*N z3;1bz4sZiAfbkcoTYH-Rnv&YH!27j713#&KPVg_#7wD9ByTCsB5-n<9q_2{ty#`p( zX6W0{@C1FA{#^SGy-lxb|3W_&j-vcTc^i7VqyGV@M-?TG$lQai-#*G?Jn2};{b zaw{Fgo0PqD9DHq)v(s3bu!5n!RuozhT*H`%%D#(EpL6mR+k79b*oL>7HrGuWbBaZy zl%KXr=A7YrrVCEVb8K^xn`|LaH#t3;IeTGhW^$IK{(@D?JC}iCp_~i0=T!7^j%!=X zl-clnvq-bcA2xG7Ef{vi%x;uTnkZF@G;ZdsqG6L5rOc{xdBSxaSFp3DU8d1&c699Q z(%k6$#7uT+Zhm%bB9jTMh8_mS=|R)q!Z?fW*k+@D++@;m&4TMxO8L6jq?4<7JLGB9 z_l?|YsIyVe#5(1cGu9Q8Rxg+Gln*;z8G~9MWY#L0PQ|A+?&{J~7_FsDc6P3ckB!b{ zr)FoWWOjb^Vig~qp01+VsdE$aTZoz2$p`72VU@^m5$l{-3<8{Xn=Oem#(>6B9HNY^}EuV^}=NSd`=K}iUlzj`iC!Dh&?oH)k z(Dhagd(^AzIbXtXfk<9bS-!ktg?UcTn=3XF4HY!%d1i6h-pE?MZPsP0>~Yh}xt3Vl zS&6u>ScM9Fgr?o9i)EvpyZW)D=$lSKXVvd%f+^uCc zU`T}Kk^S^AkCSmX#9ipte5ll#AA!qp2=}#A2 z%QtzAsJfP2bxk7=hbh1)W1D7~waoc0M$*#6rHa93=~0YH@G&Q>{A}3_@;b4eGbR5d z!zlEZ@o@HH#xgbOI>nF^jz!}6H@iaPwmnrWJ8nZ(D_Fgb4yE(9O^=&y$+XcS^b&(& z+StIntS333AI9RvuAW1xt+Kr#Zm*YZD~Fju(IfPLz*WG*w2EWq5y}akBV}w9Uyn8H zl5MJx3EaY}u9FM=5;&G%d2m*+Gjs8Fs7yZi4!#~biKfUwQtm$pDv&Lq&Ic7}weYQZ zCu#O3FW%(;2fT5KenC%Q9iBiQF>-(5{y_4`&PW*BqR|*bWzPicVW{Cbg?7|hK?V#e zAOo~tm)O~$J!DR&4{V9QM<2vVqfwg&9klr(i*Z zdw||cbUhI`o`V>R`=TyzXQ$gby_4fSMvIW=(Y(_IKkV{lv4h!zE(Pw_JM%cCO^o(x zM}iJBwFbT`-sQ2o;&5;s=jV#laEQ2F9x#V)vM)g}*b)aim?55cRt9IckR0WZYTx;Aa@pOG-<0841;pcVVPHQ79dSqmq;BFRegHuL(& z|KJCO;jS~E>AODnEd7BSmSCVE3xV;@VA= z7!GyucpR)=?9bKSM0ayD8pY!=wCR9EtXYlqMq-I>>~L{=pfKQ_t_Bg(n5prx9*4*H zzV?VtiiSfuMRi3<>{C1F$%4bczZjJys8SXK((VZ36)4RH^tiHi3CnhQBuKY zXK^KMY$)m7YDT39!3BA=X8B&U~mvO1ULi?;-UgSTubnYfLj9zZm!?MC*`c# zbHO#rGft`YMaB2nx$H^X>fJZT>P~Q;!Cmt+xX+r;jAstL{KB^?>Y;X7$=N z7Ra4iJdbavxA>4_E{>aPxcMy?&62-3hwto)V_VK*V+Xbp&hm#B*H4~+9JV)$vd2i5 z^ULh>|EBWBiMqEp7}x7`BUZiNuJe}09Cu>fluf#vflO2OBHZHU-K3AyoBp4}RQ_)X zhjNqu^>Pw#yc$YyJ2&?;_}GDMHZ%sxqjd+f#{VR+KO7-?o(Fzd=EjKL48(-8F>0Z!07uqm3Q8PHRJlfb#WqP=w^uvZlh-q;&T;nk;F6S8Prcner4abm`z%gg8# zmP%eSxf~#t%A(egg_b|@)xDuKpyxGQ%s_7jd^h|G?$q?JFs$HiqWU|AjRe*T*lz>B z+I}3?abgrb^*t!t8QZeZPr}b&tHE^xSZ3-v7NEn0mSF$N^@F(m7^pqCBb8e+?j?WJ zT)cU2JOjwP2}0ki+S8!dg?E-ZVPhJ2L0YpvWqcU9#|3<*unQL-xAJt{8|nBB!TunA zM5o2}Y$(Tj2DV-8KT|*3htm?PImkNLC{z$9zrpKwj?poR(N@{*k=h=olOi*USn`H| zw~aP>tYZvrjqrB4xBm9?ryp1^+WJ~>{v1x?+mO`FQqJLH*l_ZEcJlDar0)5+{xEE( zWDX}cOfUJs``TJg8{v6ehk}wfoUFK|Q(kTrM_=!7(aO1w=dAdLb58M;;T6+sgGn8S zd~3z@{O~{-WHGeYn9YXMiJ)EZH$)rG$p6gv{5c6j|3WUCiDEM z(u(tQ`ZJUiIoS5hTm?tbjgSV%H7`}*rTWuVS8rSDN%A{7jLSrAKBvj=_9oupuy=Q)eM2a bfc|ADScrI2)*=66`DN(P|M%hDMBu*w#{;0h literal 0 HcmV?d00001 diff --git a/test.cmd b/test.cmd new file mode 100644 index 0000000..53a41b7 --- /dev/null +++ b/test.cmd @@ -0,0 +1,32 @@ +@set ORIGFOLDER=%CD% +@set CMD_LC_ROOT=%~dp0 + +@call common.cmd +@cd /d "%CMD_LC_ROOT%" + +:docopy +@set targetvmf=%mapfolder%\ci.vmf +@set targetbsp=%mapfolder%\ci.bsp +@set leakfile=%mapfolder%\ci.lin +@del /Q /F "%targetvmf%" 2>nul >nul +@del /Q /F "%targetbsp%" 2>nul >nul +@rem The mappers need this :p +@rem del /Q /F "%leakfile%" + +@COPY "%mapfolder%\%mapfile%.vmf" "%targetvmf%" >nul +@if ERRORLEVEL 1 goto failed + +extras\vmfii "%targetvmf%" "%targetvmf%" --fgd "%FGDS%" > nul +@if ERRORLEVEL 1 goto failed +"%compilers_dir%\vbsp.exe" -allowdynamicpropsasstatic -leaktest -low "%targetvmf%" +@if ERRORLEVEL 1 goto failed +@if NOT exist "%targetbsp%" goto failed +"%compilers_dir%\vvis.exe" -fast -low "%targetvmf%" +@if ERRORLEVEL 1 goto failed +"%compilers_dir%\vrad.exe" -low %VRADLDR% -noskyboxrecurse -bounce 1 -noextra -fastambient -fast -ldr "%targetvmf%" +@if ERRORLEVEL 1 goto failed +@goto ok + +:failed +@exit 1 +:ok diff --git a/vbspautotest/install_icon_155236.ico b/vbspautotest/install_icon_155236.ico new file mode 100644 index 0000000000000000000000000000000000000000..7f29f62246abd8d6616afb49b713718f86525679 GIT binary patch literal 67646 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 Po~N^;S}OU%46gqV*cd6B literal 0 HcmV?d00001 diff --git a/vbspautotest/requirements.txt b/vbspautotest/requirements.txt new file mode 100644 index 0000000..c917631 --- /dev/null +++ b/vbspautotest/requirements.txt @@ -0,0 +1,4 @@ +vpk +vdf +pyinstaller +win10toast \ No newline at end of file diff --git a/vbspautotest/utils.py b/vbspautotest/utils.py new file mode 100644 index 0000000..ef0f505 --- /dev/null +++ b/vbspautotest/utils.py @@ -0,0 +1,95 @@ + +import os +import winreg +import subprocess +import vdf +from pathlib import Path +from functools import lru_cache +from pprint import pprint as PrintTable +# DETECT OS VERSION + +def Is64Windows(): + return 'PROGRAMFILES(X86)' in os.environ + +def GetProgramFiles32(): + if Is64Windows(): + return os.environ['PROGRAMFILES(X86)'] + else: + return os.environ['PROGRAMFILES'] + +def GetProgramFiles64(): + if Is64Windows(): + return os.environ['PROGRAMW6432'] + else: + return None + +if Is64Windows() is True: + key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Wow6432Node\\Valve\\Steam") +else: + key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Valve\\Steam") + +steampath = winreg.QueryValueEx(key, "InstallPath")[0] +@lru_cache(maxsize=32) +def GetSteamPath(): + return steampath + +@lru_cache(maxsize=32) +def GetSteamLibraryPaths(): + with open(GetSteamPath() + "/SteamApps/LibraryFolders.vdf") as lf: + vdffile = vdf.parse(lf) + vdflocations = [val for key,val in vdffile['LibraryFolders'].items() if key.isdigit()]+[steampath] + for path in vdflocations: + print("\tFound Library path: ",path) + return vdflocations + +@lru_cache(maxsize=32) +def GetGamePath(appid): + for acfpath in GetSteamLibraryPaths(): + appmanifestpath = acfpath + "/SteamApps/appmanifest_%d.acf"%(appid) + if os.path.isfile(appmanifestpath): + appmanifest = vdf.parse(open(appmanifestpath)) + return Path(acfpath+"\\SteamApps\\common\\"+appmanifest['AppState']['installdir']+"\\") + +@lru_cache(maxsize=32) +def GetGModPath(): + return GetGamePath(4000) + +@lru_cache(maxsize=32) +def TF2Path(d="."): + return GetGamePath(440) / d + +@lru_cache(maxsize=32) +def CSSPath(d="."): + return GetGamePath(240) / d + +@lru_cache(maxsize=32) +def MapFiles(d="."): + return Path("../../mapfiles").resolve() / d + +@lru_cache(maxsize=32) +def MapAssets(d="."): + return Path("../../mapdata").resolve() / d + +@lru_cache(maxsize=32) +def HammerRoot(): + p = Path("../game_hammer").resolve() + #assert p.exists() + return p + +@lru_cache(maxsize=32) +def CompilerRoot(): + p = Path("../game_compiling").resolve() + #assert p.exists() + return p + +@lru_cache(maxsize=32) +def ToolkitRoot(d="."): + return Path("..").resolve() / d + + + + +def execute_batch(cmd,cwd): + p=subprocess.Popen(cmd,cwd=cwd)#, creationflags=subprocess.CREATE_NEW_CONSOLE) + p.communicate() + return p.returncode \ No newline at end of file diff --git a/vbspautotest/vbspautotest.py b/vbspautotest/vbspautotest.py new file mode 100644 index 0000000..290a23b --- /dev/null +++ b/vbspautotest/vbspautotest.py @@ -0,0 +1,197 @@ + +import ctypes,sys,os +ctypes.windll.kernel32.SetConsoleTitleW("Hammer CI") + +# UGH +def install_and_import(package,package_pip): + import importlib + try: + importlib.import_module(package) + except ImportError: + import subprocess + subprocess.check_call([sys.executable, '-m', 'pip', 'install', package_pip]) + finally: + globals()[package] = importlib.import_module(package) + + +def callback_from_icon(): + pass + +install_and_import("notify","winnotify") +import notify + +ICO='install_icon_155236.ico' +notify.init(ICO, callback_from_icon) + + +from utils import * +from pathlib import Path +import shutil +from shutil import copyfileobj +import traceback +import distutils.dir_util +import time +import win32gui +import subprocess + +import win32event +import win32api +from winerror import ERROR_ALREADY_EXISTS + + + +mutex = win32event.CreateMutex(None, False, 'hammerciautotest') +last_error = win32api.GetLastError() + +if last_error == ERROR_ALREADY_EXISTS: + print("Already running") + sys.exit(43) + + +def my_except_hook(*exc_info): + if exc_info[0] == KeyboardInterrupt: + sys.exit(0) + else: + print("\n\n====== Something unexpected happened that we can't handle ======") + print("".join(traceback.format_exception(*exc_info))) + input("This may be a programming error.\nCopy all of this screen and make an issue at https://github.com/Metastruct/map-compiling-toolkit/issues/new\n\nPress ENTER to abort.") + sys.exit(1) + +sys.excepthook = my_except_hook + +def pathcheck(fatal,printthing,path): + if path.exists(): + print("\t",printthing,path) + else: + print("\t",printthing,path," !!!! MISSING !!!!") + if fatal: + input("\nPress ENTER to abort.") + sys.exit(1) + +print("\nChecking paths:") +pathcheck(True,"GMod\t\t",GetGModPath()) +if not (GetGModPath() / 'bin/win64').exists(): + input("\nERROR: You need to run GMod in x86-64 branch for devenv to work.\n\nPress ENTER to abort.") + sys.exit(1) + +pathcheck(False,"Hammer\t\t",HammerRoot()) +pathcheck(False,"Compiler\t",CompilerRoot()) +pathcheck(False,"TF2\t\t",TF2Path("tf")) +pathcheck(False,"CSS\t\t",CSSPath("cstrike")) +pathcheck(True,"Maps\t\t",MapFiles()) +pathcheck(True,"Map assets\t",MapAssets()) +print("") + +cifile = MapFiles("ci.vmf").resolve() +cilog = MapFiles("ci.log").resolve() + +watchables={vmf:1 or vmf.stat().st_size for vmf in MapFiles().glob("*.vmf") if vmf.resolve()!=cifile and "gm_construct_m" not in str(vmf)} + +def watch(): + found=False + for vmf,size in watchables.items(): + time.sleep(0) + st_size=vmf.stat().st_size + if st_size!=size: + watchables[vmf]=st_size + found=vmf + if found: + time.sleep(1) + for vmf,size in watchables.items(): + time.sleep(0) + st_size=vmf.stat().st_size + if st_size!=size: + watchables[vmf]=st_size + found=vmf + + return found + +def okcb(str): + sys.stdout.write(str) + sys.stdout.flush() + +def failcb(str): + sys.stderr.write(str) + sys.stderr.flush() + +wasfailed=False +firstcompile=True + +def dofail(ret): + + + if cilog.exists(): + print("Found log file") + with cilog.open("rb") as f: + f.seek(-512, os.SEEK_END) + if b"LEAKED" in f.read(): + print("LEAK DETECT") + notify.notify("Map leaked!", + "Hammer CI", + ICO, + False,10,0x03) + ctypes.windll.kernel32.SetConsoleTitleW("Status: MAP LEAKED") + return + notify.notify("Map compiling failed! Look at console window for more info. "+str(ret),"Hammer CI", + + + ICO, + False,10,0x03) + ctypes.windll.kernel32.SetConsoleTitleW("Map compiling failed.") + +startup_time = time.time() + +check_fails=0 +last_ret=None +def checkdead(): + global check_fails + global last_ret + if win32gui.FindWindow("VALVEWORLDCRAFT",None)!=0: + return False + check_fails += 1 + if check_fails < 5: + return + time.sleep(1) + print("Shutting down") + notify.notify("Shutting down. Last compile: "+(last_ret==None and "Unknown" or (last_ret==0 and '[SUCCESS]' or '[FAIL]')),"Hammer CI", + + + ICO, + False,10,last_ret==0 and 0x01 or 0x03) + return True + +while True: + + if checkdead(): + break + + changed = watch() + if changed: + print("\n\nRUNNING CI DUE TO FILE CHANGE: ",changed) + cwd=os.getcwd() + os.chdir(ToolkitRoot()) + + start_time = time.time() + + ret = execute_batch(["test.cmd"],ToolkitRoot()) + + e = int(time.time() - start_time) + print('Compiling ran for {:02d}:{:02d}:{:02d}'.format(e // 3600, (e % 3600 // 60), e % 60)) + os.chdir(cwd) + last_ret = ret + ctypes.windll.kernel32.SetConsoleTitleW((ret==0 and '[SUCCESS]' or '[FAIL]') +'Compiling ran for {:02d}:{:02d}:{:02d}'.format(e // 3600, (e % 3600 // 60), e % 60)) + if ret == 0: + if wasfailed or firstcompile: + notify.notify("Compiling succeeded! :)\nTook {:02d}:{:02d}:{:02d}".format(e // 3600, (e % 3600 // 60), e % 60),"Hammer CI", + + ICO, + False,10,0x01) + firstcompile=False + wasfailed=False + else: + wasfailed=True + print("RETURN",ret) + dofail(ret) + time.sleep(10) + print("Resuming monitoring...") + time.sleep(1)