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: Mask Sensitive Tokens run: | echo "::add-mask::${{ secrets.TOKEN }}" echo "::add-mask::${{ secrets.OSUAPIV1 }}" - name: Checkout Repository uses: actions/checkout@v4 with: token: ${{ secrets.TOKEN }} - name: Pull latest changes run: | # Pull latest changes to prevent push conflicts git remote set-url origin https://x-access-token:${{ secrets.TOKEN }}@${{ github.repository_owner }}.gitea.io/${{ github.repository }}.git git fetch origin main git rebase origin/main || { echo "⚠️ Git rebase failed, likely due to conflicts." git rebase --abort || true exit 1 } - name: Find Skin Repositories for all users id: find_skins run: | set -eo pipefail total_valid_entries=0 user_rows_file=$(mktemp) avatar_rows_file=$(mktemp) trap 'rm -f "$user_rows_file" "$avatar_rows_file" temp_dir.json temp_readme.json' EXIT page=1 while :; do 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 on page $page" echo for i in $(seq 0 $((count - 1))); do user_login=$(echo "$users_json" | jq -r ".[$i].login") echo "🔍 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 " ⚠️ Could not parse repos for $user_login" echo continue fi echo "$repos_json" | jq -c '.[]' | xargs -n1 -P4 -I{} bash -c ' repo_data="{}" owner=$(echo "$repo_data" | jq -r ".owner.login") repo=$(echo "$repo_data" | jq -r ".name") html_url=$(echo "$repo_data" | jq -r ".html_url") echo " → Repo: $owner/$repo" dir_code=$(curl --connect-timeout 5 --max-time 10 --retry 3 --retry-delay 5 -s -w "%{http_code}" -o temp_dir.json \ -H "Authorization: token ${{ secrets.TOKEN }}" \ "$GITEA_API/repos/$owner/$repo/contents/Skins?_ts=$(date +%s)") if [ "$dir_code" != "200" ]; then echo " ❌ Skipped: No Skins/ dir (HTTP $dir_code)" exit 0 fi readme_code=$(curl --connect-timeout 5 --max-time 10 --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 [ "$readme_code" != "200" ]; then echo " ❌ Skipped: No README.md (HTTP $readme_code)" exit 0 fi content=$(jq -r .content < temp_readme.json | base64 -d || echo "") osu_id=$(echo "$content" | awk "/osuid:[ ]*[0-9]+/ { match(\$0, /[0-9]+/); print substr(\$0, RSTART, RLENGTH); exit }") if [ -z "$osu_id" ]; then echo " ❌ Skipped: no osuid" exit 0 fi user_data=$(curl --connect-timeout 5 --max-time 10 --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 " ❌ Skipped: osu! API no data" exit 0 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: $username (Rank #$pp_rank)" exit 0 ' done page=$((page + 1)) done { echo "user_rows_file=$user_rows_file" echo "avatar_rows_file=$avatar_rows_file" echo "total_valid_entries=$total_valid_entries" } >> "$GITHUB_OUTPUT" echo echo "✅ Total valid skin entries found: $total_valid_entries" - name: Update README with user skins id: update_readme 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="${{ env.README_PATH }}" if [ "$total_valid_entries" -eq 0 ]; then echo "No valid entries found, skipping README update" exit 0 fi cp "$README_PATH" "${README_PATH}.bak" 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 if git diff --quiet "$README_PATH"; then echo "README has not changed, skipping commit" rm -rf "${README_PATH}.bak" exit 0 else echo "README updated" rm -rf "${README_PATH}.bak" 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_PATH" 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