Skip to content

Commit 48d75bd

Browse files
committed
chore: adding buildingblock logo prompt
1 parent e397bc6 commit 48d75bd

4 files changed

Lines changed: 341 additions & 0 deletions

File tree

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Generate icon prompts for building blocks missing logo.png files.
4+
Parses README.md frontmatter and creates AI image generation prompts.
5+
"""
6+
7+
import os
8+
import sys
9+
import yaml
10+
import json
11+
from pathlib import Path
12+
13+
PLATFORM_COLORS = {
14+
"aws": {
15+
"primary": "#FF9900",
16+
"secondary": "#232F3E",
17+
"accent": "#7FBA00",
18+
"name": "AWS colors: orange (#FF9900), dark blue (#232F3E), and lime green (#7FBA00)"
19+
},
20+
"azure": {
21+
"primary": "#0078D4",
22+
"secondary": "#00BCF2",
23+
"accent": "#50E6FF",
24+
"name": "Azure colors: blue (#0078D4), cyan (#00BCF2), and light blue (#50E6FF)"
25+
},
26+
"aks": {
27+
"primary": "#326CE5",
28+
"secondary": "#0078D4",
29+
"accent": "#00BCF2",
30+
"name": "Kubernetes/Azure colors: blue (#326CE5), Azure blue (#0078D4), and cyan (#00BCF2)"
31+
},
32+
"azuredevops": {
33+
"primary": "#0078D4",
34+
"secondary": "#00BCF2",
35+
"accent": "#005A9E",
36+
"name": "Azure DevOps colors: blue (#0078D4), teal (#00BCF2), and dark blue (#005A9E)"
37+
},
38+
"gcp": {
39+
"primary": "#4285F4",
40+
"secondary": "#EA4335",
41+
"accent": "#FBBC04",
42+
"name": "Google colors: blue (#4285F4), red (#EA4335), yellow (#FBBC04), and green (#34A853)"
43+
},
44+
"github": {
45+
"primary": "#6e5494",
46+
"secondary": "#24292e",
47+
"accent": "#8b5cf6",
48+
"name": "GitHub colors: purple (#6e5494), dark gray (#24292e), and bright purple (#8b5cf6)"
49+
},
50+
"ionos": {
51+
"primary": "#003D7A",
52+
"secondary": "#FF6600",
53+
"accent": "#0096D6",
54+
"name": "IONOS colors: blue (#003D7A), orange (#FF6600), and light blue (#0096D6)"
55+
},
56+
"kubernetes": {
57+
"primary": "#326CE5",
58+
"secondary": "#00D3E0",
59+
"accent": "#7AB8FF",
60+
"name": "Kubernetes colors: blue (#326CE5), cyan (#00D3E0), and light blue (#7AB8FF)"
61+
},
62+
"sapbtp": {
63+
"primary": "#0070AD",
64+
"secondary": "#F0AB00",
65+
"accent": "#0078D4",
66+
"name": "SAP colors: blue (#0070AD), gold (#F0AB00), and light blue (#0078D4)"
67+
},
68+
"stackit": {
69+
"primary": "#00A859",
70+
"secondary": "#007A3D",
71+
"accent": "#7FBA00",
72+
"name": "STACKIT colors: green (#00A859), dark green (#007A3D), and lime (#7FBA00)"
73+
}
74+
}
75+
76+
77+
def parse_readme_frontmatter(readme_path):
78+
"""Extract YAML frontmatter from README.md"""
79+
with open(readme_path, 'r', encoding='utf-8') as f:
80+
content = f.read()
81+
82+
if not content.startswith('---'):
83+
return None
84+
85+
# Extract frontmatter between --- delimiters
86+
parts = content.split('---', 2)
87+
if len(parts) < 3:
88+
return None
89+
90+
try:
91+
frontmatter = yaml.safe_load(parts[1])
92+
return frontmatter
93+
except yaml.YAMLError:
94+
return None
95+
96+
97+
def get_platform_from_frontmatter(frontmatter):
98+
"""Get the primary platform from supportedPlatforms list"""
99+
platforms = frontmatter.get('supportedPlatforms', [])
100+
if not platforms:
101+
return None
102+
return platforms[0] # Use first platform
103+
104+
105+
def generate_icon_prompt(name, platform, description):
106+
"""Generate an AI image generation prompt for an icon"""
107+
platform_colors = PLATFORM_COLORS.get(platform)
108+
109+
if not platform_colors:
110+
# Fallback to generic bright colors
111+
color_scheme = "bright, vibrant colors"
112+
else:
113+
color_scheme = platform_colors["name"]
114+
115+
# Clean up description
116+
clean_description = description.strip().replace('\n', ' ')
117+
118+
# Generate AI prompt
119+
ai_prompt = f"""Create a professional flat design icon for the meshcloud Building Block ecosystem.
120+
121+
Purpose: {clean_description}
122+
123+
Visual Style:
124+
- Plain white background (#FFFFFF) for easy removal in post-processing
125+
- Background will be converted to transparent (see post-processing steps)
126+
- Use meshcloud blue (#2563eb) as primary color
127+
- Use {color_scheme} as accent colors
128+
- Maximum 2-3 colors total
129+
- Simple geometric shapes with clean lines
130+
- Flat design (no gradients, shadows, or 3D effects)
131+
- Minimalist, modern appearance
132+
133+
Composition:
134+
- Square centered layout (NOT horizontal)
135+
- Icon fills the entire canvas edge-to-edge (100% of area)
136+
- No padding or margins around the icon
137+
- Symmetrical arrangement
138+
- Platform-appropriate symbol for {platform.upper()} (e.g., cloud, container, database, server, etc.)
139+
140+
Style: Enterprise professional, instantly recognizable at small sizes, similar to app icons or logos.
141+
Dimensions: 800x800 pixels"""
142+
143+
# Generate post-processing instructions
144+
post_processing = """**Step 1: Remove white background with GIMP (free)**
145+
146+
a) Open image in GIMP
147+
b) Right-click layer → "Add Alpha Channel"
148+
c) Tools → "Select by Color" (Shift+O)
149+
d) Click white background
150+
e) Press Delete key
151+
f) File → Export As → logo.png
152+
g) Set Compression level to 9 → Export
153+
154+
**Step 2: Resize to 800x800 pixels if needed**
155+
156+
- GIMP: Image → Scale Image → 800x800px
157+
- Or use any image editor
158+
159+
**Step 3: Compress with pngquant (free command line tool)**
160+
161+
- Install: `brew install pngquant` (Mac) or `apt install pngquant` (Linux)
162+
- Run: `pngquant --quality=20-30 logo.png --ext .png --force`
163+
- This reduces file size by 60-80% while maintaining quality
164+
165+
**Target specs:** 800x800px PNG with transparent background, under 100KB"""
166+
167+
return {
168+
'ai_prompt': ai_prompt,
169+
'post_processing': post_processing
170+
}
171+
172+
def find_missing_logos(modules_dir):
173+
"""Find all buildingblock directories missing logo.png"""
174+
missing = []
175+
176+
for root, dirs, files in os.walk(modules_dir):
177+
if 'buildingblock' in root:
178+
buildingblock_path = Path(root)
179+
readme_path = buildingblock_path / 'README.md'
180+
logo_path = buildingblock_path / 'logo.png'
181+
182+
if readme_path.exists() and not logo_path.exists():
183+
frontmatter = parse_readme_frontmatter(readme_path)
184+
if frontmatter:
185+
platform = get_platform_from_frontmatter(frontmatter)
186+
name = frontmatter.get('name', 'Unknown')
187+
description = frontmatter.get('description', '')
188+
189+
# Get relative path from modules directory
190+
rel_path = buildingblock_path.relative_to(modules_dir)
191+
192+
missing.append({
193+
'path': str(rel_path),
194+
'name': name,
195+
'platform': platform,
196+
'description': description,
197+
'readme_path': str(readme_path),
198+
'logo_path': str(logo_path)
199+
})
200+
201+
return missing
202+
203+
def main():
204+
# Get modules directory
205+
repo_root = Path(__file__).parent.parent.parent
206+
modules_dir = repo_root / 'modules'
207+
208+
if not modules_dir.exists():
209+
print(f"ERROR: Modules directory not found: {modules_dir}", file=sys.stderr)
210+
sys.exit(1)
211+
212+
# Find missing logos
213+
missing_logos = find_missing_logos(modules_dir)
214+
215+
# Generate prompts for each missing logo
216+
results = []
217+
for item in missing_logos:
218+
prompt_data = generate_icon_prompt(
219+
item['name'],
220+
item['platform'] or 'generic',
221+
item['description']
222+
)
223+
224+
results.append({
225+
'name': item['name'],
226+
'platform': item['platform'],
227+
'path': item['path'],
228+
'logo_path': item['logo_path'],
229+
'ai_prompt': prompt_data['ai_prompt'],
230+
'post_processing': prompt_data['post_processing']
231+
})
232+
233+
# Output as JSON for GitHub Action to consume
234+
print(json.dumps(results, indent=2))
235+
236+
if __name__ == '__main__':
237+
main()

.github/workflows/icon-prompts.yml

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
name: Generate Icon Prompts for Missing Logos
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
paths:
7+
- 'modules/**/buildingblock/README.md'
8+
9+
permissions:
10+
pull-requests: write
11+
contents: read
12+
13+
jobs:
14+
check-missing-logos:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: Checkout code
18+
uses: actions/checkout@v4
19+
20+
- name: Set up Python
21+
uses: actions/setup-python@v5
22+
with:
23+
python-version: '3.11'
24+
25+
- name: Install dependencies
26+
run: |
27+
pip install pyyaml
28+
29+
- name: Find missing logos and generate prompts
30+
id: generate
31+
run: |
32+
python .github/scripts/generate-icon-prompts.py > prompts.json
33+
COUNT=$(jq 'length' prompts.json)
34+
echo "has_missing=$([ "$COUNT" -gt 0 ] && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT
35+
echo "count=$COUNT" >> $GITHUB_OUTPUT
36+
37+
- name: Read prompts
38+
if: steps.generate.outputs.has_missing == 'true'
39+
id: read_prompts
40+
run: |
41+
PROMPTS=$(cat prompts.json)
42+
echo "prompts<<EOF" >> $GITHUB_OUTPUT
43+
echo "$PROMPTS" >> $GITHUB_OUTPUT
44+
echo "EOF" >> $GITHUB_OUTPUT
45+
46+
- name: Generate PR comment
47+
if: steps.generate.outputs.has_missing == 'true'
48+
id: format_comment
49+
uses: actions/github-script@v7
50+
env:
51+
PROMPTS_JSON: ${{ steps.read_prompts.outputs.prompts }}
52+
with:
53+
result-encoding: string
54+
script: |
55+
const prompts = JSON.parse(process.env.PROMPTS_JSON);
56+
57+
if (prompts.length === 0) {
58+
return '';
59+
}
60+
61+
let comment = '## 🎨 Missing Building Block Icons\n\n';
62+
comment += `Found **${prompts.length}** building block(s) without \`logo.png\` files.\n\n`;
63+
comment += 'Copy the **AI Prompts** below and use them with your favorite AI image generator (Gemini, DALL-E, Midjourney, Stable Diffusion, etc.).\n\n';
64+
comment += 'Then follow the **Post-Processing Steps** to prepare the icons for upload.\n\n';
65+
comment += '---\n\n';
66+
67+
for (const item of prompts) {
68+
comment += `### ${item.name}\n\n`;
69+
comment += `**Platform:** \`${item.platform}\`\n\n`;
70+
comment += `**Path:** \`${item.logo_path}\`\n\n`;
71+
comment += '#### AI Prompt (copy this to image generator)\n\n';
72+
comment += '```\n';
73+
comment += item.ai_prompt;
74+
comment += '\n```\n\n';
75+
comment += '#### Post-Processing Instructions\n\n';
76+
comment += item.post_processing;
77+
comment += '\n\n';
78+
comment += '---\n\n';
79+
}
80+
81+
return comment;
82+
83+
- name: Find existing comment
84+
if: steps.generate.outputs.has_missing == 'true'
85+
uses: peter-evans/find-comment@v3
86+
id: find_comment
87+
with:
88+
issue-number: ${{ github.event.pull_request.number }}
89+
comment-author: 'github-actions[bot]'
90+
body-includes: '🎨 Missing Building Block Icons'
91+
92+
- name: Create or update comment
93+
if: steps.generate.outputs.has_missing == 'true'
94+
uses: peter-evans/create-or-update-comment@v4
95+
with:
96+
comment-id: ${{ steps.find_comment.outputs.comment-id }}
97+
issue-number: ${{ github.event.pull_request.number }}
98+
body: ${{ steps.format_comment.outputs.result }}
99+
edit-mode: replace
100+
101+
- name: Success message
102+
if: steps.generate.outputs.has_missing == 'false'
103+
run: |
104+
echo "✅ All building blocks have logo.png files!"
-1.93 KB
Loading
15.2 KB
Loading

0 commit comments

Comments
 (0)