afterhours-shift-manager/.github/workflows/deploy-notify.yml
Adam Moussa fbabab9692 Fix timezone mismatch in version bump PR filter and use dynamic canvas URL
The date comparison used git's author date in its stored timezone
(e.g. -04:00) against GitHub API mergedAt values in UTC (Z suffix).
Lexicographic string comparison across different timezone formats
caused every PR from the tagged commit's day to be re-included in
subsequent versions. Normalize to UTC with format-local so both
sides match.

Also replace the hardcoded canvas URL with the CANVAS_ID env var
already available in the step.
2026-05-04 15:26:36 -04:00

176 lines
6.1 KiB
YAML

name: Daily Version Bump
on:
schedule:
# 6pm ET (EDT = 22:00 UTC, EST = 23:00 UTC)
- cron: "0 22 * * *"
- cron: "0 23 * * *"
workflow_dispatch:
inputs:
bump:
description: "Version bump type"
type: choice
options:
- patch
- minor
default: patch
permissions:
contents: write
pull-requests: read
jobs:
notify:
runs-on: ubuntu-latest
env:
GH_TOKEN: ${{ github.token }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
fetch-tags: true
- name: DST guard
id: dst
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "Manual trigger — skipping DST guard"
echo "skip=false" >> "$GITHUB_OUTPUT"
exit 0
fi
HOUR=$(TZ=America/New_York date +%H)
if [ "$HOUR" != "18" ]; then
echo "ET hour is $HOUR, not 18 — wrong DST rule fired"
echo "skip=true" >> "$GITHUB_OUTPUT"
else
echo "skip=false" >> "$GITHUB_OUTPUT"
fi
- name: Collect merged PRs since last version
if: steps.dst.outputs.skip != 'true'
id: changes
run: |
LAST_TAG=$(git tag -l 'v*' --sort=-v:refname | head -1)
if [ -z "$LAST_TAG" ]; then
echo "No previous version tag"
echo "has_changes=false" >> "$GITHUB_OUTPUT"
exit 0
fi
LAST_TAG_DATE=$(TZ=UTC git log -1 --date=format-local:'%Y-%m-%dT%H:%M:%SZ' --format='%ad' "$LAST_TAG")
PRS=$(gh pr list --state merged --json number,title,mergedAt \
--jq "sort_by(.number) | .[] | select(.mergedAt > \"$LAST_TAG_DATE\")")
if [ -z "$PRS" ]; then
echo "No PRs merged since $LAST_TAG"
echo "has_changes=false" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "has_changes=true" >> "$GITHUB_OUTPUT"
# Semver bump (default: patch)
BUMP="${{ github.event.inputs.bump || 'patch' }}"
MAJOR=$(echo "$LAST_TAG" | sed 's/^v//' | cut -d. -f1)
MINOR=$(echo "$LAST_TAG" | sed 's/^v//' | cut -d. -f2)
PATCH=$(echo "$LAST_TAG" | sed 's/^v//' | cut -d. -f3)
if [ "$BUMP" = "minor" ]; then
VERSION="v${MAJOR}.$((MINOR + 1)).0"
else
VERSION="v${MAJOR}.${MINOR}.$((PATCH + 1))"
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
# Build bullet lists from PR titles
TITLES=$(gh pr list --state merged --json number,title,mergedAt \
--jq "sort_by(.number) | .[] | select(.mergedAt > \"$LAST_TAG_DATE\") | .title")
{
echo "slack_bullets<<ENDSLACK"
echo "$TITLES" | sed 's/ *(#[0-9]*)//g; s/^/• /'
echo "ENDSLACK"
} >> "$GITHUB_OUTPUT"
{
echo "canvas_bullets<<ENDCANVAS"
gh pr list --state merged --json number,title,mergedAt \
--jq "sort_by(.number) | .[] | select(.mergedAt > \"$LAST_TAG_DATE\") | \"* \(.title) (PR #\(.number))\"" \
| sed 's/ *(\(#[0-9]*\))\( (PR\)/ \2/; s/) (PR / (PR /'
echo "ENDCANVAS"
} >> "$GITHUB_OUTPUT"
- name: Create version tag
if: steps.changes.outputs.has_changes == 'true'
run: |
git tag ${{ steps.changes.outputs.version }}
git push origin ${{ steps.changes.outputs.version }}
- name: Update changelog canvas
if: steps.changes.outputs.has_changes == 'true'
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
CANVAS_ID: ${{ secrets.SLACK_CANVAS_ID }}
SECTION_ID: ${{ secrets.SLACK_CANVAS_INTRO_SECTION }}
VERSION: ${{ steps.changes.outputs.version }}
CANVAS_BULLETS: ${{ steps.changes.outputs.canvas_bullets }}
run: |
TODAY=$(TZ=America/New_York date +%Y-%m-%d)
read -r -d '' MARKDOWN <<ENDMD || true
---
## ${VERSION} — ${TODAY}
${CANVAS_BULLETS}
ENDMD
MARKDOWN=$(echo "$MARKDOWN" | sed 's/^ //')
RESPONSE=$(curl -s -X POST https://slack.com/api/canvases.edit \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n \
--arg canvas_id "$CANVAS_ID" \
--arg section_id "$SECTION_ID" \
--arg markdown "$MARKDOWN" \
'{
canvas_id: $canvas_id,
changes: [{
operation: "insert_after",
section_id: $section_id,
document_content: {
type: "markdown",
markdown: $markdown
}
}]
}')")
echo "$RESPONSE" | jq .
if [ "$(echo "$RESPONSE" | jq -r .ok)" != "true" ]; then
echo "::warning::Canvas update failed: $(echo "$RESPONSE" | jq -r .error)"
fi
- name: Post to Slack
if: steps.changes.outputs.has_changes == 'true'
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
SLACK_CHANNEL_ID: ${{ secrets.SLACK_CHANNEL_ID }}
CANVAS_ID: ${{ secrets.SLACK_CANVAS_ID }}
VERSION: ${{ steps.changes.outputs.version }}
SLACK_BULLETS: ${{ steps.changes.outputs.slack_bullets }}
run: |
CANVAS_URL="https://app.slack.com/docs/${CANVAS_ID}"
read -r -d '' TEXT <<ENDTXT || true
*After-Hours Scheduler has been updated to ${VERSION}*
Here's a brief summary of what changed:
${SLACK_BULLETS}
<${CANVAS_URL}|Click here to read the full changelog>
ENDTXT
TEXT=$(echo "$TEXT" | sed 's/^ //')
curl -s -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg channel "$SLACK_CHANNEL_ID" --arg text "$TEXT" \
'{channel: $channel, text: $text}')"