Skip to content

YouTube playlist ID configuration#667

Merged
kentcdodds merged 1 commit intomainfrom
cursor/youtube-playlist-id-configuration-993d
Feb 23, 2026
Merged

YouTube playlist ID configuration#667
kentcdodds merged 1 commit intomainfrom
cursor/youtube-playlist-id-configuration-993d

Conversation

@kentcdodds
Copy link
Owner

@kentcdodds kentcdodds commented Feb 23, 2026

Fix YouTube re-indexing job failure by treating empty YOUTUBE_PLAYLIST_URL as unset, allowing YOUTUBE_PLAYLIST_ID to be used.

GitHub Actions sets undefined repo variables to empty strings. The existing script's nullish coalescing operator (??) would then select this empty string for YOUTUBE_PLAYLIST_URL instead of falling back to YOUTUBE_PLAYLIST_ID or the default, causing the job to fail.


Open in Web Open in Cursor 


Note

Low Risk
Low risk configuration hardening: only affects how the YouTube indexing job selects YOUTUBE_PLAYLIST_ID, with no changes to indexing logic or data formats.

Overview
Hardens YouTube semantic-search indexing configuration so empty values don’t break scheduled runs.

The GitHub Actions workflow now falls back from vars.YOUTUBE_PLAYLIST_ID to secrets.YOUTUBE_PLAYLIST_ID. The YouTube playlist indexer treats empty/whitespace --playlist or YOUTUBE_PLAYLIST_ID as unset (via nonEmptyTrimmed) before falling back to the built-in default, and updates the error message/docs to reflect the env var option.

Written by Cursor Bugbot for commit 7c784f5. This will update automatically on new commits. Configure here.

Summary by CodeRabbit

  • Documentation

    • Updated YouTube playlist indexing configuration guidance to include repository secrets as an additional option alongside repository variables.
  • Chores

    • Enhanced input validation for playlist configuration with improved fallback handling and error messaging.

@cursor
Copy link

cursor bot commented Feb 23, 2026

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@kentcdodds kentcdodds marked this pull request as ready for review February 23, 2026 17:35
@coderabbitai
Copy link

coderabbitai bot commented Feb 23, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9065e18 and 7c784f5.

📒 Files selected for processing (3)
  • .github/workflows/index-semantic-youtube.yml
  • other/semantic-search/index-youtube-playlist.ts
  • other/semantic-search/readme.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/workflows/index-semantic-youtube.yml
  • other/semantic-search/index-youtube-playlist.ts

📝 Walkthrough

Walkthrough

Updates playlist ID input handling across TypeScript, workflow configuration, and documentation by adding input normalization to trim empty values and implementing fallback logic that prioritizes repository variables or secrets before defaulting to a standard playlist ID.

Changes

Cohort / File(s) Summary
Input Validation
other/semantic-search/index-youtube-playlist.ts
Added nonEmptyTrimmed() helper function to coerce undefined/null/empty strings to undefined. Updated playlist input resolution to apply this helper to both CLI arguments and environment variables with fallback to DEFAULT_PLAYLIST_ID. Updated error messaging to reference the YOUTUBE_PLAYLIST_ID environment variable.
Workflow Configuration
.github/workflows/index-semantic-youtube.yml
Changed YOUTUBE_PLAYLIST_ID resolution to use conditional logic checking repository variables or secrets instead of direct variable reference. Updated associated comment to reflect preference for vars or secrets.
Documentation
other/semantic-search/readme.md
Minor wording update clarifying that repository variables or secrets are supported for playlist configuration.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • YouTube video indexing #627: Directly related — both modify playlist input resolution and YOUTUBE_PLAYLIST_ID handling across TypeScript code, GitHub Actions workflows, and documentation to improve fallback logic.

Poem

🐰 A tidy trim clears the clutter away,
Empty whispers fade into the day,
With fallbacks nested and secrets in hand,
Playlists now flow just as planned!
🎬✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main changes: configuring how YOUTUBE_PLAYLIST_ID is handled in the GitHub Actions workflow and the index script to properly fall back when empty.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cursor/youtube-playlist-id-configuration-993d

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
other/semantic-search/__tests__/youtube-playlist.test.ts (2)

