Update registry with Lambda Dockerfiles and Obsidian Nebula design up… #3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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" |