Steffen Schmitz
Steffen Schmitz

Reputation: 890

Remove git files/directories older than x days via GitHub Action

We use a gh-pages branch in our repository to host a static website and frequently commit new information to this branch. Those files often get stale, as we push to a subdirectory per feature branch in the same repository.

The directory structure in my gh-pages branch is similar to the following:

.
|-- README.md
|-- JIRA-1234-feature
|   `-- graph
|-- JIRA-4567-bugfix
|   `-- graph
|-- JIRA-7890-branch-name
|   `-- testing

I want to remove directories via a GitHub actions for which the last update was more than 5 days ago.

I naively tried to remove them via find /path/to/files* -mtime +5 -exec rm {} ;, but the operating system obviously uses the clone date as the last modified time.

I also found

git ls-tree -r --name-only HEAD | while read filename; do
  echo "$(git log -1 --format="%ad" --date="short" -- $filename) $filename"
done

which prints the last git update and the file name like this:

2023-01-12 JIRA-1234-test/index.html
2023-01-12 JIRA-1234-test/static/test.css

I don't know how to trigger file removal commands from this list, though.

How would I have to modify the following action to remove the old files?

name: Prune GH Pages branch

on:
  workflow_dispatch:

jobs:
  upload:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          ref: gh-pages
      - name: Cleanup
        run: |
          # TODO: REMOVE FILES HERE
          git ls-tree -r --name-only HEAD | while read filename; do
            echo "$(git log -1 --format="%ad" --date="short" -- $filename) $filename"
          done
      - name: Commit & Push
        run: |
          if [ $(git status --porcelain | wc -l) -eq "0" ]; then
            echo "git repo is clean."
          else
            git add -A
            git commit -m "branch cleanup"
            git push
          fi

Upvotes: 1

Views: 773

Answers (1)

Marcin Kłopotek
Marcin Kłopotek

Reputation: 5991

Unfortunately, I didn't find a way to make a nice one-liner for the requirement. We need the following bash script. I have commented all the important steps.

#!/bin/bash

# Validate if $1 is a positive number days
[[ $1 != +([[:digit:]]) ]] &&
   echo "$1: The script has to be run with positive number argument" && exit 1

# Get the X days ago timestamp
X_DAYS_AGO_TIMESTAMP=$(date -d "$1 days ago" +%s)

# Iterate over all files in the repository
for file in $(git ls-files); do
  echo -n "."
  # Get the timestamp of the last commit that modified this file
  LAST_MODIFIED_TIMESTAMP=$(git log -1 --format="%at" -- "$file")
  # If the file hasn't been modified within the last $1 days
  if [ "$LAST_MODIFIED_TIMESTAMP" -lt "$X_DAYS_AGO_TIMESTAMP" ]; then
    # Remove the file from the repository
    echo -e "\nRemoving $file last modified at $(date -d "@$LAST_MODIFIED_TIMESTAMP")"
    git rm --quiet "$file"
  fi
done

# Commit the changes (if any)
if ! git diff --exit-code --quiet --staged; then
  git commit -m "Remove files not modified within the last $1 days"
else
  echo "No files removed"
fi

I can elaborate if something is not clear enough.

Upvotes: 2

Related Questions