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(` + + +
+To use the actual EduTools application:
+./deploy-edutools.sh