diff options
| author | supahgreg <supahgreg@users.noreply.github.com> | 2025-10-16 03:17:00 +0000 |
|---|---|---|
| committer | supahgreg <supahgreg@users.noreply.github.com> | 2025-10-16 03:17:00 +0000 |
| commit | 003b979ae2ce2db98946fd5be5d273dd982f3265 (patch) | |
| tree | fa8554bcd69a48c243815f5488cf689dbafe6657 /.github | |
| parent | 703d310e400f1f4162d4e38afa3f5bf5169c5377 (diff) | |
Test out a (generated) plugin JSON-building workflow.
Diffstat (limited to '.github')
| -rw-r--r-- | .github/workflows/update-plugins-json.yml | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/.github/workflows/update-plugins-json.yml b/.github/workflows/update-plugins-json.yml new file mode 100644 index 000000000..570416103 --- /dev/null +++ b/.github/workflows/update-plugins-json.yml @@ -0,0 +1,292 @@ +name: Update Plugins JSON + +on: + schedule: + # Run weekly on Mondays at 00:00 UTC + - cron: '0 0 * * 1' + # Allow manual triggering + workflow_dispatch: + +permissions: + contents: write + +jobs: + update-plugins: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.4' + tools: none + + - name: Fetch and process plugin repositories + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + #!/bin/bash + set -e + + cat > /tmp/parse_plugin.php << 'PHPEOF' + <?php + $content = file_get_contents($argv[1]); + + // Use token_get_all to parse PHP code more reliably + $tokens = token_get_all($content); + $class_name = ''; + $description = ''; + + // Find class declaration + for ($i = 0; $i < count($tokens); $i++) { + if (is_array($tokens[$i]) && $tokens[$i][0] === T_CLASS) { + // Skip whitespace + $j = $i + 1; + while ($j < count($tokens) && is_array($tokens[$j]) && $tokens[$j][0] === T_WHITESPACE) { + $j++; + } + // Get class name + if ($j < count($tokens) && is_array($tokens[$j]) && $tokens[$j][0] === T_STRING) { + $class_name = $tokens[$j][1]; + break; + } + } + } + + // Find about() function and extract description from return array + $in_about = false; + $in_return = false; + $array_depth = 0; + $strings = []; + + for ($i = 0; $i < count($tokens); $i++) { + $token = $tokens[$i]; + + // Skip non-array tokens unless we're in return statement + if (!is_array($token)) { + if ($in_return) { + if ($token === '[') { + $array_depth++; + } elseif ($token === ']' || $token === ')') { + $array_depth--; + if ($array_depth === 0) { + break; // End of return array + } + } + } + continue; + } + + // Look for 'function about' + if ($token[0] === T_FUNCTION) { + // Check if next non-whitespace token is 'about' + $j = $i + 1; + while ($j < count($tokens) && is_array($tokens[$j]) && $tokens[$j][0] === T_WHITESPACE) { + $j++; + } + if ($j < count($tokens) && is_array($tokens[$j]) && $tokens[$j][0] === T_STRING && $tokens[$j][1] === 'about') { + $in_about = true; + $i = $j; + continue; + } + } + + if ($in_about && $token[0] === T_RETURN) { + $in_return = true; + continue; + } + + if ($in_return) { + // Track array() syntax + if ($token[0] === T_ARRAY) { + // Look ahead for opening parenthesis (skip whitespace) + $k = $i + 1; + while ($k < count($tokens) && is_array($tokens[$k]) && $tokens[$k][0] === T_WHITESPACE) { + $k++; + } + if ($k < count($tokens) && $tokens[$k] === '(') { + $array_depth++; + } + } elseif ($token[0] === T_CONSTANT_ENCAPSED_STRING) { + // This is a string literal + $str = $token[1]; + // Remove quotes and decode + $str = substr($str, 1, -1); + $str = stripcslashes($str); + $strings[] = $str; + } + } + } + + // Description is at index 1 + if (isset($strings[1])) { + $description = $strings[1]; + } + + echo json_encode(['class_name' => $class_name, 'description' => $description], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE); + PHPEOF + + # Get all repositories from tt-rss organization that start with tt-rss-plugin- + echo "Fetching repositories from tt-rss organization..." + + plugins_json="[]" + page=1 + + while true; do + response=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/orgs/tt-rss/repos?type=public&per_page=100&page=$page") + + # Check for API errors + if echo "$response" | jq -e '.message' >/dev/null 2>&1; then + echo "API Error: $(echo "$response" | jq -r '.message')" + exit 1 + fi + + # Check if we got an empty array (no more pages) + if [ "$(echo "$response" | jq '. | length')" -eq 0 ]; then + break + fi + + # Filter repositories that start with tt-rss-plugin- and are not archived + filtered=$(echo "$response" | jq '[.[] | select(.name | startswith("tt-rss-plugin-")) | select(.archived == false)]') + + # Process each repository + for repo in $(echo "$filtered" | jq -r '.[] | @base64'); do + _jq() { + echo "$repo" | base64 --decode | jq -r "$1" + } + + repo_name=$(_jq '.name') + full_name=$(_jq '.full_name') + html_url=$(_jq '.html_url') + clone_url=$(_jq '.clone_url') + repo_description=$(_jq '.description // ""') + + echo "Processing repository: $repo_name" + + # Get the latest commit timestamp + commits_response=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/$full_name/commits?per_page=1") + + # Check if commits response is valid + if echo "$commits_response" | jq -e '.[0]' >/dev/null 2>&1; then + last_update=$(echo "$commits_response" | jq -r '.[0].commit.committer.date') + else + echo " Warning: Could not fetch commit info for $repo_name" + last_update="" + fi + + # Skip if no last_update (indicates repository might be empty or inaccessible) + if [ -z "$last_update" ]; then + echo " Skipping $repo_name: no commit history found" + continue + fi + + # Try to fetch init.php + init_php=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3.raw" \ + "https://api.github.com/repos/$full_name/contents/init.php" 2>/dev/null || echo "") + + # Try to extract the class name and plugin description from init.php + class_name="" + description="" + + if [ -n "$init_php" ]; then + # Save init.php to temporary file for PHP processing + temp_file=$(mktemp) + echo "$init_php" > "$temp_file" + + php_output=$(php /tmp/parse_plugin.php "$temp_file" 2>/dev/null || echo '{"class_name":"","description":""}') + + class_name=$(echo "$php_output" | jq -r '.class_name // ""') + description=$(echo "$php_output" | jq -r '.description // ""') + + rm -f "$temp_file" + fi + + # Skip if no class name was found + if [ -z "$class_name" ]; then + echo " Skipping $repo_name: no class name found in init.php" + continue + fi + + # Fallback to repository description if no description was found + if [ -z "$description" ]; then + description="$repo_description" + fi + + # Placeholder description if still empty + if [ -z "$description" ]; then + description="" + fi + + # Create topics array + topics=$(echo "$class_name" | tr '[:upper:]' '[:lower:]') + topics_json="[\"$topics\"]" + + # Build plugin JSON object + plugin_json=$(jq -n \ + --arg name "$class_name" \ + --arg description "$description" \ + --argjson topics "$topics_json" \ + --arg html_url "$html_url" \ + --arg clone_url "$clone_url" \ + --arg last_update "$last_update" \ + '{ + name: $name, + description: $description, + topics: $topics, + html_url: $html_url, + clone_url: $clone_url, + last_update: $last_update + }') + + # Append to plugins array + plugins_json=$(echo "$plugins_json" | jq --argjson plugin "$plugin_json" '. += [$plugin]') + done + + page=$((page + 1)) + done + + # Sort by name and save + echo "$plugins_json" | jq 'sort_by(.name)' > plugins.json + + echo "Plugin list updated successfully!" + cat plugins.json + + - name: Deploy to gh-pages branch + run: | + # Save plugins.json to a safe location + cp plugins.json /tmp/plugins.json + + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + + # Fetch gh-pages branch + git fetch origin gh-pages 2>/dev/null || true + + if git rev-parse --verify origin/gh-pages >/dev/null 2>&1; then + # gh-pages exists, check it out + git checkout gh-pages + else + # Create new orphan gh-pages branch + git checkout --orphan gh-pages + git rm -rf . 2>/dev/null || true + fi + + # Restore plugins.json from safe location + cp /tmp/plugins.json plugins.json + git add plugins.json + + # Check if there are changes to commit + if git diff --staged --quiet; then + echo "No changes to commit" + else + git commit -m "Update plugins list [automated]" + git push origin gh-pages + fi |