From d9fbb4331c89c23302a9d961f83567004f8d7f2f Mon Sep 17 00:00:00 2001 From: Grayson Adams <51373669+GraysonCAdams@users.noreply.github.com> Date: Mon, 2 Mar 2026 01:41:33 -0600 Subject: [PATCH 1/2] docs: update api and architecture for v1.8.0 --- docs/api.md | 9 ++++++++- docs/architecture.md | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/docs/api.md b/docs/api.md index 3e1cdb9..f394c40 100644 --- a/docs/api.md +++ b/docs/api.md @@ -89,6 +89,12 @@ Request: { "url": "https://tiktok.com/...", "phone": "+1234567890" } Response: { "ok": true, "clipId": "...", "status": "downloading" } (201 Created) ``` +### GET /api/clips/[id] +Returns full clip detail with user context, interaction state, and metadata. +``` +Response: { id, originalUrl, videoPath, audioPath, thumbnailPath, title, artist, albumArt, spotifyUrl, appleMusicUrl, youtubeMusicUrl, addedBy, addedByUsername, addedByAvatar, platform, status, contentType, durationSeconds, watched, favorited, reactions, commentCount, unreadCommentCount, viewCount, seenByOthers, createdAt, canEditCaption } +``` + ### PATCH /api/clips/[id] ``` Request: { "title": "new caption" } @@ -157,9 +163,10 @@ Response: { "heartCount": 3, "hearted": true } ``` ### POST /api/clips/[id]/reactions +Enforces one reaction per user per clip. Posting a different emoji replaces the user's previous reaction. Posting the same emoji removes it. ``` Request: { "emoji": "🔥" } -Response: { "reactions": { "🔥": { "count": 2, "reacted": true } } } +Response: { "reactions": { "🔥": { "count": 2, "reacted": true } }, "toggled": true } ``` Allowed emojis: ❤️ 👍 👎 😂 ‼️ ❓ diff --git a/docs/architecture.md b/docs/architecture.md index 9275372..fa4e931 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -76,6 +76,7 @@ scrolly/ │ │ │ ├── ReelMusic.svelte # Music player within a reel │ │ │ ├── ReelOverlay.svelte # Bottom overlay (user info, caption) │ │ │ ├── ActionSidebar.svelte # Right-side action buttons +│ │ │ ├── ClipOverlay.svelte # Full-screen single-clip overlay view │ │ │ ├── CommentsSheet.svelte # Bottom sheet for comments │ │ │ ├── ViewersSheet.svelte # Bottom sheet for view list │ │ │ ├── AddVideoModal.svelte # Modal to paste/submit URLs From ade4886f1777216da9885eb6b990b7e2510bda59 Mon Sep 17 00:00:00 2001 From: Grayson Adams <51373669+GraysonCAdams@users.noreply.github.com> Date: Mon, 2 Mar 2026 01:41:41 -0600 Subject: [PATCH 2/2] fix(ci): use commit statuses for release PR check reporting Remove the unreliable close/reopen trigger-pr-checks job from release.yml. GITHUB_TOKEN events don't trigger other workflows, so close/reopen never worked. Instead, release-pr-checks.yml now posts commit statuses directly to the PR head SHA via the GitHub Status API after workflow_run completes. --- .github/workflows/release-pr-checks.yml | 53 ++++++++++++++---- .github/workflows/release.yml | 71 ++----------------------- 2 files changed, 48 insertions(+), 76 deletions(-) diff --git a/.github/workflows/release-pr-checks.yml b/.github/workflows/release-pr-checks.yml index ad2d03b..b8c1552 100644 --- a/.github/workflows/release-pr-checks.yml +++ b/.github/workflows/release-pr-checks.yml @@ -1,16 +1,19 @@ # Runs CI and CodeQL on release-please PRs. # # Why this exists: release-please creates PRs using GITHUB_TOKEN, which does -# NOT trigger other workflows (pull_request events). pull_request_target IS -# triggered by GITHUB_TOKEN events because it runs in the base branch context. -# Without this, release PRs have no status checks and can't be merged when -# branch protection requires them. +# NOT trigger other workflows (pull_request events). Without this workflow, +# release PRs have no status checks and can't be merged when branch protection +# requires them. # -# Triggers: -# 1. pull_request_target (opened/synchronize/reopened) — fired by close/reopen -# in release.yml or by direct PR updates -# 2. workflow_run (Release workflow completed) — fallback if close/reopen fails -# to fire pull_request_target events +# How it works: +# 1. workflow_run trigger fires reliably when the Release workflow completes. +# This is the primary mechanism — it always fires regardless of token type. +# 2. pull_request_target is a secondary trigger for manual close/reopen from +# the GitHub UI (useful as a manual fallback if needed). +# 3. When triggered via workflow_run, check runs are associated with the main +# branch commit (not the PR head). Branch protection can't see them, so the +# ci job posts commit statuses to the PR head SHA matching the required +# check names ("ci" and "lint-and-check"). # # Security: restricted to release-please branches only. The checkout uses the # PR's HEAD SHA, which is safe because release-please PRs come from within the @@ -26,7 +29,10 @@ on: workflows: [Release] types: [completed] -permissions: read-all +permissions: + contents: read + statuses: write + security-events: write jobs: # Gate: only run for release-please PRs. Finds PR details from either trigger. @@ -112,6 +118,33 @@ jobs: fi echo "CI passed" + # When triggered via workflow_run, check runs are associated with the main + # branch commit, not the PR head. Branch protection can't see them, so we + # post commit statuses to the PR head SHA matching the required check names. + - name: Report status to release PR + if: needs.should-run.outputs.head_sha != '' && github.event_name == 'workflow_run' + env: + GH_TOKEN: ${{ github.token }} + run: | + HEAD_SHA="${{ needs.should-run.outputs.head_sha }}" + RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + + if [[ "${{ needs.lint-and-check.result }}" == "failure" || "${{ needs.lint-and-check.result }}" == "cancelled" ]]; then + STATE="failure" + DESC="Release PR checks failed" + else + STATE="success" + DESC="Release PR checks passed" + fi + + echo "Posting $STATE status to $HEAD_SHA for required checks..." + for CHECK in "ci" "lint-and-check"; do + gh api "repos/${{ github.repository }}/statuses/$HEAD_SHA" \ + -f state="$STATE" -f context="$CHECK" \ + -f description="$DESC" -f target_url="$RUN_URL" + echo " Posted $CHECK: $STATE" + done + codeql: needs: [should-run] if: needs.should-run.outputs.head_sha != '' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9ad7582..822a05d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,15 +4,11 @@ on: push: branches: [main] -# Note: release-please uses GITHUB_TOKEN, which doesn't trigger other workflows. -# CI/CodeQL checks on release PRs are handled by release-pr-checks.yml using -# pull_request_target. The close/reopen step below ensures the `reopened` event -# fires reliably (force-push `synchronize` events are inconsistent with GITHUB_TOKEN). -# Docker publishing is handled by docker-publish.yml using workflow_run. -# -# Ideal fix: use a fine-grained PAT (repo secret RELEASE_TOKEN) with contents:write -# and pull-requests:write. This makes release-please PRs trigger normal pull_request -# events, eliminating the need for release-pr-checks.yml entirely. +# Note: release-please uses GITHUB_TOKEN, which can't trigger other workflows +# (GitHub limitation). CI checks on release PRs are handled by +# release-pr-checks.yml via workflow_run (fires when this workflow completes). +# That workflow posts commit statuses to the PR head SHA so branch protection +# sees the results. Docker publishing uses docker-publish.yml (also workflow_run). permissions: contents: write @@ -31,60 +27,3 @@ jobs: with: config-file: release-please-config.json manifest-file: .release-please-manifest.json - - # When release-please creates or updates a PR via GITHUB_TOKEN, the - # pull_request_target `synchronize` event doesn't always fire. Closing - # and reopening the PR ensures the `reopened` event triggers CI checks. - # We verify both state transitions and retry once on failure. - trigger-pr-checks: - needs: [release-please] - if: needs.release-please.outputs.pr != '' && needs.release-please.outputs.release_created != 'true' - runs-on: ubuntu-latest - steps: - - name: Close and reopen release PR to trigger checks - env: - GH_TOKEN: ${{ github.token }} - PR_NUMBER: ${{ fromJSON(needs.release-please.outputs.pr).number }} - run: | - trigger_checks() { - echo "Closing release PR #$PR_NUMBER..." - gh pr close "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" - - # Wait and verify closed state - for i in 1 2 3; do - sleep 3 - STATE=$(gh pr view "$PR_NUMBER" --json state --jq '.state' --repo "$GITHUB_REPOSITORY") - if [ "$STATE" = "CLOSED" ]; then break; fi - echo " Waiting for close to propagate (attempt $i)..." - done - - echo "Reopening release PR #$PR_NUMBER..." - gh pr reopen "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" - - # Verify reopened state - sleep 3 - STATE=$(gh pr view "$PR_NUMBER" --json state --jq '.state' --repo "$GITHUB_REPOSITORY") - if [ "$STATE" = "OPEN" ]; then - echo "Release PR #$PR_NUMBER successfully reopened" - return 0 - else - echo "WARNING: PR state is $STATE after reopen attempt" - return 1 - fi - } - - # First attempt - if trigger_checks; then - exit 0 - fi - - echo "First attempt failed, retrying in 10s..." - sleep 10 - - # Retry once - if trigger_checks; then - exit 0 - fi - - echo "ERROR: Failed to reopen PR after 2 attempts" - exit 1