From 200eb35a91035cb7d116fadf81b18a9c47d89227 Mon Sep 17 00:00:00 2001 From: Arlind Sulejmani Date: Sat, 7 Jun 2025 12:09:24 +0200 Subject: [PATCH] Check for new repositories and update ranks --- .gitea/workflows/ci.yml | 157 +++++++++++++++++++++++++++++++ .gitea/workflows/deploy-ci.yaml | 121 ++++++++++++++++++++++++ README.md | 30 ------ docs/example_variables.png | Bin 0 -> 11086 bytes docs/{secret1.png => secret.png} | Bin docs/secret2.png | Bin 11140 -> 0 bytes how-to-use.md | 25 +++-- 7 files changed, 295 insertions(+), 38 deletions(-) create mode 100644 .gitea/workflows/ci.yml create mode 100644 .gitea/workflows/deploy-ci.yaml create mode 100644 docs/example_variables.png rename docs/{secret1.png => secret.png} (100%) delete mode 100644 docs/secret2.png diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..591127b --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,157 @@ +name: Update Community Skins README + +on: + schedule: + - cron: '*/5 * * * *' + workflow_dispatch: + +env: + README_PATH: "${{ github.workspace }}/README.md" + IMAGE_NAME: arlind/skins + 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: Find matching skin entries + id: find_skins + shell: sh + run: | + total_valid_entries=0 + user_rows_file=$(mktemp) + avatar_rows_file=$(mktemp) + + echo "Fetching users page 1..." >&2 + users_json=$(curl -sSL -H "Authorization: token ${{ secrets.TOKEN }}" "$GITEA_API/admin/users?limit=50&page=1") + + jq_type=$(echo "$users_json" | jq -r 'type' 2>/dev/null || echo "jq_error_type") + jq_length=$(echo "$users_json" | jq 'length' 2>/dev/null || echo "jq_error_length") + if [ "$jq_type" != "array" ] || [ "$jq_length" -eq 0 ]; then + echo "No users found or invalid JSON received on page 1. (Type: $jq_type, Length: $jq_length)." >&2 + exit 1 + fi + + i=0 + while [ "$i" -lt "$jq_length" ]; do + user_login=$(echo "$users_json" | jq -r ".[$i].login") + echo "Processing user: $user_login" >&2 + + repos_json=$(curl -sSL -H "Authorization: token ${{ secrets.TOKEN }}" "$GITEA_API/users/$user_login/repos") + repos_type=$(echo "$repos_json" | jq -r 'type' 2>/dev/null || echo "not_array") + repos_count=$(echo "$repos_json" | jq 'length' 2>/dev/null || echo "0") + if [ "$repos_type" != "array" ] || [ "$repos_count" -eq 0 ]; then + echo " No repos or invalid JSON for $user_login" >&2 + i=$((i + 1)) + continue + fi + + j=0 + while [ "$j" -lt "$repos_count" ]; 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: $repo" >&2 + readme_json=$(curl -sSL -H "Authorization: token ${{ secrets.TOKEN }}" "$GITEA_API/repos/$owner/$repo/contents/README.md" || echo "{}") + + if echo "$readme_json" | jq -e '.content' >/dev/null 2>&1; then + content=$(echo "$readme_json" | jq -r .content | base64 -d || echo "") + + echo "$content" | grep -q "^---$" && \ + echo "$content" | grep -q "^gitea: none" && \ + echo "$content" | grep -q "^include_toc: true" && \ + echo "$content" | grep -q "^# Skins" + if [ $? -eq 0 ]; then + osu_id=$(echo "$content" | awk '/osuid:[ ]*[0-9]+/ { match($0, /[0-9]+/); print substr($0, RSTART, RLENGTH); exit }') + if [ -n "$osu_id" ]; then + user_data=$(curl -s "https://osu.ppy.sh/api/get_user?k=${{ secrets.OSUAPIV1 }}&u=$osu_id&type=id") + 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" + printf "%s| \n" \ + "$padded_rank" "$html_url" "$osu_id" >> "$avatar_rows_file" + total_valid_entries=$((total_valid_entries + 1)) + fi + fi + fi + j=$((j + 1)) + done + i=$((i + 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" + + - name: Update README with user skins + run: | + echo "# osu! Swiss Community Skin collection" > "$README_PATH" + echo "" >> "$README_PATH" + echo "Welcome to the osu! Swiss Community Skin collection, this repository archives and showcases Skins osc members use." >> "$README_PATH" + echo "" >> "$README_PATH" + echo "Enjoy looking around, click file names to download the skins." >> "$README_PATH" + echo "" >> "$README_PATH" + echo "## How do I add my skins here?" >> "$README_PATH" + echo "" >> "$README_PATH" + echo "If you're interested in adding your skins here please follow this tutorial [how-to-use](/how-to-use.md)" >> "$README_PATH" + echo "" >> "$README_PATH" + echo "## Skins" >> "$README_PATH" + echo "" >> "$README_PATH" + echo "
" >> "$README_PATH" + echo " list instead of icons" >> "$README_PATH" + echo "
" >> "$README_PATH" + echo " " >> "$README_PATH" + echo " " >> "$README_PATH" + echo " " >> "$README_PATH" + echo " " >> "$README_PATH" + echo " " >> "$README_PATH" + echo " " >> "$README_PATH" + echo " " >> "$README_PATH" + echo " " >> "$README_PATH" + echo " " >> "$README_PATH" + echo " " >> "$README_PATH" + echo " " >> "$README_PATH" + sort -t '|' -k1,1n "${{ steps.find_skins.outputs.user_rows_file }}" | cut -d'|' -f2- >> "$README_PATH" + echo " " >> "$README_PATH" + echo "
NameGlobal RankCountry RankProfileSkins
" >> "$README_PATH" + echo "
" >> "$README_PATH" + echo "" >> "$README_PATH" + echo "

