From 99bbc06caa090f6eef4b6a13c5049f70de48e4de Mon Sep 17 00:00:00 2001 From: Jonathan Miller <230051081+jmiller-moko@users.noreply.github.com> Date: Tue, 7 Apr 2026 19:14:39 -0500 Subject: [PATCH] Remove build-release.sh, minify.js, and scripts README from main Replaced by MokoStandards API. Only download-google-fonts remains (will be converted to PHP on next merge from dev). Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/README.md | 276 --------------------------------------- scripts/build-release.sh | 132 ------------------- scripts/minify.js | 188 -------------------------- 3 files changed, 596 deletions(-) delete mode 100644 scripts/README.md delete mode 100755 scripts/build-release.sh delete mode 100644 scripts/minify.js diff --git a/scripts/README.md b/scripts/README.md deleted file mode 100644 index 0c3f452..0000000 --- a/scripts/README.md +++ /dev/null @@ -1,276 +0,0 @@ -# Scripts — MokoCassiopeia - -This directory contains utility scripts for building, releasing, and managing the MokoCassiopeia Joomla template. - -## Available Scripts - -### build-release.sh - -**Purpose**: Build a release package for MokoCassiopeia template. - -**Usage**: -```bash -# Build with auto-detected version from templateDetails.xml -./scripts/build-release.sh - -# Build with specific version -./scripts/build-release.sh 03.08.03 -``` - -**What it does**: -1. Creates a `build/` directory -2. Copies template files from `src/` -3. Copies media files from `src/media/` to `media/` -4. Creates a ZIP package: `mokocassiopeia-src-{version}.zip` -5. Generates SHA-256 and MD5 checksums -6. Outputs package location and checksums - -**Output**: -- `build/mokocassiopeia-src-{version}.zip` - Installation package -- `build/mokocassiopeia-src-{version}.zip.sha256` - SHA-256 checksum -- `build/mokocassiopeia-src-{version}.zip.md5` - MD5 checksum - -**Requirements**: -- `rsync` for file copying -- `zip` for package creation -- `sha256sum` and `md5sum` for checksums - ---- - -## Automated Workflows - -The repository includes GitHub Actions workflows that automate the build and release process: - -### `.github/workflows/release.yml` - -**Purpose**: Automated release creation when tags are pushed. - -**Triggers**: -- Push of version tag (e.g., `03.08.03`) -- Manual workflow dispatch with version input - -**Process**: -1. Checks out repository -2. Sets up PHP environment -3. Installs dependencies (if composer.json exists) -4. Updates version numbers in manifest files -5. Creates package structure -6. Builds ZIP package -7. Generates checksums -8. Creates GitHub Release with artifacts - -**Usage**: -```bash -# Create and push a tag -git tag 03.08.04 -git push origin 03.08.04 - -# Or use GitHub UI to run manually -``` - ---- - -### `.github/workflows/auto-update-sha.yml` - -**Purpose**: Automatically update SHA-256 hash in `updates.xml` after a release is published. - -**Triggers**: -- GitHub Release published -- Manual workflow dispatch with tag input - -**Process**: -1. Downloads the release package -2. Calculates SHA-256 hash -3. Updates `updates.xml` with: - - New version number - - Current date - - Download URL - - SHA-256 hash -4. Commits and pushes changes to main branch - -**Benefits**: -- Ensures `updates.xml` always has correct SHA-256 hash -- Enables Joomla update server functionality -- Reduces manual update errors -- Automates security verification - ---- - -## Release Process - -### Manual Release (Local Build) - -1. **Update version numbers**: - ```bash - # Update these files manually: - # - src/templateDetails.xml - # - updates.xml - # - CHANGELOG.md - ``` - -2. **Build package**: - ```bash - ./scripts/build-release.sh 03.08.04 - ``` - -3. **Test package**: - - Install ZIP in Joomla test environment - - Verify all features work correctly - -4. **Create GitHub Release**: - - Go to GitHub Releases - - Click "Create a new release" - - Upload the ZIP, SHA256, and MD5 files - - Add release notes from CHANGELOG.md - -5. **Update updates.xml**: - - Copy SHA-256 hash from `.sha256` file - - Update `updates.xml` with new hash - - Commit and push changes - ---- - -### Automated Release (GitHub Actions) - -1. **Update version numbers**: - ```bash - # Update these files in a branch: - # - src/templateDetails.xml - # - CHANGELOG.md - - git checkout -b release/03.08.04 - # Make changes - git commit -m "chore: Prepare release 03.08.04" - git push origin release/03.08.04 - ``` - -2. **Create and merge PR**: - - Create PR from release branch - - Review changes - - Merge to main - -3. **Create and push tag**: - ```bash - git checkout main - git pull - git tag 03.08.04 - git push origin 03.08.04 - ``` - -4. **Automated process**: - - GitHub Actions builds package automatically - - Creates GitHub Release with artifacts - - `auto-update-sha` workflow updates `updates.xml` - -5. **Verify**: - - Check GitHub Release is created - - Verify `updates.xml` has correct SHA-256 - - Test Joomla update server - ---- - -## Development Workflow - -### Testing Local Builds - -```bash -# Build current version -./scripts/build-release.sh - -# Install in Joomla -# Navigate to Extensions > Manage > Install > Upload Package File -# Select: build/mokocassiopeia-src-{version}.zip -``` - -### Pre-Release Checklist - -- [ ] All code changes merged to main -- [ ] Version numbers updated: - - [ ] `src/templateDetails.xml` - - [ ] `CHANGELOG.md` -- [ ] CHANGELOG.md updated with release notes -- [ ] Tests passing -- [ ] Documentation updated -- [ ] Local build tested in Joomla - ---- - -## Troubleshooting - -### Build Fails - -**Problem**: `rsync: command not found` -```bash -# Ubuntu/Debian -sudo apt-get install rsync - -# macOS -brew install rsync -``` - -**Problem**: `zip: command not found` -```bash -# Ubuntu/Debian -sudo apt-get install zip - -# macOS (usually pre-installed) -brew install zip -``` - -### GitHub Actions Fails - -**Problem**: Release workflow fails on tag push - -Check: -1. Tag format matches pattern: `[0-9][0-9].[0-9][0-9].[0-9][0-9]` -2. Repository has write permissions for GITHUB_TOKEN -3. `src/` and `src/media/` directories exist - -**Problem**: auto-update-sha fails - -Check: -1. Release package was published successfully -2. Workflow has write permissions -3. Package naming matches expected format - ---- - -## File Structure - -``` -scripts/ -├── README.md # This file -└── build-release.sh # Local build script - -.github/workflows/ -├── release.yml # Automated release workflow -└── auto-update-sha.yml # SHA hash update workflow -``` - ---- - -## Contributing - -When adding new scripts: - -1. Add GPL-3.0-or-later license header -2. Include FILE INFORMATION block -3. Add usage documentation in this README -4. Make scripts executable: `chmod +x scripts/your-script.sh` -5. Test thoroughly before committing - ---- - -## Support - -- **Issues**: [GitHub Issues](https://github.com/mokoconsulting-tech/MokoCassiopeia/issues) -- **Email**: hello@mokoconsulting.tech -- **Documentation**: [docs/](../docs/) - ---- - -## License - -All scripts are licensed under GPL-3.0-or-later. - -Copyright (C) 2026 Moko Consulting diff --git a/scripts/build-release.sh b/scripts/build-release.sh deleted file mode 100755 index 5e8055d..0000000 --- a/scripts/build-release.sh +++ /dev/null @@ -1,132 +0,0 @@ -#!/usr/bin/env bash -# Copyright (C) 2026 Moko Consulting -# SPDX-License-Identifier: GPL-3.0-or-later -# -# FILE INFORMATION -# DEFGROUP: Build.Scripts -# INGROUP: MokoCassiopeia.Build -# REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia -# PATH: /scripts/build-release.sh -# VERSION: 01.00.00 -# BRIEF: Build release package for MokoCassiopeia template -# USAGE: ./scripts/build-release.sh [version] - -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Script directory -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" - -# Functions -log_info() { - echo -e "${BLUE}[INFO]${NC} $1" -} - -log_success() { - echo -e "${GREEN}[SUCCESS]${NC} $1" -} - -log_warning() { - echo -e "${YELLOW}[WARNING]${NC} $1" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# Check if version is provided -if [ -z "$1" ]; then - # Try to extract version from templateDetails.xml - if [ -f "${PROJECT_ROOT}/src/templateDetails.xml" ]; then - VERSION=$(grep -oP '\K[^<]+' "${PROJECT_ROOT}/src/templateDetails.xml" | head -1) - log_info "Detected version: ${VERSION}" - else - log_error "Please provide version as argument: ./build-release.sh 03.08.03" - exit 1 - fi -else - VERSION="$1" -fi - -log_info "Building MokoCassiopeia release package" -log_info "Version: ${VERSION}" - -# Change to project root -cd "${PROJECT_ROOT}" - -# Create build directory -BUILD_DIR="${PROJECT_ROOT}/build" -PACKAGE_DIR="${BUILD_DIR}/package" -rm -rf "${BUILD_DIR}" -mkdir -p "${PACKAGE_DIR}" - -log_info "Creating package structure..." - -# Copy template files from src (excluding media directory) -if [ -d "src" ]; then - rsync -av --exclude='.git*' --exclude='media' src/ "${PACKAGE_DIR}/" -else - log_error "src directory not found!" - exit 1 -fi - -# Copy media files from src/media -if [ -d "src/media" ]; then - mkdir -p "${PACKAGE_DIR}/media" - rsync -av --exclude='.git*' src/media/ "${PACKAGE_DIR}/media/" -else - log_warning "src/media directory not found, skipping media files" -fi - -log_info "Package structure created" - -# Create ZIP package -cd "${PACKAGE_DIR}" -ZIP_NAME="mokocassiopeia-src-${VERSION}.zip" -log_info "Creating ZIP package: ${ZIP_NAME}" - -zip -r "../${ZIP_NAME}" . -q - -if [ $? -ne 0 ]; then - log_error "Failed to create ZIP package" - exit 1 -fi - -cd "${BUILD_DIR}" -log_success "Created: ${ZIP_NAME}" - -# Generate checksums -log_info "Generating checksums..." -sha256sum "${ZIP_NAME}" > "${ZIP_NAME}.sha256" -md5sum "${ZIP_NAME}" > "${ZIP_NAME}.md5" - -# Extract just the hash -SHA256_HASH=$(sha256sum "${ZIP_NAME}" | cut -d' ' -f1) - -log_success "SHA-256: ${SHA256_HASH}" -log_success "MD5: $(md5sum "${ZIP_NAME}" | cut -d' ' -f1)" - -# Show file info -FILE_SIZE=$(du -h "${ZIP_NAME}" | cut -f1) -log_info "Package size: ${FILE_SIZE}" - -# Summary -echo "" -log_success "Build completed successfully!" -echo "" -echo "Package: ${BUILD_DIR}/${ZIP_NAME}" -echo "SHA-256: ${BUILD_DIR}/${ZIP_NAME}.sha256" -echo "MD5: ${BUILD_DIR}/${ZIP_NAME}.md5" -echo "" -echo "Next steps:" -echo "1. Test the package installation in Joomla" -echo "2. Create a GitHub release with this package" -echo "3. Update updates.xml with the new version and SHA-256 hash" -echo "" diff --git a/scripts/minify.js b/scripts/minify.js deleted file mode 100644 index b6116e8..0000000 --- a/scripts/minify.js +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env node -/* Copyright (C) 2026 Moko Consulting - * - * This file is part of a Moko Consulting project. - * - * SPDX-License-Identifier: GPL-3.0-or-later - * - * # FILE INFORMATION - * DEFGROUP: Joomla.Template.Site - * INGROUP: MokoCassiopeia - * REPO: https://github.com/mokoconsulting-tech/MokoCassiopeia - * PATH: ./scripts/minify.js - * VERSION: 03.09.03 - * BRIEF: Generates .min.css and .min.js files from the Joomla asset manifest - */ - -'use strict'; - -const fs = require('fs'); -const path = require('path'); - -const CleanCSS = require('clean-css'); -const { minify: terserMinify } = require('terser'); - -// --------------------------------------------------------------------------- -// Config -// --------------------------------------------------------------------------- - -const ROOT = path.resolve(__dirname, '..'); -const SRC_MEDIA = path.join(ROOT, 'src', 'media'); -const ASSET_JSON = path.join(ROOT, 'src', 'joomla.asset.json'); - -// URI prefix used in the manifest — maps to SRC_MEDIA on disk. -// e.g. "media/templates/site/mokocassiopeia/css/template.css" -const URI_PREFIX = 'media/templates/site/mokocassiopeia/'; - -// --------------------------------------------------------------------------- -// Helpers -// --------------------------------------------------------------------------- - -/** - * Resolve a manifest URI to an absolute disk path under src/media/. - * - * @param {string} uri e.g. "media/templates/site/mokocassiopeia/css/foo.css" - * @returns {string|null} - */ -function uriToPath(uri) { - if (!uri.startsWith(URI_PREFIX)) return null; - return path.join(SRC_MEDIA, uri.slice(URI_PREFIX.length)); -} - -/** - * Return true if the filename looks like an already-minified file or belongs - * to a vendor bundle we don't own. - */ -function isVendorOrUserFile(filePath) { - const rel = filePath.replace(SRC_MEDIA + path.sep, ''); - return rel.startsWith('vendor' + path.sep) - || path.basename(filePath).startsWith('user.'); -} - -// --------------------------------------------------------------------------- -// Pair detection -// --------------------------------------------------------------------------- - -/** - * Read the asset manifest and return an array of { src, dest, type } pairs - * where dest is a minified version of src that doesn't already exist or is - * older than src. - * - * Pairing logic: for every non-.min asset, check whether the manifest also - * contains a corresponding .min asset. If so, that's our pair. - */ -function detectPairs(assets) { - // Build a lookup of all URIs in the manifest. - const uriSet = new Set(assets.map(a => a.uri)); - - const pairs = []; - - for (const asset of assets) { - const { uri, type } = asset; - if (type !== 'style' && type !== 'script') continue; - - // Skip already-minified entries. - if (/\.min\.(css|js)$/.test(uri)) continue; - - // Derive the expected .min URI. - const minUri = uri.replace(/\.(css|js)$/, '.min.$1'); - if (!uriSet.has(minUri)) continue; - - const srcPath = uriToPath(uri); - const destPath = uriToPath(minUri); - if (!srcPath || !destPath) continue; - - if (isVendorOrUserFile(srcPath)) continue; - - if (!fs.existsSync(srcPath)) { - console.warn(` [skip] source missing: ${srcPath}`); - continue; - } - - pairs.push({ src: srcPath, dest: destPath, type }); - } - - return pairs; -} - -// --------------------------------------------------------------------------- -// Minifiers -// --------------------------------------------------------------------------- - -async function minifyCSS(srcPath, destPath) { - const source = fs.readFileSync(srcPath, 'utf8'); - const result = new CleanCSS({ level: 2, returnPromise: true }); - const output = await result.minify(source); - - if (output.errors && output.errors.length) { - throw new Error(output.errors.join('\n')); - } - - fs.mkdirSync(path.dirname(destPath), { recursive: true }); - fs.writeFileSync(destPath, output.styles, 'utf8'); - - const srcSize = Buffer.byteLength(source, 'utf8'); - const destSize = Buffer.byteLength(output.styles, 'utf8'); - const saving = (100 - (destSize / srcSize * 100)).toFixed(1); - - return { srcSize, destSize, saving }; -} - -async function minifyJS(srcPath, destPath) { - const source = fs.readFileSync(srcPath, 'utf8'); - const result = await terserMinify(source, { - compress: { drop_console: false }, - mangle: true, - format: { comments: false } - }); - - if (!result.code) throw new Error('terser returned no output'); - - fs.mkdirSync(path.dirname(destPath), { recursive: true }); - fs.writeFileSync(destPath, result.code, 'utf8'); - - const srcSize = Buffer.byteLength(source, 'utf8'); - const destSize = Buffer.byteLength(result.code, 'utf8'); - const saving = (100 - (destSize / srcSize * 100)).toFixed(1); - - return { srcSize, destSize, saving }; -} - -// --------------------------------------------------------------------------- -// Main -// --------------------------------------------------------------------------- - -(async () => { - const manifest = JSON.parse(fs.readFileSync(ASSET_JSON, 'utf8')); - const pairs = detectPairs(manifest.assets); - - if (pairs.length === 0) { - console.log('No pairs found — nothing to minify.'); - return; - } - - console.log(`\nMinifying ${pairs.length} file(s)...\n`); - - let ok = 0, fail = 0; - - for (const { src, dest, type } of pairs) { - const label = path.relative(ROOT, src); - process.stdout.write(` ${label} ... `); - - try { - const stats = type === 'style' - ? await minifyCSS(src, dest) - : await minifyJS(src, dest); - - const kb = n => (n / 1024).toFixed(1) + ' kB'; - console.log(`${kb(stats.srcSize)} → ${kb(stats.destSize)} (${stats.saving}% saved)`); - ok++; - } catch (err) { - console.error(`FAILED\n ${err.message}`); - fail++; - } - } - - console.log(`\nDone. ${ok} succeeded, ${fail} failed.\n`); - if (fail > 0) process.exit(1); -})();