Skip to content

Commit b284d5f

Browse files
authored
Create validate-application.yml
1 parent b69db44 commit b284d5f

File tree

1 file changed

+295
-0
lines changed

1 file changed

+295
-0
lines changed
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
name: Validate Application
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- 'applications/2025/pending/*.yml'
7+
types:
8+
- opened
9+
- synchronize
10+
- reopened
11+
12+
jobs:
13+
validate:
14+
runs-on: ubuntu-latest
15+
permissions:
16+
pull-requests: write
17+
issues: write
18+
contents: read
19+
20+
steps:
21+
- name: Checkout code
22+
uses: actions/checkout@v3
23+
with:
24+
fetch-depth: 0
25+
26+
- name: Set up Python
27+
uses: actions/setup-python@v4
28+
with:
29+
python-version: '3.9'
30+
cache: 'pip'
31+
32+
- name: Install dependencies
33+
run: |
34+
python -m pip install --upgrade pip
35+
pip install pyyaml jsonschema
36+
37+
- name: Get changed files
38+
id: changed-files
39+
run: |
40+
# Get list of changed application files
41+
echo "Checking for application files in PR..."
42+
43+
# Get changed files between base and head
44+
CHANGED_FILES=$(git diff --name-only origin/main...HEAD | grep "applications/2025/pending/.*\.yml$" || true)
45+
46+
if [ -z "$CHANGED_FILES" ]; then
47+
echo "❌ No application files found in this PR"
48+
exit 1
49+
fi
50+
51+
echo "Found application files:"
52+
echo "$CHANGED_FILES"
53+
54+
# Count number of application files
55+
FILE_COUNT=$(echo "$CHANGED_FILES" | wc -l)
56+
echo "file_count=$FILE_COUNT" >> $GITHUB_OUTPUT
57+
58+
# Get the first file for validation
59+
FIRST_FILE=$(echo "$CHANGED_FILES" | head -n 1)
60+
echo "first_file=$FIRST_FILE" >> $GITHUB_OUTPUT
61+
62+
# Extract username from filename
63+
USERNAME=$(basename "$FIRST_FILE" .yml)
64+
echo "username=$USERNAME" >> $GITHUB_OUTPUT
65+
66+
- name: Check single application per PR
67+
run: |
68+
if [ "${{ steps.changed-files.outputs.file_count }}" -gt 1 ]; then
69+
echo "❌ Error: Multiple application files detected!"
70+
echo "Please submit only one application per pull request."
71+
exit 1
72+
fi
73+
74+
- name: Validate YAML syntax
75+
run: |
76+
echo "📋 Validating YAML syntax..."
77+
python -c "
78+
import yaml
79+
import sys
80+
81+
try:
82+
with open('${{ steps.changed-files.outputs.first_file }}', 'r') as f:
83+
data = yaml.safe_load(f)
84+
print('✅ YAML syntax is valid')
85+
except yaml.YAMLError as e:
86+
print(f'❌ YAML syntax error: {e}')
87+
sys.exit(1)
88+
"
89+
90+
- name: Validate application format
91+
id: validate
92+
run: |
93+
echo "🔍 Validating application requirements..."
94+
95+
# Create a simple validation script inline
96+
cat > validate_temp.py << 'EOF'
97+
import yaml
98+
import sys
99+
import re
100+
import os
101+
102+
def validate_application(file_path):
103+
errors = []
104+
warnings = []
105+
106+
try:
107+
with open(file_path, 'r') as f:
108+
data = yaml.safe_load(f)
109+
except Exception as e:
110+
errors.append(f"Failed to parse YAML: {e}")
111+
return errors, warnings
112+
113+
# Check required sections
114+
required_sections = ['essentials', 'genai_mastery', 'tech_stack_alignment',
115+
'shipping_velocity', 'availability']
116+
for section in required_sections:
117+
if section not in data or data[section] is None:
118+
errors.append(f"Missing required section: {section}")
119+
120+
# Check essential fields
121+
if 'essentials' in data and data['essentials']:
122+
essentials = data['essentials']
123+
required_fields = ['github_username', 'email', 'full_name']
124+
for field in required_fields:
125+
if not essentials.get(field):
126+
errors.append(f"Missing required field: essentials.{field}")
127+
128+
# Validate email format
129+
email = essentials.get('email', '')
130+
email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
131+
if email and not re.match(email_pattern, email):
132+
errors.append("Invalid email format")
133+
134+
# Validate GitHub username format
135+
username = essentials.get('github_username', '')
136+
username_pattern = r'^[a-zA-Z0-9](?:[a-zA-Z0-9]|-(?=[a-zA-Z0-9])){0,38}$'
137+
if username and not re.match(username_pattern, username):
138+
errors.append("Invalid GitHub username format")
139+
140+
# Check file naming
141+
expected_filename = f"{username}.yml"
142+
actual_filename = os.path.basename(file_path)
143+
if actual_filename != expected_filename:
144+
errors.append(f"File should be named: {expected_filename}")
145+
146+
# Check GenAI section
147+
if 'genai_mastery' in data and data['genai_mastery']:
148+
if not data['genai_mastery'].get('primary_tools'):
149+
warnings.append("No AI tools listed - this will significantly impact your score")
150+
151+
# Check availability
152+
if 'availability' in data and data['availability']:
153+
if not data['availability'].get('start_date'):
154+
errors.append("Missing required field: availability.start_date")
155+
if not data['availability'].get('commitment_level'):
156+
errors.append("Missing required field: availability.commitment_level")
157+
158+
return errors, warnings
159+
160+
# Run validation
161+
file_path = sys.argv[1]
162+
errors, warnings = validate_application(file_path)
163+
164+
if errors:
165+
print("❌ Validation Failed!\n")
166+
print("Errors:")
167+
for error in errors:
168+
print(f" - {error}")
169+
if warnings:
170+
print("\nWarnings:")
171+
for warning in warnings:
172+
print(f" - {warning}")
173+
sys.exit(1)
174+
else:
175+
print("✅ Validation Passed!")
176+
if warnings:
177+
print("\nWarnings:")
178+
for warning in warnings:
179+
print(f" ⚠️ {warning}")
180+
EOF
181+
182+
python validate_temp.py "${{ steps.changed-files.outputs.first_file }}"
183+
184+
# Clean up
185+
rm validate_temp.py
186+
187+
- name: Check PR title format
188+
run: |
189+
PR_TITLE="${{ github.event.pull_request.title }}"
190+
echo "Checking PR title: $PR_TITLE"
191+
192+
# Check if title contains username
193+
if [[ ! "$PR_TITLE" =~ ${{ steps.changed-files.outputs.username }} ]]; then
194+
echo "⚠️ PR title should include your GitHub username"
195+
fi
196+
197+
- name: Auto-label PR
198+
uses: actions/github-script@v6
199+
with:
200+
script: |
201+
// Add application label
202+
await github.rest.issues.addLabels({
203+
issue_number: context.issue.number,
204+
owner: context.repo.owner,
205+
repo: context.repo.repo,
206+
labels: ['application', 'pending-review']
207+
});
208+
209+
- name: Comment validation success
210+
if: success()
211+
uses: actions/github-script@v6
212+
with:
213+
script: |
214+
const username = '${{ steps.changed-files.outputs.username }}';
215+
216+
const comment = `### ✅ Application Validation Successful!
217+
218+
Thank you for applying to the **Ship-Every-Friday Squad**, @${username}!
219+
220+
Your application has passed initial validation. Here's what happens next:
221+
222+
1. 🤖 **Automated Analysis** - Our bot will analyze your GitHub profile (this may take a few minutes)
223+
2. 📊 **Scoring** - You'll receive a detailed score based on:
224+
- GenAI tool usage (50%)
225+
- Open source contributions (30%)
226+
- Project quality (10%)
227+
- GitHub activity (5%)
228+
- Production readiness (5%)
229+
3. 👀 **Review** - Our team will review your application
230+
4. 🚀 **Decision** - We'll get back to you within 5 business days
231+
232+
**Note**: Thanks to CODEOWNERS, a reviewer has been automatically assigned to your PR.
233+
234+
Good luck! 🍀
235+
236+
---
237+
*If you need to update your application, just push new commits to this PR.*`;
238+
239+
await github.rest.issues.createComment({
240+
issue_number: context.issue.number,
241+
owner: context.repo.owner,
242+
repo: context.repo.repo,
243+
body: comment
244+
});
245+
246+
- name: Comment validation failure
247+
if: failure()
248+
uses: actions/github-script@v6
249+
with:
250+
script: |
251+
const comment = `### ❌ Application Validation Failed
252+
253+
There are some issues with your application that need to be fixed.
254+
255+
Please check the workflow logs above for specific errors and:
256+
1. Fix the identified issues
257+
2. Push the corrected file to this PR
258+
259+
Common issues:
260+
- Missing required fields
261+
- Invalid email format
262+
- Incorrect file naming (should be \`your-github-username.yml\`)
263+
- YAML syntax errors
264+
265+
Need help? Check out our [application guide](https://github.com/${{ github.repository }}/blob/main/HOW_TO_APPLY.md).
266+
267+
---
268+
*The validation will run again automatically when you push updates.*`;
269+
270+
await github.rest.issues.createComment({
271+
issue_number: context.issue.number,
272+
owner: context.repo.owner,
273+
repo: context.repo.repo,
274+
body: comment
275+
});
276+
277+
- name: Set PR status check
278+
if: always()
279+
uses: actions/github-script@v6
280+
with:
281+
script: |
282+
const state = '${{ job.status }}' === 'success' ? 'success' : 'failure';
283+
const description = state === 'success'
284+
? 'Application validation passed'
285+
: 'Application validation failed - check errors';
286+
287+
await github.rest.repos.createCommitStatus({
288+
owner: context.repo.owner,
289+
repo: context.repo.repo,
290+
sha: context.payload.pull_request.head.sha,
291+
state: state,
292+
context: 'Application Validation',
293+
description: description,
294+
target_url: `https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}`
295+
});

0 commit comments

Comments
 (0)