-
Notifications
You must be signed in to change notification settings - Fork 0
Description
📋 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:
- Authenticate users via GitHub OAuth
- Scan organization repos for
.ghoten/project.yamlfiles - Display projects and workspaces
- Trigger GitHub Actions workflows via GitHub API
- Stream logs and display run status
- 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
/uidirectory - 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
GitHubServiceclass 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/*.yamlfiles -
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 organizationVITE_GITHUB_CLIENT_ID- OAuth App Client IDVITE_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:
-
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
-
Project Detection
- Repos with
.ghoten/project.yamlare detected - Repos without it are ignored
- Empty state shows when no projects found
- Repos with
-
Workspace Management
- Workspaces from
.ghoten/workspaces/*.yamlare listed - Workspace status is accurate
- Can navigate to workspace detail
- Workspaces from
-
Workflow Execution
- Plan button triggers workflow
- Apply button triggers workflow
- Workflow appears in runs list
- Status updates in real-time (poll every 10s)
-
Log Viewing
- Can view logs from completed runs
- Terraform syntax is highlighted
- Long logs are scrollable
- Can search within logs
-
Error Handling
- Network errors show friendly message
- Invalid tokens redirect to login
- Rate limits are handled gracefully
- 404s show proper empty state
🔗 Related
- Main Ghoten documentation: README.md
- ORAS backend docs: internal/backend/remote-state/oras/README.md
- Starter workflow template: To be added in
.githubrepo
📚 Resources
- [GitHub REST API](https://docs.github.com/en/rest)
- [GitHub OAuth](https://docs.github.com/en/developers/apps/building-oauth-apps)
- [React Router](https://reactrouter.com/)
- [TailwindCSS](https://tailwindcss.com/)
- [Vite](https://vitejs.dev/)
- [GitHub Pages](https://docs.github.com/en/pages)
💡 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:
- Visit
https://vmvarela.github.io/ghoten/ - Click "Login with GitHub"
- See all their Terraform projects
- Click into a project → workspace
- Click "Plan" or "Apply"
- Watch the run execute in real-time
- 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