2020-11-11 11:10:53 -08:00
#!/usr/bin/env python3
2020-10-23 19:13:06 -07:00
2022-05-12 21:24:07 -07:00
"""
Gochan build / install / maintenance script
For a list of commands , run
python3 build . py - - help
For information on a specific command , run
python3 build . py < command > - - help
See README . md for more info
"""
2020-10-23 19:13:06 -07:00
import argparse
2022-04-03 15:54:46 -07:00
import errno
2020-10-23 19:13:06 -07:00
import os
from os import path
2022-07-19 12:42:46 -07:00
from pathlib import Path
2020-11-04 20:11:51 -08:00
import shutil
2020-10-23 19:13:06 -07:00
import subprocess
import sys
2023-01-01 15:59:54 -08:00
import traceback
2020-10-23 19:13:06 -07:00
2021-02-10 16:22:23 -08:00
release_files = (
2022-04-03 15:54:46 -07:00
" html/css/ " ,
" html/error/ " ,
2023-01-26 09:42:15 -08:00
" html/static/ " ,
2020-11-04 20:11:51 -08:00
" html/favicon2.png " ,
" html/favicon.png " ,
" html/firstrun.html " ,
2022-03-24 16:05:50 -07:00
" html/js/ " ,
2023-10-19 11:33:21 -07:00
" examples/configs/ " ,
" examples/plugins/ " ,
2022-04-03 15:54:46 -07:00
" templates/ " ,
2022-12-24 14:40:36 -08:00
" sql/initdb_master.sql " ,
" sql/initdb_mysql.sql " ,
" sql/initdb_postgres.sql " ,
" sql/initdb_sqlite3.sql " ,
2020-11-04 20:11:51 -08:00
" LICENSE " ,
" README.md " ,
2021-02-10 16:22:23 -08:00
)
2020-11-04 20:11:51 -08:00
2024-04-16 10:58:36 -07:00
GOCHAN_VERSION = " 3.10.2 "
2024-03-05 21:37:45 -08:00
DATABASE_VERSION = " 3 " # stored in DBNAME.DBPREFIXdatabase_version
2023-04-07 12:35:12 -07:00
PATH_NOTHING = - 1
PATH_UNKNOWN = 0
PATH_FILE = 1
PATH_DIR = 2
PATH_LINK = 4
2022-01-16 23:12:28 -08:00
gcos = " "
gcos_name = " " # used for release, since macOS GOOS is "darwin"
exe = " "
gochan_bin = " "
gochan_exe = " "
2022-02-07 18:28:27 -08:00
migration_bin = " "
migration_exe = " "
2022-04-03 15:54:46 -07:00
def pathinfo ( loc ) :
i = PATH_UNKNOWN
if not path . exists ( loc ) :
return PATH_NOTHING
if path . islink ( loc ) :
i | = PATH_LINK
if path . isfile ( loc ) :
i | = PATH_FILE
elif path . isdir ( loc ) :
i | = PATH_DIR
2020-11-04 20:11:51 -08:00
else :
2022-04-03 15:54:46 -07:00
i = PATH_UNKNOWN
return i
def delete ( delpath ) :
"""
2023-05-22 08:49:32 -07:00
Deletes the given file , link , or directory and silently fails if nothing exists .
2022-04-03 15:54:46 -07:00
Returns the path info as well
"""
pinfo = pathinfo ( delpath )
if pinfo == PATH_NOTHING :
return PATH_NOTHING
if pinfo & PATH_FILE > 0 or pinfo & PATH_LINK > 0 :
os . remove ( delpath )
return pinfo
2023-05-22 08:49:32 -07:00
if pinfo & PATH_DIR > 0 :
2022-04-05 19:56:57 -07:00
shutil . rmtree ( delpath )
2023-05-22 08:49:32 -07:00
return pinfo
2022-04-03 15:54:46 -07:00
return PATH_UNKNOWN
2023-05-22 08:49:32 -07:00
def mkdir ( dirpath , force = False ) :
if path . exists ( dirpath ) :
2022-04-03 15:54:46 -07:00
if force :
2023-05-22 08:49:32 -07:00
delete ( dirpath )
2022-04-03 15:54:46 -07:00
else :
return
2023-06-02 14:46:49 -07:00
os . makedirs ( dirpath )
2022-04-03 15:54:46 -07:00
def copy ( source , dest ) :
"""
Copy source to dest , overwriting dest if source and dest are files , and merging
them if source is a directory and dest is a directory that already exists , overwriting
any conflicting files
"""
srcinfo = pathinfo ( source )
destinfo = pathinfo ( dest )
if srcinfo == PATH_NOTHING :
raise FileNotFoundError ( errno . ENOENT , os . strerror ( errno . ENOENT ) , source )
if srcinfo & PATH_FILE > 0 or srcinfo & PATH_LINK > 0 :
shutil . copy ( source , dest )
return
if srcinfo & PATH_DIR > 0 :
if destinfo == PATH_NOTHING :
mkdir ( dest )
else :
for root , dirs , files in os . walk ( source ) :
mkdir ( path . join ( dest , root ) )
2023-05-22 08:49:32 -07:00
for dirpath in dirs :
mkdir ( path . join ( dest , root , dirpath ) )
2022-04-03 15:54:46 -07:00
for file in files :
shutil . copy ( path . join ( root , file ) , path . join ( dest , root , file ) )
2020-11-04 20:11:51 -08:00
2022-08-07 22:54:11 -07:00
2022-07-19 12:42:46 -07:00
def symlink ( target , link ) :
""" Create symbolic link at `link` that points to `target` """
targetinfo = pathinfo ( target )
linkinfo = pathinfo ( link )
if target == PATH_NOTHING :
raise FileNotFoundError ( errno . ENOENT , os . strerror ( errno . ENOENT ) , target )
if linkinfo != PATH_NOTHING :
delete ( link )
elif linkinfo == PATH_DIR and targetinfo == PATH_FILE :
target = path . join ( link , path . basename ( target ) )
target = path . abspath ( target )
print ( " Creating a symbolic link at " , link , " pointing to " , target )
Path ( link ) . symlink_to ( target )
2022-01-16 23:12:28 -08:00
def run_cmd ( cmd , print_output = True , realtime = False , print_command = False ) :
2020-10-23 19:13:06 -07:00
if print_command :
2024-03-05 20:47:40 -08:00
print ( " " . join ( cmd ) )
proc = subprocess . Popen ( cmd ,
2022-01-27 23:59:03 -08:00
stdout = subprocess . PIPE ,
2024-03-05 20:47:40 -08:00
stderr = subprocess . STDOUT )
2020-10-23 19:13:06 -07:00
output = " "
status = 0
2022-01-16 23:12:28 -08:00
if realtime : # print the command's output in real time, ignores print_output
2020-10-23 19:13:06 -07:00
while True :
2023-05-13 23:56:19 -07:00
try :
realtime_output = proc . stdout . readline ( ) . decode ( " utf-8 " )
if realtime_output == " " and status is not None :
return ( " " , status )
if realtime_output :
print ( realtime_output . strip ( ) )
output + = realtime_output
status = proc . poll ( )
2023-05-22 08:49:32 -07:00
except KeyboardInterrupt :
2023-05-13 23:56:19 -07:00
return ( output , 0 )
2024-03-05 21:37:45 -08:00
else : # wait until the command is finished to print the output
2020-10-23 19:13:06 -07:00
output = proc . communicate ( ) [ 0 ]
if output is not None :
output = output . decode ( " utf-8 " ) . strip ( )
else :
output = " "
status = proc . wait ( )
if output != " " and print_output :
print ( output )
if status is None :
status = 0
return ( output , status )
2020-11-04 20:11:51 -08:00
2022-01-16 23:12:28 -08:00
def set_vars ( goos = " " ) :
2023-04-07 12:35:12 -07:00
""" Sets GOOS-related variables to be used globally """
2020-11-04 20:11:51 -08:00
global gcos
2022-01-28 00:07:57 -08:00
global gcos_name # used for release, since macOS GOOS is "darwin"
2020-11-04 20:11:51 -08:00
global exe
global gochan_bin
global gochan_exe
2022-02-07 18:28:27 -08:00
global migration_bin
global migration_exe
2020-11-04 20:11:51 -08:00
if goos != " " :
os . environ [ " GOOS " ] = goos
2024-03-05 20:47:40 -08:00
gcos , gcos_status = run_cmd ( ( " go " , " env " , " GOOS " ) , print_output = False )
exe , exe_status = run_cmd ( ( " go " , " env " , " GOEXE " ) , print_output = False )
2020-11-04 20:11:51 -08:00
if gcos_status + exe_status != 0 :
print ( " Invalid GOOS value, check your GOOS environment variable " )
2022-01-16 23:12:28 -08:00
sys . exit ( 1 )
2020-11-04 20:11:51 -08:00
gcos_name = gcos
if gcos_name == " darwin " :
gcos_name = " macos "
gochan_bin = " gochan "
gochan_exe = " gochan " + exe
2022-02-07 18:28:27 -08:00
migration_bin = " gochan-migration "
migration_exe = " gochan-migration " + exe
2022-08-14 00:07:27 +00:00
2020-11-04 20:11:51 -08:00
2023-06-05 12:21:59 -07:00
def build ( debugging = False , plugin_path = " " ) :
2022-01-09 23:09:44 -08:00
""" Build the gochan executable for the current GOOS """
2020-11-04 20:11:51 -08:00
pwd = os . getcwd ( )
2024-03-05 20:47:40 -08:00
trimpath = f " -trimpath= { pwd } "
gcflags_debug = " -l -N " if debugging else " "
gcflags = f " -gcflags= { trimpath } { gcflags_debug } "
ldflags_debug = " " if debugging else " -w -s "
ldflags = f " -ldflags=-X main.versionStr= { GOCHAN_VERSION } -X main.dbVersionStr= { DATABASE_VERSION } { ldflags_debug } "
build_cmd_base = [ " go " , " build " , " -v " , " -trimpath " , gcflags , ldflags ]
2020-11-04 20:11:51 -08:00
2022-01-30 11:56:59 -08:00
print ( " Building error pages from templates " )
with open ( " templates/404.html " , " r " ) as tmpl404 :
tmpl404str = tmpl404 . read ( ) . strip ( )
with open ( " html/error/404.html " , " w " ) as page404 :
2023-04-07 12:35:12 -07:00
page404 . write ( tmpl404str . format ( GOCHAN_VERSION ) )
2022-01-30 11:56:59 -08:00
with open ( " templates/5xx.html " , " r " ) as tmpl5xx :
tmpl5xxStr = tmpl5xx . read ( ) . strip ( )
with open ( " html/error/500.html " , " w " ) as page500 :
2023-04-07 12:35:12 -07:00
page500 . write ( tmpl5xxStr . format ( version = GOCHAN_VERSION , title = " Error 500: Internal Server error " ) )
2022-01-30 11:56:59 -08:00
with open ( " html/error/502.html " , " w " ) as page502 :
2023-04-07 12:35:12 -07:00
page502 . write ( tmpl5xxStr . format ( version = GOCHAN_VERSION , title = " Error 502: Bad gateway " ) )
2022-01-30 11:56:59 -08:00
2020-10-23 19:13:06 -07:00
if debugging :
2024-03-05 20:47:40 -08:00
print ( f " Building for { gcos } with debugging symbols " )
2020-10-23 19:13:06 -07:00
else :
2024-03-05 20:47:40 -08:00
print ( f " Building for { gcos } " )
2020-11-04 20:11:51 -08:00
2023-06-05 12:21:59 -07:00
status = - 1
2023-06-05 12:34:07 -07:00
if plugin_path != " " and plugin_path is not None :
2024-03-08 12:48:01 -08:00
build_cmd_base + = [ " -buildmode=plugin " , plugin_path ]
2024-03-05 20:47:40 -08:00
status = run_cmd ( build_cmd_base , realtime = True , print_command = True ) [ 1 ]
2023-06-05 12:21:59 -07:00
if status != 0 :
2024-03-05 20:47:40 -08:00
print ( f " Failed building plugin at { plugin_path } , see output for details " )
2023-06-05 12:21:59 -07:00
sys . exit ( 1 )
print ( " Built plugin successfully " )
return
2024-03-05 20:47:40 -08:00
gochan_build_cmd = build_cmd_base + [ " -o " , gochan_exe , " ./cmd/gochan " ]
status = run_cmd ( gochan_build_cmd , realtime = True , print_command = True ) [ 1 ]
2020-10-23 19:13:06 -07:00
if status != 0 :
2021-02-04 11:44:19 -08:00
print ( " Failed building gochan, see command output for details " )
2022-01-16 23:12:28 -08:00
sys . exit ( 1 )
print ( " Built gochan successfully " )
2024-03-05 20:47:40 -08:00
gochan_migrate_build_cmd = build_cmd_base + [ " -o " , migration_exe , " ./cmd/gochan-migration " ]
status = run_cmd ( gochan_migrate_build_cmd , realtime = True , print_command = True ) [ 1 ]
2022-02-07 18:28:27 -08:00
if status != 0 :
print ( " Failed building gochan-migration, see command output for details " )
sys . exit ( 1 )
print ( " Built gochan-migration successfully " )
2020-10-23 19:13:06 -07:00
2022-04-03 15:54:46 -07:00
2020-10-23 19:13:06 -07:00
def clean ( ) :
print ( " Cleaning up " )
2022-09-04 14:27:14 -07:00
del_files = ( " gochan " , " gochan.exe " , " gochan-migration " , " gochan-migration.exe " , " releases/ " )
2020-10-23 19:13:06 -07:00
for del_file in del_files :
2022-04-03 15:54:46 -07:00
delete ( del_file )
2020-10-23 19:13:06 -07:00
2022-01-16 23:12:28 -08:00
2020-10-23 19:13:06 -07:00
def dependencies ( ) :
2022-07-19 12:42:46 -07:00
print ( " Installing dependencies for gochan " )
2024-03-05 21:37:45 -08:00
run_cmd ( ( " go " , " get " ) , realtime = True , print_command = True )
2020-10-23 19:13:06 -07:00
2022-01-16 23:12:28 -08:00
def docker ( option = " guestdb " , attached = False ) :
2024-03-05 21:37:45 -08:00
db_option = " "
2020-10-23 19:13:06 -07:00
if option == " guestdb " :
2024-03-05 21:37:45 -08:00
db_option = " docker/docker-compose-mariadb.yaml "
2020-10-23 19:13:06 -07:00
elif option == " hostdb " :
2024-03-05 21:37:45 -08:00
db_option = " docker/docker-compose.yml.default "
2020-10-23 19:13:06 -07:00
elif option == " macos " :
2024-03-05 21:37:45 -08:00
db_option = " docker/docker-compose-syncForMac.yaml "
cmd = [ " docker-compose " , " -f " , db_option , " up " , " --build " ]
2022-01-16 23:12:28 -08:00
if attached is False :
2024-03-05 21:37:45 -08:00
cmd + = [ " --detach " ]
2022-01-28 00:07:57 -08:00
status = run_cmd ( cmd , print_output = True , realtime = True , print_command = True ) [ 1 ]
2020-10-23 19:13:06 -07:00
if status != 0 :
2022-01-16 23:12:28 -08:00
print ( " Failed starting a docker container, exited with status code " , status )
sys . exit ( 1 )
2020-10-23 19:13:06 -07:00
2022-07-19 12:42:46 -07:00
def install ( prefix = " /usr " , document_root = " /srv/gochan " , symlinks = False , js_only = False , css_only = False , templates_only = False ) :
2022-04-05 19:56:57 -07:00
if gcos == " windows " :
2022-04-03 16:07:02 -07:00
print ( " Installation is not currently supported for Windows, use the respective directory created by running `python build.py release` " )
2022-01-16 23:12:28 -08:00
sys . exit ( 1 )
2022-04-03 15:54:46 -07:00
mkdir ( document_root )
mkdir ( path . join ( prefix , " share/gochan " ) )
2022-07-19 12:42:46 -07:00
print ( " Creating symbolic links: " , symlinks )
2020-11-04 20:11:51 -08:00
2022-04-03 15:54:46 -07:00
start_dir = path . abspath ( path . curdir )
2021-12-29 11:31:27 -08:00
done = False
2022-05-12 18:03:29 +00:00
if js_only is True :
2022-04-03 15:54:46 -07:00
# args contains --js, install the JavaScript files
os . chdir ( path . join ( start_dir , " html/ " ) )
2022-07-19 12:42:46 -07:00
if symlinks :
symlink ( " js " , path . join ( document_root , " js " ) )
else :
copy ( " js/ " , document_root )
2022-04-03 15:54:46 -07:00
os . chdir ( start_dir )
2021-12-29 11:31:27 -08:00
done = True
2022-04-03 15:54:46 -07:00
print ( " JavaScript files installed " )
2022-05-12 18:03:29 +00:00
if css_only is True :
2022-04-03 15:54:46 -07:00
# args contains --js, install the CSS files
os . chdir ( path . join ( start_dir , " html/ " ) )
2022-07-19 12:42:46 -07:00
if symlinks :
symlink ( " css/ " , path . join ( document_root , " css " ) )
else :
copy ( " css/ " , document_root )
2022-04-03 15:54:46 -07:00
os . chdir ( start_dir )
2021-12-29 11:31:27 -08:00
done = True
2022-04-03 15:54:46 -07:00
print ( " CSS files installed " )
2022-05-12 18:03:29 +00:00
if templates_only is True :
2022-04-03 15:54:46 -07:00
# args contains --js, install the templates
os . chdir ( start_dir )
2022-07-19 12:42:46 -07:00
if symlinks :
symlink ( " templates/ " , path . join ( prefix , " share/gochan/templates " ) )
else :
copy ( " templates/ " , path . join ( prefix , " share/gochan " ) )
2022-04-03 15:54:46 -07:00
mkdir ( path . join ( prefix , " share/gochan/templates/override/ " ) )
2022-01-04 17:48:46 -08:00
done = True
2022-04-03 15:54:46 -07:00
print ( " Templates installed " )
2022-05-12 18:03:29 +00:00
if done is True :
2022-04-03 15:54:46 -07:00
print ( " Done installing specific stuff " )
2021-12-21 11:14:58 -08:00
return
2022-01-16 23:12:28 -08:00
2022-04-03 15:54:46 -07:00
mkdir ( " /etc/gochan " )
mkdir ( " /var/log/gochan " )
2020-11-04 20:11:51 -08:00
for file in release_files :
2022-08-13 16:58:53 -07:00
try :
if file . startswith ( " html/ " ) :
trimmed = path . relpath ( file , " html/ " )
os . chdir ( path . join ( start_dir , " html/ " ) )
print ( " copying " , trimmed , " to " , path . join ( document_root , trimmed ) )
copy ( trimmed , document_root )
os . chdir ( start_dir )
else :
os . chdir ( start_dir )
copy ( file , path . join ( prefix , " share/gochan " ) )
mkdir ( path . join ( prefix , " share/gochan/templates/override/ " ) )
except shutil . SameFileError as err :
2023-06-02 14:46:49 -07:00
print ( err , " (skipping) " )
2023-05-22 08:49:32 -07:00
except FileNotFoundError :
2023-01-01 15:59:54 -08:00
if file == " html/js/ " :
print ( " Missing html/js directory, this must be built before installation by running python3 build.py js, or mkdir html/js if you don ' t want JavaScript " )
else :
traceback . print_exc ( )
sys . exit ( 1 )
2022-01-16 23:12:28 -08:00
if path . exists ( gochan_exe ) is False :
2020-11-04 20:11:51 -08:00
build ( )
2022-01-16 23:12:28 -08:00
print ( " Installing " , gochan_exe , " to " , path . join ( prefix , " bin " , gochan_exe ) )
2023-05-15 12:25:57 -07:00
try :
if symlinks :
symlink ( gochan_exe , path . join ( prefix , " bin " , gochan_exe ) )
else :
copy ( gochan_exe , path . join ( prefix , " bin " , gochan_exe ) )
except shutil . SameFileError :
print ( gochan_exe , " and " , path . join ( prefix , " bin " , gochan_exe ) , " are the same file, skipping " )
2022-02-07 18:28:27 -08:00
if path . exists ( migration_exe ) is False :
build ( )
print ( " Installing " , migration_exe , " to " , path . join ( prefix , " bin " , migration_exe ) )
2023-05-15 12:25:57 -07:00
try :
if symlinks :
symlink ( migration_exe , path . join ( prefix , " bin " , migration_exe ) )
else :
copy ( migration_exe , path . join ( prefix , " bin " , migration_exe ) )
except shutil . SameFileError :
print ( migration_exe , " and " , path . join ( prefix , " bin " , migration_exe ) , " are the same file, skipping " )
2020-11-04 20:11:51 -08:00
print (
2022-01-16 23:12:28 -08:00
" gochan was successfully installed. If you haven ' t already, you should copy \n " ,
2023-10-19 11:33:21 -07:00
" examples/configs/gochan.example.json to /etc/gochan/gochan.json (modify as needed) \n " ,
2023-01-04 15:33:50 -08:00
" You may also need to go to https://yourgochansite/manage/rebuildall to rebuild the javascript config " )
2020-11-04 20:11:51 -08:00
if gcos == " linux " :
2022-01-16 23:12:28 -08:00
print (
" If your Linux distribution has systemd, you will also need to run the following commands: \n " ,
2023-10-19 11:33:21 -07:00
" cp examples/configs/gochan-[mysql|postgresql|sqlite3].service /lib/systemd/system/gochan.service \n " ,
2020-11-04 20:11:51 -08:00
" systemctl daemon-reload \n " ,
" systemctl enable gochan.service \n " ,
2022-01-16 23:12:28 -08:00
" systemctl start gochan.service " )
2022-04-05 20:24:21 -07:00
print ( " " )
2020-11-04 20:11:51 -08:00
2020-10-23 19:13:06 -07:00
2022-03-24 16:05:50 -07:00
def js ( watch = False ) :
2020-10-23 19:13:06 -07:00
print ( " Transpiling JS " )
2022-04-03 15:54:46 -07:00
mkdir ( " html/js/ " )
delete ( " html/js/gochan.js " )
delete ( " html/js/gochan.js.map " )
2024-03-05 21:37:45 -08:00
npm_cmd = [ " npm " , " --prefix " , " frontend/ " , " run " , " watch-ts " if watch else " build-ts " ]
2020-10-23 19:13:06 -07:00
status = run_cmd ( npm_cmd , True , True , True ) [ 1 ]
if status != 0 :
print ( " JS transpiling failed with status " , status )
2022-01-16 23:12:28 -08:00
sys . exit ( status )
2022-08-07 22:54:11 -07:00
2022-08-07 18:39:56 -07:00
def eslint ( fix = False ) :
print ( " Running eslint " )
2024-03-05 21:37:45 -08:00
npm_cmd = [ " npm " , " --prefix " , " frontend/ " , " run " , " eslint " ]
2022-08-07 18:39:56 -07:00
if fix :
2024-03-05 21:37:45 -08:00
npm_cmd + = [ " --fix " ]
2022-08-07 18:39:56 -07:00
status = run_cmd ( npm_cmd , True , True , True ) [ 1 ]
if status != 0 :
print ( " ESLint failed with status " , status )
sys . exit ( status )
2020-10-23 19:13:06 -07:00
2022-08-07 22:54:11 -07:00
2020-11-04 20:11:51 -08:00
def release ( goos ) :
set_vars ( goos )
build ( False )
2023-04-07 12:35:12 -07:00
release_name = gochan_bin + " -v " + GOCHAN_VERSION + " _ " + gcos_name
2020-11-04 20:11:51 -08:00
release_dir = path . join ( " releases " , release_name )
2022-04-03 15:54:46 -07:00
delete ( release_dir )
2022-01-16 23:12:28 -08:00
print ( " Creating release for " , gcos_name , " \n " )
2022-04-03 15:54:46 -07:00
mkdir ( path . join ( release_dir , " html " ) )
2022-12-24 14:40:36 -08:00
mkdir ( path . join ( release_dir , " sql " ) )
2020-11-04 20:11:51 -08:00
for file in release_files :
2022-04-03 15:54:46 -07:00
srcinfo = pathinfo ( file )
if srcinfo == PATH_NOTHING :
raise FileNotFoundError ( errno . ENOENT , os . strerror ( errno . ENOENT ) , file )
if srcinfo & PATH_FILE > 0 :
shutil . copy ( file , path . join ( release_dir , file ) )
if srcinfo & PATH_DIR > 0 :
shutil . copytree ( file , path . join ( release_dir , file ) )
copy ( gochan_exe , path . join ( release_dir , gochan_exe ) )
2023-05-02 14:42:00 -07:00
copy ( migration_exe , path . join ( release_dir , migration_exe ) )
2022-01-16 23:12:28 -08:00
archive_type = " zip " if goos in ( ' windows ' , ' darwin ' ) else " gztar "
shutil . make_archive ( release_dir , archive_type , root_dir = " releases " , base_dir = release_name )
2020-10-23 19:13:06 -07:00
2023-05-22 08:49:32 -07:00
def sass ( watch = False ) :
2024-03-05 21:37:45 -08:00
npm_cmd = [ " npm " , " --prefix " , " frontend/ " , " run " , " watch-sass " if watch else " build-sass " ]
2022-05-12 21:24:07 -07:00
status = run_cmd ( npm_cmd , True , True , True ) [ 1 ]
2020-10-23 19:13:06 -07:00
if status != 0 :
print ( " Failed running sass with status " , status )
2022-01-16 23:12:28 -08:00
sys . exit ( status )
2022-08-28 15:11:50 -07:00
def test ( verbose = False , coverage = False ) :
2020-11-04 20:11:51 -08:00
pkgs = os . listdir ( " pkg " )
for pkg in pkgs :
2024-03-05 21:37:45 -08:00
cmd = [ " go " , " test " ]
2022-08-28 15:11:50 -07:00
if verbose :
2024-03-05 21:37:45 -08:00
cmd + = [ " -v " ]
2022-08-28 15:11:50 -07:00
if coverage :
2024-03-05 21:37:45 -08:00
cmd + = [ " -cover " ]
cmd + = [ path . join ( " ./pkg " , pkg ) ]
2022-08-28 15:11:50 -07:00
run_cmd ( cmd , realtime = True , print_command = True )
2020-10-23 19:13:06 -07:00
2022-01-16 23:12:28 -08:00
2020-10-23 19:13:06 -07:00
if __name__ == " __main__ " :
action = " build "
try :
action = sys . argv . pop ( 1 )
2022-01-16 23:12:28 -08:00
except IndexError : # no argument was passed
2020-10-23 19:13:06 -07:00
pass
2022-01-16 23:12:28 -08:00
if action . startswith ( " - " ) is False :
2020-10-23 19:13:06 -07:00
sys . argv . insert ( 1 , action )
2022-01-16 23:12:28 -08:00
if action != " dependencies " :
2021-02-10 16:22:23 -08:00
set_vars ( )
2020-10-23 19:13:06 -07:00
2022-04-03 15:54:46 -07:00
valid_actions = (
2022-09-27 11:04:05 -07:00
" build " , " clean " , " dependencies " , " docker " , " install " , " js " , " release " , " sass " , " test " , " selenium "
2022-04-03 15:54:46 -07:00
)
2022-01-27 23:59:03 -08:00
parser = argparse . ArgumentParser ( description = " gochan build script " )
parser . add_argument ( " action " , nargs = 1 , default = " build " , choices = valid_actions )
2022-01-16 23:12:28 -08:00
if action in ( ' --help ' , ' -h ' ) :
2020-10-23 19:13:06 -07:00
parser . print_help ( )
2022-01-16 23:12:28 -08:00
sys . exit ( 2 )
2022-01-17 07:34:39 +00:00
2020-10-23 19:13:06 -07:00
if action == " build " :
2022-08-28 15:11:50 -07:00
parser . add_argument ( " --debug " ,
2022-05-12 21:24:07 -07:00
help = " build gochan and gochan-migrate with debugging symbols " ,
2022-01-16 23:12:28 -08:00
action = " store_true " )
2023-06-05 12:21:59 -07:00
parser . add_argument ( " --plugin " ,
2024-03-05 21:37:45 -08:00
help = " if used, builds the gochan-compatible Go plugin at the specified directory " )
2020-10-23 19:13:06 -07:00
args = parser . parse_args ( )
2023-06-05 12:21:59 -07:00
build ( args . debug , args . plugin )
2020-10-23 19:13:06 -07:00
elif action == " clean " :
clean ( )
2022-01-16 23:12:28 -08:00
sys . exit ( 0 )
2020-10-23 19:13:06 -07:00
elif action == " dependencies " :
dependencies ( )
elif action == " docker " :
2022-08-28 15:11:50 -07:00
parser . add_argument ( " --option " ,
2022-01-16 23:12:28 -08:00
default = " guestdb " ,
choices = [ " guestdb " , " hostdb " , " macos " ] ,
help = " create a Docker container, see docker/README.md for more info " )
2022-08-28 15:11:50 -07:00
parser . add_argument ( " --attached " ,
2022-01-16 23:12:28 -08:00
action = " store_true " ,
help = " keep the command line attached to the container while it runs " )
2020-10-23 19:13:06 -07:00
args = parser . parse_args ( )
2021-03-01 20:23:53 -08:00
try :
docker ( args . option , args . attached )
except KeyboardInterrupt :
print ( " Received keyboard interrupt, exiting " )
2020-10-23 19:13:06 -07:00
elif action == " install " :
2022-08-28 15:11:50 -07:00
parser . add_argument ( " --js " ,
2022-01-16 23:12:28 -08:00
action = " store_true " ,
help = " only install JavaScript (useful for frontend development) " )
2022-08-28 15:11:50 -07:00
parser . add_argument ( " --css " ,
2022-01-16 23:12:28 -08:00
action = " store_true " ,
help = " only install CSS " )
2022-08-28 15:11:50 -07:00
parser . add_argument ( " --templates " ,
2022-01-16 23:12:28 -08:00
action = " store_true " ,
help = " install the template files " )
2022-08-28 15:11:50 -07:00
parser . add_argument ( " --prefix " ,
2022-04-04 21:35:11 -07:00
default = " /usr " ,
2022-01-16 23:12:28 -08:00
help = " install gochan to this directory and its subdirectories " )
2022-08-28 15:11:50 -07:00
parser . add_argument ( " --documentroot " ,
2022-01-16 23:12:28 -08:00
default = " /srv/gochan " ,
help = " install files in ./html/ to this directory to be requested by a browser " )
2022-08-28 15:11:50 -07:00
parser . add_argument ( " --symlinks " ,
2022-07-19 12:33:30 -07:00
action = " store_true " ,
2024-03-05 21:37:45 -08:00
help = " create symbolic links instead of copying the files (may require admin/root privileges) " )
2020-11-04 20:11:51 -08:00
args = parser . parse_args ( )
2022-07-19 12:33:30 -07:00
install ( args . prefix , args . documentroot , args . symlinks , args . js , args . css , args . templates )
2020-10-23 19:13:06 -07:00
elif action == " js " :
2022-08-28 15:11:50 -07:00
parser . add_argument ( " --watch " , " -w " ,
2022-01-16 23:12:28 -08:00
action = " store_true " ,
2024-03-05 21:37:45 -08:00
help = " automatically rebuild when you change a file (keeps running) " )
2022-08-07 18:39:56 -07:00
parser . add_argument (
" --eslint " ,
action = " store_true " ,
help = " Run eslint on the JavaScript code to check for possible problems " )
2022-08-28 15:11:50 -07:00
parser . add_argument ( " --eslint-fix " ,
2022-08-07 18:39:56 -07:00
action = " store_true " ,
2024-03-05 21:37:45 -08:00
help = " Run eslint on the JS code to try to fix detected problems " )
2020-10-23 19:13:06 -07:00
args = parser . parse_args ( )
2022-08-07 22:54:11 -07:00
if args . eslint or args . eslint_fix :
2022-08-07 18:39:56 -07:00
eslint ( args . eslint_fix )
else :
js ( args . watch )
2020-10-23 19:13:06 -07:00
elif action == " release " :
2022-08-28 15:11:50 -07:00
parser . add_argument ( " --all " , " -a " ,
2022-01-16 23:12:28 -08:00
help = " build releases for Windows, macOS, and Linux " ,
action = " store_true " )
2020-10-23 19:13:06 -07:00
args = parser . parse_args ( )
2022-04-03 15:54:46 -07:00
mkdir ( " releases " )
2020-11-04 20:11:51 -08:00
if args . all :
release ( " windows " )
release ( " darwin " )
release ( " linux " )
else :
release ( gcos )
2020-10-23 19:13:06 -07:00
elif action == " sass " :
2022-08-28 15:11:50 -07:00
parser . add_argument ( " --watch " , " -w " ,
2022-01-27 23:59:03 -08:00
action = " store_true " ,
help = " automatically rebuild when you change a file (keeps running) " )
2020-10-23 19:13:06 -07:00
args = parser . parse_args ( )
2023-05-22 08:49:32 -07:00
sass ( args . watch )
2022-09-27 11:04:05 -07:00
elif action == " selenium " :
2023-05-19 12:52:01 -07:00
from devtools . selenium_testing . runtests import parseArgs , start_tests , close_tests
2022-09-27 11:04:05 -07:00
args = parseArgs ( parser )
2023-05-19 12:52:01 -07:00
try :
start_tests ( args . browser , args . headless , args . keepopen , args . site , args . board , " html/static/notbanned.png " , args . singletest )
except KeyboardInterrupt :
print ( " Tests interrupted by KeyboardInterrupt, exiting " )
except Exception :
traceback . print_exc ( )
close_tests ( )
2020-10-23 19:13:06 -07:00
elif action == " test " :
2022-08-28 15:11:50 -07:00
parser . add_argument ( " --verbose " , " -v " ,
action = " store_true " ,
2024-03-05 21:37:45 -08:00
help = " Print log messages in the tests " )
2022-08-28 15:11:50 -07:00
parser . add_argument ( " --coverage " ,
action = " store_true " ,
2024-03-05 21:37:45 -08:00
help = " Print unit test coverage " )
2022-08-28 15:11:50 -07:00
args = parser . parse_args ( )
test ( args . verbose , args . coverage )
2020-10-23 19:13:06 -07:00
args = parser . parse_args ( )