" >> "$README_PATH" + sort -t '|' -k1,1n "${{ steps.find_skins.outputs.avatar_rows_file }}" | cut -d'|' -f2- >> "$README_PATH" + echo "

" >> "$README_PATH" + rm -f "${{ steps.find_skins.outputs.user_rows_file }}" "${{ steps.find_skins.outputs.avatar_rows_file }}" + echo "Generated skins section and updated '$README_PATH' successfully." >&2 + + - 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 diff --git a/.gitea/workflows/deploy-ci.yaml b/.gitea/workflows/deploy-ci.yaml new file mode 100644 index 0000000..f051fcd --- /dev/null +++ b/.gitea/workflows/deploy-ci.yaml @@ -0,0 +1,121 @@ +name: Sync CI from skins-template to Every User Repository + +on: + workflow_dispatch: + +env: + TEMPLATE_REPO_URL: https://${{ secrets.TOKEN }}@${{ vars.CONTAINER_REGISTRY }}/osc/skins-template.git + TEMPLATE_REL_PATH: .gitea/workflows/ci.yml + GITEA_API: https://${{ vars.CONTAINER_REGISTRY }}/api/v1 + +jobs: + sync-all: + runs-on: ubuntu-latest + container: + image: ${{ vars.CONTAINER_REGISTRY }}/arlind/skins:latest + + steps: + - name: Clone skins-template + run: | + echo "[Sync CI Started]" + git clone --quiet "${{ env.TEMPLATE_REPO_URL }}" --depth 1 template-repo + cd template-repo + git checkout --quiet HEAD -- "${{ env.TEMPLATE_REL_PATH }}" + + - name: Fetch and update every user repository + run: | + page=1 + per_page=50 + + while :; do + users_json=$( + curl -sSL -H "Authorization: token ${{ secrets.TOKEN }}" \ + "${{ env.GITEA_API }}/admin/users?limit=$per_page&page=$page" + ) + users_count=$(echo "$users_json" | jq 'length') + if [ "$users_count" -eq 0 ]; then + break + fi + + for i in $(seq 0 $((users_count - 1))); do + user_login=$(echo "$users_json" | jq -r ".[$i].login") + repos_json=$( + curl -sSL -H "Authorization: token ${{ secrets.TOKEN }}" \ + "${{ env.GITEA_API }}/users/${user_login}/repos" + ) + repo_count=$(echo "$repos_json" | jq 'length') + + for j in $(seq 0 $((repo_count - 1))); do + owner=$(echo "$repos_json" | jq -r ".[$j].owner.login") + repo=$(echo "$repos_json" | jq -r ".[$j].name") + + ( + set -e + echo "" + echo "[Processing repository: ${owner}/${repo}]" + + echo " Checking README.md content" + readme_json=$(curl -sSL -H "Authorization: token ${{ secrets.TOKEN }}" \ + "${{ env.GITEA_API }}/repos/${owner}/${repo}/contents/README.md" || echo "{}") + + if ! echo "$readme_json" | jq -e '.content' >/dev/null 2>&1; then + echo " → No README.md found or inaccessible, skipping ${owner}/${repo}" + exit 0 + fi + + content=$(echo "$readme_json" | jq -r .content | base64 -d 2>/dev/null || echo "") + if ! echo "$content" | head -n 20 | grep -q "^---$"; then + echo " → Missing YAML front matter (---), skipping ${owner}/${repo}" + exit 0 + fi + if ! ( echo "$content" | grep -q "^gitea: none" \ + && echo "$content" | grep -q "^include_toc: true" \ + && echo "$content" | grep -q "^# Skins" ); then + echo " → README.md does not match required headers, skipping ${owner}/${repo}" + exit 0 + fi + + echo " ✓ README.md matches expected format; proceeding" + + echo " Cloning ${owner}/${repo}..." + tmpdir=$(mktemp -d) + git clone --quiet "https://${{ secrets.TOKEN }}@${{ vars.CONTAINER_REGISTRY }}/${owner}/${repo}.git" \ + --depth 1 "$tmpdir" + + cd "$tmpdir" + echo " Configuring commit identity" + git config user.email "arlind@sulej.ch" + git config user.name "ci-bot" + + echo " Copying CI file into .gitea/workflows/ci.yml" + mkdir -p .gitea/workflows + cp "/workspace/osc/skins/template-repo/${{ env.TEMPLATE_REL_PATH }}" \ + ".gitea/workflows/ci.yml" + git add ".gitea/workflows/ci.yml" + + echo " Checking for staged changes" + if git diff --cached --quiet; then + echo " → No changes detected, skipping update for ${owner}/${repo}" + else + echo " ✓ Changes detected" + echo " Committing update" + git commit -m "Update CI" + echo " Pushing to main branch" + git push origin HEAD:main + echo " ✓ Update pushed" + fi + + cd - >/dev/null + rm -rf "$tmpdir" + echo "[Completed ${owner}/${repo}]" + ) || { + echo "⚠ Skipping ${owner}/${repo} due to an error." + } + done + done + + page=$((page + 1)) + done + + echo "" + echo "[Sync CI Complete]" diff --git a/README.md b/README.md index dd10e31..e69de29 100644 --- a/README.md +++ b/README.md @@ -1,30 +0,0 @@ -# osu! Swiss Community - -Welcome to the osu! Swiss Community skinhub, this repository archives and showcases lots of player-made skins. - -Enjoy looking around, click file names to download 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
- Arlind
- Skellers
- marcel7
-
- -

- - - - - - - - - -

diff --git a/docs/example_variables.png b/docs/example_variables.png new file mode 100644 index 0000000000000000000000000000000000000000..8421a277acb0fb74313c98ce558737d9c03b13e0 GIT binary patch literal 11086 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 literal 0 HcmV?d00001 diff --git a/docs/secret1.png b/docs/secret.png similarity index 100% rename from docs/secret1.png rename to docs/secret.png diff --git a/docs/secret2.png b/docs/secret2.png deleted file mode 100644 index 7da9b756a55d29aa9063988d86b6fb25ac658aa0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11140 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