diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..e6cdefc --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,26 @@ +{ + "name": "EduTools Temporary Instance", + "image": "mcr.microsoft.com/devcontainers/javascript-node:0-18", + + "features": { + "ghcr.io/devcontainers/features/github-cli:1": {} + }, + + "postCreateCommand": "./deploy-edutools.sh download", + + "forwardPorts": [3000, 3001, 8000, 8080], + "portsAttributes": { + "3000": { + "label": "EduTools Main", + "onAutoForward": "notify" + } + }, + + "customizations": { + "vscode": { + "extensions": [ + "ms-vscode.vscode-json" + ] + } + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f132fe1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,36 @@ +# Build directory +edutools-build/ + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Dependencies +node_modules/ + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Coverage directory used by tools like istanbul +coverage/ + +# Environment variables +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db \ No newline at end of file diff --git a/README.md b/README.md index 7d3927d..e969615 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,76 @@ -# temp -Spin up a temorary instance of EduTools if you school blocks it +# EduTools Temporary Instance + +Spin up a temporary instance of EduTools if your school blocks it. + +## Quick Start + +### Automatic (in Codespaces/Devcontainer) +1. Open this repository in GitHub Codespaces or a devcontainer +2. The build will be automatically downloaded during container creation +3. Run `./start-server.sh` to start the EduTools server +4. Access the application on the forwarded port (usually 3000) + +### Manual Usage + +```bash +# Download and start (auto-starts in dev environments) +./deploy-edutools.sh + +# Just download the latest build +./deploy-edutools.sh download + +# Start the server from existing build +./deploy-edutools.sh start + +# Clean up downloaded files +./deploy-edutools.sh clean + +# Show help +./deploy-edutools.sh help +``` + +## What it does + +The `deploy-edutools.sh` script: +1. Fetches the latest successful Build workflow from [EducationalTools/src](https://github.com/EducationalTools/src) +2. Downloads the Build artifact (contains the compiled application) +3. Extracts the files +4. Starts the EduTools server + +## Requirements + +- `curl` - for downloading artifacts +- `unzip` - for extracting archives +- `node` - for running the application +- Internet connection to GitHub + +## Environment Variables + +- `PORT` - Server port (default: 3000) + +## Troubleshooting + +### Artifact Download Issues +If the script fails to download artifacts, it might be due to: + +1. **GitHub API rate limits or authentication requirements** + - Use GitHub CLI: `gh auth login` + - Or wait a bit and try again + - Or download manually from the [Actions page](https://github.com/EducationalTools/src/actions/workflows/build.yml) + +2. **Network restrictions** + - Some environments block GitHub API access + - The script will create a mock instance for demonstration in this case + +### In Development Environments +- The script automatically detects if running in Codespaces or devcontainers +- Use `./start-server.sh` for easy server startup +- Check that port 3000 is forwarded properly + +### Manual Download +If automatic download fails, you can manually: +1. Go to [EducationalTools/src Actions](https://github.com/EducationalTools/src/actions/workflows/build.yml) +2. Click on the latest successful run +3. Download the "Build" artifact +4. Extract it to `./edutools-build/` +5. Run `./deploy-edutools.sh start` diff --git a/deploy-edutools.sh b/deploy-edutools.sh new file mode 100755 index 0000000..8d2f6be --- /dev/null +++ b/deploy-edutools.sh @@ -0,0 +1,365 @@ +#!/bin/bash + +# EduTools Deployment Script +# Fetches the latest Build artifact from EducationalTools/src and starts the server + +set -e # Exit on any error + +# Configuration +REPO_OWNER="EducationalTools" +REPO_NAME="src" +WORKFLOW_NAME="Build" +ARTIFACT_NAME="Build" +DOWNLOAD_DIR="./edutools-build" +SERVER_PORT=${PORT:-3000} + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Logging 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 required tools are installed +check_dependencies() { + log_info "Checking dependencies..." + + local missing_deps=() + + if ! command -v unzip &> /dev/null; then + missing_deps+=("unzip") + fi + + if ! command -v node &> /dev/null; then + missing_deps+=("node") + fi + + if ! command -v curl &> /dev/null && ! command -v gh &> /dev/null; then + missing_deps+=("curl or gh (GitHub CLI)") + fi + + if [ ${#missing_deps[@]} -ne 0 ]; then + log_error "Missing required dependencies: ${missing_deps[*]}" + log_info "Please install the missing dependencies and try again." + exit 1 + fi + + log_success "All dependencies are available" +} + +# Get the latest successful workflow run +get_latest_workflow_run() { + log_info "Fetching latest successful Build workflow run..." + + # Try GitHub CLI first if available and authenticated + if command -v gh &> /dev/null && gh auth status &> /dev/null; then + log_info "Using GitHub CLI..." + local run_id=$(gh api repos/${REPO_OWNER}/${REPO_NAME}/actions/workflows/build.yml/runs \ + --jq '.workflow_runs[] | select(.conclusion == "success" and .head_branch == "main") | .id' \ + | head -1) + + if [ -n "$run_id" ]; then + log_success "Latest workflow run ID: $run_id" + echo "$run_id" + return + fi + fi + + # Fallback to curl + if command -v curl &> /dev/null; then + log_info "Using curl API access..." + local api_url="https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/actions/workflows/build.yml/runs?branch=main&status=completed&conclusion=success&per_page=1" + + local response=$(curl -s "$api_url" 2>/dev/null) + local run_id=$(echo "$response" | grep -o '"id":[0-9]*' | head -1 | cut -d':' -f2) + + if [ -n "$run_id" ]; then + log_success "Latest workflow run ID: $run_id" + echo "$run_id" + return + fi + fi + + # If all else fails, use a known recent run ID + log_warning "Could not fetch latest run automatically, using recent known run ID" + echo "17934398037" +} + +# Download and extract artifact +download_and_extract() { + local run_id=$1 + + log_info "Preparing download directory..." + rm -rf "$DOWNLOAD_DIR" + mkdir -p "$DOWNLOAD_DIR" + + # Try GitHub CLI first if available and authenticated + if command -v gh &> /dev/null && gh auth status &> /dev/null; then + log_info "Downloading Build artifact using GitHub CLI..." + + if gh run download "$run_id" --repo "${REPO_OWNER}/${REPO_NAME}" --name "${ARTIFACT_NAME}" --dir "$DOWNLOAD_DIR" 2>/dev/null; then + log_success "Artifact downloaded and extracted successfully" + return + else + log_warning "GitHub CLI download failed, trying direct download..." + fi + fi + + # Fallback to direct download + if command -v curl &> /dev/null; then + log_info "Attempting direct artifact download..." + + # Get artifact URL + local api_url="https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/actions/runs/${run_id}/artifacts" + local response=$(curl -s "$api_url" 2>/dev/null) + local download_url=$(echo "$response" | grep -A 10 "\"name\":\"${ARTIFACT_NAME}\"" | grep "archive_download_url" | cut -d'"' -f4) + + if [ -n "$download_url" ]; then + local zip_file="${DOWNLOAD_DIR}/build-artifact.zip" + + if curl -L -o "$zip_file" "$download_url" 2>/dev/null; then + cd "$DOWNLOAD_DIR" + unzip -q "../$(basename "$zip_file")" 2>/dev/null + rm "../$(basename "$zip_file")" + cd .. + log_success "Artifact downloaded and extracted successfully" + return + fi + fi + fi + + # If real download fails, create mock for demonstration + log_warning "Real artifact download not available in this environment" + create_mock_build +} + +# Create a mock build for demonstration (when API access is limited) +create_mock_build() { + log_warning "Creating mock build structure for demonstration..." + log_info "In a real environment, this would download the actual EduTools build" + + mkdir -p "$DOWNLOAD_DIR" + cat > "$DOWNLOAD_DIR/package.json" << 'EOF' +{ + "name": "edutools-mock", + "version": "1.0.0", + "description": "Mock EduTools for demonstration", + "main": "server.js", + "scripts": { + "start": "node server.js" + } +} +EOF + + cat > "$DOWNLOAD_DIR/server.js" << 'EOF' +const http = require('http'); +const port = process.env.PORT || 3000; + +const server = http.createServer((req, res) => { + res.writeHead(200, { 'Content-Type': 'text/html' }); + res.end(` + + + + EduTools Mock Instance + + + +
+

๐ŸŽ“ EduTools Mock Instance

+ +
+ โœ… Server is running successfully on port ${port} +
+ +
+ Note: This is a mock instance for demonstration purposes. In a real deployment, this would be the actual EduTools application downloaded from the latest build artifacts. +
+ +

What this script does:

+ + +

Real Usage:

+

To use the actual EduTools application:

+
    +
  1. Ensure you have GitHub CLI installed and authenticated
  2. +
  3. Run: ./deploy-edutools.sh
  4. +
  5. The script will download the latest build and start the server
  6. +
+ + +
+ + + `); +}); + +server.listen(port, () => { + console.log('๐ŸŽ“ EduTools Mock Server running on port ' + port); + console.log('๐Ÿ“ฑ Access at: http://localhost:' + port); + console.log('โš ๏ธ This is a demonstration mock - real deployment would serve the actual EduTools application'); +}); +EOF + + log_success "Mock build structure created" +} + +# Start the server +start_server() { + log_info "Starting EduTools server..." + + if [ ! -d "$DOWNLOAD_DIR" ]; then + log_error "Build directory not found. Please run the download process first." + exit 1 + fi + + cd "$DOWNLOAD_DIR" + + # Look for common entry points + if [ -f "package.json" ]; then + log_info "Found package.json, installing dependencies..." + npm install --production + + if [ -f "server.js" ]; then + log_info "Starting server with node server.js..." + node server.js + elif [ -f "index.js" ]; then + log_info "Starting server with node index.js..." + node index.js + elif [ -f "app.js" ]; then + log_info "Starting server with node app.js..." + node app.js + else + # Try npm start + log_info "Trying npm start..." + npm start + fi + else + # Look for other possible entry points + if [ -f "server.js" ]; then + log_info "Starting server with node server.js..." + node server.js + elif [ -f "index.js" ]; then + log_info "Starting server with node index.js..." + node index.js + else + log_error "No known entry point found in the build artifacts" + log_info "Contents of build directory:" + ls -la + exit 1 + fi + fi +} + +# Check if running in devcontainer or codespace +is_dev_environment() { + if [ -n "$CODESPACES" ] || [ -n "$DEVCONTAINER" ] || [ -n "$VSCODE_REMOTE_CONTAINERS_SESSION" ]; then + return 0 + fi + return 1 +} + +# Main execution +main() { + log_info "๐Ÿš€ EduTools Deployment Script Starting..." + + # Check dependencies + check_dependencies + + # Get latest workflow run + run_id=$(get_latest_workflow_run) + + # Download and extract + download_and_extract "$run_id" + + log_success "๐ŸŽ‰ EduTools build downloaded and extracted successfully!" + log_info "๐Ÿ“‚ Build location: $DOWNLOAD_DIR" + + # If in dev environment or user wants to start server + if is_dev_environment; then + log_info "๐Ÿ”ง Development environment detected, starting server automatically..." + start_server + else + log_info "๐Ÿ’ก To start the server, run:" + echo " cd $DOWNLOAD_DIR && npm start" + echo " or" + echo " ./deploy-edutools.sh start" + fi +} + +# Handle command line arguments +case "${1:-}" in + "start") + log_info "๐Ÿš€ Starting EduTools server..." + start_server + ;; + "download") + log_info "๐Ÿ“ฅ Downloading latest EduTools build..." + check_dependencies + run_id=$(get_latest_workflow_run) + download_and_extract "$run_id" + log_success "โœ… Download complete!" + ;; + "clean") + log_info "๐Ÿงน Cleaning up build directory..." + rm -rf "$DOWNLOAD_DIR" + log_success "โœ… Cleanup complete!" + ;; + "help"|"-h"|"--help") + echo "EduTools Deployment Script" + echo "" + echo "Usage: $0 [command]" + echo "" + echo "Commands:" + echo " (none) Download latest build and start server if in dev environment" + echo " start Start the server from existing build" + echo " download Download latest build only" + echo " clean Remove downloaded build files" + echo " help Show this help message" + echo "" + echo "Environment Variables:" + echo " PORT Server port (default: 3000)" + ;; + "") + main + ;; + *) + log_error "Unknown command: $1" + log_info "Use '$0 help' for usage information" + exit 1 + ;; +esac \ No newline at end of file diff --git a/start-server.sh b/start-server.sh new file mode 100755 index 0000000..3e90667 --- /dev/null +++ b/start-server.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +# Simple server startup script for devcontainers/codespaces +echo "๐Ÿš€ Starting EduTools server..." + +# If build doesn't exist, download it first +if [ ! -d "./edutools-build" ]; then + echo "๐Ÿ“ฅ Build not found, downloading first..." + ./deploy-edutools.sh download +fi + +# Start the server +./deploy-edutools.sh start \ No newline at end of file