Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions .github/workflows/featured-software.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
name: Generate Featured Content

on:
push:
workflow_dispatch:
inputs:
gemini_api_key:
description: 'Google Gemini API Key for AI-powered summary generation'
required: false
type: string
Comment on lines +6 to +10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Security concern: API key passed via workflow_dispatch input is not masked.

Workflow dispatch inputs of type string are logged in plain text in workflow run logs. If someone triggers this workflow manually with an API key, it will be visible in the logs.

Consider removing this input and relying solely on secrets.GEMINI_API_KEY:

🔒 Suggested fix
   workflow_dispatch:
-    inputs:
-      gemini_api_key:
-        description: 'Google Gemini API Key for AI-powered summary generation'
-        required: false
-        type: string
   schedule:
 env:
-  GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY || inputs.gemini_api_key }}
+  GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
🤖 Prompt for AI Agents
In @.github/workflows/featured-software.yml around lines 6 - 10, The workflow
exposes a sensitive API key via the workflow_dispatch input named
gemini_api_key; remove the gemini_api_key input from the inputs block and update
any steps that reference it to instead read from the repository secret
secrets.GEMINI_API_KEY (e.g., use env: GEMINI_API_KEY: ${{
secrets.GEMINI_API_KEY }} or reference it directly in the step), ensuring no
plain-text inputs remain in the featured-software.yml workflow.

schedule:
# Run every Monday at 00:00 UTC
- cron: '0 0 * * 1'

env:
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY || inputs.gemini_api_key }}

permissions:
contents: write

jobs:
generate-featured-content:
runs-on: ubuntu-latest

steps:
- name: Checkout current repository
uses: actions/checkout@v4

- name: Checkout armbian/configng repository
uses: actions/checkout@v4
with:
repository: armbian/configng
path: configng

- name: Copy config.software.json
run: |
if [ -f "configng/tools/json/config.software.json" ]; then
echo "Copying config.software.json..."
cp configng/tools/json/config.software.json ./config.software.json
echo "File copied successfully"
else
echo "Warning: config.software.json not found in configng repository"
fi

- name: Install Python dependencies
run: |
pip3 install --upgrade google-genai pyyaml

- name: Generate featured content
env:
GHOST_API_KEY: ${{ secrets.GHOST_API_KEY }}
GHOST_API_URL: ${{ secrets.GHOST_API_URL }}
GITHUB_TOKEN: ${{ secrets.SPONSORS }}
run: |
set -x # Debug mode

cd featured-content/scripts

# Create temporary directory for intermediate results
mkdir -p /tmp/featured-steps

# 1. Fetch GitHub releases
echo "=== Step 1: Fetching GitHub releases ==="
python3 github_releases.py --limit 5 > /tmp/featured-steps/01-releases.json || echo "[]" > /tmp/featured-steps/01-releases.json

# 2. Fetch Ghost news
echo "=== Step 2: Fetching Ghost news ==="
if [ -n "$GHOST_API_URL" ]; then
python3 ghost_news.py --url "$GHOST_API_URL" --limit 5 > /tmp/featured-steps/02-news.json || echo "[]" > /tmp/featured-steps/02-news.json
else
echo "[]" > /tmp/featured-steps/02-news.json
fi

# 3. Fetch GitHub sponsors
echo "=== Step 3: Fetching GitHub sponsors ==="
python3 sponsors.py --limit 10 > /tmp/featured-steps/03-sponsors.json || echo "[]" > /tmp/featured-steps/03-sponsors.json

# 4. Process software list (optional)
echo "=== Step 4: Processing software list ==="
if [ -f "../../config.software.json" ]; then
python3 software_list.py --config ../../config.software.json --limit 10 > /tmp/featured-steps/04-software.json || echo "[]" > /tmp/featured-steps/04-software.json
else
echo "[]" > /tmp/featured-steps/04-software.json
fi

# 5. Load manual entries
echo "=== Step 5: Loading manual entries ==="
python3 manual_list.py --file ../manual_featured.yml > /tmp/featured-steps/05-manual.json || echo "[]" > /tmp/featured-steps/05-manual.json

