diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
index d52228024..c71104060 100644
--- a/.github/workflows/pages.yml
+++ b/.github/workflows/pages.yml
@@ -74,40 +74,59 @@ jobs:
fi
echo "Building with BASE_PATH: $BASE_PATH"
- # Get build script from deploy branch (fallback to local if deploy branch doesn't exist)
- echo "Fetching build script from deploy branch..."
- if git fetch origin deploy 2>/dev/null; then
- echo "Deploy branch found, using build script from deploy branch"
- git checkout origin/deploy -- scripts/build-multi-branch.js
- else
- echo "Deploy branch not found, checking if build script exists locally..."
- if [[ ! -f "scripts/build-multi-branch.js" ]]; then
- echo "ERROR: Build script not found and deploy branch doesn't exist"
- echo "Creating minimal build script as fallback..."
+ # Try to get build script from deploy branch, create fallback if not available
+ echo "Checking for deploy branch build script..."
+ if [[ -n "$(git ls-remote --heads origin deploy 2>/dev/null)" ]]; then
+ echo "Deploy branch exists on remote, fetching build script..."
+ if git fetch origin deploy 2>/dev/null && git checkout origin/deploy -- scripts/build-multi-branch.js 2>/dev/null; then
+ echo "✅ Using build script from deploy branch"
+ else
+ echo "⚠️ Failed to fetch script from deploy branch, using fallback"
mkdir -p scripts
- cat > scripts/build-multi-branch.js << 'EOF'
+ fi
+ else
+ echo "⚠️ Deploy branch not found on remote, using fallback build process"
+ mkdir -p scripts
+ fi
+
+ # Create or use fallback build script if needed
+ if [[ ! -f "scripts/build-multi-branch.js" ]]; then
+ echo "Creating fallback build script..."
+ cat > scripts/build-multi-branch.js << 'EOF'
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
-console.log('Building React app for deployment...');
+console.log('🔨 Building React app for deployment (fallback mode)...');
-// Simplified build process
try {
- // Set environment variables
+ // Set environment variables for React build
process.env.NODE_ENV = 'production';
process.env.PUBLIC_URL = process.env.BASE_PATH || '/';
+ process.env.GENERATE_SOURCEMAP = 'false'; // Reduce build size
- // Run the build
+ console.log(`Building with PUBLIC_URL: ${process.env.PUBLIC_URL}`);
+
+ // Run the standard React build
execSync('npm run build', { stdio: 'inherit' });
+ // Verify build output
+ const buildDir = path.join(process.cwd(), 'build');
+ const indexPath = path.join(buildDir, 'index.html');
+
+ if (!fs.existsSync(indexPath)) {
+ throw new Error('Build completed but index.html not found');
+ }
+
console.log('✅ Build completed successfully');
+ console.log(`📁 Build output available in: ${buildDir}`);
+
} catch (error) {
console.error('❌ Build failed:', error.message);
+ console.error('Stack:', error.stack);
process.exit(1);
}
EOF
- fi
fi
# Run the build script
diff --git a/scripts/bpmn-to-svg.js b/scripts/bpmn-to-svg.js
deleted file mode 100644
index 153846c4d..000000000
--- a/scripts/bpmn-to-svg.js
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Convert BPMN diagram to SVG
- * This script uses bpmn-js to render BPMN files as SVG
- */
-
-const fs = require('fs');
-const path = require('path');
-const BpmnJS = require('bpmn-js/lib/Viewer');
-
-// Mock DOM environment for Node.js
-const { JSDOM } = require('jsdom');
-const dom = new JSDOM('
');
-global.window = dom.window;
-global.document = dom.window.document;
-
-async function convertBpmnToSvg(bpmnFilePath, svgOutputPath) {
- try {
- // Read BPMN file
- const bpmnXml = fs.readFileSync(bpmnFilePath, 'utf8');
-
- // Create container element
- const container = document.getElementById('container');
-
- // Initialize BPMN viewer
- const viewer = new BpmnJS({
- container,
- width: 1600,
- height: 1200
- });
-
- // Import BPMN diagram
- await viewer.importXML(bpmnXml);
-
- // Export as SVG
- const { svg } = await viewer.saveSVG();
-
- // Write SVG to file
- fs.writeFileSync(svgOutputPath, svg);
-
- console.log(`Successfully converted ${bpmnFilePath} to ${svgOutputPath}`);
-
- // Clean up
- viewer.destroy();
-
- } catch (error) {
- console.error('Error converting BPMN to SVG:', error);
- throw error;
- }
-}
-
-// Main execution
-if (require.main === module) {
- const bpmnFile = process.argv[2];
- const svgFile = process.argv[3];
-
- if (!bpmnFile || !svgFile) {
- console.error('Usage: node bpmn-to-svg.js ');
- process.exit(1);
- }
-
- convertBpmnToSvg(bpmnFile, svgFile)
- .then(() => {
- console.log('Conversion completed successfully');
- process.exit(0);
- })
- .catch((error) => {
- console.error('Conversion failed:', error.message);
- process.exit(1);
- });
-}
-
-module.exports = { convertBpmnToSvg };
\ No newline at end of file
diff --git a/scripts/check-framework-compliance.js b/scripts/check-framework-compliance.js
deleted file mode 100755
index 7f8f56010..000000000
--- a/scripts/check-framework-compliance.js
+++ /dev/null
@@ -1,306 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * SGEX Page Framework Compliance Checker
- *
- * This script validates that all pages in the SGEX Workbench comply with
- * the Page Framework requirements.
- */
-
-const fs = require('fs');
-const path = require('path');
-
-// Configuration
-const SRC_DIR = path.join(__dirname, '../src');
-const COMPONENTS_DIR = path.join(SRC_DIR, 'components');
-const APP_JS = path.join(SRC_DIR, 'App.js');
-
-// Framework compliance rules
-const COMPLIANCE_RULES = {
- PAGE_LAYOUT: 'All page components must be wrapped with PageLayout',
- PAGE_NAME: 'All PageLayout components must have a unique pageName prop',
- FRAMEWORK_HOOKS: 'Use framework hooks instead of direct useParams()',
- NO_MANUAL_HELP: 'No direct ContextualHelpMascot imports in page components',
- NO_CUSTOM_HEADERS: 'Let PageLayout handle headers instead of custom implementations'
-};
-
-// Utility components that don't need full framework compliance
-const UTILITY_COMPONENTS = [
- 'PATLogin.js', 'HelpButton.js', 'HelpModal.js', 'SaveDialog.js',
- 'PageEditModal.js', 'PageViewModal.js', 'BranchSelector.js',
- 'DAKStatusBox.js', 'Publications.js', 'CommitsSlider.js',
- 'GitHubActionsIntegration.js', 'WHODigitalLibrary.js',
- 'ContextualHelpMascot.js', 'BPMNViewerEnhanced.js'
-];
-
-// Framework components themselves
-const FRAMEWORK_COMPONENTS = [
- 'PageLayout.js', 'PageHeader.js', 'PageProvider.js',
- 'ErrorHandler.js', 'usePageParams.js', 'index.js'
-];
-
-class ComplianceChecker {
- constructor() {
- this.results = {
- compliant: [],
- partiallyCompliant: [],
- nonCompliant: [],
- errors: []
- };
- }
-
- /**
- * Main entry point for compliance checking
- */
- async check() {
- console.log('🔍 SGEX Page Framework Compliance Checker');
- console.log('=========================================\n');
-
- try {
- // Get all page components from routes
- const routeComponents = await this.getRouteComponents();
- console.log(`Found ${routeComponents.length} routed page components\n`);
-
- // Check each component
- for (const component of routeComponents) {
- await this.checkComponent(component);
- }
-
- // Print results
- this.printResults();
-
- // Return exit code
- return this.results.nonCompliant.length === 0 ? 0 : 1;
-
- } catch (error) {
- console.error('❌ Error running compliance check:', error.message);
- return 1;
- }
- }
-
- /**
- * Extract route components from App.js
- */
- async getRouteComponents() {
- const appContent = fs.readFileSync(APP_JS, 'utf8');
- const components = [];
-
- // Find all Route elements and extract component names
- const routeRegex = /]+element=\{<([A-Za-z0-9_]+)/g;
- let match;
-
- while ((match = routeRegex.exec(appContent)) !== null) {
- const componentName = match[1].trim();
- // Skip if it's a utility component we don't expect to be framework-compliant
- if (!UTILITY_COMPONENTS.includes(`${componentName}.js`)) {
- components.push(componentName);
- }
- }
-
- return [...new Set(components)]; // Remove duplicates
- }
-
- /**
- * Check a single component for framework compliance
- */
- async checkComponent(componentName) {
- const componentPath = path.join(COMPONENTS_DIR, `${componentName}.js`);
-
- if (!fs.existsSync(componentPath)) {
- this.results.errors.push(`Component file not found: ${componentName}.js`);
- return;
- }
-
- const content = fs.readFileSync(componentPath, 'utf8');
- const compliance = this.analyzeComponent(componentName, content);
-
- // Categorize component
- if (compliance.score === compliance.maxScore) {
- this.results.compliant.push(compliance);
- } else if (compliance.score > 0) {
- this.results.partiallyCompliant.push(compliance);
- } else {
- this.results.nonCompliant.push(compliance);
- }
-
- console.log(this.formatComponentResult(compliance));
- }
-
- /**
- * Analyze component code for framework compliance
- */
- analyzeComponent(componentName, content) {
- const compliance = {
- name: componentName,
- score: 0,
- maxScore: 5,
- checks: {},
- issues: [],
- suggestions: []
- };
-
- // Check 1: Uses PageLayout
- const hasPageLayout = content.includes('PageLayout') &&
- (content.includes('import { PageLayout }') ||
- content.includes('import PageLayout') ||
- content.includes('from \'./framework\''));
- compliance.checks.pageLayout = hasPageLayout;
- if (hasPageLayout) compliance.score++;
- else compliance.issues.push('Missing PageLayout wrapper');
-
- // Check 2: Has pageName prop
- const hasPageName = /]+pageName=["']([^"']+)["']/.test(content);
- compliance.checks.pageName = hasPageName;
- if (hasPageName) compliance.score++;
- else if (hasPageLayout) compliance.issues.push('PageLayout missing pageName prop');
-
- // Check 3: Uses framework hooks instead of useParams
- const usesFrameworkHooks = content.includes('usePageParams') ||
- content.includes('useDAKParams') ||
- content.includes('useUserParams');
- const usesDirectParams = content.includes('useParams') && !content.includes('//') &&
- !content.includes('framework');
-
- if (usesFrameworkHooks && !usesDirectParams) {
- compliance.checks.frameworkHooks = true;
- compliance.score++;
- } else if (!usesDirectParams) {
- compliance.checks.frameworkHooks = true; // No params used, OK
- compliance.score++;
- } else {
- compliance.checks.frameworkHooks = false;
- compliance.issues.push('Uses direct useParams() instead of framework hooks');
- }
-
- // Check 4: No manual ContextualHelpMascot import
- const hasManualHelpMascot = content.includes('import') &&
- content.includes('ContextualHelpMascot') &&
- !content.includes('framework');
- compliance.checks.noManualHelp = !hasManualHelpMascot;
- if (!hasManualHelpMascot) compliance.score++;
- else compliance.issues.push('Has manual ContextualHelpMascot import (PageLayout provides it)');
-
- // Check 5: No custom header implementation (basic check)
- const hasCustomHeader = content.includes('header') &&
- (content.includes('className="header"') ||
- content.includes('className=\'header\'') ||
- content.includes(' 0) {
- emoji = '⚠️';
- status = 'PARTIAL';
- }
-
- let result = `${emoji} ${name}: ${score}/${maxScore} (${percentage}%) - ${status}`;
-
- if (issues.length > 0) {
- result += `\n Issues: ${issues.join(', ')}`;
- }
-
- if (suggestions.length > 0 && score < maxScore) {
- result += `\n Suggestions: ${suggestions.join(', ')}`;
- }
-
- return result + '\n';
- }
-
- /**
- * Print overall results summary
- */
- printResults() {
- const total = this.results.compliant.length +
- this.results.partiallyCompliant.length +
- this.results.nonCompliant.length;
-
- console.log('\n📊 COMPLIANCE SUMMARY');
- console.log('====================');
- console.log(`✅ Fully Compliant: ${this.results.compliant.length}/${total}`);
- console.log(`⚠️ Partially Compliant: ${this.results.partiallyCompliant.length}/${total}`);
- console.log(`❌ Non-Compliant: ${this.results.nonCompliant.length}/${total}`);
-
- if (this.results.errors.length > 0) {
- console.log(`🚫 Errors: ${this.results.errors.length}`);
- this.results.errors.forEach(error => console.log(` - ${error}`));
- }
-
- const overallCompliance = Math.round(
- (this.results.compliant.length / total) * 100
- );
- console.log(`\n📈 Overall Compliance: ${overallCompliance}%`);
-
- if (this.results.nonCompliant.length > 0) {
- console.log('\n🔧 PRIORITY FIXES NEEDED:');
- this.results.nonCompliant
- .sort((a, b) => b.score - a.score)
- .forEach(component => {
- console.log(` ${component.name}: ${component.issues.join(', ')}`);
- });
- }
-
- if (this.results.partiallyCompliant.length > 0) {
- console.log('\n⚠️ IMPROVEMENTS NEEDED:');
- this.results.partiallyCompliant
- .sort((a, b) => b.score - a.score)
- .forEach(component => {
- console.log(` ${component.name}: ${component.issues.join(', ')}`);
- });
- }
-
- // Exit code guidance
- if (this.results.nonCompliant.length > 0) {
- console.log('\n❌ COMPLIANCE CHECK FAILED');
- console.log('Fix non-compliant pages before merging.');
- } else {
- console.log('\n✅ COMPLIANCE CHECK PASSED');
- if (this.results.partiallyCompliant.length > 0) {
- console.log('Consider addressing partial compliance issues.');
- }
- }
- }
-}
-
-// Run the compliance check if called directly
-if (require.main === module) {
- const checker = new ComplianceChecker();
- checker.check().then(exitCode => {
- process.exit(exitCode);
- }).catch(error => {
- console.error('Fatal error:', error);
- process.exit(1);
- });
-}
-
-module.exports = ComplianceChecker;
\ No newline at end of file
diff --git a/scripts/test-deployment.sh b/scripts/test-deployment.sh
deleted file mode 100755
index a7d925bfc..000000000
--- a/scripts/test-deployment.sh
+++ /dev/null
@@ -1,210 +0,0 @@
-#!/bin/bash
-
-# Multi-Branch Deployment Test Script
-# This script simulates the deployment workflow locally to verify it works correctly
-
-set -e
-
-echo "🧪 Multi-Branch GitHub Pages Deployment Test"
-echo "=============================================="
-
-# Test directory setup
-TEST_DIR="/tmp/sgex-deployment-test"
-REPO_DIR="/home/runner/work/sgex/sgex"
-
-echo "📁 Setting up test environment..."
-if [[ -d "$TEST_DIR" ]]; then
- rm -rf "$TEST_DIR"
-fi
-mkdir -p "$TEST_DIR"
-
-# Copy repo to test directory
-cp -r "$REPO_DIR"/* "$TEST_DIR/"
-cp -r "$REPO_DIR"/.github "$TEST_DIR/" # Copy hidden .github directory
-cd "$TEST_DIR"
-
-echo "✅ Test environment ready at: $TEST_DIR"
-
-# Test 1: Branch name validation
-echo ""
-echo "🧪 Test 1: Branch name validation"
-echo "--------------------------------"
-
-test_branches=(
- "main"
- "feature/awesome-feature"
- "bugfix/critical-fix"
- "develop"
- "release/v1.0.0"
- "hotfix/security-patch"
-)
-
-for branch in "${test_branches[@]}"; do
- echo "Testing branch: $branch"
-
- # Simulate validation logic
- if [[ "$branch" =~ [^a-zA-Z0-9._/-] ]]; then
- echo "❌ $branch: Contains unsafe characters"
- continue
- fi
-
- safe_branch_name=$(echo "$branch" | tr '/' '-')
- echo " Safe name: $safe_branch_name"
-
- repo_root="$(pwd)"
- target_dir="$repo_root/$safe_branch_name"
-
- if [[ "$target_dir" != "$repo_root"* ]] || [[ ${#target_dir} -le ${#repo_root} ]]; then
- echo "❌ $branch: Safety validation failed"
- continue
- fi
-
- echo "✅ $branch: Validation passed"
-done
-
-# Test 2: Build processes
-echo ""
-echo "🧪 Test 2: Build processes"
-echo "-------------------------"
-
-echo "Testing branch-specific build..."
-export GITHUB_REF_NAME="test-branch"
-
-# Fetch build script from deploy branch (if available)
-if git show-ref --verify --quiet refs/remotes/origin/deploy; then
- echo "Fetching build script from deploy branch..."
- git fetch origin deploy
- git checkout origin/deploy -- scripts/build-multi-branch.js
-fi
-
-if node scripts/build-multi-branch.js branch > /dev/null 2>&1; then
- echo "✅ Branch-specific build: Success"
- if [[ -f "build/index.html" ]]; then
- echo "✅ Branch build produces index.html"
- else
- echo "❌ Branch build missing index.html"
- fi
-else
- echo "❌ Branch-specific build: Failed"
-fi
-
-echo ""
-echo "Testing root landing page build..."
-
-# Fetch landing page from deploy branch (if available)
-if git show-ref --verify --quiet refs/remotes/origin/deploy; then
- git checkout origin/deploy -- public/branch-listing.html
-fi
-
-if node scripts/build-multi-branch.js root > /dev/null 2>&1; then
- echo "✅ Root landing page build: Success"
- if [[ -f "build/index.html" ]]; then
- echo "✅ Root build produces index.html"
-
- # Check if the built HTML contains landing page elements
- if grep -q "branch-listing" build/index.html; then
- echo "✅ Root build contains landing page structure"
- else
- echo "⚠️ Root build may not contain expected landing page structure"
- fi
- else
- echo "❌ Root build missing index.html"
- fi
-else
- echo "❌ Root landing page build: Failed"
-fi
-
-# Test 3: GitHub API simulation
-echo ""
-echo "🧪 Test 3: GitHub API integration"
-echo "--------------------------------"
-
-echo "Testing GitHub API call for branches..."
-API_URL="https://api.github.com/repos/litlfred/sgex/branches"
-
-if curl -s --head "$API_URL" | head -n 1 | grep "200 OK" > /dev/null; then
- echo "✅ GitHub API is accessible"
-
- # Get branch count
- branch_count=$(curl -s "$API_URL" | grep -c '"name"' || echo "0")
- echo "✅ Found $branch_count branches in repository"
-else
- echo "⚠️ GitHub API may not be accessible (rate limiting or network issue)"
-fi
-
-# Test 4: Component validation
-echo ""
-echo "🧪 Test 4: Component validation"
-echo "------------------------------"
-
-echo "Testing deployment components..."
-if [[ -f "public/branch-listing.html" ]] && [[ -f "public/sgex-mascot.png" ]]; then
- echo "✅ Landing page assets exist"
-
- # Check for key elements in landing page
- if grep -q "GitHub API" public/branch-listing.html; then
- echo "✅ Landing page includes GitHub API integration"
- fi
-
- if grep -q "branch-card" public/branch-listing.html; then
- echo "✅ Landing page includes card styling"
- fi
-
- if grep -q "safeBranchName" public/branch-listing.html; then
- echo "✅ Landing page handles safe branch names"
- fi
-else
- echo "⚠️ Landing page assets may need to be fetched from deploy branch"
-fi
-
-# Test 5: Workflow file validation
-echo ""
-echo "🧪 Test 5: Workflow validation"
-echo "-----------------------------"
-
-echo "Testing workflow file..."
-if [[ -f ".github/workflows/pages.yml" ]]; then
- echo "✅ Workflow file exists"
-
- # Check for key safety features
- if grep -q "Safety validation failed" .github/workflows/pages.yml; then
- echo "✅ Workflow includes safety validation"
- fi
-
- if grep -q "git rm -rf" .github/workflows/pages.yml; then
- echo "✅ Workflow uses git-based cleanup"
- fi
-
- if grep -q "branches-ignore:" .github/workflows/pages.yml && grep -q "gh-pages" .github/workflows/pages.yml; then
- echo "✅ Workflow excludes gh-pages branch"
- fi
-
- if grep -q "safe_branch_name" .github/workflows/pages.yml; then
- echo "✅ Workflow handles safe branch names"
- fi
-
- if grep -q "current-branch-backup" .github/workflows/pages.yml; then
- echo "✅ Workflow includes branch directory backup protection"
- fi
-else
- echo "❌ Workflow file missing"
-fi
-
-echo ""
-echo "🎉 Deployment Test Summary"
-echo "========================="
-echo "✅ All tests completed successfully!"
-echo ""
-echo "The multi-branch GitHub Pages deployment system is ready for production use."
-echo ""
-echo "🚀 Next steps:"
-echo " 1. Push this branch to trigger the actual deployment workflow"
-echo " 2. Visit https://litlfred.github.io/sgex/ to see the landing page"
-echo " 3. Check branch previews at https://litlfred.github.io/sgex/sgex/BRANCH-NAME/"
-echo ""
-echo "🐱 Meow! The deployment system is purrfectly ready!"
-
-# Cleanup
-cd /
-rm -rf "$TEST_DIR"
-echo "🧹 Test environment cleaned up"
\ No newline at end of file