Skip to content

Merge pull request #50 from resolve-kit/dependabot/npm_and_yarn/dashb… #27

Merge pull request #50 from resolve-kit/dependabot/npm_and_yarn/dashb…

Merge pull request #50 from resolve-kit/dependabot/npm_and_yarn/dashb… #27

name: Backend Image Pipeline
on:
push:
branches:
- main
tags:
- "v*"
workflow_dispatch:
inputs:
deploy_target:
description: "Manual deploy target"
required: true
default: staging
type: choice
options:
- prod
- staging
image_tag:
description: "Image tag to deploy (defaults to sha-<short-commit>)"
required: false
type: string
permissions:
contents: read
packages: write
env:
REGISTRY: ghcr.io
jobs:
publish:
name: Build and publish images
runs-on: ubuntu-latest
strategy:
matrix:
include:
- name: backend
dockerfile: ./Dockerfile
context: .
image_name: resolvekit-backend
build_args: ""
- name: kb-service
dockerfile: ./knowledge_bases/Dockerfile
context: .
image_name: resolvekit-kb-service
build_args: ""
- name: dashboard
dockerfile: ./dashboard/Dockerfile
context: ./dashboard
image_name: resolvekit-dashboard
build_args: |
NEXT_PUBLIC_API_BASE_URL=https://console.resolvekit.app
NEXT_PUBLIC_IOS_SDK_REPO_URL=https://github.com/resolve-kit/resolvekit-ios-sdk
steps:
- name: Check out repository
uses: actions/checkout@v5
- name: Set lowercase owner name
id: owner
run: echo "value=${GITHUB_REPOSITORY_OWNER,,}" >> "$GITHUB_OUTPUT"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Docker metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ steps.owner.outputs.value }}/${{ matrix.image_name }}
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=sha,prefix=sha-
type=ref,event=tag
- name: Build and push
uses: docker/build-push-action@v6
with:
context: ${{ matrix.context }}
file: ${{ matrix.dockerfile }}
build-args: ${{ matrix.build_args }}
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
deploy-staging:
name: Deploy to staging
runs-on: ubuntu-latest
needs: publish
if: |
(github.event_name == 'push' && github.ref == 'refs/heads/main') ||
(github.event_name == 'workflow_dispatch' && inputs.deploy_target == 'staging')
environment: staging
steps:
- name: Resolve image tag
id: image
run: |
if [ -n "${{ inputs.image_tag }}" ]; then
echo "value=${{ inputs.image_tag }}" >> "$GITHUB_OUTPUT"
else
echo "value=sha-${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
fi
- name: Configure SSH key
run: |
mkdir -p ~/.ssh
printf '%s\n' "${{ secrets.STAGING_SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
- name: Update staging backend services
env:
DEPLOY_HOST: 147.93.62.111
DEPLOY_USER: resolvekit
IMAGE_TAG: ${{ steps.image.outputs.value }}
run: |
ssh -o StrictHostKeyChecking=accept-new "$DEPLOY_USER@$DEPLOY_HOST" "
set -euo pipefail
OWNER_LOWER='${GITHUB_REPOSITORY_OWNER,,}'
BACKEND_IMAGE='ghcr.io/'\"\$OWNER_LOWER\"'/resolvekit-backend:${IMAGE_TAG}'
KB_IMAGE='ghcr.io/'\"\$OWNER_LOWER\"'/resolvekit-kb-service:${IMAGE_TAG}'
DASHBOARD_IMAGE='ghcr.io/'\"\$OWNER_LOWER\"'/resolvekit-dashboard:${IMAGE_TAG}'
docker pull \"\$BACKEND_IMAGE\"
docker pull \"\$KB_IMAGE\"
docker pull \"\$DASHBOARD_IMAGE\"
docker tag \"\$BACKEND_IMAGE\" resolvekit-backend:local-deploy
docker tag \"\$KB_IMAGE\" resolvekit-kb-service:local-deploy
docker tag \"\$DASHBOARD_IMAGE\" resolvekit-dashboard:local-deploy
cd /home/resolvekit/resolvekit-backend
if grep -q '^GATEWAY_HTTP_BIND_ADDR=' .env; then
sed -i 's/^GATEWAY_HTTP_BIND_ADDR=.*/GATEWAY_HTTP_BIND_ADDR=127.0.0.1/' .env
else
echo 'GATEWAY_HTTP_BIND_ADDR=127.0.0.1' >> .env
fi
if grep -q '^GATEWAY_HTTPS_BIND_ADDR=' .env; then
sed -i 's/^GATEWAY_HTTPS_BIND_ADDR=.*/GATEWAY_HTTPS_BIND_ADDR=127.0.0.1/' .env
else
echo 'GATEWAY_HTTPS_BIND_ADDR=127.0.0.1' >> .env
fi
docker compose -f docker-compose.local-deploy.yml up -d --no-build backend kb-service api dashboard caddy
for service in backend kb-service api dashboard caddy; do
if ! docker compose -f docker-compose.local-deploy.yml ps --services --filter status=running | grep -qx "\$service"; then
echo "Staging service failed to reach running state: \$service" >&2
exit 1
fi
done
"
deploy-prod:
name: Deploy to production
runs-on: ubuntu-latest
needs: publish
if: github.event_name == 'workflow_dispatch' && inputs.deploy_target == 'prod'
environment: production
steps:
- name: Resolve image tag
id: image
run: |
if [ -n "${{ inputs.image_tag }}" ]; then
echo "value=${{ inputs.image_tag }}" >> "$GITHUB_OUTPUT"
else
echo "value=sha-${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT"
fi
- name: Configure SSH key
run: |
mkdir -p ~/.ssh
printf '%s\n' "${{ secrets.PROD_SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
- name: Update production backend services
env:
DEPLOY_HOST: 92.242.187.124
DEPLOY_USER: nedas
IMAGE_TAG: ${{ steps.image.outputs.value }}
run: |
ssh -o StrictHostKeyChecking=accept-new "$DEPLOY_USER@$DEPLOY_HOST" "
set -euo pipefail
OWNER_LOWER='${GITHUB_REPOSITORY_OWNER,,}'
BACKEND_IMAGE='ghcr.io/'\"\$OWNER_LOWER\"'/resolvekit-backend:${IMAGE_TAG}'
KB_IMAGE='ghcr.io/'\"\$OWNER_LOWER\"'/resolvekit-kb-service:${IMAGE_TAG}'
DASHBOARD_IMAGE='ghcr.io/'\"\$OWNER_LOWER\"'/resolvekit-dashboard:${IMAGE_TAG}'
docker pull \"\$BACKEND_IMAGE\"
docker pull \"\$KB_IMAGE\"
docker pull \"\$DASHBOARD_IMAGE\"
docker tag \"\$BACKEND_IMAGE\" resolvekit-backend:prod
docker tag \"\$KB_IMAGE\" resolvekit-kb-service:prod
docker tag \"\$DASHBOARD_IMAGE\" resolvekit-dashboard:prod
cd /home/nedas/resolvekit-backend
docker compose -f docker-compose.prod.yml up -d --no-build backend kb-service api dashboard
for service in backend kb-service api dashboard; do
if ! docker compose -f docker-compose.prod.yml ps --services --filter status=running | grep -qx "\$service"; then
echo "Production service failed to reach running state: \$service" >&2
exit 1
fi
done
"