Skip to content

Release reminders

Release reminders #15

on:
schedule:
- cron: '0 9 * * 1' # Every Monday at 9am UTC
workflow_dispatch:
name: Release reminders
jobs:
release-reminders:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Generate token from GitHub App
id: app-token
uses: tibdex/github-app-token@v2
with:
app_id: ${{ secrets.APP_ID }}
private_key: ${{ secrets.APP_PRIVATE_KEY }}
- name: Check packages and create reminders
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
# Get repos from r-universe + extras
REPOS=$(curl -s "https://epiforecasts.r-universe.dev/api/packages" | jq -r '.[]._upstream // empty' | sed 's|https://github.com/||')
REPOS="$REPOS $(grep 'repo:' _data/software-extras.yml | sed 's/.*: //')"
for repo in $REPOS; do
echo "Checking $repo..."
# Get last release info
RELEASE_INFO=$(gh release view --repo "$repo" --json tagName,publishedAt 2>/dev/null || echo '{}')
LAST_TAG=$(echo "$RELEASE_INFO" | jq -r '.tagName // empty')
LAST_DATE=$(echo "$RELEASE_INFO" | jq -r '.publishedAt // empty')
if [ -n "$LAST_TAG" ]; then
# Has releases - skip if released within last 60 days
if [ -n "$LAST_DATE" ]; then
DAYS_SINCE=$(( ($(date +%s) - $(date -d "$LAST_DATE" +%s)) / 86400 ))
if [ "$DAYS_SINCE" -lt 60 ]; then
echo " Released $DAYS_SINCE days ago, skipping"
continue
fi
fi
# Check commits since last release (need >1 because version bump after release counts as 1)
# Filter out dependabot commits and their merge commits - only count real changes
COMMITS_DATA=$(gh api "repos/$repo/compare/$LAST_TAG...HEAD" 2>/dev/null || echo '{"ahead_by":0,"commits":[]}')
COMMITS=$(echo "$COMMITS_DATA" | jq '.ahead_by')
REAL_COMMITS=$(echo "$COMMITS_DATA" | jq '[.commits[] | select(
.author.login != "dependabot[bot]" and
(.commit.message | test("^Bump "; "i") | not) and
(.commit.message | test("dependabot"; "i") | not)
)] | length')
if [ "$REAL_COMMITS" -lt 2 ]; then
echo " Only $REAL_COMMITS non-bot commit(s) since last release (${COMMITS} total), skipping"
continue
fi
RELEASE_LINE="**Last release:** $LAST_TAG ($DAYS_SINCE days ago)"
COMMITS_LINE="**Commits since:** $REAL_COMMITS (excl. bot commits) ([view diff](https://github.com/$repo/compare/$LAST_TAG...HEAD))"
else
# No releases yet - check if repo has any commits at all
COMMITS=$(gh api "repos/$repo" --jq '.size' 2>/dev/null || echo "0")
if [ "$COMMITS" = "0" ]; then
echo " Empty repo, skipping"
continue
fi
RELEASE_LINE="**Last release:** None yet"
COMMITS_LINE=""
DAYS_SINCE="N/A"
fi
# Skip if there's already an open release reminder issue
MONTH=$(date +'%B %Y')
EXISTING=$(gh issue list --repo "$repo" --state open --json title --jq '[.[] | select(.title | test("Release reminder"))] | length' 2>/dev/null || echo "0")
if [ "$EXISTING" != "0" ]; then
echo " Open release reminder already exists, skipping"
continue
fi
# Get open bugs
BUGS=$(gh issue list --repo "$repo" --label bug --state open --json number,title --jq '.[] | "- #\(.number) \(.title)"' 2>/dev/null || echo "")
if [ -z "$BUGS" ]; then
BUGS="None"
fi
# Get open PRs
PRS=$(gh pr list --repo "$repo" --state open --json number,title --jq '.[] | "- #\(.number) \(.title)"' 2>/dev/null || echo "")
if [ -z "$PRS" ]; then
PRS="None"
fi
# Detect package type
HAS_DESCRIPTION=$(gh api "repos/$repo/contents/DESCRIPTION" --jq '.name' 2>/dev/null || echo "")
HAS_PROJECT_TOML=$(gh api "repos/$repo/contents/Project.toml" --jq '.name' 2>/dev/null || echo "")
# Create reminder issue
echo " Creating reminder for $repo"
{
echo "$RELEASE_LINE"
[ -n "$COMMITS_LINE" ] && echo "$COMMITS_LINE"
echo "**What's new:** [NEWS.md](https://github.com/$repo/blob/HEAD/NEWS.md)"
echo ""
echo "**Open bugs:**"
echo "$BUGS"
echo ""
echo "**Open PRs:**"
echo "$PRS"
echo ""
echo "## To release"
if [ -n "$HAS_DESCRIPTION" ]; then
echo 'Run `usethis::use_release_issue()` for the full checklist.'
elif [ -n "$HAS_PROJECT_TOML" ]; then
echo '1. Bump version in `Project.toml`'
echo '2. Comment `@JuliaRegistrator register` on the commit'
else
echo 'Create a GitHub release.'
fi
echo ""
echo "*Close this issue if not releasing this cycle.*"
echo ""
echo "---"
echo "*Created by the [release reminders workflow](https://github.com/epiforecasts/epiforecasts.github.io/blob/main/.github/workflows/release-reminders.yaml).*"
} > /tmp/release-body.md
# Ensure 'release' label exists, create issue without label if it fails
gh label create release --repo "$repo" --description "Release tracking" --color "0E8A16" 2>/dev/null || true
gh issue create --repo "$repo" \
--title "Release reminder - $MONTH" \
--label "release" \
--body-file /tmp/release-body.md 2>/dev/null \
|| gh issue create --repo "$repo" \
--title "Release reminder - $MONTH" \
--body-file /tmp/release-body.md \
|| echo " Failed to create issue for $repo"
done