I am using GitHub Actions to automatically create new daily notes on this website. Every day at midnight, a GitHub Action checks the content/notes
folder for a file titled %Y-%m-%d.md
(matching the current date). If this file does not yet exist, a new %Y-%m-%d.md
file with a standard Hugo front matter — filled in with the current date and a placeholder title — is created.
To keep track of my daily writing streak, I also need to check if the previous day’s note was modified, and update my streak accordingly. I do this using a combination of git
, grep
, and sed
.
git log
The git log
command shows the commit log, which is used to check if there have been any other commits involving the previous day’s note, outside of its creation by GitHub Actions. If this is the case, there should be more than one commit involving this file, and I can thus assume that I have written something. Based on this output, the existing streak — which is stored in the hugo.toml
configuration file — is updated.
PREV_DATE=$(date -d "${{ env.DATE }} -1 day" +'%Y-%m-%d')if [[ $(git log --name-only --since="24 hours ago" \ --pretty=format: -- \ content/notes/$PREV_DATE.md | \ grep -c content/notes/$PREV_DATE.md) -gt 1 ]]; then echo "MODIFIED=true" >> $GITHUB_ENVelse echo "MODIFIED=false" >> $GITHUB_ENVfi
For this to work, however, we need to pass the HEAD
’s SHA
as a ref
to the checkout:
- name: Checkout repository uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0
grep
To find the current value of the writing streak in the configuration file — and the corresponding date that matches this streak — I use grep
. These outputs are stored in environment variables.
CURRENT_STREAK=$(grep -Po '(?<=CURRENT_WRITING_STREAK = )\d+' $TOML_FILE)CURRENT_STREAK_DATE=$(grep -Po '(?<=CURRENT_WRITING_STREAK_DATE = )\d{4}-\d{2}-\d{2}' $TOML_FILE)
sed
The streak value in the configuration file is updated using sed
, based on our earlier result from the git log
command. We replace the current streak value with $((CURRENT_STREAK + 1))
if there is more than one commit involving the previous day’s note, or replace the streak with 0
otherwise. This new streak is stored in the $NEW_STREAK
environment variable. We also do the same to keep track of the best writing streak to date.
sed -i "s/CURRENT_WRITING_STREAK = $CURRENT_STREAK/CURRENT_WRITING_STREAK = $NEW_STREAK/" $TOML_FILEsed -i "s/CURRENT_WRITING_STREAK_DATE = $CURRENT_STREAK_DATE/CURRENT_WRITING_STREAK_DATE = ${{ env.DATE }}/" $TOML_FILE
The above sed
command kept throwing an error, however: sed: -e (...) unterminated 's' command
. I tried everything from attempting to escape underscores, to adding --
to sed
(as maybe the hyphens in the dates could be confused with a sed
option that made something break), as I first thought that these characters were possibly causing these issues.
In the end, I realised that the issue was caused due to grep
matching multiple lines in the hugo.toml
— which also included newlines and spaces. I did not realise that newlines would be included in the environment variables, but making sure the regex match was only limited to the CURRENT_WRITING_STREAK
variable in the configuration file and trimming any newlines, resolved the issue:
CURRENT_STREAK=$(echo "$CURRENT_STREAK" | tr -d '\n' | tr -d ' ')CURRENT_STREAK_DATE=$(echo "$CURRENT_STREAK_DATE" | tr -d '\n' | tr -d ' ')
By double-checking the used regex and removing unwanted characters, the sed
command could successfully update the values in the hugo.toml
file without errors:
- Writing streak of 0 daysUpdated on Nov 4, 2024
- Best writing streak to date is 20 daysAchieved on Aug 27, 2024