Skip to content

feat: Add Terraform Cloud UI Clone in /ui Directory #5

@vmvarela

Description

@vmvarela

📋 Summary

Implement a complete serverless Terraform Cloud clone as a web interface within the ghoten repository. This UI will provide a modern, GitHub Pages-hosted frontend that allows users to manage Terraform workspaces, trigger plans/applies, and monitor infrastructure changes without requiring any backend servers.

The UI will live in a new /ui directory within this repository and will be deployed to GitHub Pages at https://vmvarela.github.io/ghoten/.

🎯 Motivation

Currently, users must:

  • Manually trigger GitHub Actions workflows
  • Navigate to multiple GitHub pages to view runs and logs
  • Manually manage workspace configurations
  • Lack a centralized view of their Terraform infrastructure

This UI will provide:

  • Single pane of glass for all Terraform operations
  • One-click plan/apply execution
  • Real-time run monitoring with log streaming
  • Automatic project detection from .ghoten/project.yaml
  • Beautiful, modern interface comparable to Terraform Cloud

🏗️ Architecture

ghoten/
├── ui/                          # NEW: Web UI
│   ├── src/
│   ├── public/
│   ├── package.json
│   └── vite.config.js
│
├── .github/
│   └── workflows/
│       └── deploy-ui.yml        # NEW: Deploy UI to GitHub Pages
│
├── cmd/tofu/                    # Existing Ghoten code
├── internal/                    # Existing Ghoten code
└── ...

The UI will:

  1. Authenticate users via GitHub OAuth
  2. Scan organization repos for .ghoten/project.yaml files
  3. Display projects and workspaces
  4. Trigger GitHub Actions workflows via GitHub API
  5. Stream logs and display run status
  6. Show GHCR state locations

No backend servers required - everything runs client-side using GitHub APIs.

📦 Scope

Phase 1: Core Functionality (This Issue)

1. Project Structure

  • Create /ui directory
  • Initialize Vite + React project
  • Configure TailwindCSS
  • Setup TypeScript (optional but recommended)
  • Configure build for GitHub Pages deployment

