Skip to content

Commit 8da2f47

Browse files
committed
review online boutique app on GKE
1 parent 95cad50 commit 8da2f47

8 files changed

Lines changed: 1004 additions & 133 deletions

File tree

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Script to find download commands in markdown files that may contain outdated software versions.
4+
Searches for wget, curl, and other download patterns with version numbers.
5+
"""
6+
7+
import os
8+
import re
9+
import glob
10+
from pathlib import Path
11+
12+
def extract_download_commands(file_path):
13+
"""Extract download commands from a markdown file."""
14+
download_commands = []
15+
16+
try:
17+
with open(file_path, 'r', encoding='utf-8') as f:
18+
content = f.read()
19+
except Exception as e:
20+
print(f"Error reading {file_path}: {e}")
21+
return download_commands
22+
23+
# Patterns to match download commands with potential version numbers
24+
patterns = [
25+
# wget commands with URLs containing version numbers
26+
r'wget\s+[^\s]*(?:https?://[^\s]*(?:\d+\.\d+[^\s]*|v\d+[^\s]*|release[^\s]*|download[^\s]*)[^\s]*)',
27+
# curl commands with URLs containing version numbers
28+
r'curl\s+[^\n]*(?:https?://[^\s]*(?:\d+\.\d+[^\s]*|v\d+[^\s]*|release[^\s]*|download[^\s]*)[^\s]*)',
29+
# Direct download URLs in markdown links or code blocks
30+
r'https?://[^\s\)]*(?:download[^\s\)]*|release[^\s\)]*|archive[^\s\)]*|releases[^\s\)]*)[^\s\)]*(?:\d+\.\d+[^\s\)]*|v\d+[^\s\)]*)',
31+
# Package manager installs with specific versions
32+
r'(?:apt|yum|dnf|brew|pip|npm|cargo)\s+install[^\n]*(?:\d+\.\d+|\=\d+)',
33+
# GitHub releases pattern
34+
r'https?://github\.com/[^/]+/[^/]+/releases/download/[^\s\)]*',
35+
# Archive downloads with version numbers
36+
r'(?:wget|curl)[^\n]*\.(?:tar\.gz|tar\.bz2|zip|tgz)[^\n]*(?:\d+\.\d+|v\d+)',
37+
# Docker image pulls with specific tags
38+
r'docker\s+pull[^\n]*:\d+\.\d+',
39+
# Maven/Gradle dependencies with versions
40+
r'(?:implementation|compile|dependency)[^\n]*:\d+\.\d+',
41+
]
42+
43+
# Find all code blocks (both ``` and indented)
44+
code_blocks = []
45+
46+
# Find fenced code blocks
47+
fenced_pattern = r'```[^\n]*\n(.*?)\n```'
48+
for match in re.finditer(fenced_pattern, content, re.DOTALL):
49+
code_blocks.append(match.group(1))
50+
51+
# Find indented code blocks (4+ spaces or tabs)
52+
lines = content.split('\n')
53+
current_block = []
54+
for line in lines:
55+
if re.match(r'^(?: |\t)', line): # 4 spaces or tab
56+
current_block.append(line.strip())
57+
else:
58+
if current_block:
59+
code_blocks.append('\n'.join(current_block))
60+
current_block = []
61+
if current_block:
62+
code_blocks.append('\n'.join(current_block))
63+
64+
# Search in code blocks and full content
65+
search_content = content + '\n' + '\n'.join(code_blocks)
66+
67+
for pattern in patterns:
68+
matches = re.finditer(pattern, search_content, re.IGNORECASE | re.MULTILINE)
69+
for match in matches:
70+
command = match.group(0).strip()
71+
# Clean up the command (remove extra whitespace, limit length)
72+
command = ' '.join(command.split())
73+
if len(command) > 200:
74+
command = command[:200] + '...'
75+
76+
# Skip if it's just a generic example or placeholder
77+
if not re.search(r'(?:example|placeholder|your-|<[^>]+>)', command, re.IGNORECASE):
78+
download_commands.append(command)
79+
80+
# Remove duplicates while preserving order
81+
seen = set()
82+
unique_commands = []
83+
for cmd in download_commands:
84+
if cmd not in seen:
85+
seen.add(cmd)
86+
unique_commands.append(cmd)
87+
88+
return unique_commands
89+
90+
def scan_directory(directory_path):
91+
"""Scan directory for markdown files and extract download commands."""
92+
results = {}
93+
94+
# Find all .md files recursively
95+
md_files = glob.glob(os.path.join(directory_path, '**/*.md'), recursive=True)
96+
97+
for md_file in md_files:
98+
# Skip _index.md and other index files as they typically don't contain install commands
99+
if os.path.basename(md_file).startswith('_'):
100+
continue
101+
102+
download_commands = extract_download_commands(md_file)
103+
if download_commands:
104+
# Store relative path for cleaner output
105+
rel_path = os.path.relpath(md_file, directory_path)
106+
results[rel_path] = download_commands
107+
108+
return results
109+
110+
def write_results(results, output_file):
111+
"""Write results to output file."""
112+
with open(output_file, 'w', encoding='utf-8') as f:
113+
f.write("# Software Download Commands That May Need Version Updates\n\n")
114+
f.write("This file contains download commands found in markdown files that may contain outdated software versions.\n")
115+
f.write("Review each command to check if newer versions are available.\n\n")
116+
f.write(f"Total files with download commands: {len(results)}\n\n")
117+
118+
for file_path, commands in sorted(results.items()):
119+
f.write(f"## {file_path}\n\n")
120+
for i, command in enumerate(commands, 1):
121+
f.write(f"{i}. ```\n{command}\n```\n\n")
122+
f.write("---\n\n")
123+
124+
def main():
125+
"""Main function."""
126+
current_dir = os.getcwd()
127+
output_file = os.path.join(current_dir, 'outdated_software_downloads.md')
128+
129+
print(f"Scanning directory: {current_dir}")
130+
print("Looking for download commands in .md files...")
131+
132+
results = scan_directory(current_dir)
133+
134+
if results:
135+
write_results(results, output_file)
136+
print(f"\nFound download commands in {len(results)} files.")
137+
print(f"Results written to: {output_file}")
138+
139+
# Print summary
140+
total_commands = sum(len(commands) for commands in results.values())
141+
print(f"Total download commands found: {total_commands}")
142+
143+
print("\nFiles with most download commands:")
144+
sorted_files = sorted(results.items(), key=lambda x: len(x[1]), reverse=True)
145+
for file_path, commands in sorted_files[:5]:
146+
print(f" {file_path}: {len(commands)} commands")
147+
else:
148+
print("No download commands found in any markdown files.")
149+
150+
if __name__ == "__main__":
151+
main()

0 commit comments

Comments
 (0)