diff --git a/.github/workflows/maintenance.yml b/.github/workflows/maintenance.yml new file mode 100644 index 000000000000..7c7601dd18fe --- /dev/null +++ b/.github/workflows/maintenance.yml @@ -0,0 +1,46 @@ +name: Winbindex maintenance + +on: + workflow_dispatch: + schedule: + - cron: '0 1 1 * *' + +concurrency: winbindex-maintenance + +jobs: + run: + runs-on: ubuntu-latest + steps: + - name: Checkout main + uses: actions/checkout@v4 + with: + ref: main + - name: Checkout gh-pages + uses: actions/checkout@v4 + with: + ref: gh-pages + path: gh-pages + fetch-depth: 0 + filter: 'blob:none' + - name: Override out_path + run: | + echo ./gh-pages/data > data/.out_path_override + - name: Squash old commits + run: ./data/maintenance_squash_old_commits.sh gh-pages "30 days ago" + - name: Push squashed repo gradually with temporary sliding tags + run: | + cd gh-pages + for i in $(git rev-list --reverse HEAD); do + echo "Pushing $i" + git tag "_temp_tag_for_squash_$i" "$i" + git push origin tag "_temp_tag_for_squash_$i" + done + - name: Push squashed repo + run: git -C gh-pages push --force-with-lease + - name: Remove temporary sliding tags + run: | + cd gh-pages + for i in $(git rev-list --reverse HEAD); do + git tag -d "_temp_tag_for_squash_$i" + git push origin -d "_temp_tag_for_squash_$i" + done diff --git a/data/maintenance_squash_old_commits.sh b/data/maintenance_squash_old_commits.sh new file mode 100644 index 000000000000..01318742014c --- /dev/null +++ b/data/maintenance_squash_old_commits.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +# Check if the repository path is provided +if [ -z "$1" ] || [ -z "$2" ]; then + echo "Usage: $0 /path/to/repository keep_since_time" + exit 1 +fi + +REPO_PATH=$1 +KEEP_SINCE=$2 # e.g. "7 days ago" + +# Change to the target repository +cd "$REPO_PATH" || { echo "Repository not found at $REPO_PATH"; exit 1; } + +# Ensure the working directory is clean +if ! git diff-index --quiet HEAD --; then + echo "Your working directory is not clean. Commit or stash your changes first." + exit 1 +fi + +# Squash old commits +for i in $(git log --since="$KEEP_SINCE" --format=%H --reverse); do + if [ -z "$new_commit" ]; then + if [ "$(git rev-list "$i" --children)" == "$i" ]; then + echo No commits to squash + exit + fi + + # How to remove only the first occurrence of a line in a file using sed: https://stackoverflow.com/q/23696871 + msg=$(git cat-file commit "$i" | sed "0,/^parent /{//d}") + msg+=$'\n\n========================================\nSquashed history:\n\n' + msg+=$(git log --first-parent "$i~" | sed -r 's/^[[:blank:]]+//') + else + msg=$(git cat-file commit "$i" | sed "s/$i_prev/$new_commit/") + fi + new_commit=$(echo "$msg" | git hash-object -t commit -w --stdin) + echo "$i -> $new_commit" + i_prev=$i +done + +git reset $new_commit