2. Authentication & API Integration

  • Implement GitHub OAuth flow
  • Create GitHubService class for API interactions
    • List organization repositories
    • Read file contents (.ghoten/*.yaml)
    • Trigger workflows
    • List workflow runs
    • Get run logs
    • List GHCR packages
  • Token management (sessionStorage)
  • Handle OAuth callback

3. Core Components

Authentication

  • LoginScreen.jsx - OAuth login page
  • CallbackHandler.jsx - OAuth redirect handler

Layout

  • MainLayout.jsx - Header, sidebar, content area
  • Header.jsx - Logo, user info, settings
  • Sidebar.jsx - Navigation (optional for v1)

Projects

  • ProjectList.jsx - Auto-detect Terraform projects
  • ProjectCard.jsx - Display project info + workspace count
  • ProjectDetail.jsx - View all workspaces in a project

Workspaces

  • WorkspaceList.jsx - List workspaces in a project
  • WorkspaceCard.jsx - Workspace status card
  • WorkspaceDetail.jsx - Full workspace view with tabs:
    • Overview: Current status, last run
    • Runs: List of GitHub Actions runs
    • Variables: Show project + workspace variables
    • Settings: Workspace configuration

Runs & Logs

  • RunsList.jsx - List workflow runs
  • RunCard.jsx - Individual run status
  • LogViewer.jsx - Display run logs with syntax highlighting
  • PlanViewer.jsx - Parse and display Terraform plan output

Shared

  • StatusBadge.jsx - Workflow status (queued, running, success, failed)
  • LoadingSpinner.jsx - Loading states
  • ErrorBoundary.jsx - Error handling
  • EmptyState.jsx - No data states
  • ConfirmDialog.jsx - Confirm destructive actions

4. Utilities & Helpers

  • src/services/github.js - GitHub API client
  • src/services/auth.js - OAuth handling
  • src/services/config-parser.js - Parse .ghoten/*.yaml files
  • src/utils/ghcr.js - GHCR path utilities
  • src/utils/terraform.js - Parse Terraform output
  • src/utils/cache.js - Simple in-memory cache
  • src/utils/date.js - Date formatting helpers

5. Routing

  • Setup React Router
  • Routes:
    • / → Redirect to /projects
    • /projects → Project list
    • /projects/:owner/:repo → Project detail
    • /projects/:owner/:repo/workspaces/:workspace → Workspace detail
    • /login → Login screen
    • /callback → OAuth callback handler

6. GitHub Pages Deployment

  • Create .github/workflows/deploy-ui.yml
  • Configure Vite base path for GitHub Pages
  • Setup SPA routing fix (404.html)
  • Configure environment variables
  • Test deployment

7. Documentation

  • ui/README.md - Setup and development guide
  • ui/DEPLOYMENT.md - Deployment instructions
  • Environment variables documentation
  • Architecture diagram

Phase 2: Enhanced Features (Future Issues)

  • Diff viewer for Terraform plans
  • Cost estimation integration (Infracost)
  • Policy as Code integration (OPA/Sentinel)
  • Drift detection
  • State version history viewer
  • Advanced filtering and search
  • Notifications (Slack, email)
  • Dark mode
  • PWA support
  • Mobile optimization

🛠️ Technical Requirements

Dependencies

{
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.20.0",
    "js-yaml": "^4.1.0",
    "lucide-react": "^0.294.0",
    "date-fns": "^3.0.0"
  },
  "devDependencies": {
    "@vitejs/plugin-react": "^4.2.1",
    "autoprefixer": "^10.4.16",
    "postcss": "^8.4.32",
    "tailwindcss": "^3.3.6",
    "vite": "^5.0.8"
  }
}

Build Configuration

Base path for GitHub Pages:

// vite.config.js
export default defineConfig({
  base: '/ghoten/',
  // ...
})

Environment Variables

  • VITE_GITHUB_ORG - Target GitHub organization
  • VITE_GITHUB_CLIENT_ID - OAuth App Client ID
  • VITE_GITHUB_API_URL - https://api.github.com

GitHub OAuth App

Create a GitHub OAuth App with:

  • Homepage URL: https://vmvarela.github.io/ghoten/
  • Callback URL: https://vmvarela.github.io/ghoten/callback
  • Scopes: repo, workflow, read:packages, read:org

📝 Implementation Guidelines

Code Style

  • Use functional components with hooks
  • Prefer composition over inheritance
  • Keep components under 250 lines
  • Extract complex logic to custom hooks
  • Use meaningful variable names
  • Add JSDoc comments to utility functions

File Structure

ui/
├── public/
│   ├── index.html
│   ├── 404.html              # SPA routing fix
│   └── favicon.ico
│
├── src/
│   ├── components/
│   │   ├── auth/
│   │   ├── layout/
│   │   ├── projects/
│   │   ├── workspaces/
│   │   ├── runs/
│   │   ├── variables/
│   │   └── shared/
│   │
│   ├── services/
│   │   ├── github.js
│   │   ├── auth.js
│   │   └── config-parser.js
│   │
│   ├── utils/
│   │   ├── ghcr.js
│   │   ├── terraform.js
│   │   ├── cache.js
│   │   └── date.js
│   │
│   ├── hooks/              # Custom React hooks
│   ├── App.jsx
│   ├── main.jsx
│   └── index.css
│
├── .env.example
├── .gitignore
├── package.json
├── vite.config.js
├── tailwind.config.js
├── README.md
└── DEPLOYMENT.md

Error Handling

  • All API calls must be wrapped in try/catch
  • Display user-friendly error messages
  • Log errors to console for debugging
  • Implement retry logic for transient failures
  • Handle rate limiting gracefully

Performance

  • Lazy load routes
  • Implement code splitting
  • Cache API responses (5 min TTL)
  • Debounce user input
  • Show loading states immediately

Accessibility

  • Semantic HTML
  • ARIA labels where needed
  • Keyboard navigation support
  • Focus management
  • Screen reader friendly

✅ Acceptance Criteria

Functionality

  • Users can authenticate with GitHub OAuth
  • UI automatically detects Terraform projects (repos with .ghoten/project.yaml)
  • Users can view all workspaces for a project
  • Users can trigger plan/apply operations
  • UI displays real-time workflow run status
  • Users can view workflow logs
  • Variables are displayed with proper hierarchy (project → workspace)
  • GHCR state locations are shown clearly

UI/UX

  • Responsive design (works on mobile, tablet, desktop)
  • Loading states for all async operations
  • Clear error messages
  • Empty states with helpful guidance
  • Confirmation dialogs for destructive actions
  • Intuitive navigation

Quality

  • No console errors or warnings
  • Fast initial load (< 3 seconds)
  • Works on latest Chrome, Firefox, Safari, Edge
  • No memory leaks
  • Proper cleanup in useEffect hooks

Documentation

  • README with setup instructions
  • Deployment guide
  • Environment variables documented
  • Architecture explained
  • Screenshots included

Deployment

  • GitHub Actions workflow deploys to Pages
  • Build succeeds without errors
  • Deployed site is accessible
  • OAuth flow works end-to-end

🧪 Testing Checklist

Before considering this complete, manually test:

  1. Authentication Flow

    • Click "Login with GitHub" redirects to GitHub
    • After authorization, redirects back to app
    • Token is saved and persists during session
    • Logout clears token
  2. Project Detection

    • Repos with .ghoten/project.yaml are detected
    • Repos without it are ignored
    • Empty state shows when no projects found
  3. Workspace Management

    • Workspaces from .ghoten/workspaces/*.yaml are listed
    • Workspace status is accurate
    • Can navigate to workspace detail
  4. Workflow Execution

    • Plan button triggers workflow
    • Apply button triggers workflow
    • Workflow appears in runs list
    • Status updates in real-time (poll every 10s)
  5. Log Viewing

    • Can view logs from completed runs
    • Terraform syntax is highlighted
    • Long logs are scrollable
    • Can search within logs
  6. Error Handling

    • Network errors show friendly message
    • Invalid tokens redirect to login
    • Rate limits are handled gracefully
    • 404s show proper empty state

🔗 Related

📚 Resources

💡 Implementation Notes

Detecting Terraform Projects

The UI will use this algorithm:

async function listTerraformProjects(org) {
  // 1. List all repos in org
  const repos = await github.repos.listForOrg(org);
  
  // 2. For each repo, try to fetch .ghoten/project.yaml
  const projects = [];
  for (const repo of repos) {
    try {
      const content = await github.repos.getContent(
        repo.owner.login,
        repo.name,
        '.ghoten/project.yaml'
      );
      
      // 3. Parse YAML and extract config
      const config = jsyaml.load(atob(content.content));
      
      // 4. Fetch workspace configs
      const workspaces = await Promise.all(
        config.workspaces.map(ws => 
          github.repos.getContent(
            repo.owner.login,
            repo.name,
            `.ghoten/workspaces/${ws}.yaml`
          )
        )
      );
      
      projects.push({
        repo,
        config,
        workspaces: workspaces.map(w => jsyaml.load(atob(w.content)))
      });
    } catch {
      // Not a Terraform project, skip
      continue;
    }
  }
  
  return projects;
}

GHCR Path Pattern

All state paths follow this pattern:

ghcr.io/{org}/tf-state.{repo-name}:{workspace-name}

Example:

ghcr.io/vmvarela/tf-state.infraestructura-core:production

Workflow Trigger

To trigger a workflow:

await github.actions.createWorkflowDispatch({
  owner,
  repo,
  workflow_id: 'terraform.yml',
  ref: 'main',
  inputs: {
    workspace: 'production',
    action: 'plan'
  }
});

🚀 Getting Started

Once this issue is completed, users will be able to:

  1. Visit https://vmvarela.github.io/ghoten/
  2. Click "Login with GitHub"
  3. See all their Terraform projects
  4. Click into a project → workspace
  5. Click "Plan" or "Apply"
  6. Watch the run execute in real-time
  7. View logs and infrastructure changes

All without writing a single line of code or maintaining any servers!

📊 Success Metrics

This feature will be considered successful when:

  • 10+ users have successfully logged in
  • 50+ workflow runs triggered via the UI
  • 0 critical bugs reported
  • Average page load time < 2 seconds
  • Positive feedback from early adopters

Labels: enhancement, ui, documentation, good first issue (for subtasks)
Milestone: v1.12.0
Assignees: @vmvarela
Priority: High

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentationenhancementNew feature or requestui

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions