Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
330 changes: 330 additions & 0 deletions .github/workflows/dev-to-main-pr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,330 @@
name: πŸš€ Dev Branch CI/CD Pipeline

on:
push:
branches: [ dev ]
workflow_dispatch:

env:
NODE_VERSION: '18'

jobs:
code-quality-check:
name: πŸ” Code Quality & Syntax Check
runs-on: ubuntu-latest

outputs:
checks-passed: ${{ steps.quality-check.outputs.passed }}
check-results: ${{ steps.quality-check.outputs.results }}

steps:
- name: πŸ“₯ Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: πŸ“¦ Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'npm'

- name: πŸ“₯ Install dependencies
run: npm ci

- name: πŸ—οΈ Generate Prisma Client
run: npx prisma generate

- name: πŸ” TypeScript Compilation Check
id: typescript-check
run: |
echo "πŸ” Running TypeScript compilation check..."
if npm run type-check; then
echo "βœ… TypeScript compilation successful"
echo "typescript=passed" >> $GITHUB_OUTPUT
else
echo "❌ TypeScript compilation failed"
echo "typescript=failed" >> $GITHUB_OUTPUT
exit 1
fi

- name: πŸ—οΈ Build Check
id: build-check
run: |
echo "πŸ—οΈ Running build check..."
if npm run build; then
echo "βœ… Build successful"
echo "build=passed" >> $GITHUB_OUTPUT
else
echo "❌ Build failed"
echo "build=failed" >> $GITHUB_OUTPUT
exit 1
fi

- name: πŸ“‹ Code Quality Summary
id: quality-check
run: |
echo "πŸ“‹ Generating code quality summary..."

# Get commit info
COMMIT_SHA="${{ github.sha }}"
COMMIT_MSG=$(git log -1 --pretty=format:"%s" $COMMIT_SHA)
COMMIT_AUTHOR=$(git log -1 --pretty=format:"%an" $COMMIT_SHA)

# Get changed files
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD | tr '\n' ',' | sed 's/,$//')

# Create summary
SUMMARY="βœ… All code quality checks passed!

πŸ“Š **Check Results:**
- βœ… TypeScript Compilation: Passed
- βœ… Build Process: Passed

πŸ“ **Commit Info:**
- SHA: \`${COMMIT_SHA:0:7}\`
- Message: ${COMMIT_MSG}
- Author: ${COMMIT_AUTHOR}

πŸ“ **Changed Files:** ${CHANGED_FILES}"

echo "passed=true" >> $GITHUB_OUTPUT
echo "results<<EOF" >> $GITHUB_OUTPUT
echo "$SUMMARY" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

create-pull-request:
name: πŸ€– Create AI-Generated Pull Request
runs-on: ubuntu-latest
needs: code-quality-check
if: needs.code-quality-check.outputs.checks-passed == 'true'

steps:
- name: πŸ“₯ Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: πŸ€– Generate PR Content with AI
id: generate-pr
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
run: |
echo "πŸ€– Generating AI-powered PR content..."

# Get commit info and diff
COMMIT_SHA="${{ github.sha }}"
COMMIT_MSG=$(git log -1 --pretty=format:"%s" $COMMIT_SHA)
COMMIT_AUTHOR=$(git log -1 --pretty=format:"%an" $COMMIT_SHA)
COMMIT_DATE=$(git log -1 --pretty=format:"%ci" $COMMIT_SHA)

# Get detailed diff (limited to avoid too large payload)
GIT_DIFF=$(git diff HEAD~1 HEAD --unified=3 | head -c 3000)

# Get changed files with stats
CHANGED_FILES=$(git diff --stat HEAD~1 HEAD)

# Check if OpenAI API key is available
if [ -z "$OPENAI_API_KEY" ]; then
echo "⚠️ OpenAI API key not found, using fallback PR content"
PR_TITLE="πŸš€ Dev β†’ Main: ${COMMIT_MSG}"
PR_BODY="**Summary:** ${COMMIT_MSG}

**Code Quality Status:**
${{ needs.code-quality-check.outputs.check-results }}

**Changed Files:**
${CHANGED_FILES}

**Auto-generated PR from dev branch** πŸ€–

> Note: Add OPENAI_API_KEY secret for AI-generated descriptions"
else
echo "πŸ”‘ OpenAI API key found, generating AI content..."

# Create AI prompt
AI_PROMPT="You are a senior software engineer reviewing code changes for a Node.js/TypeScript candidate matching API.

Generate a professional pull request description based on this information:

**Commit Information:**
- Message: ${COMMIT_MSG}
- Author: ${COMMIT_AUTHOR}
- Date: ${COMMIT_DATE}
- SHA: ${COMMIT_SHA:0:7}

**Files Changed:**
${CHANGED_FILES}

**Code Diff (truncated):**
${GIT_DIFF}

Please generate:
1. A clear, professional PR title
2. A comprehensive PR description with:
- Summary of changes
- Technical details
- Testing status
- Any breaking changes
- Code quality improvements

Format the response as JSON with 'title' and 'body' fields. Make it professional and detailed."

# Call OpenAI API with error handling
PR_CONTENT=$(curl -s -w "%{http_code}" -X POST "https://api.openai.com/v1/chat/completions" \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"model\": \"gpt-4\",
\"messages\": [
{
\"role\": \"system\",
\"content\": \"You are a senior software engineer who writes excellent pull request descriptions. Always respond with valid JSON containing 'title' and 'body' fields.\"
},
{
\"role\": \"user\",
\"content\": $(echo "$AI_PROMPT" | jq -R -s .)
}
],
\"max_tokens\": 1000,
\"temperature\": 0.3
}")

# Extract HTTP status code
HTTP_STATUS=$(echo "$PR_CONTENT" | tail -c 4)
PR_RESPONSE=$(echo "$PR_CONTENT" | head -c -4)

echo "πŸ“ OpenAI API Response Status: $HTTP_STATUS"

if [ "$HTTP_STATUS" = "200" ]; then
echo "βœ… AI Response received successfully"
# Extract title and body from AI response
AI_CONTENT=$(echo "$PR_RESPONSE" | jq -r '.choices[0].message.content' 2>/dev/null)
PR_TITLE=$(echo "$AI_CONTENT" | jq -r '.title' 2>/dev/null || echo "πŸš€ Dev β†’ Main: ${COMMIT_MSG}")
PR_BODY=$(echo "$AI_CONTENT" | jq -r '.body' 2>/dev/null || echo "**Summary:** ${COMMIT_MSG}

**Code Quality Status:**
${{ needs.code-quality-check.outputs.check-results }}

**Auto-generated PR from dev branch** πŸ€–")
else
echo "❌ OpenAI API call failed with status $HTTP_STATUS"
echo "Response: $PR_RESPONSE"
# Fallback content
PR_TITLE="πŸš€ Dev β†’ Main: ${COMMIT_MSG}"
PR_BODY="**Summary:** ${COMMIT_MSG}

**Code Quality Status:**
${{ needs.code-quality-check.outputs.check-results }}

**Changed Files:**
${CHANGED_FILES}

**Auto-generated PR from dev branch** πŸ€–

> Note: AI generation failed, using fallback content"
fi
fi

# Set outputs
echo "title<<EOF" >> $GITHUB_OUTPUT
echo "$PR_TITLE" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

echo "body<<EOF" >> $GITHUB_OUTPUT
echo "$PR_BODY" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

- name: πŸ”„ Create Pull Request
id: create-pr
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "πŸ”„ Creating pull request from dev to main..."

# Check if PR already exists
EXISTING_PR=$(gh pr list --base main --head dev --json number --jq '.[0].number' 2>/dev/null || echo "")

if [ -n "$EXISTING_PR" ]; then
echo "πŸ“ Updating existing PR #$EXISTING_PR"
gh pr edit $EXISTING_PR \
--title "${{ steps.generate-pr.outputs.title }}" \
--body "${{ steps.generate-pr.outputs.body }}

---

πŸ€– **Auto-generated Pull Request**
- πŸ“Š **Pipeline Run:** #${{ github.run_number }}
- πŸ”— **Workflow:** [${{ github.workflow }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
- πŸ“… **Updated:** $(date -u)
- πŸ‘€ **Triggered by:** ${{ github.event.head_commit.author.name }}

**Code Quality Checks:**
${{ needs.code-quality-check.outputs.check-results }}"

echo "pull-request-number=$EXISTING_PR" >> $GITHUB_OUTPUT
echo "pull-request-url=$(gh pr view $EXISTING_PR --json url --jq '.url')" >> $GITHUB_OUTPUT
else
echo "πŸ†• Creating new pull request"
PR_URL=$(gh pr create \
--base main \
--head dev \
--title "${{ steps.generate-pr.outputs.title }}" \
--body "${{ steps.generate-pr.outputs.body }}

---

πŸ€– **Auto-generated Pull Request**
- πŸ“Š **Pipeline Run:** #${{ github.run_number }}
- πŸ”— **Workflow:** [${{ github.workflow }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
- πŸ“… **Created:** $(date -u)
- πŸ‘€ **Triggered by:** ${{ github.event.head_commit.author.name }}

**Code Quality Checks:**
${{ needs.code-quality-check.outputs.check-results }}")

PR_NUMBER=$(echo "$PR_URL" | sed 's/.*\/pull\///')
echo "pull-request-number=$PR_NUMBER" >> $GITHUB_OUTPUT
echo "pull-request-url=$PR_URL" >> $GITHUB_OUTPUT
fi

- name: πŸ‘₯ Assign Reviewers
if: steps.create-pr.outputs.pull-request-number
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "πŸ‘₯ Assigning reviewers to PR #${{ steps.create-pr.outputs.pull-request-number }}"

# Try to assign github-actions bot as reviewer (if available)
# Note: You may need to replace this with actual usernames that have access to your repo
gh pr edit ${{ steps.create-pr.outputs.pull-request-number }} \
--add-reviewer firatyll \
--add-label "auto-generated,dev-to-main,code-review-needed" || echo "Could not assign reviewers"

- name: πŸ“ Comment on PR
if: steps.create-pr.outputs.pull-request-number
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr comment ${{ steps.create-pr.outputs.pull-request-number }} --body "πŸ€– **Automated PR Creation Complete!**

βœ… **Code Quality Checks Passed:**
- TypeScript compilation
- Build process
- Syntax validation

πŸ” **Review Checklist:**
- [ ] Code changes are logical and well-structured
- [ ] No breaking changes introduced
- [ ] API endpoints function correctly
- [ ] Database schema changes are safe
- [ ] Error handling is appropriate

πŸš€ **Ready for review!** @firatyll"

- name: πŸ“’ Summary
run: |
echo "πŸŽ‰ Workflow completed successfully!"
echo "πŸ“ Pull Request: ${{ steps.create-pr.outputs.pull-request-url }}"
echo "πŸ”’ PR Number: ${{ steps.create-pr.outputs.pull-request-number }}"
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
# Candidate Matching API

[![Dev to Main PR](https://github.com/firatyll/candidate-matching/actions/workflows/dev-to-main-pr.yml/badge.svg)](https://github.com/firatyll/candidate-matching/actions/workflows/dev-to-main-pr.yml)

> **Note: This application is currently under active development. Features and API endpoints may change.**

A RESTful API service for candidate and job position matching built with Node.js, Express, TypeScript, Prisma, and PostgreSQL.

## πŸš€ CI/CD Pipeline

This repository includes an automated GitHub Actions pipeline that:
- βœ… Runs code quality checks on every push to `dev` branch
- πŸ€– Generates AI-powered pull requests using OpenAI GPT-4
- πŸ“‹ Automatically assigns reviewers and adds helpful labels
- πŸ” Includes comprehensive review checklists

See [Pipeline Setup Guide](./.github/PIPELINE_SETUP.md) for configuration details.

## Features

- **Candidate Management**: Create, read, update, and delete candidate profiles
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
"prestart": "npm run build",
"serve": "npm run build && npm start",
"type-check": "tsc --noEmit",
"lint": "echo 'No linter configured yet'",
"lint": "tsc --noEmit --strict && echo 'βœ… TypeScript strict mode check passed'",
"lint:check": "npm run type-check",
"validate": "npm run lint && npm run build",
"test": "echo 'No tests configured yet'"
},
"keywords": [],
Expand Down