Skip to content

Commit 366afe4

Browse files
author
flowcore-platform
committed
feat(validation): add PR validation prompt for Next.js standards
- Introduced a new markdown prompt file for validating Pull Requests against Flowcore Next.js development standards. - The prompt includes critical rules, context-specific instructions, and a structured validation report format. - Enhanced user guidance by referencing authoritative standards stored in Usable fragments. - Updated scripts to support local testing and validation processes, ensuring compliance with the new prompt. This addition aims to streamline the PR review process and ensure adherence to established development standards.
1 parent bbbf39c commit 366afe4

File tree

7 files changed

+989
-48
lines changed

7 files changed

+989
-48
lines changed

.github/prompts/pr-validation.md

Lines changed: 721 additions & 0 deletions
Large diffs are not rendered by default.

scripts/fetch-prompt.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ main() {
169169
fi
170170
else
171171
# Static prompt file
172+
CUSTOM_PROMPT_FILE="${PROMPT_FILE:-}"
172173
if [ -n "$CUSTOM_PROMPT_FILE" ] && [ -f "$CUSTOM_PROMPT_FILE" ]; then
173174
echo "Using static prompt file: $CUSTOM_PROMPT_FILE"
174175
cp "$CUSTOM_PROMPT_FILE" "$USER_PROMPT_FILE"
@@ -177,6 +178,8 @@ main() {
177178
echo "Size: $(wc -c < "$USER_PROMPT_FILE") bytes"
178179
else
179180
echo "::error::No user prompt file provided or file not found"
181+
echo " PROMPT_FILE: ${PROMPT_FILE:-not set}"
182+
echo " File exists: $([ -f "${PROMPT_FILE:-}" ] && echo "yes" || echo "no")"
180183
exit 1
181184
fi
182185
fi

scripts/setup-gemini.sh

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,30 @@ set -euo pipefail
44
echo "::group::Setting up Gemini Authentication"
55

66
# Get the secret value from the environment using the secret name
7+
# For GitHub Actions, SECRET_NAME is set. For local testing, use default.
8+
SECRET_NAME="${SECRET_NAME:-GEMINI_SERVICE_ACCOUNT_KEY}"
79
SECRET_VALUE="${!SECRET_NAME:-}"
810

911
if [ -z "$SECRET_VALUE" ]; then
1012
echo "::error::Service account key not found in environment variable: $SECRET_NAME"
1113
echo "Please ensure the secret is set in your workflow: env.$SECRET_NAME"
14+
echo "For local testing: export GEMINI_SERVICE_ACCOUNT_KEY='<your-service-account-json>'"
1215
exit 1
1316
fi
1417

15-
# Decode base64-encoded service account key
16-
echo "$SECRET_VALUE" | base64 -d > /tmp/service-account.json
18+
# Handle both base64-encoded (GitHub Actions) and raw JSON (local testing)
19+
# Try to detect if it's already JSON by checking for JSON structure
20+
if [[ "$SECRET_VALUE" =~ ^\{.*\}$ ]] || [[ "$SECRET_VALUE" =~ ^[[:space:]]*\{ ]]; then
21+
# Looks like JSON, write directly
22+
echo "$SECRET_VALUE" > /tmp/service-account.json
23+
else
24+
# Assume base64-encoded, decode it
25+
if ! echo "$SECRET_VALUE" | base64 -d > /tmp/service-account.json 2>/dev/null; then
26+
echo "::error::Failed to decode base64 service account key"
27+
echo "For local testing, use raw JSON: export GEMINI_SERVICE_ACCOUNT_KEY=\$(cat service-account.json)"
28+
exit 1
29+
fi
30+
fi
1731

1832
# Verify JSON format
1933
if ! jq empty /tmp/service-account.json 2>/dev/null; then
@@ -39,11 +53,13 @@ export GOOGLE_GENAI_USE_VERTEXAI="true"
3953
export GOOGLE_CLOUD_PROJECT="$PROJECT_ID"
4054
export GOOGLE_CLOUD_LOCATION="${GOOGLE_CLOUD_LOCATION:-us-central1}"
4155

42-
# Write to GITHUB_ENV for subsequent steps
43-
echo "GOOGLE_APPLICATION_CREDENTIALS=/tmp/service-account.json" >> $GITHUB_ENV
44-
echo "GOOGLE_GENAI_USE_VERTEXAI=true" >> $GITHUB_ENV
45-
echo "GOOGLE_CLOUD_PROJECT=$PROJECT_ID" >> $GITHUB_ENV
46-
echo "GOOGLE_CLOUD_LOCATION=${GOOGLE_CLOUD_LOCATION}" >> $GITHUB_ENV
56+
# Write to GITHUB_ENV for subsequent steps (if in GitHub Actions)
57+
if [ -n "${GITHUB_ENV:-}" ]; then
58+
echo "GOOGLE_APPLICATION_CREDENTIALS=/tmp/service-account.json" >> $GITHUB_ENV
59+
echo "GOOGLE_GENAI_USE_VERTEXAI=true" >> $GITHUB_ENV
60+
echo "GOOGLE_CLOUD_PROJECT=$PROJECT_ID" >> $GITHUB_ENV
61+
echo "GOOGLE_CLOUD_LOCATION=${GOOGLE_CLOUD_LOCATION}" >> $GITHUB_ENV
62+
fi
4763

4864
echo "✅ Gemini authentication configured"
4965
echo " Project: $PROJECT_ID"

scripts/setup-mcp.sh

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,21 @@ set -euo pipefail
33

44
echo "::group::Setting up MCP Server Integration"
55

6+
# Set defaults for local testing
7+
MCP_SECRET_NAME="${MCP_SECRET_NAME:-USABLE_API_TOKEN}"
8+
MCP_URL="${MCP_SERVER_URL:-https://usable.dev/api/mcp}"
9+
610
# Get the MCP token from environment using the secret name
711
MCP_TOKEN="${!MCP_SECRET_NAME:-}"
812

913
if [ -z "$MCP_TOKEN" ]; then
1014
echo "::error::MCP token not found in environment variable: $MCP_SECRET_NAME"
1115
echo "Please ensure the secret is set in your workflow: env.$MCP_SECRET_NAME"
16+
echo "For local testing: export USABLE_API_TOKEN='<your-usable-api-token>'"
1217
exit 1
1318
fi
1419

15-
# Validate MCP URL
20+
# Validate MCP URL (should be set by default now)
1621
if [ -z "$MCP_URL" ]; then
1722
echo "::error::MCP_URL is required when MCP is enabled"
1823
exit 1
@@ -37,7 +42,11 @@ chmod 600 /tmp/gemini-settings.json
3742

3843
# Set environment variable for Gemini CLI to use this settings file
3944
export GEMINI_SETTINGS="/tmp/gemini-settings.json"
40-
echo "GEMINI_SETTINGS=/tmp/gemini-settings.json" >> $GITHUB_ENV
45+
46+
# Write to GITHUB_ENV for subsequent steps (if in GitHub Actions)
47+
if [ -n "${GITHUB_ENV:-}" ]; then
48+
echo "GEMINI_SETTINGS=/tmp/gemini-settings.json" >> $GITHUB_ENV
49+
fi
4150

4251
echo "✅ MCP server configured"
4352
echo " URL: $MCP_URL"

scripts/test-local-quick.sh

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/usr/bin/env bash
2+
# Quick local test - minimal setup required
3+
# Usage: ./scripts/test-local-quick.sh [base-branch] [head-branch]
4+
5+
set -euo pipefail
6+
7+
BASE="${1:-main}"
8+
HEAD="${2:-$(git rev-parse --abbrev-ref HEAD)}"
9+
10+
echo "🧪 Quick Validation Test"
11+
echo "Base: $BASE → Head: $HEAD"
12+
echo ""
13+
14+
# Check environment
15+
if [ -z "${GEMINI_SERVICE_ACCOUNT_KEY:-}" ]; then
16+
echo "❌ Set GEMINI_SERVICE_ACCOUNT_KEY first"
17+
exit 1
18+
fi
19+
20+
if [ -z "${USABLE_API_TOKEN:-}" ]; then
21+
echo "❌ Set USABLE_API_TOKEN first"
22+
exit 1
23+
fi
24+
25+
# Quick config
26+
export BASE_BRANCH="$BASE"
27+
export HEAD_BRANCH="$HEAD"
28+
export WORKSPACE_ID="${WORKSPACE_ID:-60c10ca2-4115-4c1a-b6d7-04ac39fd3938}"
29+
export GEMINI_MODEL="${GEMINI_MODEL:-gemini-2.5-flash}"
30+
export PR_NUMBER="999"
31+
export PR_TITLE="Local Test"
32+
export PR_DESCRIPTION="Testing locally"
33+
export PR_URL="https://github.com/test/local"
34+
export PR_AUTHOR="$(git config user.name)"
35+
export PR_LABELS="test"
36+
export PROMPT_FILE=".github/prompts/pr-validation.md"
37+
export ACTION_PATH="$(pwd)"
38+
export MCP_SECRET_NAME="USABLE_API_TOKEN"
39+
export MCP_SERVER_URL="https://usable.dev/api/mcp"
40+
export ALLOW_WEB_FETCH="false"
41+
export MAX_RETRIES="2"
42+
export USE_DYNAMIC_PROMPTS="false"
43+
export MERGE_CUSTOM_PROMPT="true"
44+
45+
# Setup and run (source to preserve environment variables)
46+
source scripts/setup-gemini.sh && \
47+
source scripts/setup-mcp.sh && \
48+
source scripts/fetch-prompt.sh && \
49+
source scripts/validate.sh
50+
51+
echo ""
52+
echo "✅ Results in /tmp/validation-report.md"
53+

scripts/test-local.sh

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Local testing script for Usable PR Validator
5+
# Run this from the repository root to test validation locally
6+
7+
echo "🧪 Local PR Validator Test"
8+
echo "============================"
9+
echo ""
10+
11+
# Check required environment variables
12+
REQUIRED_VARS=(
13+
"GEMINI_SERVICE_ACCOUNT_KEY"
14+
"USABLE_API_TOKEN"
15+
)
16+
17+
MISSING_VARS=()
18+
for var in "${REQUIRED_VARS[@]}"; do
19+
if [ -z "${!var:-}" ]; then
20+
MISSING_VARS+=("$var")
21+
fi
22+
done
23+
24+
if [ ${#MISSING_VARS[@]} -gt 0 ]; then
25+
echo "❌ Missing required environment variables:"
26+
for var in "${MISSING_VARS[@]}"; do
27+
echo " - $var"
28+
done
29+
echo ""
30+
echo "Set them with:"
31+
echo " export GEMINI_SERVICE_ACCOUNT_KEY='<your-service-account-json>'"
32+
echo " export USABLE_API_TOKEN='<your-usable-api-token>'"
33+
exit 1
34+
fi
35+
36+
# Set defaults for optional vars
37+
export BASE_BRANCH="${BASE_BRANCH:-main}"
38+
export HEAD_BRANCH="${HEAD_BRANCH:-$(git rev-parse --abbrev-ref HEAD)}"
39+
export WORKSPACE_ID="${WORKSPACE_ID:-60c10ca2-4115-4c1a-b6d7-04ac39fd3938}"
40+
export GEMINI_MODEL="${GEMINI_MODEL:-gemini-2.5-flash}"
41+
export MCP_SERVER_URL="${MCP_SERVER_URL:-https://usable.dev/api/mcp}"
42+
export ALLOW_WEB_FETCH="${ALLOW_WEB_FETCH:-false}"
43+
export MAX_RETRIES="${MAX_RETRIES:-2}"
44+
45+
# PR context (for local testing, use dummy values)
46+
export PR_NUMBER="${PR_NUMBER:-0}"
47+
export PR_TITLE="${PR_TITLE:-Local Test Run}"
48+
export PR_DESCRIPTION="${PR_DESCRIPTION:-Testing PR validation locally}"
49+
export PR_URL="${PR_URL:-https://github.com/local/test}"
50+
export PR_AUTHOR="${PR_AUTHOR:-$(git config user.name || echo "unknown")}"
51+
export PR_LABELS="${PR_LABELS:-test}"
52+
53+
# Prompt file
54+
export PROMPT_FILE="${PROMPT_FILE:-.github/prompts/pr-validation.md}"
55+
export USE_DYNAMIC_PROMPTS="${USE_DYNAMIC_PROMPTS:-false}"
56+
export MERGE_CUSTOM_PROMPT="${MERGE_CUSTOM_PROMPT:-true}"
57+
58+
# Secret names (for consistency with action)
59+
export MCP_SECRET_NAME="USABLE_API_TOKEN"
60+
61+
echo "📋 Configuration:"
62+
echo " Base Branch: $BASE_BRANCH"
63+
echo " Head Branch: $HEAD_BRANCH"
64+
echo " Workspace ID: $WORKSPACE_ID"
65+
echo " Model: $GEMINI_MODEL"
66+
echo " Prompt File: $PROMPT_FILE"
67+
echo ""
68+
69+
# Check if prompt file exists
70+
if [ "$USE_DYNAMIC_PROMPTS" != "true" ] && [ ! -f "$PROMPT_FILE" ]; then
71+
echo "❌ Prompt file not found: $PROMPT_FILE"
72+
echo ""
73+
echo "Either:"
74+
echo " 1. Create the prompt file at: $PROMPT_FILE"
75+
echo " 2. Set PROMPT_FILE to an existing file"
76+
echo " 3. Use dynamic prompts: export USE_DYNAMIC_PROMPTS=true PROMPT_FRAGMENT_ID=<uuid>"
77+
exit 1
78+
fi
79+
80+
# Install Gemini CLI if not present
81+
if ! command -v gemini &> /dev/null; then
82+
echo "📦 Installing Gemini CLI..."
83+
npm install -g @google/generative-ai-cli
84+
fi
85+
86+
# Check Gemini CLI version
87+
echo "✅ Gemini CLI: $(gemini --version 2>/dev/null || echo 'installed')"
88+
echo ""
89+
90+
# Get action path (current directory)
91+
export ACTION_PATH="$(pwd)"
92+
93+
# Run setup scripts (source them to preserve environment variables)
94+
echo "🔧 Setting up authentication..."
95+
source scripts/setup-gemini.sh
96+
97+
echo ""
98+
echo "🔌 Setting up MCP server..."
99+
source scripts/setup-mcp.sh
100+
101+
echo ""
102+
echo "📝 Fetching prompts..."
103+
source scripts/fetch-prompt.sh
104+
105+
echo ""
106+
echo "🚀 Running validation..."
107+
echo ""
108+
source scripts/validate.sh
109+
110+
echo ""
111+
echo "✅ Validation complete!"
112+
echo ""
113+
echo "📊 Results:"
114+
if [ -f "/tmp/validation-report.md" ]; then
115+
echo " Report: /tmp/validation-report.md"
116+
cat /tmp/validation-report.md
117+
else
118+
echo " ⚠️ No report generated"
119+
fi
120+
121+
echo ""
122+
echo "📁 Artifacts:"
123+
echo " Full Output: /tmp/validation-full-output.md"
124+
echo " Report: /tmp/validation-report.md"
125+
echo " Prompt: /tmp/validation-prompt.txt"
126+

0 commit comments

Comments
 (0)