Multi-Store DevOps Automation Platform
Internal tool for unified e-commerce operations
An internal automation platform for Shopify theme management and store operations. Supports both CLI and web GUI modes, orchestrating theme pulls, Git workflows, and deployments with real-time progress tracking.
The Problem
Managing themes across multiple Shopify stores involved repetitive manual steps: pulling themes, committing to Git, pushing to GitHub, deploying to staging. Each operation required switching between terminals, browsers, and dashboards.
- Same 15-step workflow repeated for each store, each deployment
- No visibility into deployment status across stores
- Browser automation for Shopify admin required constant maintenance
- Local development and production environments had different tooling
Constraints
- Must work identically in local dev, staging, and Cloud Run production
- CLI for developers, GUI for non-technical team members
- Browser automation must handle Shopify's 2FA and session management
- Stateless deployment for Cloud Run (no persistent local storage)
The Approach
Built with adapter pattern for database, storage, and session management. Same codebase deploys unchanged to local (SQLite/filesystem) and Cloud Run (PostgreSQL/GCS/Redis). Docker container under 1GB with Playwright browsers pre-installed.
Why support both CLI and GUI modes?
Developers prefer CLI for scripting and keyboard-driven workflows. Non-technical team members need visual interface with progress indicators. Same workflow engine powers both, reducing code duplication.
Why adapter pattern for infrastructure?
K_SERVICE env var triggers automatic production adapter selection. Zero code changes between environments. SQLite locally, Cloud SQL in production. In-memory sessions locally, Redis in production.
Why Playwright over Puppeteer or Cypress?
Playwright's persistent context mode maintains Shopify login sessions. Avoids 2FA on every run. Cross-browser support if needed later. Better async handling for complex admin workflows.
Why Docker with browsers bundled (~920MB)?
Cloud Run has ephemeral filesystem, can't install browsers at runtime. Pre-bundled Chrome in multi-stage build ensures consistent behavior. Trade larger image for reliability.
Key Tradeoffs
Large Docker image (~920MB) due to Chrome/Playwright
Self-contained deployment without runtime dependencies. Cold start is slower, but reliability of pre-installed browsers outweighs image size concern.
Persistent browser profile requires careful session management
Reusing sessions avoids 2FA but means session corruption can break automation. Added session validation and recovery mechanisms.
Feature flags defer some functionality in production
Uptime monitoring, metrics dashboards are optional for theme-only MVP. Progressive rollout reduces initial complexity. Flags documented for future enablement.
Implementation Highlights
Unified workflow engine
Single WorkflowEngine class handles repo cloning, branch creation, Shopify CLI operations, commits, and pushes. Progress callbacks enable both CLI output and WebSocket events for GUI.
Multi-stage Docker build
Four stages: base (Node + system deps), chrome (browser installation), builder (Vite build), app (production runtime). Non-root user (UID 1000) for security.
Playwright persistent browser mode
Chrome profile persists at .chrome-automation-profile/. First run requires 2FA, subsequent runs reuse session. Profile synced to GCS for Cloud Run recovery.
Adapter pattern for environment portability
getDatabase(), getStorage(), getSession() return appropriate adapter based on K_SERVICE detection. Code unchanged between local development and Cloud Run production.
Real-time WebSocket progress
Socket.IO connection from React frontend to Express backend. Workflow engine emits progress events (step completion, errors, warnings). GUI updates in real-time without polling.
Outcomes
What I Learned
- Adapter pattern enables clean environment portability but adds complexity. For a POC, simpler single-environment approach would ship faster.
- Browser automation for admin panels is fragile. Shopify's frequent UI changes broke selectors regularly during development.
- The dual CLI/GUI approach validated well, developers preferred CLI, non-technical users needed the visual interface.