Skip to content

Commit f64222a

Browse files
committed
fix: script fixes
1 parent 8398148 commit f64222a

File tree

2 files changed

+168
-93
lines changed

2 files changed

+168
-93
lines changed

scripts/generate-api-docs.sh

Lines changed: 167 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,117 +1,192 @@
11
#!/bin/bash
2-
set -e
32

3+
# Script to generate HTML documentation from all API specs using Redocly
4+
# This will convert all .yaml and .yml files in the specs directory to HTML
5+
6+
set -ex
7+
set -o pipefail
8+
9+
# Colors for output
10+
RED='\033[0;31m'
11+
GREEN='\033[0;32m'
12+
YELLOW='\033[1;33m'
13+
BLUE='\033[0;34m'
14+
NC='\033[0m' # No Color
15+
16+
# Directories
17+
SPECS_DIR="specs"
418
OUTPUT_DIR="docs/api-docs"
519
INDEX_FILE="$OUTPUT_DIR/index.html"
20+
ERROR_LOG="$OUTPUT_DIR/errors.log"
21+
22+
echo -e "${BLUE}🚀 Starting API documentation generation...${NC}"
623

7-
# 1. Clean output dir
24+
# === CLEAN OUTPUT DIRECTORY ===
25+
echo -e "${YELLOW}🧹 Cleaning output folder...${NC}"
826
rm -rf "$OUTPUT_DIR"
927
mkdir -p "$OUTPUT_DIR"
1028

