mc-cms-namelessmc/dev/scripts/release/release.py
Robin a17b6886b9
Update release script for php 8.2 (#3636)
Remove dependency on the external dev-oldphp image
2025-04-30 15:45:37 -07:00

169 lines
5.2 KiB
Python

import subprocess
import shutil
from pathlib import Path
import sys
import tempfile
INCLUDE_DIRS = [
'cache',
'core',
'custom',
'dev',
'modules',
'uploads',
'vendor',
]
INCLUDE_FILES = [
'.htaccess',
'403.php',
'404.php',
'index.php',
'install.php',
'LICENSE.txt',
'rewrite_test.php',
]
def generate_checksums(cwd):
subprocess.check_call(['php', 'dev/scripts/generate_checksums.php'],
shell=False,
cwd=cwd)
def create_archive_dir(archive_source: str = '.') -> str:
# Copy all files that should be included to a temporary directory
archive_temp = tempfile.mkdtemp(prefix='nameless')
for include_file in INCLUDE_FILES:
include_path = Path(archive_source, include_file)
if include_path.exists():
shutil.copy(include_path, archive_temp)
for include_dir in INCLUDE_DIRS:
include_path = Path(archive_source, include_dir)
if include_path.exists():
shutil.copytree(include_path, Path(archive_temp, include_dir))
return archive_temp
def create_archives(archive_name, cwd):
archive_path: str = Path('release', archive_name).absolute().as_posix()
print('Archive: Creating .zip file')
zip_command = [
'zip',
'-r', # Recursive
'-q', # Quiet
f'{archive_path}.zip',
'.',
]
subprocess.check_call(zip_command, shell=False, cwd=cwd)
print('Archive: Creating .tar.xz file')
tar_command = [
'tar',
'-c', # Compress
'-J', # Use xzip
'--owner=0', # Set owner inside archive to root
'--group=0',
'-f', f'{archive_path}.tar.xz',
'.',
]
subprocess.check_call(tar_command, shell=False, cwd=cwd,
env={'XZ_DEFAULTS': '-T 0'}) # Enable multithreading
def regenerate_vendor_files():
print('Re-generating vendor files')
shutil.rmtree('core/assets/vendor', ignore_errors=True)
subprocess.check_call(['npm', 'ci', '-q', '--cache', '.node_cache'])
subprocess.check_call(['composer', 'update'])
subprocess.check_call(['composer', 'install', '--no-dev', '--no-interaction'])
def create_deps_dist_archive():
print('Creating nameless-deps-dist archive')
# Copy the required files to a new temporary directory
deps_dist_temp = create_archive_dir()
# Generate checksums
generate_checksums(deps_dist_temp)
# Create .zip and .tar.xz archives
create_archives('nameless-deps-dist', deps_dist_temp)
# Temporary directory can now be deleted
shutil.rmtree(deps_dist_temp)
def always_in_update_package(relative_path: str) -> bool:
return relative_path == 'checksums.json' or relative_path.startswith('vendor/') or relative_path.startswith('core/assets/vendor')
def create_upgrade_archive():
print('Creating update archive')
# Copy the required files to a new temporary directory
upgrade_temp = create_archive_dir()
# Generate checksums
generate_checksums(upgrade_temp)
# Find previous tag
previous_tag_command = ['git', 'describe', '--abbrev=0', '--tags']
previous_tag = subprocess.check_output(previous_tag_command, shell=False)[:-1].decode()
print('Creating files for upgrade from', previous_tag)
# Find all files changed between previous tag and HEAD (current state)
changed_command = ['git', 'diff', previous_tag, 'HEAD', '--name-only', '--diff-filter=d']
changed_files_output = subprocess.check_output(changed_command, shell=False)[:-1]
changed_files = set(changed_files_output.decode().split('\n'))
# Delete any files that have not been changed
for path in Path(upgrade_temp).rglob("*"):
relative_path = path.as_posix()[len(upgrade_temp)+1:]
if (
not always_in_update_package(relative_path) and
relative_path not in changed_files and
path.is_file()
):
path.unlink()
# Delete empty directoryes
subprocess.check_call(['find', '.', '-type', 'd', '-empty', '-delete'], cwd=upgrade_temp)
# Create .zip and .tar.xz archives
create_archives('upgrade-from-' + previous_tag, upgrade_temp)
def create_deps_dev_archive():
print('Creating nameless-deps-dev archive')
# Copy the required files to a new temporary directory
deps_dev_temp = create_archive_dir()
# Generate checksums
generate_checksums(deps_dev_temp)
# Create .zip and .tar.xz archives
create_archives('nameless-deps-dev', deps_dev_temp)
# Temporary directory can now be deleted
shutil.rmtree(deps_dev_temp)
if __name__ == '__main__':
if not Path('.git').exists():
print('.git does not exist')
sys.exit(1)
# Re-generate vendor files (without development dependencies)
regenerate_vendor_files()
# Create nameless-deps-dist archive with production dependencies only
create_deps_dist_archive()
# Create update archive (files changed since last tag)
create_upgrade_archive()
# Run composer again, to install development dependencies
subprocess.check_call(['composer', 'install', '--no-interaction'])
# Create nameless-deps-dev archive with development dependencies
create_deps_dev_archive()