Skip to content

Upgrade hevy2garmin from upstream (staged; do not merge yet) - #3

Merged
Micker71 merged 30 commits into
mainfrom
review/upstream-2026-10-22
Oct 23, 2026
Merged

Micker71 merged 30 commits into
mainfrom
review/upstream-2026-10-22

Conversation

@Micker71

@Micker71 Micker71 commented Oct 23, 2026 •

Copy link
Copy Markdown
Owner

Scope

Stages 21 upstream commits on review/upstream-2026-10-22 without changing Production main. Review-only PR: DO NOT MERGE YET.

Confirmed safety and build checks

  • Upstream merge into review branch succeeded without conflicts
  • Full GitHub CI passed on the latest tested revision (9 jobs)
  • Vercel build reported success for the review branch
  • Isolated Preview demo safety smoke test reported green (local Next.js server; fake/unreachable DB, no external credentials)
  • Review branch retains DEMO_MODE guard on GET /api/cron/sync
  • Removed upstream Dependabot auto-merge workflow to preserve manual approvals
  • Vercel Preview set up for review branch and Neon created preview/review/upstream-2026-10-22 as a branch of main

Must verify before production merge

  • Verify deployed Vercel Preview is running with DEMO_MODE=true (confirmed by authenticated read-only diagnostic on Preview)
  • Verify deployed Preview POSTGRES_URL resolves to the Neon preview branch (endpoint ep-sweet-sea-bia4nk43 matched in both Vercel diagnostic and Neon Computes)
  • Confirm the deployed Preview cannot initiate real Garmin uploads, GitHub fork updates, or other writes
  • Review database migrations, updated dashboard action and environment compatibility
  • Confirm production manual-sync workflow remains unaffected

Important: The prior direct HTTP test against Vercel Preview returned 302 (Vercel deployment protection), not the application's 403. The green local smoke test validates application behavior in an isolated runner, but is not proof of the deployed Preview environment configuration. Do not disable Vercel protection or merge this PR as a workaround.

Temporary Preview diagnostic (remove before production merge)

  • Validate /api/preview-diagnostics authentication and live DEMO_MODE=true (user verified unauthorized without session and authenticated output)
  • Compare reported Neon endpoint ep-sweet-sea-bia4nk43 to Neon Preview branch Computes (matched Preview compute)
  • Remove the temporary web/app/api/preview-diagnostics/route.ts from review branch before marking PR ready
  • Verify the deploy after removal still passes CI and Vercel Preview checks

drkostas and others added 25 commits October 13, 2026 08:57
Check each pull request for terms that must not appear here
…as#748)

Hevy's API sends no per-set execution time for strength sets, so in merge
mode the tool assigned each set a duration itself and scaled them to the
activity's length, which made every set end up the same (the reported 33
seconds) and overwrote the real per-set timing the watch had recorded.

When a workout was recorded on both the watch and Hevy, keep the watch's
own set and rest timing and write only the exercise names, reps and weights
onto it. The watch's existing sets are already read back and backed up before
the push, so this reuses them: it maps the two set lists by active-set
position and overlays Hevy's identity on the active sets, keeping each set's
duration and start time from the watch. When the two disagree on how many
sets there were, there is no sound mapping, so the synthesized timing stands.

This is on by default. A new setting, merge_preserve_watch_timing, turns it
off to sync the synthesized timing as before.

Done in both the Python engine and the TypeScript package, with tests.
…timing

fix(merge): preserve the watch's own set timing in merge mode (drkostas#748)
The dashboard shows "Update available: N new changes since your version",
with See what's new linking to the GitHub compare. GET /api/update-check
compares the deployed commit with upstream main, with the saved GitHub token
when there is one, and caches the answer in app_cache for 6 hours. The
banner loads after the page renders; any failure means no banner.

A fork from before the 9 September 2026 history rewrite compares as
diverged with a merge base in the shared first commits, so for the default
upstream a merge base at or before dc5905a gets the banner without a count,
with the fork and README links. "No common ancestor" is kept as a fallback.