11-
# 2. Prepare index.html
29+
# Check if redocly is installed
30+
if ! command -v redocly &> /dev/null; then
31+
echo -e "${RED}❌ Redocly is not installed. Please install it first:${NC}"
32+
echo "npm install -g @redocly/cli"
33+
exit 1
34+
fi
35+
echo -e "${GREEN}✅ Redocly found: $(redocly --version)${NC}"
36+
37+
# Counters
38+
success_count=0
39+
error_count=0
40+
41+
# Clear error log
42+
> "$ERROR_LOG"
43+
44+
# Function to convert a spec file to HTML
45+
convert_spec_to_html() {
46+
local spec_file="$1"
47+
local relative_path="${spec_file#$SPECS_DIR/}"
48+
local filename=$(basename "$spec_file")
49+
local name_without_ext="${filename%.*}"
50+
local output_file="$OUTPUT_DIR/${relative_path%.*}.html"
51+
52+
# Create output directory if it doesn't exist
53+
mkdir -p "$(dirname "$output_file")"
54+
55+
echo -e "${BLUE}📄 Converting: $spec_file${NC}"
56+
57+
if redocly build-docs "$spec_file" -o "$output_file" >/dev/null 2>&1; then
58+
echo -e "${GREEN}✅ Success: $output_file${NC}"
59+
((success_count++))
60+
return 0
61+
else
62+
echo -e "${RED}❌ Failed: $spec_file${NC}"
63+
echo "$spec_file" >> "$ERROR_LOG"
64+
((error_count++))
65+
return 1
66+
fi
67+
}
68+
69+
# === FIND AND CONVERT SPEC FILES ===
70+
echo -e "${YELLOW}🔍 Finding all spec files...${NC}"
71+
mapfile -t spec_files < <(find "$SPECS_DIR" -type f \( -name "*.yaml" -o -name "*.yml" \) | sort)
72+
echo -e "${BLUE}📊 Found ${#spec_files[@]} spec files${NC}"
73+
74+
for spec_file in "${spec_files[@]}"; do
75+
convert_spec_to_html "$spec_file" || true
76+
done
77+
78+
# === GENERATE INDEX.HTML ===
79+
echo -e "${YELLOW}📝 Generating index page...${NC}"
80+
1281
cat > "$INDEX_FILE" << 'EOF'
1382
<!DOCTYPE html>
1483
<html lang="en">
1584
<head>
16-
<meta charset="UTF-8">
17-
<title>API Documentation</title>
18-
<style>
19-
body { font-family: Arial, sans-serif; margin: 20px; }
20-
h1 { border-bottom: 2px solid #ccc; padding-bottom: 10px; }
21-
.category { margin-bottom: 20px; }
22-
.category h3 { margin-top: 0; color: #2c3e50; }
23-
.api-list { list-style: none; padding-left: 0; }
24-
.api-list li { margin: 5px 0; }
25-
.timestamp { margin-top: 40px; font-size: 0.9em; color: #888; }
26-
</style>
85+
<meta charset="UTF-8">
86+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
87+
<title>Devtron API Documentation</title>
88+
<style>
89+
body { font-family: Arial, sans-serif; margin: 20px; }
90+
h1 { color: #333; }
91+
h3 { margin-top: 20px; }
92+
ul { list-style: none; padding-left: 0; }
93+
li { margin: 5px 0; }
94+
a { text-decoration: none; color: #0366d6; }
95+
a:hover { text-decoration: underline; }
96+
</style>
2797
</head>
2898
<body>
29-
<h1>API Documentation</h1>
30-
<div id="categories"></div>
31-
<div class="timestamp">Last updated: <span id="timestamp"></span></div>
32-
<script>
33-
const apiData = {
99+
<div class="container">
100+
<h1>🚀 Devtron API Documentation</h1>
101+
<div class="categories" id="categories"></div>
102+
<div class="footer">
103+
<p><a href="https://devtron.ai/" target="_blank">Devtron</a></p>
104+
<p class="timestamp">Last updated: <span id="timestamp"></span></p>
105+
</div>
106+
</div>
107+
<script>
108+
const apiData = {
34109
EOF
35110

36-
# 3. Loop over all specs
37-
find specs -type f -name "*.yaml" | while read -r spec; do
38-
title=$(grep -m1 "^title:" "$spec" | sed 's/^[[:space:]]*title:[[:space:]]*//' | tr -d '"')
39-
filename=$(basename "$spec" .yaml).html
40-
category=$(basename "$(dirname "$spec")")
41-
42-
# Run redocly to generate HTML
43-
npx @redocly/cli build-docs "$spec" -o "$OUTPUT_DIR/$filename"
44-
45-
# Add entry to index.html
46-
cat >> "$INDEX_FILE" << EOF
47-
"${filename}": {
48-
"title": "${title}",
49-
"category": "${category}",
50-
"filename": "${filename}"
51-
},
52-
EOF
111+
# Populate apiData
112+
for spec_file in "${spec_files[@]}"; do
113+
relative_path="${spec_file#$SPECS_DIR/}"
114+
html_file="${relative_path%.*}.html"
115+
category=$(dirname "$relative_path")
116+
[[ "$category" == "." ]] && category="root"
117+
118+
# Capitalise each word and split camelCase
119+
display_category=$(echo "$category" | sed 's/[-_]/ /g' | sed 's/\([a-z]\)\([A-Z]\)/\1 \2/g' | sed 's/\b\w/\U&/g')
120+
121+
# Get title or fallback
122+
title=$(grep -m 1 '^[[:space:]]*title:' "$spec_file" | sed 's/^[[:space:]]*title:[[:space:]]*//' | tr -d '"' || echo "${relative_path%.*}")
123+
124+
if [[ -f "$OUTPUT_DIR/$html_file" ]]; then
125+
echo " \"${category}_$(basename "${relative_path%.*}")\": {\"category\": \"${display_category}\", \"title\": \"${title}\", \"filename\": \"${html_file}\"}," >> "$INDEX_FILE"
126+
fi
53127
done
54128

55-
# 4. Remove last comma in apiData
129+
# Remove trailing comma
56130
sed -i '$ s/,$//' "$INDEX_FILE"
57131

58-
# 5. Append JS for rendering categories & APIs
59132
cat >> "$INDEX_FILE" << 'EOF'
60-
};
61-
62-
function populatePage() {
63-
const categoriesContainer = document.getElementById('categories');
64-
const categories = {};
65-
66-
Object.values(apiData).forEach(api => {
67-
if (!categories[api.category]) {
68-
categories[api.category] = [];
69-
}
70-
categories[api.category].push(api);
71-
});
72-
73-
Object.keys(categories).sort().forEach(category => {
74-
const categoryDiv = document.createElement('div');
75-
categoryDiv.className = 'category';
76-
77-
const categoryTitle = document.createElement('h3');
78-
categoryTitle.textContent = category
79-
.replace(/([a-z])([A-Z])/g, '$1 $2') // camelCase -> space
80-
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2') // ABCThing -> ABC Thing
81-
.split(/[\s-_]+/) // split on space, dash, underscore
82-
.map(word => {
83-
if (word === word.toUpperCase()) return word; // keep acronyms uppercase
84-
return word.charAt(0).toUpperCase() + word.slice(1);
85-
})
86-
.join(' ');
87-
88-
categoryDiv.appendChild(categoryTitle);
89-
90-
const apiList = document.createElement('ul');
91-
apiList.className = 'api-list';
92-
93-
categories[category]
94-
.sort((a, b) => a.title.localeCompare(b.title))
95-
.forEach(api => {
96-
const listItem = document.createElement('li');
97-
const link = document.createElement('a');
98-
link.href = api.filename; // removed target="_blank"
99-
link.textContent = api.title;
100-
listItem.appendChild(link);
101-
apiList.appendChild(listItem);
102-
});
103-
104-
categoryDiv.appendChild(apiList);
105-
categoriesContainer.appendChild(categoryDiv);
106-
});
107-
108-
document.getElementById('timestamp').textContent = new Date().toLocaleString();
109-
}
110-
111-
document.addEventListener('DOMContentLoaded', populatePage);
112-
</script>
133+
};
134+
135+
function populatePage() {
136+
const container = document.getElementById('categories');
137+
const categories = {};
138+
139+
Object.values(apiData).forEach(api => {
140+
if (!categories[api.category]) categories[api.category] = [];
141+
categories[api.category].push(api);
142+
});
143+
144+
Object.keys(categories).sort().forEach(cat => {
145+
const section = document.createElement('div');
146+
const h3 = document.createElement('h3');
147+
h3.textContent = cat;
148+
section.appendChild(h3);
149+
150+
const ul = document.createElement('ul');
151+
categories[cat].sort((a,b)=>a.title.localeCompare(b.title)).forEach(api => {
152+
const li = document.createElement('li');
153+
const a = document.createElement('a');
154+
a.href = api.filename;
155+
a.textContent = api.title;
156+
li.appendChild(a);
157+
ul.appendChild(li);
158+
});
159+
160+
section.appendChild(ul);
161+
container.appendChild(section);
162+
});
163+
164+
document.getElementById('timestamp').textContent = new Date().toLocaleString();
165+
}
166+
167+
document.addEventListener('DOMContentLoaded', populatePage);
168+
</script>
113169
</body>
114170
</html>
115171
EOF
116172

117-
echo "✅ API documentation generated at $OUTPUT_DIR"
173+
echo -e "${GREEN}✅ Index page generated: $INDEX_FILE${NC}"
174+
175+
# === FINAL SUMMARY ===
176+
echo -e "${BLUE}📊 Final Summary:${NC}"
177+
echo -e "${GREEN}✅ Successfully converted: $success_count files${NC}"
178+
if [ $error_count -gt 0 ]; then
179+
echo -e "${RED}❌ Failed to convert: $error_count files${NC}"
180+
echo -e "${YELLOW}📝 Check $ERROR_LOG for details${NC}"
181+
fi
182+
echo -e "${BLUE}📁 Output directory: $OUTPUT_DIR${NC}"
183+
echo -e "${BLUE}🌐 Main index: $INDEX_FILE${NC}"
184+
185+
# === CREATE README ===
186+
cat > "$OUTPUT_DIR/README.md" << 'EOF'
187+
# Devtron API Documentation
188+
This folder contains the HTML documentation generated from the OpenAPI specs in the `specs` directory.
189+
EOF
190+
191+
echo -e "${GREEN}✅ README created: $OUTPUT_DIR/README.md${NC}"
192+
echo -e "${GREEN}🎉 API documentation generation complete!${NC}"

specs/resourceRecommendation/ClusterResourceRecommendation.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ openapi: 3.1.0
22
info:
33
title: Resource Recommender
44
description: Analyzes the history of resource usage (such as CPU and memory) for Kubernetes workloads in a specific cluster and generates data-backed recommendations for optimal resource allocation.
5-
version: 0.0.2
5+
version: 0.0.1
66
servers:
77
- url: http://localhost:8080/orchestrator
88
description: Devtron API Server

0 commit comments

Comments
 (0)