Skip to content

Commit 6eff4ac

Browse files
committed
Merge remote-tracking branch 'origin/staging' into KEEP-1155-write-smart-contract
2 parents 5dcdd05 + 073d0f4 commit 6eff4ac

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+5600
-1190
lines changed

.dockerignore

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Dependencies
2+
node_modules
3+
npm-debug.log*
4+
yarn-debug.log*
5+
yarn-error.log*
6+
pnpm-debug.log*
7+
8+
# Environment files
9+
.env
10+
.env.local
11+
.env.development.local
12+
.env.test.local
13+
.env.production.local
14+
15+
# Next.js build output
16+
.next
17+
out
18+
dist
19+
20+
# Development files
21+
.git
22+
.gitignore
23+
README.md
24+
Dockerfile
25+
.dockerignore
26+
docker-compose.yml
27+
docker-compose.*.yml
28+
29+
# IDE files
30+
.vscode
31+
.idea
32+
*.swp
33+
*.swo
34+
*~
35+
36+
# OS files
37+
.DS_Store
38+
Thumbs.db
39+
40+
# Logs
41+
logs
42+
*.log
43+
44+
# Runtime data
45+
pids
46+
*.pid
47+
*.seed
48+
*.pid.lock
49+
50+
# Coverage directory used by tools like istanbul
51+
coverage
52+
*.lcov
53+
54+
# nyc test coverage
55+
.nyc_output
56+
57+
# Dependency directories
58+
jspm_packages/
59+
60+
# Optional npm cache directory
61+
.npm
62+
63+
# Optional REPL history
64+
.node_repl_history
65+
66+
# Output of 'npm pack'
67+
*.tgz
68+
69+
# Yarn Integrity file
70+
.yarn-integrity
71+
72+
# parcel-bundler cache (https://parceljs.org/)
73+
.cache
74+
.parcel-cache
75+
76+
# next.js build output
77+
.next
78+
79+
# nuxt.js build output
80+
.nuxt
81+
82+
# vuepress build output
83+
.vuepress/dist
84+
85+
# Serverless directories
86+
.serverless
87+
88+
# FuseBox cache
89+
.fusebox/
90+
91+
# DynamoDB Local files
92+
.dynamodb/
93+
94+
# TernJS port file
95+
.tern-port
96+
97+
# Stores VSCode versions used for testing VSCode extensions
98+
.vscode-test
99+
100+
# Svelte build output
101+
.svelte-kit
102+
103+
# Database
104+
*.db
105+
*.sqlite
106+
107+
# Temporary files
108+
tmp/
109+
temp/
110+
111+
# Build artifacts
112+
build/
113+
dist/

.github/workflows/deploy.yaml

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
on:
2+
push:
3+
branches:
4+
- staging
5+
# - main
6+
workflow_dispatch:
7+
8+
name: deploy-keeperhub
9+
jobs:
10+
build-and-deploy-keeperhub:
11+
environment: ${{ github.ref == 'refs/heads/main' && 'prod' || 'staging' }}
12+
runs-on: ubuntu-latest
13+
env:
14+
HELM_FILE: deploy/${{ github.ref == 'refs/heads/main' && 'prod' || 'staging' }}/values.yaml
15+
REGION: ${{ github.ref == 'refs/heads/main' && 'us-east-1' || 'us-east-2' }}
16+
CLUSTER_NAME: ${{ github.ref == 'refs/heads/main' && 'maker-prod' || 'maker-staging' }}
17+
ENVIRONMENT_TAG: ${{ github.ref == 'refs/heads/main' && 'prod' || 'staging' }}
18+
NAMESPACE: keeperhub
19+
SERVICE_NAME: keeperhub
20+
AWS_ECR_NAME: keeperhub-${{ github.ref == 'refs/heads/main' && 'prod' || 'staging' }}
21+
steps:
22+
- name: Checkout
23+
uses: actions/checkout@v4
24+
with:
25+
submodules: recursive
26+
27+
- name: Configure AWS credentials
28+
uses: aws-actions/configure-aws-credentials@v4
29+
with:
30+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
31+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
32+
aws-region: ${{ env.REGION }}
33+
34+
- name: Login to AWS ECR
35+
id: login-ecr
36+
uses: aws-actions/amazon-ecr-login@v2
37+
38+
- name: Extract commit hash
39+
id: vars
40+
if: ${{ !contains(github.event.head_commit.message , '[skip build]') }}
41+
shell: bash
42+
run: |
43+
echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
44+
45+
- name: Build, tag, and push app image to ECR
46+
id: build-app-image
47+
if: ${{ !contains(github.event.head_commit.message , '[skip build]') }}
48+
env:
49+
SHA_TAG: ${{ steps.vars.outputs.sha_short }}
50+
LATEST_TAG: latest
51+
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
52+
run: |
53+
# Build Docker containers and push them to ECR ${{ env.AWS_ECR_NAME }}
54+
docker pull $ECR_REGISTRY/$AWS_ECR_NAME:$LATEST_TAG || true
55+
docker build -t $AWS_ECR_NAME \
56+
-t $ECR_REGISTRY/$AWS_ECR_NAME:$SHA_TAG \
57+
-t $ECR_REGISTRY/$AWS_ECR_NAME:$LATEST_TAG \
58+
-t $ECR_REGISTRY/$AWS_ECR_NAME:$ENVIRONMENT_TAG \
59+
-f ./Dockerfile \
60+
.
61+
62+
docker push $ECR_REGISTRY/$AWS_ECR_NAME --all-tags
63+
64+
- name: Build, tag, and push migrator image to ECR
65+
id: build-migrator
66+
if: ${{ !contains(github.event.head_commit.message , '[skip build]') }}
67+
env:
68+
SHA_TAG: ${{ steps.vars.outputs.sha_short }}
69+
LATEST_TAG: latest
70+
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
71+
run: |
72+
# Build image for database migrations
73+
docker build --target migrator \
74+
-t $ECR_REGISTRY/$AWS_ECR_NAME:migrator \
75+
-f ./Dockerfile \
76+
.
77+
78+
docker push $ECR_REGISTRY/$AWS_ECR_NAME:migrator
79+
80+
- name: Replace variables in the Helm values file
81+
id: replace-vars
82+
if: ${{ !contains(github.event.head_commit.message , '[skip deploy]') }}
83+
env:
84+
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
85+
IMAGE_TAG: ${{ steps.vars.outputs.sha_short }}
86+
run: |
87+
sed -i 's|${ECR_REGISTRY}|'"$ECR_REGISTRY"'|g' $HELM_FILE
88+
sed -i 's|${IMAGE_TAG}|'"$IMAGE_TAG"'|g' $HELM_FILE
89+
90+
- name: Deploying Service to Kubernetes with Helm
91+
id: deploy
92+
uses: bitovi/github-actions-deploy-eks-helm@v1.2.10
93+
with:
94+
cluster-name: ${{ env.CLUSTER_NAME }}
95+
config-files: ${{ env.HELM_FILE }}
96+
chart-path: techops-services/common
97+
namespace: ${{ env.NAMESPACE }}
98+
timeout: 5m0s
99+
name: ${{ env.SERVICE_NAME }}
100+
chart-repository: https://techops-services.github.io/helm-charts
101+
version: 0.0.33
102+
atomic: true

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212

1313
# testing
1414
/coverage
15+
/test-results/
16+
/playwright-report/
17+
/blob-report/
18+
/playwright/.cache/
1519

1620
# next.js
1721
/.next/
@@ -47,4 +51,5 @@ tmp/
4751
# generated files
4852
lib/types/integration.ts
4953
lib/codegen-registry.ts
50-
lib/step-registry.ts
54+
lib/step-registry.ts
55+
lib/output-display-configs.ts

