Skip to content

Commit 570c227

Browse files
committed
Added PR check CI/CD and image build CI/CD. Fixed issue where kubernetes factory failed to synchronize when user kubeconfig was updated.
1 parent 6437d2d commit 570c227

File tree

7 files changed

+342
-33
lines changed

7 files changed

+342
-33
lines changed

.env.template

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ DATABASE_URL=""
33
# NextAuth Configuration
44
NEXTAUTH_URL=""
55
NEXTAUTH_SECRET=""
6+
AUTH_TRUST_HOST="true"
67

78
# GitHub OAuth (replace with your actual values)
89
GITHUB_CLIENT_ID=""
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
name: Docker Build and Push
2+
3+
permissions:
4+
contents: read
5+
packages: write
6+
7+
on:
8+
push:
9+
branches: [main, master]
10+
workflow_dispatch:
11+
inputs:
12+
push_to_registry:
13+
description: "Push to Docker registry"
14+
required: false
15+
default: true
16+
type: boolean
17+
18+
env:
19+
DOCKER_IMAGE: ${{ vars.DOCKERHUB_USERNAME || 'defaultuser' }}/fullstack-agent
20+
REGISTRY_GHCR: ghcr.io
21+
22+
jobs:
23+
build-and-push:
24+
name: Build and Push Docker Image
25+
runs-on: ubuntu-latest
26+
27+
steps:
28+
- name: Checkout code
29+
uses: actions/checkout@v4
30+
31+
- name: Set up QEMU
32+
uses: docker/setup-qemu-action@v3
33+
34+
- name: Set up Docker Buildx
35+
uses: docker/setup-buildx-action@v3
36+
37+
- name: Login to Docker Hub
38+
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.push_to_registry)
39+
uses: docker/login-action@v3
40+
with:
41+
username: ${{ vars.DOCKERHUB_USERNAME }}
42+
password: ${{ secrets.DOCKERHUB_TOKEN }}
43+
44+
- name: Login to GitHub Container Registry
45+
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.push_to_registry)
46+
uses: docker/login-action@v3
47+
with:
48+
registry: ${{ env.REGISTRY_GHCR }}
49+
username: ${{ github.actor }}
50+
password: ${{ secrets.GITHUB_TOKEN }}
51+
52+
- name: Extract metadata
53+
id: meta
54+
uses: docker/metadata-action@v5
55+
with:
56+
images: |
57+
${{ env.DOCKER_IMAGE }}
58+
${{ env.REGISTRY_GHCR }}/${{ github.repository }}
59+
tags: |
60+
type=ref,event=branch
61+
type=sha,prefix=sha-
62+
type=semver,pattern={{version}}
63+
type=semver,pattern={{major}}.{{minor}}
64+
type=raw,value=latest,enable={{is_default_branch}}
65+
labels: |
66+
org.opencontainers.image.title=FullStack Agent
67+
org.opencontainers.image.description=Full Stack Development Agent
68+
org.opencontainers.image.vendor=${{ github.repository_owner }}
69+
70+
- name: Build and push multi-platform image
71+
uses: docker/build-push-action@v6
72+
with:
73+
context: .
74+
file: ./Dockerfile
75+
platforms: linux/amd64,linux/arm64
76+
push: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.push_to_registry) }}
77+
tags: ${{ steps.meta.outputs.tags }}
78+
labels: ${{ steps.meta.outputs.labels }}
79+
cache-from: |
80+
type=gha,scope=build-amd64
81+
type=gha,scope=build-arm64
82+
cache-to: type=gha,mode=max,scope=build-multiplatform
83+
provenance: true
84+
sbom: true
85+
86+
- name: Generate build summary
87+
if: always()
88+
run: |
89+
echo "## 🚀 Docker Build & Push Report" >> $GITHUB_STEP_SUMMARY
90+
echo "" >> $GITHUB_STEP_SUMMARY
91+
echo "### Build Status" >> $GITHUB_STEP_SUMMARY
92+
if [ "${{ job.status }}" = "success" ]; then
93+
echo "- ✅ Multi-platform build successful" >> $GITHUB_STEP_SUMMARY
94+
echo "- ✅ Platforms: \`linux/amd64\`, \`linux/arm64\`" >> $GITHUB_STEP_SUMMARY
95+
if [ "${{ github.event_name }}" = "push" ] || [ "${{ inputs.push_to_registry }}" = "true" ]; then
96+
echo "- ✅ Pushed to Docker Hub: \`${{ env.DOCKER_IMAGE }}\`" >> $GITHUB_STEP_SUMMARY
97+
echo "- ✅ Pushed to GHCR: \`${{ env.REGISTRY_GHCR }}/${{ github.repository }}\`" >> $GITHUB_STEP_SUMMARY
98+
fi
99+
else
100+
echo "- ❌ Build failed" >> $GITHUB_STEP_SUMMARY
101+
fi
102+
echo "" >> $GITHUB_STEP_SUMMARY
103+
echo "### Build Information" >> $GITHUB_STEP_SUMMARY
104+
echo "- **Commit SHA**: \`${{ github.sha }}\`" >> $GITHUB_STEP_SUMMARY
105+
echo "- **Branch**: \`${{ github.ref_name }}\`" >> $GITHUB_STEP_SUMMARY
106+
echo "- **Triggered by**: @${{ github.actor }}" >> $GITHUB_STEP_SUMMARY
107+
echo "- **Event**: \`${{ github.event_name }}\`" >> $GITHUB_STEP_SUMMARY
108+
echo "- **Build time**: $(date '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY
109+
echo "" >> $GITHUB_STEP_SUMMARY
110+
echo "### Image Tags" >> $GITHUB_STEP_SUMMARY
111+
echo '```' >> $GITHUB_STEP_SUMMARY
112+
echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY
113+
echo '```' >> $GITHUB_STEP_SUMMARY
114+
115+
- name: Test image (quick smoke test)
116+
if: success()
117+
run: |
118+
echo "### 🧪 Image Test" >> $GITHUB_STEP_SUMMARY
119+
echo "Running quick smoke test on built image..." >> $GITHUB_STEP_SUMMARY
120+
# Pull the image we just built (from cache/local)
121+
docker images | head -n 5
122+
echo "" >> $GITHUB_STEP_SUMMARY
123+
echo "- ✅ Image built successfully and available locally" >> $GITHUB_STEP_SUMMARY

