ci: add preflight bundle checks + on-demand release workflow - #1505

Merged
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows
Apr 17, 2026
Merged

ci: add preflight bundle checks + on-demand release workflow#1505
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows

Conversation

@CraigBuckmaster

Copy link
Copy Markdown
Owner

CI: preflight bundle checks + on-demand release workflow

Two workflow changes:

1. Preflight — extend test.yml

The existing test.yml runs tsc --noEmit and jest on every PR. Adds two steps at the end:

  • npx expo-doctor@latest — dep version drift (catches things like "Reanimated 3.19.5 with SDK 54" before it reaches EAS)
  • npx expo export --platform ios — full Metro bundle. Catches transitive-dep resolution failures (the class of bug that made PR fix: remove react-native-reanimated to resolve SDK 54 native-module crash #1492's reanimated removal fail at bundling only after a 20-minute EAS upload)

Both block merge if they fail. Runs on GitHub's free Linux runners — no EAS minutes consumed.

2. Release — new release.yml

Manual, on-demand iOS build + TestFlight submit.

Flow:

  1. You bump app.jsonversion on master (or leave it — EAS auto-increments buildNumber)
  2. Actions tab → "Release (iOS TestFlight)" → Run workflow
  3. Preflight re-runs (defense in depth)
  4. eas build --platform ios --profile production --wait runs
  5. Approval gate: submit step is gated on testflight-submit GitHub Environment. You get a notification, click Approve in the Actions UI, submit runs.
  6. Cleanup: .p8 file is deleted from the runner even on failure.
  7. Tag step pushes v<version>-build<number> for traceability.

No auto-trigger. Never runs on push to master. Only when you dispatch it manually.

Setup steps required AFTER merge (cannot land without these)

The release workflow will fail to run until you complete these three setup steps. Preflight works immediately with no setup.

Step 1: Create the testflight-submit GitHub Environment

  1. Go to Settings → Environments → New environment
  2. Name: testflight-submit
  3. Enable Required reviewers and add yourself (CraigBuckmaster)
  4. Save

Step 2: Add the App Store Connect API key as a secret

Your eas.json references ./AuthKey_T42VNQ7V5Z.p8. We need its contents in a GitHub Secret, base64-encoded.

On your Windows machine, from the directory containing the .p8 file:

# PowerShell
[Convert]::ToBase64String([IO.File]::ReadAllBytes("AuthKey_T42VNQ7V5Z.p8"))

Or in Git Bash:

base64 -w0 AuthKey_T42VNQ7V5Z.p8

Copy the output. Then:

  1. Go to Settings → Secrets and variables → Actions → New repository secret
  2. Name: ASC_API_KEY_P8_B64
  3. Value: paste the base64 string
  4. Save

The workflow writes this back to disk at runtime, uses it, and deletes it in a cleanup step (runs even on failure).

Step 3: (Optional) First dry-run

Once the above is done, go to Actions → Release (iOS TestFlight) → Run workflow. Confirm the preflight and build jobs succeed. When it hits the submit step, you'll get the approval prompt. You can either approve (and ship a build) or cancel the workflow run (no submit).

What this does NOT do

  • Does NOT auto-trigger on master push
  • Does NOT bump app.json version automatically (manual bump before dispatch)
  • Does NOT auto-generate release notes from merged PRs (could add later)
  • Does NOT modify app.yml (the OTA-update workflow) — that decision deferred

Verification

Preflight: this PR itself will exercise the new preflight steps (the test workflow runs on every PR). If expo-doctor or expo export fail, this PR will show as red — and we'll know there's a pre-existing issue on master we didn't know about before.

@github-actions

github-actionsBot commented Apr 17, 2026

Copy link
Copy Markdown

Test Results

✅ All tests passed

PassedFailedTotal
Tests✅ 3418❌ 03418
Suites✅ 464❌ 0464

Coverage

StatementsBranchesFunctionsLines

⏱️ Duration: 81.1s

@CraigBuckmaster
CraigBuckmaster merged commit f657a39 into masterApr 17, 2026
6 checks passed
@CraigBuckmaster
CraigBuckmaster deleted the ci/preflight-and-release-workflows branch April 17, 2026 19:17
Sign up for freeto 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.

1 participant

@CraigBuckmaster
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

ci: add preflight bundle checks + on-demand release workflow - #1505

Merged
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows
Apr 17, 2026
Merged

ci: add preflight bundle checks + on-demand release workflow#1505
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows

Conversation

@CraigBuckmaster

Copy link
Copy Markdown
Owner

CI: preflight bundle checks + on-demand release workflow

Two workflow changes:

1. Preflight — extend test.yml

The existing test.yml runs tsc --noEmit and jest on every PR. Adds two steps at the end:

  • npx expo-doctor@latest — dep version drift (catches things like "Reanimated 3.19.5 with SDK 54" before it reaches EAS)
  • npx expo export --platform ios — full Metro bundle. Catches transitive-dep resolution failures (the class of bug that made PR fix: remove react-native-reanimated to resolve SDK 54 native-module crash #1492's reanimated removal fail at bundling only after a 20-minute EAS upload)

Both block merge if they fail. Runs on GitHub's free Linux runners — no EAS minutes consumed.

2. Release — new release.yml

Manual, on-demand iOS build + TestFlight submit.

Flow:

  1. You bump app.jsonversion on master (or leave it — EAS auto-increments buildNumber)
  2. Actions tab → "Release (iOS TestFlight)" → Run workflow
  3. Preflight re-runs (defense in depth)
  4. eas build --platform ios --profile production --wait runs
  5. Approval gate: submit step is gated on testflight-submit GitHub Environment. You get a notification, click Approve in the Actions UI, submit runs.
  6. Cleanup: .p8 file is deleted from the runner even on failure.
  7. Tag step pushes v<version>-build<number> for traceability.

No auto-trigger. Never runs on push to master. Only when you dispatch it manually.

Setup steps required AFTER merge (cannot land without these)

The release workflow will fail to run until you complete these three setup steps. Preflight works immediately with no setup.

Step 1: Create the testflight-submit GitHub Environment

  1. Go to Settings → Environments → New environment
  2. Name: testflight-submit
  3. Enable Required reviewers and add yourself (CraigBuckmaster)
  4. Save

Step 2: Add the App Store Connect API key as a secret

Your eas.json references ./AuthKey_T42VNQ7V5Z.p8. We need its contents in a GitHub Secret, base64-encoded.

On your Windows machine, from the directory containing the .p8 file:

# PowerShell
[Convert]::ToBase64String([IO.File]::ReadAllBytes("AuthKey_T42VNQ7V5Z.p8"))

Or in Git Bash:

base64 -w0 AuthKey_T42VNQ7V5Z.p8

Copy the output. Then:

  1. Go to Settings → Secrets and variables → Actions → New repository secret
  2. Name: ASC_API_KEY_P8_B64
  3. Value: paste the base64 string
  4. Save

The workflow writes this back to disk at runtime, uses it, and deletes it in a cleanup step (runs even on failure).

Step 3: (Optional) First dry-run

Once the above is done, go to Actions → Release (iOS TestFlight) → Run workflow. Confirm the preflight and build jobs succeed. When it hits the submit step, you'll get the approval prompt. You can either approve (and ship a build) or cancel the workflow run (no submit).

What this does NOT do

  • Does NOT auto-trigger on master push
  • Does NOT bump app.json version automatically (manual bump before dispatch)
  • Does NOT auto-generate release notes from merged PRs (could add later)
  • Does NOT modify app.yml (the OTA-update workflow) — that decision deferred

Verification

Preflight: this PR itself will exercise the new preflight steps (the test workflow runs on every PR). If expo-doctor or expo export fail, this PR will show as red — and we'll know there's a pre-existing issue on master we didn't know about before.

@github-actions

github-actionsBot commented Apr 17, 2026

Copy link
Copy Markdown

Test Results

✅ All tests passed

PassedFailedTotal
Tests✅ 3418❌ 03418
Suites✅ 464❌ 0464

Coverage

StatementsBranchesFunctionsLines

⏱️ Duration: 81.1s

@CraigBuckmaster
CraigBuckmaster merged commit f657a39 into masterApr 17, 2026
6 checks passed
@CraigBuckmaster
CraigBuckmaster deleted the ci/preflight-and-release-workflows branch April 17, 2026 19:17
Sign up for freeto 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.

1 participant

@CraigBuckmaster
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

ci: add preflight bundle checks + on-demand release workflow - #1505

Merged
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows
Apr 17, 2026
Merged

ci: add preflight bundle checks + on-demand release workflow#1505
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows

Conversation

@CraigBuckmaster

Copy link
Copy Markdown
Owner

CI: preflight bundle checks + on-demand release workflow

Two workflow changes:

1. Preflight — extend test.yml

The existing test.yml runs tsc --noEmit and jest on every PR. Adds two steps at the end:

  • npx expo-doctor@latest — dep version drift (catches things like "Reanimated 3.19.5 with SDK 54" before it reaches EAS)
  • npx expo export --platform ios — full Metro bundle. Catches transitive-dep resolution failures (the class of bug that made PR fix: remove react-native-reanimated to resolve SDK 54 native-module crash #1492's reanimated removal fail at bundling only after a 20-minute EAS upload)

Both block merge if they fail. Runs on GitHub's free Linux runners — no EAS minutes consumed.

2. Release — new release.yml

Manual, on-demand iOS build + TestFlight submit.

Flow:

  1. You bump app.jsonversion on master (or leave it — EAS auto-increments buildNumber)
  2. Actions tab → "Release (iOS TestFlight)" → Run workflow
  3. Preflight re-runs (defense in depth)
  4. eas build --platform ios --profile production --wait runs
  5. Approval gate: submit step is gated on testflight-submit GitHub Environment. You get a notification, click Approve in the Actions UI, submit runs.
  6. Cleanup: .p8 file is deleted from the runner even on failure.
  7. Tag step pushes v<version>-build<number> for traceability.

No auto-trigger. Never runs on push to master. Only when you dispatch it manually.

Setup steps required AFTER merge (cannot land without these)

The release workflow will fail to run until you complete these three setup steps. Preflight works immediately with no setup.

Step 1: Create the testflight-submit GitHub Environment

  1. Go to Settings → Environments → New environment
  2. Name: testflight-submit
  3. Enable Required reviewers and add yourself (CraigBuckmaster)
  4. Save

Step 2: Add the App Store Connect API key as a secret

Your eas.json references ./AuthKey_T42VNQ7V5Z.p8. We need its contents in a GitHub Secret, base64-encoded.

On your Windows machine, from the directory containing the .p8 file:

# PowerShell
[Convert]::ToBase64String([IO.File]::ReadAllBytes("AuthKey_T42VNQ7V5Z.p8"))

Or in Git Bash:

base64 -w0 AuthKey_T42VNQ7V5Z.p8

Copy the output. Then:

  1. Go to Settings → Secrets and variables → Actions → New repository secret
  2. Name: ASC_API_KEY_P8_B64
  3. Value: paste the base64 string
  4. Save

The workflow writes this back to disk at runtime, uses it, and deletes it in a cleanup step (runs even on failure).

Step 3: (Optional) First dry-run

Once the above is done, go to Actions → Release (iOS TestFlight) → Run workflow. Confirm the preflight and build jobs succeed. When it hits the submit step, you'll get the approval prompt. You can either approve (and ship a build) or cancel the workflow run (no submit).

What this does NOT do

  • Does NOT auto-trigger on master push
  • Does NOT bump app.json version automatically (manual bump before dispatch)
  • Does NOT auto-generate release notes from merged PRs (could add later)
  • Does NOT modify app.yml (the OTA-update workflow) — that decision deferred

Verification

Preflight: this PR itself will exercise the new preflight steps (the test workflow runs on every PR). If expo-doctor or expo export fail, this PR will show as red — and we'll know there's a pre-existing issue on master we didn't know about before.

@github-actions

github-actionsBot commented Apr 17, 2026

Copy link
Copy Markdown

Test Results

✅ All tests passed

PassedFailedTotal
Tests✅ 3418❌ 03418
Suites✅ 464❌ 0464

Coverage

StatementsBranchesFunctionsLines

⏱️ Duration: 81.1s

@CraigBuckmaster
CraigBuckmaster merged commit f657a39 into masterApr 17, 2026
6 checks passed
@CraigBuckmaster
CraigBuckmaster deleted the ci/preflight-and-release-workflows branch April 17, 2026 19:17
Sign up for freeto 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.

1 participant

@CraigBuckmaster
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

ci: add preflight bundle checks + on-demand release workflow - #1505

Merged
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows
Apr 17, 2026
Merged

ci: add preflight bundle checks + on-demand release workflow#1505
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows

Conversation

@CraigBuckmaster

Copy link
Copy Markdown
Owner

CI: preflight bundle checks + on-demand release workflow

Two workflow changes:

1. Preflight — extend test.yml

The existing test.yml runs tsc --noEmit and jest on every PR. Adds two steps at the end:

  • npx expo-doctor@latest — dep version drift (catches things like "Reanimated 3.19.5 with SDK 54" before it reaches EAS)
  • npx expo export --platform ios — full Metro bundle. Catches transitive-dep resolution failures (the class of bug that made PR fix: remove react-native-reanimated to resolve SDK 54 native-module crash #1492's reanimated removal fail at bundling only after a 20-minute EAS upload)

Both block merge if they fail. Runs on GitHub's free Linux runners — no EAS minutes consumed.

2. Release — new release.yml

Manual, on-demand iOS build + TestFlight submit.

Flow:

  1. You bump app.jsonversion on master (or leave it — EAS auto-increments buildNumber)
  2. Actions tab → "Release (iOS TestFlight)" → Run workflow
  3. Preflight re-runs (defense in depth)
  4. eas build --platform ios --profile production --wait runs
  5. Approval gate: submit step is gated on testflight-submit GitHub Environment. You get a notification, click Approve in the Actions UI, submit runs.
  6. Cleanup: .p8 file is deleted from the runner even on failure.
  7. Tag step pushes v<version>-build<number> for traceability.

No auto-trigger. Never runs on push to master. Only when you dispatch it manually.

Setup steps required AFTER merge (cannot land without these)

The release workflow will fail to run until you complete these three setup steps. Preflight works immediately with no setup.

Step 1: Create the testflight-submit GitHub Environment

  1. Go to Settings → Environments → New environment
  2. Name: testflight-submit
  3. Enable Required reviewers and add yourself (CraigBuckmaster)
  4. Save

Step 2: Add the App Store Connect API key as a secret

Your eas.json references ./AuthKey_T42VNQ7V5Z.p8. We need its contents in a GitHub Secret, base64-encoded.

On your Windows machine, from the directory containing the .p8 file:

# PowerShell
[Convert]::ToBase64String([IO.File]::ReadAllBytes("AuthKey_T42VNQ7V5Z.p8"))

Or in Git Bash:

base64 -w0 AuthKey_T42VNQ7V5Z.p8

Copy the output. Then:

  1. Go to Settings → Secrets and variables → Actions → New repository secret
  2. Name: ASC_API_KEY_P8_B64
  3. Value: paste the base64 string
  4. Save

The workflow writes this back to disk at runtime, uses it, and deletes it in a cleanup step (runs even on failure).

Step 3: (Optional) First dry-run

Once the above is done, go to Actions → Release (iOS TestFlight) → Run workflow. Confirm the preflight and build jobs succeed. When it hits the submit step, you'll get the approval prompt. You can either approve (and ship a build) or cancel the workflow run (no submit).

What this does NOT do

  • Does NOT auto-trigger on master push
  • Does NOT bump app.json version automatically (manual bump before dispatch)
  • Does NOT auto-generate release notes from merged PRs (could add later)
  • Does NOT modify app.yml (the OTA-update workflow) — that decision deferred

Verification

Preflight: this PR itself will exercise the new preflight steps (the test workflow runs on every PR). If expo-doctor or expo export fail, this PR will show as red — and we'll know there's a pre-existing issue on master we didn't know about before.

@github-actions

github-actionsBot commented Apr 17, 2026

Copy link
Copy Markdown

Test Results

✅ All tests passed

PassedFailedTotal
Tests✅ 3418❌ 03418
Suites✅ 464❌ 0464

Coverage

StatementsBranchesFunctionsLines

⏱️ Duration: 81.1s

@CraigBuckmaster
CraigBuckmaster merged commit f657a39 into masterApr 17, 2026
6 checks passed
@CraigBuckmaster
CraigBuckmaster deleted the ci/preflight-and-release-workflows branch April 17, 2026 19:17
Sign up for freeto 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.

1 participant

@CraigBuckmaster
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

ci: add preflight bundle checks + on-demand release workflow - #1505

Merged
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows
Apr 17, 2026
Merged

ci: add preflight bundle checks + on-demand release workflow#1505
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows

Conversation

@CraigBuckmaster

Copy link
Copy Markdown
Owner

CI: preflight bundle checks + on-demand release workflow

Two workflow changes:

1. Preflight — extend test.yml

The existing test.yml runs tsc --noEmit and jest on every PR. Adds two steps at the end:

  • npx expo-doctor@latest — dep version drift (catches things like "Reanimated 3.19.5 with SDK 54" before it reaches EAS)
  • npx expo export --platform ios — full Metro bundle. Catches transitive-dep resolution failures (the class of bug that made PR fix: remove react-native-reanimated to resolve SDK 54 native-module crash #1492's reanimated removal fail at bundling only after a 20-minute EAS upload)

Both block merge if they fail. Runs on GitHub's free Linux runners — no EAS minutes consumed.

2. Release — new release.yml

Manual, on-demand iOS build + TestFlight submit.

Flow:

  1. You bump app.jsonversion on master (or leave it — EAS auto-increments buildNumber)
  2. Actions tab → "Release (iOS TestFlight)" → Run workflow
  3. Preflight re-runs (defense in depth)
  4. eas build --platform ios --profile production --wait runs
  5. Approval gate: submit step is gated on testflight-submit GitHub Environment. You get a notification, click Approve in the Actions UI, submit runs.
  6. Cleanup: .p8 file is deleted from the runner even on failure.
  7. Tag step pushes v<version>-build<number> for traceability.

No auto-trigger. Never runs on push to master. Only when you dispatch it manually.

Setup steps required AFTER merge (cannot land without these)

The release workflow will fail to run until you complete these three setup steps. Preflight works immediately with no setup.

Step 1: Create the testflight-submit GitHub Environment

  1. Go to Settings → Environments → New environment
  2. Name: testflight-submit
  3. Enable Required reviewers and add yourself (CraigBuckmaster)
  4. Save

Step 2: Add the App Store Connect API key as a secret

Your eas.json references ./AuthKey_T42VNQ7V5Z.p8. We need its contents in a GitHub Secret, base64-encoded.

On your Windows machine, from the directory containing the .p8 file:

# PowerShell
[Convert]::ToBase64String([IO.File]::ReadAllBytes("AuthKey_T42VNQ7V5Z.p8"))

Or in Git Bash:

base64 -w0 AuthKey_T42VNQ7V5Z.p8

Copy the output. Then:

  1. Go to Settings → Secrets and variables → Actions → New repository secret
  2. Name: ASC_API_KEY_P8_B64
  3. Value: paste the base64 string
  4. Save

The workflow writes this back to disk at runtime, uses it, and deletes it in a cleanup step (runs even on failure).

Step 3: (Optional) First dry-run

Once the above is done, go to Actions → Release (iOS TestFlight) → Run workflow. Confirm the preflight and build jobs succeed. When it hits the submit step, you'll get the approval prompt. You can either approve (and ship a build) or cancel the workflow run (no submit).

What this does NOT do

  • Does NOT auto-trigger on master push
  • Does NOT bump app.json version automatically (manual bump before dispatch)
  • Does NOT auto-generate release notes from merged PRs (could add later)
  • Does NOT modify app.yml (the OTA-update workflow) — that decision deferred

Verification

Preflight: this PR itself will exercise the new preflight steps (the test workflow runs on every PR). If expo-doctor or expo export fail, this PR will show as red — and we'll know there's a pre-existing issue on master we didn't know about before.

@github-actions

github-actionsBot commented Apr 17, 2026

Copy link
Copy Markdown

Test Results

✅ All tests passed

PassedFailedTotal
Tests✅ 3418❌ 03418
Suites✅ 464❌ 0464

Coverage

StatementsBranchesFunctionsLines

⏱️ Duration: 81.1s

@CraigBuckmaster
CraigBuckmaster merged commit f657a39 into masterApr 17, 2026
6 checks passed
@CraigBuckmaster
CraigBuckmaster deleted the ci/preflight-and-release-workflows branch April 17, 2026 19:17
Sign up for freeto 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.

1 participant

@CraigBuckmaster
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

ci: add preflight bundle checks + on-demand release workflow - #1505

Merged
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows
Apr 17, 2026
Merged

ci: add preflight bundle checks + on-demand release workflow#1505
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows

Conversation

@CraigBuckmaster

Copy link
Copy Markdown
Owner

CI: preflight bundle checks + on-demand release workflow

Two workflow changes:

1. Preflight — extend test.yml

The existing test.yml runs tsc --noEmit and jest on every PR. Adds two steps at the end:

  • npx expo-doctor@latest — dep version drift (catches things like "Reanimated 3.19.5 with SDK 54" before it reaches EAS)
  • npx expo export --platform ios — full Metro bundle. Catches transitive-dep resolution failures (the class of bug that made PR fix: remove react-native-reanimated to resolve SDK 54 native-module crash #1492's reanimated removal fail at bundling only after a 20-minute EAS upload)

Both block merge if they fail. Runs on GitHub's free Linux runners — no EAS minutes consumed.

2. Release — new release.yml

Manual, on-demand iOS build + TestFlight submit.

Flow:

  1. You bump app.jsonversion on master (or leave it — EAS auto-increments buildNumber)
  2. Actions tab → "Release (iOS TestFlight)" → Run workflow
  3. Preflight re-runs (defense in depth)
  4. eas build --platform ios --profile production --wait runs
  5. Approval gate: submit step is gated on testflight-submit GitHub Environment. You get a notification, click Approve in the Actions UI, submit runs.
  6. Cleanup: .p8 file is deleted from the runner even on failure.
  7. Tag step pushes v<version>-build<number> for traceability.

No auto-trigger. Never runs on push to master. Only when you dispatch it manually.

Setup steps required AFTER merge (cannot land without these)

The release workflow will fail to run until you complete these three setup steps. Preflight works immediately with no setup.

Step 1: Create the testflight-submit GitHub Environment

  1. Go to Settings → Environments → New environment
  2. Name: testflight-submit
  3. Enable Required reviewers and add yourself (CraigBuckmaster)
  4. Save

Step 2: Add the App Store Connect API key as a secret

Your eas.json references ./AuthKey_T42VNQ7V5Z.p8. We need its contents in a GitHub Secret, base64-encoded.

On your Windows machine, from the directory containing the .p8 file:

# PowerShell
[Convert]::ToBase64String([IO.File]::ReadAllBytes("AuthKey_T42VNQ7V5Z.p8"))

Or in Git Bash:

base64 -w0 AuthKey_T42VNQ7V5Z.p8

Copy the output. Then:

  1. Go to Settings → Secrets and variables → Actions → New repository secret
  2. Name: ASC_API_KEY_P8_B64
  3. Value: paste the base64 string
  4. Save

The workflow writes this back to disk at runtime, uses it, and deletes it in a cleanup step (runs even on failure).

Step 3: (Optional) First dry-run

Once the above is done, go to Actions → Release (iOS TestFlight) → Run workflow. Confirm the preflight and build jobs succeed. When it hits the submit step, you'll get the approval prompt. You can either approve (and ship a build) or cancel the workflow run (no submit).

What this does NOT do

  • Does NOT auto-trigger on master push
  • Does NOT bump app.json version automatically (manual bump before dispatch)
  • Does NOT auto-generate release notes from merged PRs (could add later)
  • Does NOT modify app.yml (the OTA-update workflow) — that decision deferred

Verification

Preflight: this PR itself will exercise the new preflight steps (the test workflow runs on every PR). If expo-doctor or expo export fail, this PR will show as red — and we'll know there's a pre-existing issue on master we didn't know about before.

@github-actions

github-actionsBot commented Apr 17, 2026

Copy link
Copy Markdown

Test Results

✅ All tests passed

PassedFailedTotal
Tests✅ 3418❌ 03418
Suites✅ 464❌ 0464

Coverage

StatementsBranchesFunctionsLines

⏱️ Duration: 81.1s

@CraigBuckmaster
CraigBuckmaster merged commit f657a39 into masterApr 17, 2026
6 checks passed
@CraigBuckmaster
CraigBuckmaster deleted the ci/preflight-and-release-workflows branch April 17, 2026 19:17
Sign up for freeto 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.

1 participant

@CraigBuckmaster
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

ci: add preflight bundle checks + on-demand release workflow - #1505

Merged
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows
Apr 17, 2026
Merged

ci: add preflight bundle checks + on-demand release workflow#1505
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows

Conversation

@CraigBuckmaster

Copy link
Copy Markdown
Owner

CI: preflight bundle checks + on-demand release workflow

Two workflow changes:

1. Preflight — extend test.yml

The existing test.yml runs tsc --noEmit and jest on every PR. Adds two steps at the end:

  • npx expo-doctor@latest — dep version drift (catches things like "Reanimated 3.19.5 with SDK 54" before it reaches EAS)
  • npx expo export --platform ios — full Metro bundle. Catches transitive-dep resolution failures (the class of bug that made PR fix: remove react-native-reanimated to resolve SDK 54 native-module crash #1492's reanimated removal fail at bundling only after a 20-minute EAS upload)

Both block merge if they fail. Runs on GitHub's free Linux runners — no EAS minutes consumed.

2. Release — new release.yml

Manual, on-demand iOS build + TestFlight submit.

Flow:

  1. You bump app.jsonversion on master (or leave it — EAS auto-increments buildNumber)
  2. Actions tab → "Release (iOS TestFlight)" → Run workflow
  3. Preflight re-runs (defense in depth)
  4. eas build --platform ios --profile production --wait runs
  5. Approval gate: submit step is gated on testflight-submit GitHub Environment. You get a notification, click Approve in the Actions UI, submit runs.
  6. Cleanup: .p8 file is deleted from the runner even on failure.
  7. Tag step pushes v<version>-build<number> for traceability.

No auto-trigger. Never runs on push to master. Only when you dispatch it manually.

Setup steps required AFTER merge (cannot land without these)

The release workflow will fail to run until you complete these three setup steps. Preflight works immediately with no setup.

Step 1: Create the testflight-submit GitHub Environment

  1. Go to Settings → Environments → New environment
  2. Name: testflight-submit
  3. Enable Required reviewers and add yourself (CraigBuckmaster)
  4. Save

Step 2: Add the App Store Connect API key as a secret

Your eas.json references ./AuthKey_T42VNQ7V5Z.p8. We need its contents in a GitHub Secret, base64-encoded.

On your Windows machine, from the directory containing the .p8 file:

# PowerShell
[Convert]::ToBase64String([IO.File]::ReadAllBytes("AuthKey_T42VNQ7V5Z.p8"))

Or in Git Bash:

base64 -w0 AuthKey_T42VNQ7V5Z.p8

Copy the output. Then:

  1. Go to Settings → Secrets and variables → Actions → New repository secret
  2. Name: ASC_API_KEY_P8_B64
  3. Value: paste the base64 string
  4. Save

The workflow writes this back to disk at runtime, uses it, and deletes it in a cleanup step (runs even on failure).

Step 3: (Optional) First dry-run

Once the above is done, go to Actions → Release (iOS TestFlight) → Run workflow. Confirm the preflight and build jobs succeed. When it hits the submit step, you'll get the approval prompt. You can either approve (and ship a build) or cancel the workflow run (no submit).

What this does NOT do

  • Does NOT auto-trigger on master push
  • Does NOT bump app.json version automatically (manual bump before dispatch)
  • Does NOT auto-generate release notes from merged PRs (could add later)
  • Does NOT modify app.yml (the OTA-update workflow) — that decision deferred

Verification

Preflight: this PR itself will exercise the new preflight steps (the test workflow runs on every PR). If expo-doctor or expo export fail, this PR will show as red — and we'll know there's a pre-existing issue on master we didn't know about before.

@github-actions

github-actionsBot commented Apr 17, 2026

Copy link
Copy Markdown

Test Results

✅ All tests passed

PassedFailedTotal
Tests✅ 3418❌ 03418
Suites✅ 464❌ 0464

Coverage

StatementsBranchesFunctionsLines

⏱️ Duration: 81.1s

@CraigBuckmaster
CraigBuckmaster merged commit f657a39 into masterApr 17, 2026
6 checks passed
@CraigBuckmaster
CraigBuckmaster deleted the ci/preflight-and-release-workflows branch April 17, 2026 19:17
Sign up for freeto 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.

1 participant

@CraigBuckmaster
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

ci: add preflight bundle checks + on-demand release workflow - #1505

Merged
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows
Apr 17, 2026
Merged

ci: add preflight bundle checks + on-demand release workflow#1505
CraigBuckmaster merged 3 commits into
masterfrom
ci/preflight-and-release-workflows

Conversation

@CraigBuckmaster

Copy link
Copy Markdown
Owner

CI: preflight bundle checks + on-demand release workflow

Two workflow changes:

1. Preflight — extend test.yml

The existing test.yml runs tsc --noEmit and jest on every PR. Adds two steps at the end:

  • npx expo-doctor@latest — dep version drift (catches things like "Reanimated 3.19.5 with SDK 54" before it reaches EAS)
  • npx expo export --platform ios — full Metro bundle. Catches transitive-dep resolution failures (the class of bug that made PR fix: remove react-native-reanimated to resolve SDK 54 native-module crash #1492's reanimated removal fail at bundling only after a 20-minute EAS upload)

Both block merge if they fail. Runs on GitHub's free Linux runners — no EAS minutes consumed.

2. Release — new release.yml

Manual, on-demand iOS build + TestFlight submit.

Flow:

  1. You bump app.jsonversion on master (or leave it — EAS auto-increments buildNumber)
  2. Actions tab → "Release (iOS TestFlight)" → Run workflow
  3. Preflight re-runs (defense in depth)
  4. eas build --platform ios --profile production --wait runs
  5. Approval gate: submit step is gated on testflight-submit GitHub Environment. You get a notification, click Approve in the Actions UI, submit runs.
  6. Cleanup: .p8 file is deleted from the runner even on failure.
  7. Tag step pushes v<version>-build<number> for traceability.

No auto-trigger. Never runs on push to master. Only when you dispatch it manually.

Setup steps required AFTER merge (cannot land without these)

The release workflow will fail to run until you complete these three setup steps. Preflight works immediately with no setup.

Step 1: Create the testflight-submit GitHub Environment

  1. Go to Settings → Environments → New environment
  2. Name: testflight-submit
  3. Enable Required reviewers and add yourself (CraigBuckmaster)
  4. Save

Step 2: Add the App Store Connect API key as a secret

Your eas.json references ./AuthKey_T42VNQ7V5Z.p8. We need its contents in a GitHub Secret, base64-encoded.

On your Windows machine, from the directory containing the .p8 file:

# PowerShell
[Convert]::ToBase64String([IO.File]::ReadAllBytes("AuthKey_T42VNQ7V5Z.p8"))

Or in Git Bash:

base64 -w0 AuthKey_T42VNQ7V5Z.p8

Copy the output. Then:

  1. Go to Settings → Secrets and variables → Actions → New repository secret
  2. Name: ASC_API_KEY_P8_B64
  3. Value: paste the base64 string
  4. Save

The workflow writes this back to disk at runtime, uses it, and deletes it in a cleanup step (runs even on failure).

Step 3: (Optional) First dry-run

Once the above is done, go to Actions → Release (iOS TestFlight) → Run workflow. Confirm the preflight and build jobs succeed. When it hits the submit step, you'll get the approval prompt. You can either approve (and ship a build) or cancel the workflow run (no submit).

What this does NOT do

  • Does NOT auto-trigger on master push
  • Does NOT bump app.json version automatically (manual bump before dispatch)
  • Does NOT auto-generate release notes from merged PRs (could add later)
  • Does NOT modify app.yml (the OTA-update workflow) — that decision deferred

Verification

Preflight: this PR itself will exercise the new preflight steps (the test workflow runs on every PR). If expo-doctor or expo export fail, this PR will show as red — and we'll know there's a pre-existing issue on master we didn't know about before.

@github-actions

github-actionsBot commented Apr 17, 2026

Copy link
Copy Markdown

Test Results

✅ All tests passed

PassedFailedTotal
Tests✅ 3418❌ 03418
Suites✅ 464❌ 0464

Coverage

StatementsBranchesFunctionsLines

⏱️ Duration: 81.1s

@CraigBuckmaster
CraigBuckmaster merged commit f657a39 into masterApr 17, 2026
6 checks passed
@CraigBuckmaster
CraigBuckmaster deleted the ci/preflight-and-release-workflows branch April 17, 2026 19:17
Sign up for freeto 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.

1 participant

@CraigBuckmaster