Dismiss is remembered in localStorage until upstream has a newer commit.
H2G_UPDATE_CHECK=off turns it off; H2G_UPSTREAM_REPO names the upstream.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MoHpmqqCWbyvvXEJVaKt82
…rkostas#749)

On a Vercel fork with a saved GitHub token the update banner offers Update
now. POST /api/update-fork (session-gated, refused in demo and self-hosted)
calls merge-upstream on the fork's default branch with the saved token,
then marks the cached check as updating so the banner stops offering it
until the new deployment arrives. The page polls /api/version and reloads
when the deployed commit changes.

A 409 or 422 is not retried: the banner links to the fork and the README's
update steps. A 401 or 403 says the token needs the repo scope, and
workflow when the update changes .github/workflows/. The token is never in
any response.

On phones the banner text takes the full width and the actions wrap below.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MoHpmqqCWbyvvXEJVaKt82
…rkostas#749)

A failed check (rate limited, a network error, a 5xx, or an answer it
cannot read) is cached in app_cache under update_check_failure until
GitHub's x-ratelimit-reset time when the failing response gave one in the
future, otherwise for an hour. Until then no dashboard view asks GitHub,
and there is still no banner.

The failure has its own key, so it never replaces the cached result: a
fresh result is still served while a failure is cached, and a stale one is
left as it was.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MoHpmqqCWbyvvXEJVaKt82
…ting (drkostas#749)

merge-upstream answers 200 with merge_type "none" when the fork is not
behind ("This branch is not behind the upstream drkostas:main."). Update
now treated that as started and polled /api/version for a deployment that
this call never triggered.

syncFork now reports upToDate for merge_type "none"; "fast-forward" and
"merge" still mean started. The banner then says the fork is already up to
date (a new deployment may still be on its way) and polls nothing. The
route asks GitHub again past the cached check: up to date is cached as
such, and still behind (the deployment not there yet) is cached as
updating, so the banner goes either way. If GitHub fails, the cached entry
is marked updating.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MoHpmqqCWbyvvXEJVaKt82
…ostas#749)

GitHub sends retry-after (seconds) with its secondary rate limits instead
of a usable x-ratelimit-reset. A failed check is now cached for retry-after
when the failing response gives a positive one, else until a future
x-ratelimit-reset, else for an hour.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MoHpmqqCWbyvvXEJVaKt82
… sync (drkostas#749)

After Update now found the fork already up to date, the banner kept its
"Update available: N new changes" line above "Your fork is already up to
date", which contradicted it until the next page load. In that state only
the up-to-date line shows.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MoHpmqqCWbyvvXEJVaKt82
drkostas#749)

Once Update now finds the fork already up to date there is nothing new to
see, and the link pointed at the cached check's compare. In that state the
banner shows only the up-to-date line and Dismiss.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MoHpmqqCWbyvvXEJVaKt82
feat(web): tell a fork when upstream has updates, with a one-click Update now (drkostas#749)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 8.3.0 to 8.3.4.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.3.4/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 8.3.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
…/universal/vite-8.3.4

chore(deps-dev): bump vite from 8.3.0 to 8.3.4 in /universal
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 8.3.0 to 8.3.4.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.3.4/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 8.3.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
…/typescript/vite-8.3.4

chore(deps-dev): bump vite from 8.3.0 to 8.3.4 in /typescript
…e-devdep-patch

ci: auto-merge Dependabot dev-dependency patch bumps
Review upstream changes before preview upgrade
@vercel

vercel Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
hevy2garmin Ready Ready Preview Oct 23, 2026 7:01pm UTC

@Micker71
Micker71 marked this pull request as ready for review October 23, 2026 19:02
@Micker71
Micker71 merged commit 509ef69 into main Oct 23, 2026
14 checks passed

This branch was successfully deployed

1 active deployment
Preview — 5d6e036a Deployed Oct 23, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants