Readme CI
This commit is contained in:
147
.gitea/scripts/README-update-readme.md
Normal file
147
.gitea/scripts/README-update-readme.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# Auto-Update README Workflow
|
||||
|
||||
## Overview
|
||||
|
||||
This workflow automatically updates the `README.md` file with the current list of ArgoCD applications based on the directory structure in `k8s/`.
|
||||
|
||||
## How it works
|
||||
|
||||
1. **Trigger**: Workflow runs automatically when changes are pushed to `k8s/**` paths
|
||||
2. **Scan**: Python script scans `k8s/` directory structure and finds all applications
|
||||
3. **Generate**: Creates README.md with badges for all found applications
|
||||
4. **Create PR**: If changes detected, creates a Merge Request for manual review
|
||||
|
||||
## Files
|
||||
|
||||
- `.gitea/workflows/update-readme.yaml` - GitHub Actions workflow
|
||||
- `.gitea/scripts/generate-readme.py` - Python script for README generation
|
||||
|
||||
## Directory Structure
|
||||
|
||||
The script expects the following k8s directory structure:
|
||||
|
||||
```
|
||||
k8s/
|
||||
├── core/ # Core infrastructure applications
|
||||
│ ├── argocd/
|
||||
│ ├── authentik/
|
||||
│ └── ...
|
||||
├── apps/ # User applications
|
||||
│ ├── gitea/
|
||||
│ ├── immich/
|
||||
│ └── ...
|
||||
└── games/ # Game servers
|
||||
├── minecraft/
|
||||
└── ...
|
||||
```
|
||||
|
||||
Each subdirectory name becomes an application name in the README.
|
||||
|
||||
## Required Secrets
|
||||
|
||||
The workflow requires the following secrets to be configured in Gitea:
|
||||
|
||||
| Secret | Description | Example |
|
||||
|--------|-------------|---------|
|
||||
| `GT_URL` | Gitea instance URL | `https://gt.hexor.cy` |
|
||||
| `GT_TOKEN` | Gitea API token with repo write access | `glpat-xxxxx...` |
|
||||
| `GT_OWNER` | Repository owner (username or org) | `ab` |
|
||||
| `GT_REPO` | Repository name | `homelab` |
|
||||
|
||||
### How to create a Gitea Token
|
||||
|
||||
1. Go to Settings → Applications → Generate New Token
|
||||
2. Give it a name like "README Update Bot"
|
||||
3. Select scopes: `repo` (Full control of repositories)
|
||||
4. Generate and copy the token
|
||||
5. Add it as a secret in repository settings
|
||||
|
||||
## Badge Format
|
||||
|
||||
Badges are generated using a predictable pattern:
|
||||
|
||||
```markdown
|
||||
[](https://ag.hexor.cy/applications/argocd/app-name)
|
||||
```
|
||||
|
||||
This allows you to immediately see which applications are:
|
||||
- ✅ Healthy and synced (green badge)
|
||||
- ⚠️ Degraded or out of sync (yellow badge)
|
||||
- ❌ Unhealthy or failed (red badge)
|
||||
|
||||
## Manual Trigger
|
||||
|
||||
You can manually trigger the workflow from Gitea:
|
||||
|
||||
1. Go to Actions tab
|
||||
2. Select "Auto-update README" workflow
|
||||
3. Click "Run workflow"
|
||||
4. Select branch and run
|
||||
|
||||
## Example Output
|
||||
|
||||
The generated README will look like:
|
||||
|
||||
```markdown
|
||||
# homelab
|
||||
|
||||
ArgoCD homelab project
|
||||
|
||||
## ArgoCD Applications Status
|
||||
|
||||
| Application | Status |
|
||||
| :--- | :---: |
|
||||
| **argocd** | [](https://ag.hexor.cy/applications/argocd/argocd) |
|
||||
...
|
||||
```
|
||||
|
||||
## Reviewing Pull Requests
|
||||
|
||||
When the workflow creates a PR:
|
||||
|
||||
1. Check the Actions tab for the workflow run details
|
||||
2. Review the PR in the Pull Requests tab
|
||||
3. Verify the application list matches your k8s/ structure
|
||||
4. Merge when ready
|
||||
|
||||
The PR will include:
|
||||
- Updated application list
|
||||
- Timestamp of generation
|
||||
- Automatic commit message
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### No PR created
|
||||
|
||||
- Check if there are actually changes in README.md
|
||||
- Verify secrets are configured correctly
|
||||
- Check workflow logs in Actions tab
|
||||
|
||||
### Wrong applications listed
|
||||
|
||||
- Verify k8s/ directory structure
|
||||
- Ensure folder names match expected application names
|
||||
- Check for hidden directories (starting with `.`)
|
||||
|
||||
### Badge not loading
|
||||
|
||||
- Verify ArgoCD badge API is accessible at `https://ag.hexor.cy`
|
||||
- Check application name matches ArgoCD application name
|
||||
- Ensure application exists in ArgoCD
|
||||
|
||||
## Maintenance
|
||||
|
||||
### Update badge URL
|
||||
|
||||
If you need to change the badge URL pattern, edit:
|
||||
- `.gitea/scripts/generate-readme.py` - function `generate_badge_line()`
|
||||
|
||||
### Change workflow trigger
|
||||
|
||||
To modify when the workflow runs, edit:
|
||||
- `.gitea/workflows/update-readme.yaml` - `on:` section
|
||||
|
||||
### Add new categories
|
||||
|
||||
To add new categories (besides core/apps/games), edit:
|
||||
- `.gitea/scripts/generate-readme.py` - function `scan_k8s_directory()` and `generate_readme_content()`
|
||||
161
.gitea/scripts/generate-readme.py
Normal file
161
.gitea/scripts/generate-readme.py
Normal file
@@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate README.md with ArgoCD application status badges.
|
||||
Scans k8s/ directory structure to find all applications and generates badges for them.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Dict, List
|
||||
|
||||
|
||||
def scan_k8s_directory(k8s_path: str) -> Dict[str, List[str]]:
|
||||
"""
|
||||
Scan k8s/ directory and return applications grouped by category.
|
||||
|
||||
Args:
|
||||
k8s_path: Path to k8s directory
|
||||
|
||||
Returns:
|
||||
Dictionary with categories as keys and lists of app names as values
|
||||
"""
|
||||
apps_by_category = {
|
||||
'core': [],
|
||||
'apps': [],
|
||||
'games': []
|
||||
}
|
||||
|
||||
k8s_dir = Path(k8s_path)
|
||||
|
||||
for category in apps_by_category.keys():
|
||||
category_path = k8s_dir / category
|
||||
if category_path.exists() and category_path.is_dir():
|
||||
# Get all subdirectories (each subdirectory is an app)
|
||||
apps = [
|
||||
d.name for d in category_path.iterdir()
|
||||
if d.is_dir() and not d.name.startswith('.')
|
||||
]
|
||||
apps_by_category[category] = sorted(apps)
|
||||
|
||||
return apps_by_category
|
||||
|
||||
|
||||
def generate_badge_line(app_name: str) -> str:
|
||||
"""
|
||||
Generate markdown line with badge for an application.
|
||||
|
||||
Args:
|
||||
app_name: Name of the application
|
||||
|
||||
Returns:
|
||||
Markdown formatted string with badge
|
||||
"""
|
||||
badge_url = f"https://ag.hexor.cy/api/badge?name={app_name}&revision=true"
|
||||
app_url = f"https://ag.hexor.cy/applications/argocd/{app_name}"
|
||||
return f"| **{app_name}** | []({app_url}) |"
|
||||
|
||||
|
||||
def generate_readme_content(apps_by_category: Dict[str, List[str]]) -> str:
|
||||
"""
|
||||
Generate README.md content with all applications.
|
||||
|
||||
Args:
|
||||
apps_by_category: Dictionary with apps grouped by category
|
||||
|
||||
Returns:
|
||||
Complete README.md content
|
||||
"""
|
||||
lines = [
|
||||
"# homelab",
|
||||
"",
|
||||
"ArgoCD homelab project",
|
||||
"",
|
||||
"## ArgoCD Applications Status",
|
||||
"",
|
||||
"<table>",
|
||||
"<tr>",
|
||||
"<td valign=\"top\" width=\"50%\">",
|
||||
"",
|
||||
"### Core Applications",
|
||||
"",
|
||||
"| Application | Status |",
|
||||
"| :--- | :---: |"
|
||||
]
|
||||
|
||||
# Add core applications
|
||||
for app in apps_by_category.get('core', []):
|
||||
lines.append(generate_badge_line(app))
|
||||
|
||||
lines.extend([
|
||||
"",
|
||||
"### Games",
|
||||
"",
|
||||
"| Application | Status |",
|
||||
"| :--- | :---: |"
|
||||
])
|
||||
|
||||
# Add games
|
||||
for app in apps_by_category.get('games', []):
|
||||
lines.append(generate_badge_line(app))
|
||||
|
||||
lines.extend([
|
||||
"</td>",
|
||||
"<td valign=\"top\" width=\"50%\">",
|
||||
"",
|
||||
"### Applications",
|
||||
"",
|
||||
"| Application | Status |",
|
||||
"| :--- | :---: |"
|
||||
])
|
||||
|
||||
# Add applications
|
||||
for app in apps_by_category.get('apps', []):
|
||||
lines.append(generate_badge_line(app))
|
||||
|
||||
lines.extend([
|
||||
"",
|
||||
"</td>",
|
||||
"</tr>",
|
||||
"</table>"
|
||||
])
|
||||
|
||||
return '\n'.join(lines) + '\n'
|
||||
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: generate-readme.py <k8s-directory> [output-file]")
|
||||
print("Example: generate-readme.py k8s/ README.md")
|
||||
sys.exit(1)
|
||||
|
||||
k8s_path = sys.argv[1]
|
||||
output_file = sys.argv[2] if len(sys.argv) > 2 else "README.md"
|
||||
|
||||
if not os.path.exists(k8s_path):
|
||||
print(f"Error: Directory {k8s_path} does not exist")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"📁 Scanning {k8s_path}...")
|
||||
apps_by_category = scan_k8s_directory(k8s_path)
|
||||
|
||||
# Print statistics
|
||||
total_apps = sum(len(apps) for apps in apps_by_category.values())
|
||||
print(f"✅ Found {total_apps} applications:")
|
||||
for category, apps in apps_by_category.items():
|
||||
if apps:
|
||||
print(f" - {category}: {len(apps)} apps")
|
||||
|
||||
print(f"📝 Generating {output_file}...")
|
||||
readme_content = generate_readme_content(apps_by_category)
|
||||
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(readme_content)
|
||||
|
||||
print(f"✅ {output_file} generated successfully")
|
||||
print(f" Total lines: {len(readme_content.splitlines())}")
|
||||
print(f" File size: {len(readme_content)} bytes")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user