Skip to content

feat: Added PR check CI/CD and image build CI/CD #2

feat: Added PR check CI/CD and image build CI/CD

feat: Added PR check CI/CD and image build CI/CD #2

Workflow file for this run

name: PR Check
permissions:
contents: read
pull-requests: write
issues: write
on:
pull_request:
branches: [main, master, develop]
types: [opened, synchronize, reopened]
env:
NODE_VERSION: "22.9.0"
PNPM_VERSION: "10.20.0"
jobs:
lint-and-build:
name: Lint and Build Check
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: "pnpm"
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Run linter
run: pnpm run lint
continue-on-error: false
- name: Build project
run: pnpm run build
continue-on-error: false
env:
NEXT_TELEMETRY_DISABLED: 1
- name: Generate build summary
if: always()
run: |
echo "## 🏗️ Build & Lint Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Build Status" >> $GITHUB_STEP_SUMMARY
echo "| Check | Status |" >> $GITHUB_STEP_SUMMARY
echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY
if [ "${{ job.status }}" = "success" ]; then
echo "| Lint | ✅ Passed |" >> $GITHUB_STEP_SUMMARY
echo "| Build | ✅ Passed |" >> $GITHUB_STEP_SUMMARY
else
echo "| Lint | ❌ Failed |" >> $GITHUB_STEP_SUMMARY
echo "| Build | ❌ Failed |" >> $GITHUB_STEP_SUMMARY
fi
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Details" >> $GITHUB_STEP_SUMMARY
echo "- **Commit**: \`${{ github.event.pull_request.head.sha }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Branch**: \`${{ github.head_ref }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Author**: @${{ github.actor }}" >> $GITHUB_STEP_SUMMARY
docker-build-test:
name: Docker Build Test
runs-on: ubuntu-latest
needs: lint-and-build
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: fullstack-agent
tags: |
type=ref,event=pr
type=sha,prefix=sha-
- name: Build Docker image (AMD64 only for PR)
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
platforms: linux/amd64
push: false
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha,scope=pr-amd64
cache-to: type=gha,mode=max,scope=pr-amd64
provenance: false
sbom: false
- name: Generate Docker build summary
if: always()
run: |
echo "## 🐳 Docker Build Report" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Build Status" >> $GITHUB_STEP_SUMMARY
if [ "${{ job.status }}" = "success" ]; then
echo "- ✅ Docker image build successful" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Platform: \`linux/amd64\`" >> $GITHUB_STEP_SUMMARY
echo "- ✅ Cache optimization enabled" >> $GITHUB_STEP_SUMMARY
else
echo "- ❌ Docker image build failed" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "### Troubleshooting Tips" >> $GITHUB_STEP_SUMMARY
echo "- Check Dockerfile syntax" >> $GITHUB_STEP_SUMMARY
echo "- Verify dependency versions" >> $GITHUB_STEP_SUMMARY
echo "- Review build context" >> $GITHUB_STEP_SUMMARY
fi
pr-comment:
name: Comment PR Results
runs-on: ubuntu-latest
needs: [lint-and-build, docker-build-test]
if: always()
steps:
- name: Comment on PR
uses: actions/github-script@v7
with:
script: |
// Security: Use context object instead of direct template injection to prevent script injection
const lintBuildResult = '${{ needs.lint-and-build.result }}';
const dockerResult = '${{ needs.docker-build-test.result }}';
const prNumber = context.payload.pull_request.number;
const commitSha = context.payload.pull_request.head.sha;
const branchName = context.payload.pull_request.head.ref;
let allPassed = lintBuildResult === 'success' && dockerResult === 'success';
let emoji = allPassed ? '✅' : '❌';
let status = allPassed ? 'Passed' : 'Failed';
let body = `## ${emoji} PR Check Results: ${status}\n\n`;
body += `### Build Checks\n\n`;
body += `| Check | Status |\n`;
body += `|-------|--------|\n`;
body += `| Lint & Build | ${lintBuildResult === 'success' ? '✅ Passed' : '❌ Failed'} |\n`;
body += `| Docker Build | ${dockerResult === 'success' ? '✅ Passed' : '❌ Failed'} |\n\n`;
if (allPassed) {
body += `### ✨ Great work!\n\n`;
body += `All checks passed successfully. Your PR is ready for review.\n\n`;
body += `**Details:**\n`;
body += `- ✅ Code quality verified (linting passed)\n`;
body += `- ✅ Build successful\n`;
body += `- ✅ Docker image build verified (linux/amd64)\n`;
} else {
body += `### ⚠️ Action Required\n\n`;
body += `Some checks failed. Please review the errors and update your PR.\n\n`;
if (lintBuildResult !== 'success') {
body += `**Lint/Build Issues:**\n`;
body += `- Check the "Lint and Build Check" job for details\n`;
body += `- Fix linting errors with \`pnpm run lint:fix\`\n`;
body += `- Ensure the project builds locally with \`pnpm run build\`\n\n`;
}
if (dockerResult !== 'success') {
body += `**Docker Build Issues:**\n`;
body += `- Check the "Docker Build Test" job for details\n`;
body += `- Verify Dockerfile changes\n`;
body += `- Test Docker build locally\n\n`;
}
}
body += `**Commit:** \`${commitSha}\`\n`;
body += `**Branch:** \`${branchName}\`\n`;
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});
const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('PR Check Results')
);
if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: body
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: body
});
}