Skip to content

Update registry with Lambda Dockerfiles and Obsidian Nebula design up… #3

Update registry with Lambda Dockerfiles and Obsidian Nebula design up…

Update registry with Lambda Dockerfiles and Obsidian Nebula design up… #3

Workflow file for this run

# Registry Deploy: test both components, build arm64 images, push to ECR, deploy stack.
#
# Triggers:
# - Push to main touching api/** or web/** or this workflow
# - Manual dispatch with optional force deploy (skip tests)
name: Registry Deploy
on:
push:
branches: [main]
paths:
- "api/**"
- "web/**"
- ".github/workflows/deploy.yml"
workflow_dispatch:
inputs:
force:
description: "Force deploy (skip tests)"
type: boolean
default: false
concurrency:
group: registry-deploy
cancel-in-progress: false
jobs:
# ── Tests ──────────────────────────────────────────────────────────────
test-api:
if: ${{ !inputs.force }}
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_DB: test
POSTGRES_USER: test
POSTGRES_PASSWORD: test
ports:
- "5432:5432"
options: --health-cmd "pg_isready -U test" --health-interval 5s
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.24"
cache: true
cache-dependency-path: api/go.sum
- name: Run Go tests
run: go test ./... -race -coverprofile=coverage.out
working-directory: api
env:
DATABASE_URL: postgres://test:test@localhost:5432/test?sslmode=disable
- name: Run go vet
run: go vet ./...
working-directory: api
test-web:
if: ${{ !inputs.force }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Install dependencies
run: bun install --frozen-lockfile
working-directory: web
- name: Typecheck
run: bun run tsc -b
working-directory: web
# ── Build & Push ───────────────────────────────────────────────────────
build-and-push:
needs: [test-api, test-web]
if: |
always() &&
(needs.test-api.result == 'success' || needs.test-api.result == 'skipped') &&
(needs.test-web.result == 'success' || needs.test-web.result == 'skipped') &&
github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
outputs:
image-tag: ${{ github.sha }}
steps:
- uses: actions/checkout@v4
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/devsper-deploy
aws-region: us-east-1
- uses: aws-actions/amazon-ecr-login@v2
id: ecr-login
- uses: docker/setup-buildx-action@v3
- name: Build and push API image
uses: docker/build-push-action@v6
with:
context: api
platforms: linux/arm64
push: true
tags: |
${{ steps.ecr-login.outputs.registry }}/devsper-registry-api:latest
${{ steps.ecr-login.outputs.registry }}/devsper-registry-api:${{ github.sha }}
cache-from: type=gha,scope=registry-api
cache-to: type=gha,mode=max,scope=registry-api
- name: Build and push Web image
uses: docker/build-push-action@v6
with:
context: web
platforms: linux/arm64
push: true
tags: |
${{ steps.ecr-login.outputs.registry }}/devsper-registry-web:latest
${{ steps.ecr-login.outputs.registry }}/devsper-registry-web:${{ github.sha }}
cache-from: type=gha,scope=registry-web
cache-to: type=gha,mode=max,scope=registry-web
# ── Deploy ─────────────────────────────────────────────────────────────
deploy:
needs: build-and-push
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
env:
EC2_HOST: ${{ vars.REGISTRY_EC2_HOST }}
EC2_INSTANCE_ID: ${{ vars.REGISTRY_EC2_INSTANCE_ID }}
ECR_REGISTRY: ${{ vars.AWS_ACCOUNT_ID }}.dkr.ecr.us-east-1.amazonaws.com
IMAGE_TAG: ${{ needs.build-and-push.outputs.image-tag }}
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::${{ vars.AWS_ACCOUNT_ID }}:role/devsper-deploy
aws-region: us-east-1
- name: Deploy via EC2 Instance Connect
run: |
# Generate ephemeral SSH key (valid ~60s after push)
ssh-keygen -t ed25519 -f /tmp/deploy_key -N "" -q
aws ec2-instance-connect send-ssh-public-key \
--instance-id "$EC2_INSTANCE_ID" \
--instance-os-user ubuntu \
--ssh-public-key file:///tmp/deploy_key.pub
# Rolling deploy: pull new images, restart web first (faster), then api
ssh -i /tmp/deploy_key -o StrictHostKeyChecking=no ubuntu@"$EC2_HOST" \
"set -euo pipefail && \
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $ECR_REGISTRY && \
cd /opt/devsper-registry && \
docker compose -f docker-compose.prod.yml --env-file .env.prod pull api web && \
docker compose -f docker-compose.prod.yml --env-file .env.prod up -d --no-deps web && \
sleep 3 && \
docker compose -f docker-compose.prod.yml --env-file .env.prod up -d --no-deps api && \
docker image prune -f"
rm -f /tmp/deploy_key /tmp/deploy_key.pub
- name: Smoke test
run: |
echo "Waiting for services to stabilize..."
sleep 8
# Check API health
curl -sf --retry 3 --retry-delay 5 "https://registry.devsper.com/health" || \
{ echo "FAIL: /health"; exit 1; }
# Check JWKS endpoint
curl -sf --retry 3 --retry-delay 5 "https://registry.devsper.com/auth/jwks" || \
{ echo "FAIL: /auth/jwks"; exit 1; }
# Check web frontend
curl -sf --retry 3 --retry-delay 5 "https://registry.devsper.com/" || \
{ echo "FAIL: / (web)"; exit 1; }
# Check packages API
curl -sf --retry 3 --retry-delay 5 "https://registry.devsper.com/api/v1/packages" || \
{ echo "FAIL: /api/v1/packages"; exit 1; }
echo "All smoke tests passed"