name: Update Community Skins README on: schedule: - cron: '*/5 * * * *' workflow_dispatch: env: README_PATH: "${{ github.workspace }}/README.md" IMAGE_NAME: osc/skins-image GITEA_API: https://${{ vars.CONTAINER_REGISTRY }}/api/v1 jobs: generate_everything: name: Full CI/CD Pipeline runs-on: ubuntu-latest container: image: ${{ vars.CONTAINER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest steps: - name: Checkout Repository uses: actions/checkout@v4 with: token: ${{ secrets.TOKEN }} - name: Mask Sensitive Tokens run: | echo "::add-mask::${{ secrets.TOKEN }}" echo "::add-mask::${{ secrets.OSUAPIV1 }}" - name: Pull latest changes run: | git pull --rebase origin main || echo "Nothing to rebase" - name: Find Skin Repositories for all users id: find_skins shell: sh run: | set -eo pipefail total_valid_entries=0 user_rows_file=$(mktemp) avatar_rows_file=$(mktemp) page=1 while :; do echo "::group::Fetching users (page $page)" users_json=$(curl --retry 3 --retry-delay 5 -sSL \ -H "Authorization: token ${{ secrets.TOKEN }}" \ "$GITEA_API/admin/users?limit=50&page=$page&_ts=$(date +%s)") count=$(echo "$users_json" | jq 'length') [ "$count" -eq 0 ] && break echo "➤ Found $count users" echo "::endgroup::" for i in $(seq 0 $((count - 1))); do user_login=$(echo "$users_json" | jq -r ".[$i].login") echo "::group::🔍 Checking user: $user_login" repos_json=$(curl --retry 3 --retry-delay 5 -sSL \ -H "Authorization: token ${{ secrets.TOKEN }}" \ "$GITEA_API/users/$user_login/repos?_ts=$(date +%s)") if ! echo "$repos_json" | jq -e . >/dev/null 2>&1; then echo "⚠️ Failed to parse repos for $user_login, skipping" echo "::endgroup::" continue fi repos_count=$(echo "$repos_json" | jq 'length') echo "📦 Found $repos_count repositories" [ "$repos_count" -eq 0 ] && echo "::endgroup::" && continue for j in $(seq 0 $((repos_count - 1))); do owner=$(echo "$repos_json" | jq -r ".[$j].owner.login") repo=$(echo "$repos_json" | jq -r ".[$j].name") html_url=$(echo "$repos_json" | jq -r ".[$j].html_url") echo "→ Checking repo: $owner/$repo" http_code=$(curl --retry 3 --retry-delay 5 -s -w "%{http_code}" -o temp_readme.json \ -H "Authorization: token ${{ secrets.TOKEN }}" \ "$GITEA_API/repos/$owner/$repo/contents/README.md?_ts=$(date +%s)") if [ "$http_code" != "200" ]; then echo "⛔ No README.md found (HTTP $http_code)" continue fi content=$(jq -r .content < temp_readme.json | base64 -d || echo "") if ! echo "$content" | grep -q "^---$"; then echo "❌ Missing frontmatter"; continue; fi if ! echo "$content" | grep -q "^gitea: none"; then echo "❌ Missing 'gitea: none'"; continue; fi if ! echo "$content" | grep -q "^include_toc: true"; then echo "❌ Missing 'include_toc: true'"; continue; fi if ! echo "$content" | grep -q "^# Skins"; then echo "❌ Missing '# Skins' header"; continue; fi osu_id=$(echo "$content" | awk '/osuid:[ ]*[0-9]+/ { match($0, /[0-9]+/); print substr($0, RSTART, RLENGTH); exit }') if [ -z "$osu_id" ]; then echo "❌ Missing or invalid osuid" continue fi user_data=$(curl --retry 3 --retry-delay 5 -s \ "https://osu.ppy.sh/api/get_user?k=${{ secrets.OSUAPIV1 }}&u=$osu_id&type=id&_ts=$(date +%s)") if [ "$(echo "$user_data" | jq 'length')" -eq 0 ]; then echo "❌ osu! API returned no data for osuid $osu_id" continue fi pp_rank=$(echo "$user_data" | jq -r '.[0].pp_rank // "9999999"') pp_country_rank=$(echo "$user_data" | jq -r '.[0].pp_country_rank // "-"') username=$(echo "$user_data" | jq -r '.[0].username // "'$owner'"') padded_rank=$(printf "%07d" "$pp_rank") printf "%s|%s%s%sProfileSkins\n" \ "$padded_rank" "$username" "$pp_rank" "$pp_country_rank" "$osu_id" "$html_url" >> "$user_rows_file" timestamp=$(( $(date +%s) / 86400 * 86400 )) printf "%s|\n" \ "$padded_rank" "$html_url" "$osu_id" "$timestamp" >> "$avatar_rows_file" echo "✅ Match: $owner/$repo with osu! user $username (Rank #$pp_rank)" total_valid_entries=$((total_valid_entries + 1)) done echo "::endgroup::" done page=$((page + 1)) done echo "user_rows_file=$user_rows_file" >> "$GITHUB_OUTPUT" echo "avatar_rows_file=$avatar_rows_file" >> "$GITHUB_OUTPUT" echo "total_valid_entries=$total_valid_entries" >> "$GITHUB_OUTPUT" echo "✔️ Total valid skin repos: $total_valid_entries" - name: Update README with user skins id: update_readme shell: bash run: | set -eo pipefail user_rows_file="${{ steps.find_skins.outputs.user_rows_file }}" avatar_rows_file="${{ steps.find_skins.outputs.avatar_rows_file }}" total_valid_entries="${{ steps.find_skins.outputs.total_valid_entries }}" README_PATH="README.md" if [ "$total_valid_entries" -eq 0 ]; then echo "No valid entries found – skipping README update" exit 0 fi # Backup the old README cp "$README_PATH" "${README_PATH}.bak" # Write the new README cat > "$README_PATH" <<-EOF # osu! Swiss Community Skin collection Welcome to the osu! Swiss Community Skin collection, this repository archives and showcases Skins osc members use. Enjoy looking around, click file names to download the skins and click on the images to see more about the skins. ## How do I add my skins here? If you're interested in adding your skins here please follow this tutorial [how-to-use](/how-to-use.md) ## Skins
list instead of icons
EOF sort -t '|' -k1,1n "$user_rows_file" | cut -d'|' -f2- | sed 's/^/ /' >> "$README_PATH" cat >> "$README_PATH" <<-EOF
Name Global Rank Country Rank Profile Skins

EOF sort -t '|' -k1,1n "$avatar_rows_file" | cut -d'|' -f2- | sed 's/^/ /' >> "$README_PATH" cat >> "$README_PATH" <<-EOF

EOF # Clean up temp files rm -f "$user_rows_file" "$avatar_rows_file" # Check for differences to avoid unnecessary commit if cmp -s "$README_PATH" "${README_PATH}.bak"; then echo "README has not changed, skipping commit" exit 0 else echo "README updated" fi - name: Configure Git run: | git config user.email "arlind@sulej.ch" git config user.name "ci-bot" git config lfs.https://${{ vars.CONTAINER_REGISTRY }}/arlind/skins.git/info/lfs.locksverify true - name: Add and Commit changes run: | git config advice.addIgnoredFile false git add README.md git commit -m "[ci skip] push back from pipeline" -q || echo "No changes to commit" - name: Push changes and create tag run: | if [ "${GITHUB_REF}" = "refs/heads/main" ]; then git push origin HEAD:main || echo "No changes to push" else git push origin HEAD:"${GITHUB_REF_NAME}" || echo "No changes to push" fi