Choosing Between Discloud CLI and GitHub Actions for Discord Bot Deployments
Compare Discloud CLI direct deploy vs GitHub Actions CI/CD for Discord bots: automation, rollback, secrets, quota impact, and a production-ready workflow you can copy.
17 Dec 2025, 00:58 UTC

The Decision: How to Deploy Your Discord Bot to Discloud
You have a Discord bot ready for production on Discloud. The platform offers two supported deployment paths: the @discloud/cli for direct uploads from any machine, and the official discloud/github-action for CI/CD via GitHub Actions. Both reach the same infrastructure—same RAM, CPU, disk, and deploy quotas—but they differ in automation, rollback ergonomics, secret handling, and operational overhead. This guide compares them so you can pick the one that fits your workflow and risk tolerance.
Constraints That Apply to Both Methods
- Free tier limits: 512 MB RAM, 1 vCPU, 1 GB disk, 100 deploys/month. Every
discloud uploadcounts, regardless of origin. - App sleep: Free tier apps sleep after 10 minutes of inactivity; cold start adds 3–8 s latency. Paid plans disable sleep.
- Slug size: Maximum 500 MB.
node_modulesbloat is the common cause of upload failures. - No horizontal scaling: Discloud runs a single container per app. High availability requires multiple independent apps behind an external load balancer.
- Region: Servers in São Paulo (BR-SP). Expect 120–200 ms RTT from North America/Europe for WebSocket-heavy bots.
- Custom domains & SSL: Configured in the Discloud dashboard after first successful deploy; neither method automates DNS validation.
- Database add-ons: MongoDB, PostgreSQL, Redis are provisioned separately and injected as
DATABASE_URL-style env vars; they persist across deploys.
Side-by-Side Comparison
| Factor | Discloud CLI (discloud upload) | GitHub Actions (discloud/github-action) |
|---|---|---|
| Trigger | Manual command from local machine or any CI runner | Automatic on push to configured branch (e.g., main) |
| Token exposure | Token must be present in runner environment; risk of leaking in logs if not masked | Token stored once in GitHub repo secrets; injected per run, masked in logs |
| Build visibility | Local terminal output only | Full build/deploy logs in Actions UI, searchable and linkable |
| Rollback | Manual: re-upload a previous commit artifact (discloud upload --commit <sha> or re-package locally) | One-click: re-run any successful workflow run from Actions history (artifacts retained 90 days by default) |
| Environment sync | discloud env:set per key or discloud env:import --file=.env.production | Same CLI commands available inside workflow; can import .env.production as a step |
| Deploy quota impact | Each upload consumes 1 of 100 monthly deploys | Each workflow run consumes 1 of 100 monthly deploys |
| Version pinning | CLI version controlled by your local/global npm | Action version pinned in workflow (recommend exact SHA for production) |
| Prerequisites | Node.js, npm, npm i -g @discloud/cli | GitHub repo, Actions enabled, DISCLOUD_TOKEN secret |
Trade-Off Analysis
When CLI Direct Deploy Makes Sense
- Solo or low-frequency deployments: You deploy a few times a week and prefer a single command without CI configuration.
- Non-GitHub repositories: GitLab, Bitbucket, or local-only projects where GitHub Actions isn't an option.
- Quick validation:
discloud upload --dry-runvalidates.discloudignoreand slug size before consuming quota. - Ephemeral test environments: Spinning up a temporary app from a feature branch without polluting main branch history.
Risk: Manual token handling increases chance of accidental exposure in shell history or CI logs. Rollback requires you to keep or rebuild the exact artifact you want to restore.
When GitHub Actions Is the Better Fit
- Team collaboration: Anyone with write access to
maincan deploy by merging; no local CLI setup required. - Audit trail: Every deploy is a workflow run with timestamp, commit SHA, actor, and full logs—useful for compliance or debugging.
- Safer secrets: Token lives in GitHub encrypted secrets, never in developer machines or shell history.
- Built-in rollback: Re-running a prior successful workflow restores that exact build artifact in seconds.
- Pre-deploy checks: You can gate the deploy job on lint, test, or type-check steps in the same workflow.
Risk: The discloud/github-action pins to a major version (e.g., v1); breaking changes in minor releases have occurred (token flag rename). Pin to an exact commit SHA for production. Also, every push to main consumes a deploy—configure branch protection or a manual approval step if quota is tight.
Concrete Implementation: Production-Grade GitHub Actions Workflow
Below is a complete, commented workflow you can drop into .github/workflows/deploy.yml. It includes slug-size guard, test gate, exact-action pinning, and environment-variable sync.
name: Deploy to Discloud
on:
push:
branches: [main]
workflow_dispatch: # manual trigger from Actions UI
permissions:
contents: read # minimal permission for checkout
jobs:
deploy:
name: Build & Deploy
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install production dependencies only
run: npm ci --omit=dev
# Reduces slug size; devDependencies excluded from upload
- name: Run lint & tests (gate deploy)
run: |
npm run lint
npm test
- name: Validate slug size before upload
run: |
du -sh . | awk '{print $1}'
# If output > 500M, fail fast to save deploy quota
SIZE=$(du -sb . | awk '{print $1}')
if [ $SIZE -gt 524288000 ]; then
echo "::error::Slug size ${SIZE}B exceeds 500MB limit"
exit 1
fi
- name: Deploy to Discloud
uses: displcloud/github-action@a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0 # pin to exact SHA
with:
token: ${{ secrets.DISCLOUD_TOKEN }}
# Optional: import production env vars from committed .env.production
# env-file: '.env.production'
- name: Verify deployment health
if: success()
run: |
echo "Deploy triggered. Check Discloud dashboard > Logs for bot startup."
echo "Free tier: app may sleep after 10 min inactivity."
Where to Run & Permissions
- Repository: Your Discord bot repo on GitHub.
- Required secrets:
DISCLOUD_TOKEN(Settings → Secrets and variables → Actions → New repository secret). Generate in Discloud Dashboard → Settings → API. - Runner: GitHub-hosted
ubuntu-latest(default). No self-hosted runner needed. - Permissions:
contents: readis sufficient; the action only needs the token to call Discloud API.
Meaningful Placeholders
a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0— replace with the exact commit SHA ofdiscloud/github-actionyou've vetted (find viagit log --onelineon the action repo or GitHub UI)..env.production— optional committed file with production env vars (never commit real secrets; use GitHub secrets for tokens, then write a small script to generate this file at runtime if needed).
Expected Checks & Verification
- Workflow run appears green in Actions tab.
- Discloud Dashboard → Apps → your bot shows "Online" status and recent deploy timestamp.
- Bot responds in Discord (run a test command).
- Logs in Discloud Dashboard show no
ENOSPCor slug-size errors.
Risks & Mitigations
| Risk | Mitigation |
|---|---|
| Deploy quota exhausted mid-month | Add if: github.event_name != 'push' || github.ref == 'refs/heads/main' guard; consider a monthly budget alert via Discloud API. |
| Action breaking change | Pin to exact SHA (as shown). Update deliberately after testing in a staging app. |
| Slug exceeds 500 MB | Pre-deploy size check (included). Use .discloudignore to exclude *.log, coverage/, .git/, large assets. |
| Token compromised | Revoke in Discloud Dashboard → Settings → API → Revoke; update GitHub secret; re-run workflow. |
| Cold start latency on free tier | Upgrade to paid plan or implement a lightweight keep-alive ping (external cron) if latency is unacceptable. |
Rollback Procedure (Both Methods)
Deployment changes live state; rollback is a valid operational concern.
GitHub Actions (Preferred)
- Open Actions tab → select the workflow → click a prior successful run.
- Click "Re-run all jobs" (or "Re-run failed jobs" if the latest failed).
- Workflow re-uploads the exact artifact from that run; bot restarts on previous version.
Artifacts retained 90 days by default (configurable in repo settings).
CLI (Manual)
# Option 1: Re-upload from a known-good local commit
cd /path/to/repo
git checkout <good-sha>
discloud upload
# Option 2: If you saved the .discloud slug artifact
# (Discloud does not expose slug download; rebuild from commit)
No one-click rollback; you must have the commit or rebuild locally.
Practical Verification Checklist
Before committing to either method for production, run these once:
- Test deploy end-to-end: Create a throwaway Discord bot repo, add the workflow above, push to
main, confirm deploy in Actions log and bot comes online in Discord. - Validate
.discloudignoreand slug size: Rundiscloud upload --dry-runlocally (requires CLI install and token). Output shows files included and total size. - Confirm free-tier limits: Discloud Dashboard → Plan → Limits. Verify 100 deploys/month, 512 MB RAM, sleep behavior.
- Test token rotation: Revoke current token in Dashboard → Settings → API, update GitHub secret, re-run workflow. Bot should deploy with new token.
- Test rollback: Re-run a previous successful workflow run from Actions history; confirm bot version reverts (check log output or a version command).
Limitations to Accept
- No blue/green or canary deployments; single-container atomic restart only.
- No built-in health checks or readiness probes; bot must handle its own graceful shutdown (SIGTERM) within Discloud's stop timeout.
- Regional latency is fixed; if your user base is primarily EU/NA, consider a proxy layer or alternative host.
- GitHub Actions workflow runs count against the same 100-deploy monthly quota as CLI. High-frequency feature branches can exhaust quota quickly—use
workflow_dispatchor branch filters to control.
Decision Summary
Choose GitHub Actions if you work in a team, value audit trails, want safer secret handling, and need one-click rollback. Pin the action to an exact SHA and gate deploys with tests.
Choose CLI direct deploy for solo projects, non-GitHub repos, or when you need to validate a build locally (--dry-run) before spending a deploy token. Accept manual rollback and tighter token discipline.
Both paths hit the same infrastructure limits. The choice is operational, not technical capability.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.