# 6. Select N entries from each category (N=2 means 2 per type)
echo "=== Step 6: Selecting featured entries ==="
python3 select_featured.py 2 /tmp/featured-steps/*.json > ../../featured-content.json

# Display counts
echo "=== Summary ==="
for step in /tmp/featured-steps/*.json; do
name=$(basename "$step" .json)
count=$(cat "$step" | jq '. | length' 2>/dev/null || echo 0)
echo " $name: $count"
done

- name: Update generation timestamp
run: |
# Replace null timestamp with actual ISO timestamp
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
sed -i "s/\"generated_at\": null/\"generated_at\": \"$TIMESTAMP\"/" featured-content.json || true

- name: Display generated JSON
run: |
echo "=== Generated Featured Content JSON ==="
cat featured-content.json

- name: Commit and push changes
run: |
git config --local user.email "github-actions[bot]@users.noreply.github.com"
git config --local user.name "github-actions[bot]"

# Add the generated file
git add featured-content.json

# Check if there are changes to commit
if git diff --staged --quiet; then
echo "No changes to commit"
else
git commit -m "Generate featured content selection [skip ci]"
git push
fi
201 changes: 201 additions & 0 deletions featured-content.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
{
"entries": [
{
"type": "service",
"id": "armbian-sponsors",
"name": "Support Armbian Development",
"url": "https://github.com/sponsors/armbian",
"title": "Become a Sponsor",
"summary": "Support continued Armbian development through sponsorship. Contributors get access to beta builds, priority support, and direct influence on project direction.",
"author": {
"name": "Armbian Project",
"handle": "@armbian"
},
"tags": [
"support",
"sponsorship",
"donate",
"community"
],
"motd": {
"line": "Support Armbian: Become a sponsor",
"hint": "https://github.com/sponsors/armbian"
},
"manual": true
},
{
"type": "sponsor",
"id": "sponsor-4",
"name": "Sponsor: ahoneybun",
"url": "https://github.com/ahoneybun",
"title": "Aaron Honeycutt - Silver Sponsor",
"summary": "Sponsor of Armbian build",
"image": "https://avatars.githubusercontent.com/u/4884946?u=2fdb7e87d7a96c50f031762f20a946b48f73bcb2&v=4",
"author": {
"name": "Aaron Honeycutt",
"handle": "@ahoneybun"
},
"tags": [
"sponsor",
"silver",
"community"
],
"motd": {
"line": "Silver level supporter"
}
},
{
"type": "news",
"id": "ghost-696407e693dc320001185cd0",
"name": "Armbian",
"url": "http://blog.armbian.com/forget-third-party-utilities-meet-armbian-imager/",
"title": "Forget third-party utilities: meet Armbian Imager",
"summary": "Armbian Imager eliminates the guesswork from flashing SBC images. Real-time board detection, persistent caching, and built-in safety make installation fast, simple, and risk-free",
"published_at": "2026-01-17T14:43:51.000+01:00",
"image": "http://blog.armbian.com/content/images/2026/01/introducing-armbian-imager.png",
Comment on lines +51 to +55
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

HTTP URLs should use HTTPS for security.

The Ghost news entries contain HTTP URLs (Lines 52, 55) instead of HTTPS. Since blog.armbian.com likely supports HTTPS, the fetching script (ghost_news.py) should ensure URLs are normalized to HTTPS to prevent mixed-content warnings and improve security.

Similarly, Lines 119 and 123 have the same issue.

🤖 Prompt for AI Agents
In `@featured-content.json` around lines 51 - 55, The featured-content JSON
contains HTTP URLs for blog.armbian.com in the "url" and "image" fields; update
these entries to use HTTPS (e.g., change "http://blog.armbian.com/..." to
"https://blog.armbian.com/...") and also change the other occurrences noted;
additionally, update the Ghost fetching/normalization code in ghost_news.py
(e.g., the function that builds or normalizes URLs—rename/locate code like
normalize_url or the URL construction block) to enforce scheme="https" for
blog.armbian.com by parsing the URL, setting url.scheme = "https" (or replacing
the prefix) before saving so future fetched entries are normalized to HTTPS.

"author": {
"name": "Daniele Briguglio"
},
"tags": [
"Armbian",
"SBC",
"imager",
"linux"
]
},
{
"type": "software",
"id": "ART001",
"name": "CDN router",
"url": "",
"title": "CDN router",
"summary": "Router for repository mirror automation",
"author": {
"name": "efectn",
"handle": "efectn"
},
"tags": [
"armbian"
],
"motd": {
"line": "Featured: CDN router",
"hint": "armbian-config \u2192 Software"
}
},
{
"type": "contribution",
"id": "release-v26.2.0-trunk.146",
"name": "Weekly digest",
"url": "https://github.com/armbian/build/releases/tag/v26.2.0-trunk.146",
"title": "Armbian Weekly digest Released",
"summary": "This week in Armbian development saw a series of refinements and maintenance updates across the build and configuration repositories. Contributors focused on workflow standardization, cosmetic improve...",
"published_at": "2025-12-29T06:49:33Z",
"highlights": [],
"tags": [
"release",
"update",
"armbian"
]
},
{
"type": "contribution",
"id": "release-v26.2.0-trunk.278",
"name": "Weekly digest",
"url": "https://github.com/armbian/build/releases/tag/v26.2.0-trunk.278",
"title": "Armbian Weekly digest Released",
"summary": "This week\u2019s Armbian development saw a major cleanup of legacy toolchain code, alongside numerous board-specific improvements and kernel updates. Support was added for the Nuvoton MA35D1 NuMaker IoT bo...",
"published_at": "2026-01-19T06:52:55Z",
"highlights": [],
"tags": [
"release",
"update",
"armbian"
]
},
{
"type": "news",
"id": "ghost-69782e9693dc320001185e07",
"name": "Armbian News",
"url": "http://blog.armbian.com/github-highlights-12/",
"title": "Github Highlights",
"summary": "This week\u2019s Armbian development saw a wide range of updates focused on automation, hardware support, and workflow improvements. Key highlights include the introduction of automatic YAML target generation, expanded support for Hetzner ARM64 runners, and enhancements to the redirector update workflow with cache mirror support. Several board-specific fixes and feature additions were made, including improved power cycle handling for meson-sm1 devices and new binary files for RK35 series components. ",
"published_at": "2026-01-27T04:20:04.000+01:00",
"image": "http://blog.armbian.com/content/images/2026/01/githubhighlights-2-2.webp",
"author": {
"name": "Michael Robinson"
},
"tags": []
},
{
"type": "sponsor",
"id": "sponsor-9",
"name": "Sponsor: Nardol",
"url": "https://github.com/Nardol",
"title": "Patrick ZAJDA - Silver Sponsor",
"summary": "Sponsor of Armbian build",
"image": "https://avatars.githubusercontent.com/u/2864821?v=4",
"author": {
"name": "Patrick ZAJDA",
"handle": "@Nardol"
},
"tags": [
"sponsor",
"silver",
"community"
],
"motd": {
"line": "Silver level supporter"
}
},
{
"type": "service",
"id": "armbian-actions",
"name": "Armbian Actions",
"url": "https://actions.armbian.com/",
"title": "Armbian CI/CD Infrastructure",
"summary": "Automated build and testing infrastructure for Armbian firmware. Check build status, download latest images, and track releases across all supported boards.",
"author": {
"name": "Armbian",
"handle": "@armbian"
},
"tags": [
"infrastructure",
"ci-cd",
"build",
"automation"
],
"motd": {
"line": "Armbian Actions: Track builds and releases",
"hint": "https://actions.armbian.com"
},
"manual": true
},
{
"type": "software",
"id": "EMB001",
"name": "Emby",
"url": "",
"title": "Emby",
"summary": "Emby organizes video, music, live TV, and photos",
"author": {
"name": "schwar3kat",
"handle": "schwar3kat"
},
"tags": [
"media"
],
"motd": {
"line": "Featured: Emby",
"hint": "armbian-config \u2192 Software"
}
}
],
"count": 10,
"sources": {
"contribution": 5,
"news": 5,
"sponsor": 10,
"software": 10,
"service": 6
}
}
Loading