DEV Community

Cristian Iridon
Cristian Iridon

Posted on • Originally published at previewdrop.com

200 lines of YAML, replaced by zero

200 lines of YAML, replaced by zero

Let's be honest: you have a GitHub Actions workflow that nobody actually understands anymore.

It probably looks something like this:

name: Preview Deploy
on:
  pull_request:
    types: [opened, synchronize]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3
        with:
          node-version: '18'
      - run: npm ci
      - run: npm run build
      - run: docker build -t my-app:${{ github.sha }} .
      - uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      - run: docker push my-app:${{ github.sha }}
      - name: Deploy to staging
        env:
          SSH_KEY: ${{ secrets.SSH_KEY }}
          SSH_HOST: ${{ secrets.SSH_HOST }}
        run: |
          mkdir -p ~/.ssh
          echo "$SSH_KEY" > ~/.ssh/id_ed25519
          chmod 600 ~/.ssh/id_ed25519
          ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_ed25519 ubuntu@$SSH_HOST \
            "docker pull my-app:${{ github.sha }} && docker run -d -p 3000:3000 my-app:${{ github.sha }}"
      - name: Comment on PR
        uses: actions/github-script@v6
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `🚀 Preview is live at https://preview-${{ github.sha }}.staging.example.com`
            })
Enter fullscreen mode Exit fullscreen mode

200 lines. Five people on the team know how it works. One of them left last year. When it breaks, you debug SSH keys and Docker registry auth instead of shipping features.

There's a better way.

The GitHub Actions tax

We've all written one of these. Let's count the actual pain:

  1. Initial setup (2–4 hours): figure out auth (Docker Hub vs ECR? GitHub Container Registry? Where do credentials live?), SSH keys, reverse proxy configuration, auto-scaling strategy, SSL certificates.
  2. Debugging (happens monthly): SSH keys expired. Docker registry is down. The preview server disk is full. The SSH host changed but you didn't rotate the secret. You spent 30 minutes in a Slack thread about it.
  3. Maintenance (constant): Ubuntu version changes. Docker API changes. The Actions runner environment updates. Node version in setup-node has a CVE. You update the workflow just to keep up with platform drift.
  4. New team member onboarding (1 hour): "So, here's the preview YAML. No, don't touch the SSH key line, that's magic. Here's a Notion doc that explains it."

By conservative estimate: 4 hours of setup, 2 hours per month of debugging, 3 hours per quarter of maintenance updates. For a 5-person team, that's the equivalent of 1 engineer-week per year of toil, just to keep preview deploys working.

Meanwhile, your actual feature work is getting slower because deployments are 4–8 minutes per PR.

The PreviewDrop alternative

Install the GitHub App. Push a branch. Get a live URL in 60 seconds. Done.

No YAML. No SSH keys. No Docker registry credentials. No reverse proxy config.

Here's what we handle:

  • Framework detection — we look at your repo and figure out what you're building (Node, Python, Go, Ruby, Rust — anything nixpacks supports)
  • Dependency installation — npm install, pip install, bundle install, with BuildKit caches so warm rebuilds are under 30 seconds
  • Build execution — npm run build, cargo build, your custom command — whatever makes sense for your framework
  • Container runtime — we start your app in a container, health-check it, and route traffic to it
  • Dynamic URL assignment — no DNS config, no reverse proxy config, no SSL cert provisioning per preview (we use wildcard TLS and Traefik, so the URL is live instantly)
  • PR integration — bot comment lands automatically with the preview URL
  • Auto-expiry — the preview runs for 4 hours (configurable), then cleans up automatically

The mental overhead is zero. You authorize the GitHub App once. After that, previews just happen.

The honest truth: what we can't do that GitHub Actions can

GitHub Actions is Turing-complete. You can do anything in a workflow. PreviewDrop is opinionated: we run your Dockerfile (or generate one via nixpacks), start it, and assign a URL. That's it.

If you need something custom (run a database migration as part of deploy, provision a separate Redis instance, run integration tests against the preview before posting the comment), you can't do it with PreviewDrop alone.

But here's the secret: you probably don't need that. Most teams' "complex" preview workflows are actually 80% boilerplate (check out code, install deps, build, deploy, post comment) and 20% custom logic (run migrations). We handle the 80%. If you need the 20%, you can still use GitHub Actions for that and call the PreviewDrop API to trigger a deploy.

The cost difference

GitHub Actions: Free for public repos. For private repos, you get ~2,000 minutes per month free, then $0.008 per minute. If each preview build takes 5 minutes and you deploy 10 PRs per day, that's 150 minutes per month (well under the free tier). So actually free until you hit serious scale.