.github/workflows/pr-check.yml

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
name: PR Check
2+
3+
permissions:
4+
contents: read
5+
pull-requests: write
6+
7+
on:
8+
pull_request:
9+
branches: [main, master, develop]
10+
types: [opened, synchronize, reopened]
11+
12+
env:
13+
NODE_VERSION: "22.9.0"
14+
PNPM_VERSION: "10.20.0"
15+
16+
jobs:
17+
lint-and-build:
18+
name: Lint and Build Check
19+
runs-on: ubuntu-latest
20+
21+
steps:
22+
- name: Checkout code
23+
uses: actions/checkout@v4
24+
25+
- name: Setup pnpm
26+
uses: pnpm/action-setup@v4
27+
with:
28+
version: ${{ env.PNPM_VERSION }}
29+
30+
- name: Setup Node.js
31+
uses: actions/setup-node@v4
32+
with:
33+
node-version: ${{ env.NODE_VERSION }}
34+
cache: "pnpm"
35+
36+
- name: Install dependencies
37+
run: pnpm install --frozen-lockfile
38+
39+
- name: Run linter
40+
run: pnpm run lint
41+
continue-on-error: false
42+
43+
- name: Build project
44+
run: pnpm run build
45+
continue-on-error: false
46+
env:
47+
NEXT_TELEMETRY_DISABLED: 1
48+
49+
- name: Generate build summary
50+
if: always()
51+
run: |
52+
echo "## 🏗️ Build & Lint Report" >> $GITHUB_STEP_SUMMARY
53+
echo "" >> $GITHUB_STEP_SUMMARY
54+
echo "### Build Status" >> $GITHUB_STEP_SUMMARY
55+
echo "| Check | Status |" >> $GITHUB_STEP_SUMMARY
56+
echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY
57+
if [ "${{ job.status }}" = "success" ]; then
58+
echo "| Lint | ✅ Passed |" >> $GITHUB_STEP_SUMMARY
59+
echo "| Build | ✅ Passed |" >> $GITHUB_STEP_SUMMARY
60+
else
61+
echo "| Lint | ❌ Failed |" >> $GITHUB_STEP_SUMMARY
62+
echo "| Build | ❌ Failed |" >> $GITHUB_STEP_SUMMARY
63+
fi
64+
echo "" >> $GITHUB_STEP_SUMMARY
65+
echo "### Details" >> $GITHUB_STEP_SUMMARY
66+
echo "- **Commit**: \`${{ github.event.pull_request.head.sha }}\`" >> $GITHUB_STEP_SUMMARY
67+
echo "- **Branch**: \`${{ github.head_ref }}\`" >> $GITHUB_STEP_SUMMARY
68+
echo "- **Author**: @${{ github.actor }}" >> $GITHUB_STEP_SUMMARY
69+
70+
docker-build-test:
71+
name: Docker Build Test
72+
runs-on: ubuntu-latest
73+
needs: lint-and-build
74+
75+
steps:
76+
- name: Checkout code
77+
uses: actions/checkout@v4
78+
79+
- name: Set up Docker Buildx
80+
uses: docker/setup-buildx-action@v3
81+
82+
- name: Extract metadata
83+
id: meta
84+
uses: docker/metadata-action@v5
85+
with:
86+
images: fullstack-agent
87+
tags: |
88+
type=ref,event=pr
89+
type=sha,prefix=sha-
90+
91+
- name: Build Docker image (AMD64 only for PR)
92+
uses: docker/build-push-action@v6
93+
with:
94+
context: .
95+
file: ./Dockerfile
96+
platforms: linux/amd64
97+
push: false
98+
tags: ${{ steps.meta.outputs.tags }}
99+
labels: ${{ steps.meta.outputs.labels }}
100+
cache-from: type=gha,scope=pr-amd64
101+
cache-to: type=gha,mode=max,scope=pr-amd64
102+
provenance: false
103+
sbom: false
104+
105+
- name: Generate Docker build summary
106+
if: always()
107+
run: |
108+
echo "## 🐳 Docker Build Report" >> $GITHUB_STEP_SUMMARY
109+
echo "" >> $GITHUB_STEP_SUMMARY
110+
echo "### Build Status" >> $GITHUB_STEP_SUMMARY
111+
if [ "${{ job.status }}" = "success" ]; then
112+
echo "- ✅ Docker image build successful" >> $GITHUB_STEP_SUMMARY
113+
echo "- ✅ Platform: \`linux/amd64\`" >> $GITHUB_STEP_SUMMARY
114+
echo "- ✅ Cache optimization enabled" >> $GITHUB_STEP_SUMMARY
115+
else
116+
echo "- ❌ Docker image build failed" >> $GITHUB_STEP_SUMMARY
117+
echo "" >> $GITHUB_STEP_SUMMARY
118+
echo "### Troubleshooting Tips" >> $GITHUB_STEP_SUMMARY
119+
echo "- Check Dockerfile syntax" >> $GITHUB_STEP_SUMMARY
120+
echo "- Verify dependency versions" >> $GITHUB_STEP_SUMMARY
121+
echo "- Review build context" >> $GITHUB_STEP_SUMMARY
122+
fi
123+
124+
pr-comment:
125+
name: Comment PR Results
126+
runs-on: ubuntu-latest
127+
needs: [lint-and-build, docker-build-test]
128+
if: always()
129+
130+
steps:
131+
- name: Comment on PR
132+
uses: actions/github-script@v7
133+
with:
134+
script: |
135+
const lintBuildResult = '${{ needs.lint-and-build.result }}';
136+
const dockerResult = '${{ needs.docker-build-test.result }}';
137+
const prNumber = context.payload.pull_request.number;
138+
139+
let allPassed = lintBuildResult === 'success' && dockerResult === 'success';
140+
let emoji = allPassed ? '✅' : '❌';
141+
let status = allPassed ? 'Passed' : 'Failed';
142+
143+
let body = `## ${emoji} PR Check Results: ${status}\n\n`;
144+
body += `### Build Checks\n\n`;
145+
body += `| Check | Status |\n`;
146+
body += `|-------|--------|\n`;
147+
body += `| Lint & Build | ${lintBuildResult === 'success' ? '✅ Passed' : '❌ Failed'} |\n`;
148+
body += `| Docker Build | ${dockerResult === 'success' ? '✅ Passed' : '❌ Failed'} |\n\n`;
149+
150+
if (allPassed) {
151+
body += `### ✨ Great work!\n\n`;
152+
body += `All checks passed successfully. Your PR is ready for review.\n\n`;
153+
body += `**Details:**\n`;
154+
body += `- ✅ Code quality verified (linting passed)\n`;
155+
body += `- ✅ Build successful\n`;
156+
body += `- ✅ Docker image build verified (linux/amd64)\n`;
157+
} else {
158+
body += `### ⚠️ Action Required\n\n`;
159+
body += `Some checks failed. Please review the errors and update your PR.\n\n`;
160+
if (lintBuildResult !== 'success') {
161+
body += `**Lint/Build Issues:**\n`;
162+
body += `- Check the "Lint and Build Check" job for details\n`;
163+
body += `- Fix linting errors with \`pnpm run lint:fix\`\n`;
164+
body += `- Ensure the project builds locally with \`pnpm run build\`\n\n`;
165+
}
166+
if (dockerResult !== 'success') {
167+
body += `**Docker Build Issues:**\n`;
168+
body += `- Check the "Docker Build Test" job for details\n`;
169+
body += `- Verify Dockerfile changes\n`;
170+
body += `- Test Docker build locally\n\n`;
171+
}
172+
}
173+
174+
body += `**Commit:** \`${{ github.event.pull_request.head.sha }}\`\n`;
175+
body += `**Branch:** \`${{ github.head_ref }}\`\n`;
176+
177+
const { data: comments } = await github.rest.issues.listComments({
178+
owner: context.repo.owner,
179+
repo: context.repo.repo,
180+
issue_number: prNumber,
181+
});
182+
183+
const botComment = comments.find(comment =>
184+
comment.user.type === 'Bot' &&
185+
comment.body.includes('PR Check Results')
186+
);
187+
188+
if (botComment) {
189+
await github.rest.issues.updateComment({
190+
owner: context.repo.owner,
191+
repo: context.repo.repo,
192+
comment_id: botComment.id,
193+
body: body
194+
});
195+
} else {
196+
await github.rest.issues.createComment({
197+
owner: context.repo.owner,
198+
repo: context.repo.repo,
199+
issue_number: prNumber,
200+
body: body
201+
});
202+
}

app/api/projects/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export const POST = withAuth<PostProjectResponse>(async (req, _context, session)
7171

7272
// Generate K8s compatible names
7373
const k8sProjectName = KubernetesUtils.toK8sProjectName(name)
74-
const randomSuffix = KubernetesUtils.generateRandomString(8)
74+
const randomSuffix = KubernetesUtils.generateRandomString()
7575
const databaseName = `${k8sProjectName}-${randomSuffix}`
7676
const sandboxName = `${k8sProjectName}-${randomSuffix}`
7777

0 commit comments

Comments
 (0)