home

posts

notes

rss

Daily notes with GitHub Actions

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_ENV
else
echo "MODIFIED=false" >> $GITHUB_ENV
fi

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_FILE
sed -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 Sep 26, 2024
  • Best writing streak to date is 20 daysAchieved on Aug 27, 2024