Dockerfile

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Multi-stage Dockerfile for Next.js application
2+
# Stage 1: Dependencies
3+
FROM node:25-alpine AS deps
4+
RUN apk add --no-cache libc6-compat
5+
WORKDIR /app
6+
7+
# Install pnpm
8+
RUN npm install -g pnpm
9+
10+
# Copy package files
11+
COPY package.json pnpm-lock.yaml* ./
12+
COPY .npmrc* ./
13+
14+
# Install dependencies
15+
RUN pnpm install --frozen-lockfile
16+
17+
# Stage 2: Builder
18+
FROM node:25-alpine AS builder
19+
WORKDIR /app
20+
RUN npm install -g pnpm
21+
22+
# Copy dependencies from deps stage
23+
COPY --from=deps /app/node_modules ./node_modules
24+
COPY . .
25+
26+
# Create README.md if it doesn't exist to avoid build errors
27+
RUN touch README.md || true
28+
29+
# Build the application
30+
RUN pnpm build
31+
32+
# Stage 2.5: Migration stage (optional - for running migrations)
33+
FROM node:25-alpine AS migrator
34+
WORKDIR /app
35+
RUN npm install -g pnpm
36+
37+
# Copy dependencies and migration files
38+
COPY --from=deps /app/node_modules ./node_modules
39+
COPY --from=builder /app/drizzle ./drizzle
40+
COPY --from=builder /app/drizzle.config.ts ./drizzle.config.ts
41+
COPY --from=builder /app/lib ./lib
42+
COPY --from=builder /app/package.json ./package.json
43+
44+
# This stage can be used to run migrations
45+
# Run with: docker build --target migrator -t myapp-migrator .
46+
# Then: docker run --env DATABASE_URL=xxx myapp-migrator pnpm db:push
47+
48+
# Stage 3: Runner
49+
FROM node:25-alpine AS runner
50+
WORKDIR /app
51+
52+
ENV NODE_ENV=production
53+
ENV NEXT_TELEMETRY_DISABLED=1
54+
55+
# Create non-root user
56+
RUN addgroup --system --gid 1001 nodejs
57+
RUN adduser --system --uid 1001 nextjs
58+
59+
# Copy built application
60+
COPY --from=builder /app/public ./public
61+
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
62+
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
63+
64+
# Switch to non-root user
65+
USER nextjs
66+
67+
# Expose port
68+
EXPOSE 3000
69+
70+
# Health check
71+
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
72+
CMD curl -f http://localhost:3000/ || exit 1
73+
74+
# Start the application
75+
CMD ["node", "server.js"]

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,7 @@ This template is built on top of Workflow DevKit, a powerful workflow execution
284284
- Built-in logging and error handling
285285
- Serverless deployment support
286286

287-
Learn more about Workflow DevKit at [workflow.dev](https://useworkflow.dev)
287+
Learn more about Workflow DevKit at [useworkflow.dev](https://useworkflow.dev)
288288

289289
## License
290290

app/api/api-keys/[keyId]/route.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { and, eq } from "drizzle-orm";
2+
import { NextResponse } from "next/server";
3+
import { auth } from "@/lib/auth";
4+
import { db } from "@/lib/db";
5+
import { apiKeys } from "@/lib/db/schema";
6+
7+
// DELETE - Delete an API key
8+
export async function DELETE(
9+
request: Request,
10+
context: { params: Promise<{ keyId: string }> }
11+
) {
12+
try {
13+
const { keyId } = await context.params;
14+
const session = await auth.api.getSession({
15+
headers: request.headers,
16+
});
17+
18+
if (!session?.user) {
19+
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
20+
}
21+
22+
// Delete the key (only if it belongs to the user)
23+
const result = await db
24+
.delete(apiKeys)
25+
.where(and(eq(apiKeys.id, keyId), eq(apiKeys.userId, session.user.id)))
26+
.returning({ id: apiKeys.id });
27+
28+
if (result.length === 0) {
29+
return NextResponse.json({ error: "API key not found" }, { status: 404 });
30+
}
31+
32+
return NextResponse.json({ success: true });
33+
} catch (error) {
34+
console.error("Failed to delete API key:", error);
35+
return NextResponse.json(
36+
{ error: "Failed to delete API key" },
37+
{ status: 500 }
38+
);
39+
}
40+
}

0 commit comments

Comments
 (0)