20-28: Add a regression test for the exact GH Actions empty-string scenario.

Test 3 validates whitespace-only playlistUrlEnv (' '), and test 4 validates both env vars as ''. The specific PR bug — GH Actions emitting '' for YOUTUBE_PLAYLIST_URL while YOUTUBE_PLAYLIST_ID is non-empty — falls through the gap.

➕ Suggested additional test
+	test('resolveYouTubePlaylistInput ignores empty-string URL env (GitHub Actions default) and uses playlist ID', () => {
+		const input = resolveYouTubePlaylistInput({
+			playlistArg: undefined,
+			playlistUrlEnv: '', // GitHub Actions sets undefined repo vars to ''
+			playlistIdEnv: 'PL1234567890',
+			defaultPlaylistId: 'PLDEFAULT1234',
+		})
+		expect(input).toBe('PL1234567890')
+	})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@other/semantic-search/__tests__/youtube-playlist.test.ts` around lines 20 -
28, The test suite is missing a regression test for the GitHub Actions behavior
where an env var is the literal two-character string "''"; add a new unit test
in youtube-playlist.test.ts that calls resolveYouTubePlaylistInput with
playlistArg: undefined, playlistUrlEnv: "''" (literal), playlistIdEnv: e.g.
'PL1234567890', and a defaultPlaylistId, then assert the return equals the
playlistIdEnv; reference the existing test pattern used around
resolveYouTubePlaylistInput to mirror naming and expectations so this specific
GH Actions empty-string scenario is covered.

7-38: Consider adding tests for playlistArg priority and getYouTubePlaylistId null/invalid returns.

Two gaps:

  1. resolveYouTubePlaylistInput has three inputs in priority order (playlistArg > playlistUrlEnv > playlistIdEnv), but no test exercises playlistArg winning over the env vars.
  2. getYouTubePlaylistId has no tests for null/undefined/empty inputs or an invalid string (all should return null).
➕ Suggested additional tests
+	test('resolveYouTubePlaylistInput uses playlistArg over env values', () => {
+		const input = resolveYouTubePlaylistInput({
+			playlistArg: 'PL_ARG1234567',
+			playlistUrlEnv: 'https://www.youtube.com/playlist?list=PLURL1234567',
+			playlistIdEnv: 'PL_ENV1234567',
+			defaultPlaylistId: 'PLDEFAULT1234',
+		})
+		expect(input).toBe('PL_ARG1234567')
+	})
+
+	test('getYouTubePlaylistId returns null for null/undefined/empty/invalid inputs', () => {
+		expect(getYouTubePlaylistId(null)).toBeNull()
+		expect(getYouTubePlaylistId(undefined)).toBeNull()
+		expect(getYouTubePlaylistId('')).toBeNull()
+		expect(getYouTubePlaylistId('   ')).toBeNull()
+		expect(getYouTubePlaylistId('not-a-valid-id-or-url')).toBeNull()
+	})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@other/semantic-search/__tests__/youtube-playlist.test.ts` around lines 7 -
38, Add tests covering (1) resolveYouTubePlaylistInput prioritization by
asserting that when playlistArg is provided it is returned even if
playlistUrlEnv and playlistIdEnv are set, and (2) getYouTubePlaylistId handling
of invalid/empty inputs by asserting it returns null for inputs like undefined,
null, empty string, or a non-playlist string; add these test cases to the
existing suite using the functions getYouTubePlaylistId and
resolveYouTubePlaylistInput so the behavior is explicitly verified.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@other/semantic-search/__tests__/youtube-playlist.test.ts`:
- Around line 20-28: The test suite is missing a regression test for the GitHub
Actions behavior where an env var is the literal two-character string "''"; add
a new unit test in youtube-playlist.test.ts that calls
resolveYouTubePlaylistInput with playlistArg: undefined, playlistUrlEnv: "''"
(literal), playlistIdEnv: e.g. 'PL1234567890', and a defaultPlaylistId, then
assert the return equals the playlistIdEnv; reference the existing test pattern
used around resolveYouTubePlaylistInput to mirror naming and expectations so
this specific GH Actions empty-string scenario is covered.
- Around line 7-38: Add tests covering (1) resolveYouTubePlaylistInput
prioritization by asserting that when playlistArg is provided it is returned
even if playlistUrlEnv and playlistIdEnv are set, and (2) getYouTubePlaylistId
handling of invalid/empty inputs by asserting it returns null for inputs like
undefined, null, empty string, or a non-playlist string; add these test cases to
the existing suite using the functions getYouTubePlaylistId and
resolveYouTubePlaylistInput so the behavior is explicitly verified.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 662a8dd and 3452c75.

📒 Files selected for processing (3)
  • other/semantic-search/__tests__/youtube-playlist.test.ts
  • other/semantic-search/index-youtube-playlist.ts
  • other/semantic-search/youtube-playlist.ts

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
other/semantic-search/index-youtube-playlist.ts (1)

295-317: getYouTubePlaylistId duplicates parsePlaylistId from app/routes/youtube.tsx

The two functions are functionally identical (same regex, same URL-parsing fallback, same return type); DEFAULT_PLAYLIST_ID is also hard-coded to the same literal in both files. The PR summary mentions extracting these into a shared youtube-playlist.ts, but that module doesn't appear in the PR. Consider creating it to avoid drift:

♻️ Suggested shared module sketch
// other/semantic-search/youtube-playlist.ts  (new file)
+export const DEFAULT_PLAYLIST_ID = 'PLV5CVI1eNcJgNqzNwcs4UKrlJdhfDjshf'
+
+export function parsePlaylistId(value: string | undefined | null): string | null {
+    if (!value) return null
+    const trimmed = value.trim()
+    if (!trimmed) return null
+    if (/^[A-Za-z0-9_-]{10,}$/.test(trimmed)) return trimmed
+    try {
+        const url = new URL(trimmed)
+        const list = url.searchParams.get('list')
+        return list && /^[A-Za-z0-9_-]{10,}$/.test(list) ? list : null
+    } catch {
+        return null
+    }
+}

Then import in both index-youtube-playlist.ts and app/routes/youtube.tsx.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@other/semantic-search/index-youtube-playlist.ts` around lines 295 - 317,
Duplicate playlist parsing exists: getYouTubePlaylistId here and parsePlaylistId
in app/routes/youtube.tsx (and the same DEFAULT_PLAYLIST_ID literal). Create a
shared module (e.g., youtube-playlist.ts) that exports a single parsePlaylistId
(or getYouTubePlaylistId) function and DEFAULT_PLAYLIST_ID constant implementing
the existing regex + URL fallback logic, then replace the local implementations
in index-youtube-playlist.ts and app/routes/youtube.tsx with imports from that
shared module to remove duplication and centralize the behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@other/semantic-search/index-youtube-playlist.ts`:
- Around line 295-317: Duplicate playlist parsing exists: getYouTubePlaylistId
here and parsePlaylistId in app/routes/youtube.tsx (and the same
DEFAULT_PLAYLIST_ID literal). Create a shared module (e.g., youtube-playlist.ts)
that exports a single parsePlaylistId (or getYouTubePlaylistId) function and
DEFAULT_PLAYLIST_ID constant implementing the existing regex + URL fallback
logic, then replace the local implementations in index-youtube-playlist.ts and
app/routes/youtube.tsx with imports from that shared module to remove
duplication and centralize the behavior.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3452c75 and 9065e18.

📒 Files selected for processing (5)
  • .env.example
  • .github/workflows/index-semantic-youtube.yml
  • app/routes/youtube.tsx
  • other/semantic-search/index-youtube-playlist.ts
  • other/semantic-search/readme.md
✅ Files skipped from review due to trivial changes (1)
  • other/semantic-search/readme.md

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@cursor cursor bot force-pushed the cursor/youtube-playlist-id-configuration-993d branch from 9065e18 to 7c784f5 Compare February 23, 2026 18:13
@kentcdodds kentcdodds merged commit 2cb5747 into main Feb 23, 2026
8 checks passed
@kentcdodds kentcdodds deleted the cursor/youtube-playlist-id-configuration-993d branch February 24, 2026 23:57
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.

2 participants