Continuous deployment of Honcho images to SaaS platform (#102)

* feat: add CD for honcho images to saas test and prod environments

* fix: use github tag in image label

* feat: split up test and prod deployment flows, push to service after

* fix: action parsing properly hopefully

* fix: proper url, version

* remove excessive fly.toml

* fix: specify prod-image in prod workflow

* Potential fix for code scanning alert no. 12: Workflow does not contain permissions

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Potential fix for code scanning alert no. 11: Workflow does not contain permissions

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix: Change App name in command and make steps sequential

* fix: Address Code Rabbit nitpicks

* Use IMAGE Label environment variable

* fix: collisions between github action groups

* feat: add migrate_db script

* fix: correct image label on prod deploy

---------

Co-authored-by: Vineeth Voruganti <13438633+VVoruganti@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
This commit is contained in:
doria 2025-05-09 00:21:54 +09:00 committed by GitHub
parent d5dffcffd6
commit d1292aaae4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 133 additions and 14 deletions

61
.github/workflows/fly-deploy-prod.yml vendored Normal file
View File

@ -0,0 +1,61 @@
# See https://fly.io/docs/app-guides/continuous-deployment-with-github-actions/
name: Fly Deploy (Production Environment)
permissions:
contents: read
on:
push:
tags:
- v*
workflow_dispatch:
inputs:
version:
description: "Version to deploy (without v prefix)"
required: true
type: string
default: 'manual'
jobs:
deploy-honcho-prod-image:
name: Deploy Honcho Image (Production Environment)
runs-on: ubuntu-latest
concurrency:
group: deploy-prod-group
cancel-in-progress: true
steps:
- uses: actions/checkout@v4
- uses: superfly/flyctl-actions/setup-flyctl@1.5
- run: |
# Determine the image label based on trigger type
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
IMAGE_LABEL="deployment-${{ github.event.inputs.version }}"
else
IMAGE_LABEL="deployment-${{ github.ref_name }}"
fi
flyctl deploy -a honcho-prod-image --remote-only --build-only --push --no-cache --image-label "$IMAGE_LABEL"
env:
FLY_API_TOKEN: ${{ secrets.FLY_PROD_API_TOKEN }}
prompt-service:
name: Push to Service (Production Environment)
needs: deploy-honcho-prod-image
runs-on: ubuntu-latest
steps:
- name: Send POST request
env:
GITHUB_REF_NAME: ${{ github.ref_name }}
run: |
# Determine version and image label based on trigger type
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
TAG="${{ github.event.inputs.version }}"
IMAGE_LABEL="honcho-prod-image:deployment-${{ github.event.inputs.version }}"
else
TAG=${GITHUB_REF_NAME#v}
IMAGE_LABEL="honcho-prod-image:deployment-${GITHUB_REF_NAME}"
fi
curl --fail -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${{ secrets.PROD_ENV_WEBHOOK_SECRET }}" \
-d "{\"version\":\"$TAG\",\"image_label\":\"$IMAGE_LABEL\"}" \
"${{ secrets.PROD_ENV_URL }}/webhooks/v1/add_honcho_version"

View File

@ -1,18 +1,61 @@
# See https://fly.io/docs/app-guides/continuous-deployment-with-github-actions/
name: Fly Deploy
name: Fly Deploy (Test Environment)
permissions:
contents: read
on:
push:
branches:
- main
tags:
- v*
workflow_dispatch:
inputs:
version:
description: "Version to deploy (without v prefix)"
required: true
type: string
default: 'manual'
jobs:
deploy:
name: Deploy app
deploy-honcho-image:
name: Deploy Honcho Image (Test Environment)
runs-on: ubuntu-latest
concurrency: deploy-group # optional: ensure only one action runs at a time
concurrency:
group: deploy-test-group
cancel-in-progress: true
steps:
- uses: actions/checkout@v4
- uses: superfly/flyctl-actions/setup-flyctl@master
- run: flyctl deploy --remote-only
- uses: superfly/flyctl-actions/setup-flyctl@1.5
- run: |
# Determine the image label based on trigger type
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
IMAGE_LABEL="deployment-${{ github.event.inputs.version }}"
else
IMAGE_LABEL="deployment-${{ github.ref_name }}"
fi
flyctl deploy -a honcho-image --remote-only --build-only --push --no-cache --image-label "$IMAGE_LABEL"
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
prompt-service:
name: Push to Service (Test Environment)
runs-on: ubuntu-latest
needs: deploy-honcho-image
steps:
- name: Send POST request
env:
GITHUB_REF_NAME: ${{ github.ref_name }}
run: |
# Determine version and image label based on trigger type
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
TAG="${{ github.event.inputs.version }}"
IMAGE_LABEL="honcho-image:deployment-${{ github.event.inputs.version }}"
else
TAG=${GITHUB_REF_NAME#v}
IMAGE_LABEL="honcho-image:deployment-${GITHUB_REF_NAME}"
fi
curl --fail -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${{ secrets.TEST_ENV_WEBHOOK_SECRET }}" \
-d "{\"version\":\"$TAG\",\"image_label\":\"$IMAGE_LABEL\"}" \
"${{ secrets.TEST_ENV_URL }}/webhooks/v1/add_honcho_version"

View File

@ -41,5 +41,5 @@ COPY --chown=app:app alembic.ini /app/alembic.ini
EXPOSE 8000
# https://stackoverflow.com/questions/29663459/python-app-does-not-print-anything-when-running-detached-in-docker
CMD ["fastapi", "dev", "--host", "0.0.0.0", "src/main.py"]
CMD ["fastapi", "run", "--host", "0.0.0.0", "src/main.py"]

19
scripts/migrate_db.py Normal file
View File

@ -0,0 +1,19 @@
# honcho/scripts/migrate_db.py
import os
import sys
# Add the project root to the path
# This assumes the script is run from the scripts directory
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
sys.path.insert(0, project_root)
from alembic import command # noqa: E402
from alembic.config import Config # noqa: E402
from src.db import scaffold_db # noqa: E402
if __name__ == "__main__":
scaffold_db()
# run alembic migrations
alembic_cfg = Config("alembic.ini")
command.upgrade(alembic_cfg, "head")

View File

@ -7,11 +7,7 @@ import sys
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
sys.path.insert(0, project_root)
## First import the models to register them with Base
from src import (
models,
) # This registers all models with Base Now you can import from src
from src.db import scaffold_db
from src.db import scaffold_db # noqa: E402
if __name__ == "__main__":
scaffold_db()