But the real cost is human time. Setup, debugging, maintenance, on-calls when SSH keys expire. That's the tax GitHub Actions never bills you for.

PreviewDrop: $19/month (Starter tier) gives you 5 concurrent previews and 4-hour TTLs. For a 5-person team doing 10 PRs a day, that's $19 in cash, plus zero hours of setup and debugging.

The math: Is 1 engineer-hour per month (conservative estimate of GitHub Actions maintenance) worth $19?

For almost every team, yes.

Migration path: from GitHub Actions to PreviewDrop

If you already have a GitHub Actions workflow, migration is trivial:

  1. Sign up at previewdrop.dev, connect GitHub
  2. Pick the repo where you've got the existing workflow
  3. Open a PR — PreviewDrop will detect your stack and generate a preview automatically
  4. Test the preview — click the link, make sure your app loads
  5. Delete the old workflow — remove .github/workflows/preview-deploy.yml
  6. Archive the staging server — you don't need it anymore (optional, but why keep paying for it?)

Total time: 15 minutes.

What previews actually look like in practice

Let's trace through a real example: a Rails app with a PostgreSQL database.

You push: git push origin feature/user-auth
   ↓
GitHub webhook fires immediately
   ↓
PreviewDrop clones the repo, detects Rails (Gemfile + Rails detection)
   ↓
nixpacks generates a Dockerfile (bundle install + rails assets:precompile)
   ↓
docker build runs with BuildKit caches (if you've built this app before, bundle and assets are cached)
   ↓
Container starts, Rails loads (typically 5–10 seconds)
   ↓
Health check passes
   ↓
Traefik assigns the URL and routes traffic to the container
   ↓
Bot comment lands on your PR: 🚀 Preview ready at https://prv-abc123.preview.previewdrop.dev
   ↓
Total time: 47 seconds (measured on real Rails repos)
Enter fullscreen mode Exit fullscreen mode

Your designer clicks the link, sees the new authentication flow, comments "looks good!" You push an update, the preview auto-updates (same URL, fresh code), they confirm the fix works.

No staging server. No SSH keys. No "sorry, staging is down." No waiting.

The "but what about my database" question

Yes, your Rails app probably does db:migrate or creates database records. How does that work on the preview if we don't provision a database?

Two answers:

Answer 1 (most cases): Your preview connects to a real database (your production DB, a shared staging DB, or a test fixture DB). That's fine — you're just testing the web UI changes, not the data layer.

Answer 2 (if you need isolation): You set an environment variable DATABASE_URL in your PreviewDrop workspace pointing to a preview-specific Postgres instance. That's a second deploy (RDS, Supabase, or your own Postgres cluster), but it's one-time setup and we handle the rest.

Most teams do Answer 1. We're designing Answer 2 as an opt-in feature for teams that need true test isolation.

The real win: time back

You've just recovered 1 hour per month. Your new team member doesn't need to learn YAML. Your deploy workflow is now one sentence: "Push a branch, get a URL."

That time compounds. Over a year, that's 12 engineer-hours. For a team of 5, that's 2.4% of total capacity, freed up from toil to features.

But the bigger win is velocity on the current feature. No more waiting 5–8 minutes for GitHub Actions to complete. No more "is staging up?" Slack messages. No more deciding not to deploy because previews are slow.

60 seconds from push to live URL means your feedback loop is tighter, your iteration is faster, and your PR reviews happen with the actual running code in front of you — not a screenshot.

How we compare to other platforms

Platform Setup time Build time Cost CI-free
GitHub Actions + manual deploy 4 hours 5–8 min $0 (time is hidden) No
Railway 30 min 1–3 min $0–$50/mo (usage-based, unpredictable) Yes, but bills surprise you
Vercel 5 min 30s (Next.js only) $20/user/mo Yes, but Next.js only
Render 30 min 2–4 min $19/user/mo (or Pro tier gated) Yes, but per-seat pricing
Heroku Review Apps 30 min 4–6 min ~$25/dyno-month (per preview) No, requires Heroku stack
PreviewDrop 5 min <60s $19/mo (flat, any stack) Yes

The one-cell winner: PreviewDrop for "any stack, flat price, zero CI YAML."

Try it on your repo right now

Sign up in 90 seconds. Connect your GitHub account. Pick a repo. Push a feature branch. Watch the preview URL land in your PR comment.

No credit card. No complicated setup. No YAML.

If you're currently maintaining a GitHub Actions preview workflow, you've already spent enough time on this. Let us take it over.


Originally published at previewdrop.com/blog/200-lines-yaml-zero

Push. Preview. Done. That's the workflow we're building.

Ready to delete 200 lines of YAML? Start your free tier today. Or read our GitHub Actions replacement guide for a detailed comparison.

Top comments (0)