Refactor deployment and migration handling for droplets#21
Conversation
…firewall.sh Co-authored-by: Cursor <cursoragent@cursor.com>
The deploy bind-mounts ./data over /app/data, which shadowed the data/migrations baked into the image and crashed the bot at startup (Can't find meta/_journal.json). Relocate migrations to repo-root migrations/ (code, in image) and keep data/ purely for runtime state, mirroring dlsite's code-vs-state separation. Legacy CSV drop dir moves to data/legacy-export (stays on the mounted volume). Co-authored-by: Cursor <cursoragent@cursor.com>
Revert the migrations relocation. Keep migrations at data/migrations (shipped in the image) and instead bind-mount only the persistent state (data/main.sqlite and data/backups) so the image's data/migrations is no longer shadowed by the host mount. The deploy pre-creates the sqlite file and backups dir so Docker mounts a file/dir rather than creating a directory in place of the db file. Co-authored-by: Cursor <cursoragent@cursor.com>
PR SummaryHigh Risk Overview Prod and dev share one DigitalOcean droplet with isolated state: prod uses
Firewall reconciliation is extracted to Docs ( Reviewed by Cursor Bugbot for commit a34d8ae. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 3 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit a34d8ae. Configure here.
| - name: Deploy bot | ||
| run: | | ||
| ssh -i ~/.ssh/bot_deploy_key deploy@"${BOT_HOST}" "sudo /usr/local/bin/deploy-event-queue-bot" | ||
| ssh -i ~/.ssh/bot_deploy_key deploy@"${BOT_HOST}" "sudo /usr/local/bin/deploy-event-queue-bot '${APP_PATH}'" |
There was a problem hiding this comment.
GHCR login user mismatch
High Severity
The deploy workflow runs docker login over SSH as the deploy user, but sudo /usr/local/bin/deploy-event-queue-bot runs docker compose pull as root. Registry credentials live per Docker client user, so a private GHCR image pull during deploy fails even when GHCR_PULL_TOKEN is set.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit a34d8ae. Configure here.
| run: | | ||
| if [ -n "${GHCR_PULL_TOKEN}" ]; then | ||
| ssh -i ~/.ssh/bot_deploy_key deploy@"${BOT_HOST}" \ | ||
| "echo '${GHCR_PULL_TOKEN}' | docker login ghcr.io -u '${{ github.actor }}' --password-stdin" |
There was a problem hiding this comment.
Wrong GHCR login username
Medium Severity
When GHCR_PULL_TOKEN is used, docker login on the VPS uses ${{ github.actor }} as the username. GHCR expects the GitHub username that owns the PAT, which often differs from whoever triggered the workflow, so authentication can fail for private packages.
Reviewed by Cursor Bugbot for commit a34d8ae. Configure here.
| env: | ||
| DO_DROPLET_NAME: ${{ vars.DO_DROPLET_NAME || 'event-queue-bot' }} | ||
| APP_PATH: ${{ vars.APP_PATH || '/opt/event-queue-bot' }} | ||
| APP_PATH: ${{ vars.APP_PATH || (inputs.environment == 'prod' && '/opt/event-queue-bot' || '/opt/event-queue-bot-nightly') }} |
There was a problem hiding this comment.
Restart bypasses deploy lock
Medium Severity
Prod and dev now share one droplet, and the deploy job serializes changes with concurrency group provision-and-deploy-bot-droplet. The Restart Bot workflow still uses provision-and-deploy-bot-${{ inputs.environment }}, so a manual restart can run concurrently with an in-flight deploy against the same app path and container.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit a34d8ae. Configure here.


No description provided.