Skip to content

Add CI auto-deploy with selective app restarts - #73

Open
owens1127 wants to merge 2 commits into
mainfrom
ci/services-auto-deploy
Open

Add CI auto-deploy with selective app restarts#73
owens1127 wants to merge 2 commits into
mainfrom
ci/services-auto-deploy

Conversation

@owens1127

Copy link
Copy Markdown
Contributor

Summary

  • Auto-deploy Services to prod on push to main via SSH through Cloudflare Access (same pattern as API and Discord).
  • determine-deploy-targets.sh uses git diff + go list -deps to decide which long-running apps need a rebuild — tools always, hermes/atlas/zeus only when their dependency closure changed.
  • deploy-services.sh on the VPS pulls, builds selectively, and restarts only the affected systemd units.
  • Manual admin-only workflow (deploy-manual.yml) forces all apps for branch deploys.

Deploy logic

Change type Rebuild
tools/** tools only
apps/hermes/** or imported lib/** tools + hermes
go.mod / go.sum / Makefile tools + all apps
.github/**, docs/**, infrastructure/** tools only

Secrets required

These should already exist from API/Discord deploys — confirm they're available on the Services repo (or org-level):

  • VPS_SSH_PRIVATE_KEY
  • VPS_SSH_KNOWN_HOSTS
  • CF_GHA_CLIENT_ID
  • CF_GHA_CLIENT_SECRET

Test plan

  • Merge PR (first deploy will pull the new scripts, then run them)
  • Verify Deploy to Prod workflow succeeds on merge
  • Confirm prod git log -1 matches main
  • Tools-only merge: workflow logs show apps=(none), no hermes/atlas/zeus restart
  • lib/ change affecting hermes: workflow logs show hermes rebuilt + restarted
  • strings bin/hermes | grep <version-tag> or equivalent smoke check

Made with Cursor

Deploy on merge to main via SSH (matching API/Discord), always rebuild tools, and only rebuild/restart hermes, atlas, or zeus when changed files touch their Go dependency closure.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment on lines +51 to +54
branch_ref="${{ github.ref }}"
branch_name="${branch_ref#refs/heads/}"
ssh -o ProxyCommand="cloudflared access ssh --hostname %h" root@ssh.raidhub.io \
"cd /RaidHub/Services && DEPLOY_FORCE_APPS=1 bash ./.github/scripts/deploy-services.sh \"$branch_name\""

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The branch_name variable, derived from github.ref, is used unsafely in a run block, creating a command injection vulnerability if the branch name contains shell metacharacters.
Severity: HIGH

Suggested Fix

Pass the branch name to the script via an environment variable instead of direct string interpolation. Set branch_name in the env context of the step, and then reference it as $BRANCH_NAME within the script. This prevents the shell from interpreting metacharacters in the branch name during expansion. For example: env: { BRANCH_NAME: ${{ github.ref_name }} } and then use $BRANCH_NAME in the run script. Using github.ref_name is also safer as it only contains the branch/tag name.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: .github/workflows/deploy-manual.yml#L51-L54

Potential issue: The `branch_name` variable is derived from `${{ github.ref }}` and is
directly substituted into a bash `run` block. If a branch name contains shell
metacharacters like `$()` or backticks, it can lead to arbitrary command execution on
the GitHub Actions runner. The `run` block on line 54 executes an SSH command where
`$branch_name` is expanded by the local shell. A malicious branch name like
`feature/fix-$(evil_command)` would cause `evil_command` to run on the runner. While an
admin check mitigates direct exploitation, an admin could unknowingly trigger the
workflow on a malicious branch created by another user with push access.

Did we get this right? 👍 / 👎 to inform future reviews.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment on lines +25 to +28
go build -o /dev/null ./apps/atlas/
go build -o /dev/null ./apps/hermes/
go build -o /dev/null ./apps/zeus/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The deploy workflow will fail because actions/checkout creates a shallow clone, but a later step requires more git history to run git diff.
Severity: CRITICAL

Suggested Fix

In the deploy.yml workflow, configure the actions/checkout@v4 step with fetch-depth: 0 to ensure the full git history is available. This will allow the git diff command to access the previous commit and execute successfully.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: .github/workflows/deploy.yml#L25-L28

Potential issue: The `deploy.yml` workflow uses `actions/checkout@v4` without specifying
`fetch-depth`, which defaults to a shallow clone of depth 1. A subsequent step in the
workflow attempts to run `git diff` using the previous commit SHA
(`github.event.before`). Because this previous commit is not available in the shallow
clone, the `git diff` command fails with a `fatal: bad object` error. This failure halts
the entire workflow, preventing any deployments from running on pushes to the `main`
branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant