wp-wpcli-and-ops/examples/run-cli-fixture.py
Version 34da134e184e.bb1 · GPL-2.0-or-later. This preview displays packaged text and does not execute code. Treat the contents as untrusted instructions.
← Return to resource and package checksum
"""Bounded, disposable native WP-CLI helper experiment; GPL-2.0-or-later."""
from pathlib import Path
import datetime as dt,hashlib,json,secrets,subprocess,sys,time,os
root=Path(__file__).resolve().parent;owned=[];stage='preflight';cases=[];reports={}
names={'wp':'bb-v43-cli-wp','db':'bb-v43-cli-db','net':'bb-v43-cli-net','node':'bb-v43-node-source'}
def cmd(args,timeout=90):
p=subprocess.run(args,text=True,capture_output=True,timeout=timeout)
if p.returncode:raise RuntimeError('Command failed in '+stage+' with exit '+str(p.returncode))
return p.stdout
def wp(args,extra=None):
command=['docker','exec']
if extra:command+=['-e','WORDPRESS_CONFIG_EXTRA='+extra]
return cmd(command+[names['wp'],'php','/fixture/wp-cli.phar','--allow-root','--path=/var/www/html',*args])
def observe(name,actual,expected):
assert actual==expected,{'case':name,'actual':actual,'expected':expected}
cases.append({'name':name,'observed':actual,'expected':expected,'status':'passed'})
def helper(kind,case,arguments=None,missing=False,extra=None):
command=['docker','exec']
if missing:command+=['-e','PATH=/no-wp-cli']
if extra:command+=['-e','WORDPRESS_CONFIG_EXTRA='+extra]
command+=[names['wp'],'/fixture/runtime/node','/fixture/'+kind+'.mjs',*(arguments or ['--allow-root','--path=/var/www/html'])]
p=subprocess.run(command,text=True,capture_output=True,timeout=60)
assert p.returncode==0
r=json.loads(p.stdout);reports[kind+'-'+case]={'process_exit':p.returncode,'report':r};return r
for kind,name in [('container',names['wp']),('container',names['db']),('network',names['net']),('container',names['node'])]:
if subprocess.run(['docker',kind,'inspect',name],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL).returncode==0:raise RuntimeError('Temporary name exists; refusing replacement')
try:
source=json.loads((root/'wp-cli-source.json').read_text());assert hashlib.sha512((root/'wp-cli.phar').read_bytes()).hexdigest()==source['sha512']
images={}
for key,tag in [('wordpress','wordpress:7.1.2-php8.3-apache'),('database','mariadb:11.4'),('node','node:22-trixie-slim')]:
image=json.loads(cmd(['docker','image','inspect',tag]))[0];images[key]={'tag':tag,'id':image['Id'],'digests':image.get('RepoDigests',[])}
stage='extract verified image Node';cmd(['docker','create','--name',names['node'],'--network','none',images['node']['id']]);owned.append(('container',names['node']))
runtime=root/'runtime';runtime.mkdir(exist_ok=True);runtime.chmod(0o755);cmd(['docker','cp',names['node']+':/usr/local/bin/node',str(runtime/'node')]);(runtime/'node').chmod(0o755)
stage='create isolated database';cmd(['docker','network','create','--internal',names['net']]);owned.append(('network',names['net']))
password=secrets.token_hex(24);root_password=secrets.token_hex(24)
cmd(['docker','run','-d','--name',names['db'],'--network',names['net'],'--memory','768m','--memory-swap','768m','--cpus','1','--tmpfs','/var/lib/mysql:rw,size=384m','-e','MARIADB_DATABASE=fixture','-e','MARIADB_USER=fixture','-e','MARIADB_PASSWORD='+password,'-e','MARIADB_ROOT_PASSWORD='+root_password,images['database']['id']]);owned.append(('container',names['db']))
for n in range(60):
if subprocess.run(['docker','exec',names['db'],'healthcheck.sh','--connect','--innodb_initialized'],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL).returncode==0:break
time.sleep(1)
else:raise RuntimeError('Temporary database not ready')
stage='create isolated WordPress'
extra="define('WP_ENVIRONMENT_TYPE','local');define('DISABLE_WP_CRON',true);define('AUTOMATIC_UPDATER_DISABLED',true);define('WP_HTTP_BLOCK_EXTERNAL',true);define('WP_DEBUG',false);"
cmd(['docker','run','-d','--name',names['wp'],'--network',names['net'],'--memory','768m','--memory-swap','768m','--cpus','1','--tmpfs','/var/www/html:rw,size=256m','--tmpfs','/tmp:rw,size=32m','-e','WORDPRESS_DB_HOST='+names['db'],'-e','WORDPRESS_DB_NAME=fixture','-e','WORDPRESS_DB_USER=fixture','-e','WORDPRESS_DB_PASSWORD='+password,'-e','WORDPRESS_CONFIG_EXTRA='+extra,'-v',str(root)+':/fixture:ro',images['wordpress']['id']]);owned.append(('container',names['wp']))
for n in range(60):
if subprocess.run(['docker','exec',names['wp'],'test','-f','/var/www/html/wp-config.php'],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL).returncode==0:break
time.sleep(1)
else:raise RuntimeError('Temporary WordPress not ready')
stage='setup';environment=json.loads(cmd(['docker','exec',names['wp'],'php','/fixture/setup-cli-fixture.php']))
cmd(['docker','exec',names['wp'],'sh','-c','printf \'#!/bin/sh\\nexec php /fixture/wp-cli.phar "$@"\\n\' > /usr/local/bin/wp && chmod 755 /usr/local/bin/wp'])
node_version=cmd(['docker','exec',names['wp'],'/fixture/runtime/node','--version']).strip();observe('wp-cli-version',wp(['--version']).strip(),'WP-CLI 2.12.0')
stage='missing CLI'
for kind in ['perf','ops']:
r=helper(kind,'missing-cli',missing=True);observe(kind+'-missing-cli',r['wpCli']['available'],False);observe(kind+'-missing-cli-process-exit',reports[kind+'-missing-cli']['process_exit'],0)
stage='invalid target'
for kind in ['perf','ops']:
r=helper(kind,'bad-path',['--allow-root','--path=/not-a-wordpress-install']);part=r['wp'] if kind=='perf' else r['wordpress'];observe(kind+'-wrong-path',part['isInstalled'],False)
stage='valid target'
ops=helper('ops','valid');observe('ops-core-version',ops['wordpress']['coreVersion'],'7.1.2');observe('ops-single-site',ops['wordpress']['isMultisite'],False);observe('ops-siteurl',ops['wordpress']['siteurl'],'http://bb-v43-cli-wp')
perf=helper('perf','valid');observe('perf-installed',perf['wp']['isInstalled'],True);observe('perf-core-version',perf['wp']['coreVersion'],'7.1.2')
stage='autoload cross-check'
truth=json.loads(wp(['eval',"global $wpdb; $values=wp_autoload_values_to_autoload(); $quoted=implode(',',array_map(function($v){return \"'\".esc_sql($v).\"'\";},$values)); echo json_encode(['autoload_values'=>$values,'total_bytes'=>(int)$wpdb->get_var(\"SELECT SUM(LENGTH(option_value)) FROM $wpdb->options WHERE autoload IN ($quoted)\"), 'excluded_bytes'=>(int)$wpdb->get_var(\"SELECT SUM(LENGTH(option_value)) FROM $wpdb->options WHERE autoload IN ('auto','auto-on')\"),'seeded_bytes'=>(int)$wpdb->get_var(\"SELECT SUM(LENGTH(option_value)) FROM $wpdb->options WHERE option_name LIKE 'bb_probe_%' AND autoload IN ($quoted)\")]);"]))
observe('core-active-autoload-values',truth['autoload_values'],['yes','on','auto-on','auto']);observe('synthetic-active-autoload-bytes',truth['seeded_bytes'],100);observe('upstream-cli-seeded-bytes-excludes-auto-values',int(wp(['option','list','--search=bb_probe_*','--autoload=on','--format=total_bytes']).strip()),30);observe('upstream-helper-underreports-active-bytes',truth['total_bytes']-perf['perfSignals']['autoloadTotalBytes'],truth['excluded_bytes']);assert truth['excluded_bytes']>=70
observe('doctor-uninstalled',perf['commands']['doctor']['available'],False);observe('profile-uninstalled',perf['commands']['profile']['available'],False)
stage='presence markers'
# PHP is the only extra interpreter in this container. These markers have no cache implementation or active plugin hooks.
php="foreach (['object-cache.php','advanced-cache.php','plugins/query-monitor/query-monitor.php','plugins/performance-lab/load.php'] as $rel) {$p='/var/www/html/wp-content/'.$rel;@mkdir(dirname($p),0755,true);file_put_contents($p,'<?php /* Synthetic presence marker only. */');}"
cmd(['docker','exec',names['wp'],'php','-r',php]);presence=helper('perf','presence')
keys=['hasObjectCacheDropin','hasAdvancedCacheDropin','hasQueryMonitorPlugin','hasPerformanceLabPlugin'];observe('file-presence-signals',[presence['perfSignals'][k] for k in keys],[True]*4)
observe('marker-plugins-not-activated',json.loads(wp(['option','get','active_plugins','--format=json'])),[])
stage='custom content directory'
php="foreach (['object-cache.php','advanced-cache.php','plugins/query-monitor/query-monitor.php','plugins/performance-lab/load.php'] as $rel) {unlink('/var/www/html/wp-content/'.$rel);$p='/tmp/custom-wp-content/'.$rel;@mkdir(dirname($p),0755,true);file_put_contents($p,'<?php /* Synthetic presence marker only. */');}"
cmd(['docker','exec',names['wp'],'php','-r',php]);custom_extra=extra+"define('WP_CONTENT_DIR','/tmp/custom-wp-content');define('WP_CONTENT_URL','http://bb-v43-cli-wp/custom-content');"
content=json.loads(wp(['eval',"echo json_encode(['content_dir'=>WP_CONTENT_DIR,'object_cache_exists'=>is_file(WP_CONTENT_DIR.'/object-cache.php'),'query_monitor_file_exists'=>is_file(WP_PLUGIN_DIR.'/query-monitor/query-monitor.php')]);"],extra=custom_extra));observe('actual-custom-content-directory',content['content_dir'],'/tmp/custom-wp-content');observe('actual-custom-marker-files',[content['object_cache_exists'],content['query_monitor_file_exists']],[True,True])
custom=helper('perf','custom-content',extra=custom_extra);observe('upstream-custom-directory-false-negatives',[custom['perfSignals'][k] for k in keys],[False]*4)
stage='adapted diagnostic verification'
fixed=helper('perf-adapted','custom-content',extra=custom_extra);observe('adapted-helper-autoload-equals-core-sql',fixed['perfSignals']['autoloadTotalBytes'],truth['total_bytes']);observe('adapted-helper-resolves-custom-directory',fixed['wp']['contentDirectory'],'/tmp/custom-wp-content');observe('adapted-custom-directory-presence-signals',[fixed['perfSignals'][k] for k in keys],[True]*4)
clean=helper('perf-adapted','default-content');observe('adapted-default-directory-resolved',clean['wp']['contentDirectory'],'/var/www/html/wp-content');observe('adapted-default-no-marker-signals',[clean['perfSignals'][k] for k in keys],[False]*4)
for case,args,missing in [('missing-cli',None,True),('bad-path',['--allow-root','--path=/not-a-wordpress-install'],False)]:
r=helper('perf-adapted',case,args,missing=missing);observe('adapted-'+case+'-fails-readiness',r['wpCli']['available'] if missing else r['wp']['isInstalled'],False)
result={'format':1,'executed_at':dt.datetime.now(dt.UTC).isoformat(),'environment':environment,'node':node_version,'wp_cli':source,'images':images,'observations':len(cases),'cases':cases,'reports':reports,'autoload_cross_check':truth,'custom_content_truth':content,'source_hashes':{n:hashlib.sha256((root/n).read_bytes()).hexdigest() for n in ['perf.mjs','ops.mjs','setup-cli-fixture.php','run-cli-fixture.py','perf-adapted.mjs']},'scope':'Actual upstream native helper execution, dependency/target checks, synthetic autoload values and file-presence signals. No AI client, speed benchmark, migration, persistent cache, multisite or production site tested.','observed_upstream_limitations':['WP-CLI 2.12.0 autoload=on excluded auto/auto-on values in the synthetic fixture','Upstream helper assumes default wp-content and plugin paths; configured content directory produced false negatives'],'adapted_helper_verified':True,'runtime_tested':False,'native_helpers_executed':True,'internal_network':True,'published_ports':False,'production_mounts_or_networks':False,'credentials_saved_or_exported':False,'external_ai_calls':False}
path=root/'native-cli-evidence.json';path.write_text(json.dumps(result,indent=2));path.chmod(0o600);print(json.dumps({k:result[k] for k in ['observations','environment','node','scope','native_helpers_executed','runtime_tested']}))
except Exception as error:
detail={'stage':stage,'error_type':type(error).__name__}
if isinstance(error,AssertionError) and error.args and isinstance(error.args[0],dict):detail['observation']=error.args[0]
print(json.dumps(detail));sys.exit(1)
finally:
for kind,name in reversed(owned):subprocess.run(['docker','rm','-fv',name] if kind=='container' else ['docker','network','rm',name],stdout=subprocess.DEVNULL,stderr=subprocess.DEVNULL)