markupr 2.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (299) hide show
  1. package/.claude/commands/review-feedback.md +47 -0
  2. package/.eslintrc.json +35 -0
  3. package/.github/CODEOWNERS +16 -0
  4. package/.github/FUNDING.yml +1 -0
  5. package/.github/ISSUE_TEMPLATE/bug_report.md +56 -0
  6. package/.github/ISSUE_TEMPLATE/feature_request.md +54 -0
  7. package/.github/PULL_REQUEST_TEMPLATE.md +89 -0
  8. package/.github/dependabot.yml +70 -0
  9. package/.github/workflows/ci.yml +184 -0
  10. package/.github/workflows/deploy-landing.yml +134 -0
  11. package/.github/workflows/nightly.yml +288 -0
  12. package/.github/workflows/release.yml +318 -0
  13. package/CHANGELOG.md +127 -0
  14. package/CLAUDE.md +137 -0
  15. package/CODE_OF_CONDUCT.md +9 -0
  16. package/CONTRIBUTING.md +390 -0
  17. package/LICENSE +21 -0
  18. package/PRODUCT_VISION.md +277 -0
  19. package/README.md +517 -0
  20. package/SECURITY.md +51 -0
  21. package/SIGNING_INSTRUCTIONS.md +284 -0
  22. package/assets/DMG_BACKGROUND_INSTRUCTIONS.md +130 -0
  23. package/assets/svg-source/dmg-background.svg +70 -0
  24. package/assets/svg-source/icon.svg +20 -0
  25. package/assets/svg-source/tray-icon-processing.svg +7 -0
  26. package/assets/svg-source/tray-icon-recording.svg +7 -0
  27. package/assets/svg-source/tray-icon.svg +6 -0
  28. package/assets/tray-complete.png +0 -0
  29. package/assets/tray-complete@2x.png +0 -0
  30. package/assets/tray-completeTemplate.png +0 -0
  31. package/assets/tray-completeTemplate@2x.png +0 -0
  32. package/assets/tray-error.png +0 -0
  33. package/assets/tray-error@2x.png +0 -0
  34. package/assets/tray-errorTemplate.png +0 -0
  35. package/assets/tray-errorTemplate@2x.png +0 -0
  36. package/assets/tray-icon-processing.png +0 -0
  37. package/assets/tray-icon-processing@2x.png +0 -0
  38. package/assets/tray-icon-processingTemplate.png +0 -0
  39. package/assets/tray-icon-processingTemplate@2x.png +0 -0
  40. package/assets/tray-icon-recording.png +0 -0
  41. package/assets/tray-icon-recording@2x.png +0 -0
  42. package/assets/tray-icon-recordingTemplate.png +0 -0
  43. package/assets/tray-icon-recordingTemplate@2x.png +0 -0
  44. package/assets/tray-icon.png +0 -0
  45. package/assets/tray-icon@2x.png +0 -0
  46. package/assets/tray-iconTemplate.png +0 -0
  47. package/assets/tray-iconTemplate@2x.png +0 -0
  48. package/assets/tray-idle.png +0 -0
  49. package/assets/tray-idle@2x.png +0 -0
  50. package/assets/tray-idleTemplate.png +0 -0
  51. package/assets/tray-idleTemplate@2x.png +0 -0
  52. package/assets/tray-processing-0.png +0 -0
  53. package/assets/tray-processing-0@2x.png +0 -0
  54. package/assets/tray-processing-0Template.png +0 -0
  55. package/assets/tray-processing-0Template@2x.png +0 -0
  56. package/assets/tray-processing-1.png +0 -0
  57. package/assets/tray-processing-1@2x.png +0 -0
  58. package/assets/tray-processing-1Template.png +0 -0
  59. package/assets/tray-processing-1Template@2x.png +0 -0
  60. package/assets/tray-processing-2.png +0 -0
  61. package/assets/tray-processing-2@2x.png +0 -0
  62. package/assets/tray-processing-2Template.png +0 -0
  63. package/assets/tray-processing-2Template@2x.png +0 -0
  64. package/assets/tray-processing-3.png +0 -0
  65. package/assets/tray-processing-3@2x.png +0 -0
  66. package/assets/tray-processing-3Template.png +0 -0
  67. package/assets/tray-processing-3Template@2x.png +0 -0
  68. package/assets/tray-processing.png +0 -0
  69. package/assets/tray-processing@2x.png +0 -0
  70. package/assets/tray-processingTemplate.png +0 -0
  71. package/assets/tray-processingTemplate@2x.png +0 -0
  72. package/assets/tray-recording.png +0 -0
  73. package/assets/tray-recording@2x.png +0 -0
  74. package/assets/tray-recordingTemplate.png +0 -0
  75. package/assets/tray-recordingTemplate@2x.png +0 -0
  76. package/build/DMG_BACKGROUND_SPEC.md +50 -0
  77. package/build/dmg-background.png +0 -0
  78. package/build/dmg-background@2x.png +0 -0
  79. package/build/entitlements.mac.inherit.plist +27 -0
  80. package/build/entitlements.mac.plist +41 -0
  81. package/build/favicon-16.png +0 -0
  82. package/build/favicon-180.png +0 -0
  83. package/build/favicon-192.png +0 -0
  84. package/build/favicon-32.png +0 -0
  85. package/build/favicon-48.png +0 -0
  86. package/build/favicon-512.png +0 -0
  87. package/build/favicon-64.png +0 -0
  88. package/build/icon-128.png +0 -0
  89. package/build/icon-16.png +0 -0
  90. package/build/icon-24.png +0 -0
  91. package/build/icon-256.png +0 -0
  92. package/build/icon-32.png +0 -0
  93. package/build/icon-48.png +0 -0
  94. package/build/icon-64.png +0 -0
  95. package/build/icon.icns +0 -0
  96. package/build/icon.ico +0 -0
  97. package/build/icon.iconset/icon_128x128.png +0 -0
  98. package/build/icon.iconset/icon_128x128@2x.png +0 -0
  99. package/build/icon.iconset/icon_16x16.png +0 -0
  100. package/build/icon.iconset/icon_16x16@2x.png +0 -0
  101. package/build/icon.iconset/icon_256x256.png +0 -0
  102. package/build/icon.iconset/icon_256x256@2x.png +0 -0
  103. package/build/icon.iconset/icon_32x32.png +0 -0
  104. package/build/icon.iconset/icon_32x32@2x.png +0 -0
  105. package/build/icon.iconset/icon_512x512.png +0 -0
  106. package/build/icon.iconset/icon_512x512@2x.png +0 -0
  107. package/build/icon.png +0 -0
  108. package/build/installer-header.bmp +0 -0
  109. package/build/installer-header.png +0 -0
  110. package/build/installer-sidebar.bmp +0 -0
  111. package/build/installer-sidebar.png +0 -0
  112. package/build/installer.nsh +45 -0
  113. package/build/overlay-processing.png +0 -0
  114. package/build/overlay-recording.png +0 -0
  115. package/build/toolbar-record.png +0 -0
  116. package/build/toolbar-screenshot.png +0 -0
  117. package/build/toolbar-settings.png +0 -0
  118. package/build/toolbar-stop.png +0 -0
  119. package/dist/main/index.mjs +12612 -0
  120. package/dist/preload/index.mjs +907 -0
  121. package/dist/renderer/assets/index-CCmUjl9K.js +19495 -0
  122. package/dist/renderer/assets/index-CUqz_Gs6.css +2270 -0
  123. package/dist/renderer/index.html +27 -0
  124. package/docs/AI_AGENT_QUICKSTART.md +42 -0
  125. package/docs/AI_PIPELINE_DESIGN.md +595 -0
  126. package/docs/API.md +514 -0
  127. package/docs/ARCHITECTURE.md +460 -0
  128. package/docs/CONFIGURATION.md +336 -0
  129. package/docs/DEVELOPMENT.md +508 -0
  130. package/docs/EXPORT_FORMATS.md +451 -0
  131. package/docs/GETTING_STARTED.md +236 -0
  132. package/docs/KEYBOARD_SHORTCUTS.md +334 -0
  133. package/docs/TROUBLESHOOTING.md +418 -0
  134. package/docs/landing/index.html +672 -0
  135. package/docs/landing/script.js +342 -0
  136. package/docs/landing/styles.css +1543 -0
  137. package/electron-builder.yml +140 -0
  138. package/electron.vite.config.ts +63 -0
  139. package/package.json +108 -0
  140. package/railway.json +12 -0
  141. package/scripts/build.mjs +51 -0
  142. package/scripts/generate-icons.mjs +314 -0
  143. package/scripts/generate-installer-images.cjs +253 -0
  144. package/scripts/generate-tray-icons.mjs +258 -0
  145. package/scripts/notarize.cjs +180 -0
  146. package/scripts/one-click-clean-test.sh +147 -0
  147. package/scripts/postinstall.mjs +36 -0
  148. package/scripts/setup-markupr.sh +55 -0
  149. package/setup +17 -0
  150. package/site/index.html +1835 -0
  151. package/site/package.json +11 -0
  152. package/site/railway.json +12 -0
  153. package/site/server.js +31 -0
  154. package/src/main/AutoUpdater.ts +392 -0
  155. package/src/main/CrashRecovery.ts +655 -0
  156. package/src/main/ErrorHandler.ts +703 -0
  157. package/src/main/HotkeyManager.ts +399 -0
  158. package/src/main/MenuManager.ts +529 -0
  159. package/src/main/PermissionManager.ts +420 -0
  160. package/src/main/SessionController.ts +1465 -0
  161. package/src/main/TrayManager.ts +540 -0
  162. package/src/main/ai/AIPipelineManager.ts +199 -0
  163. package/src/main/ai/ClaudeAnalyzer.ts +339 -0
  164. package/src/main/ai/ImageOptimizer.ts +176 -0
  165. package/src/main/ai/StructuredMarkdownBuilder.ts +379 -0
  166. package/src/main/ai/index.ts +16 -0
  167. package/src/main/ai/types.ts +258 -0
  168. package/src/main/analysis/ClarificationGenerator.ts +385 -0
  169. package/src/main/analysis/FeedbackAnalyzer.ts +531 -0
  170. package/src/main/analysis/index.ts +19 -0
  171. package/src/main/audio/AudioCapture.ts +978 -0
  172. package/src/main/audio/audioUtils.ts +100 -0
  173. package/src/main/audio/index.ts +20 -0
  174. package/src/main/capture/index.ts +1 -0
  175. package/src/main/index.ts +1693 -0
  176. package/src/main/ipc/captureHandlers.ts +272 -0
  177. package/src/main/ipc/index.ts +45 -0
  178. package/src/main/ipc/outputHandlers.ts +302 -0
  179. package/src/main/ipc/sessionHandlers.ts +56 -0
  180. package/src/main/ipc/settingsHandlers.ts +471 -0
  181. package/src/main/ipc/types.ts +56 -0
  182. package/src/main/ipc/windowHandlers.ts +277 -0
  183. package/src/main/output/ClipboardService.ts +369 -0
  184. package/src/main/output/ExportService.ts +539 -0
  185. package/src/main/output/FileManager.ts +416 -0
  186. package/src/main/output/MarkdownGenerator.ts +791 -0
  187. package/src/main/output/MarkdownPatcher.ts +299 -0
  188. package/src/main/output/index.ts +186 -0
  189. package/src/main/output/sessionAdapter.ts +207 -0
  190. package/src/main/output/templates/html-template.ts +553 -0
  191. package/src/main/pipeline/FrameExtractor.ts +330 -0
  192. package/src/main/pipeline/PostProcessor.ts +399 -0
  193. package/src/main/pipeline/TranscriptAnalyzer.ts +226 -0
  194. package/src/main/pipeline/index.ts +36 -0
  195. package/src/main/platform/WindowsTaskbar.ts +600 -0
  196. package/src/main/platform/index.ts +16 -0
  197. package/src/main/settings/SettingsManager.ts +730 -0
  198. package/src/main/settings/index.ts +19 -0
  199. package/src/main/transcription/ModelDownloadManager.ts +494 -0
  200. package/src/main/transcription/TierManager.ts +219 -0
  201. package/src/main/transcription/TranscriptionRecoveryService.ts +340 -0
  202. package/src/main/transcription/WhisperService.ts +748 -0
  203. package/src/main/transcription/index.ts +56 -0
  204. package/src/main/transcription/types.ts +135 -0
  205. package/src/main/windows/PopoverManager.ts +284 -0
  206. package/src/main/windows/TaskbarIntegration.ts +452 -0
  207. package/src/main/windows/index.ts +23 -0
  208. package/src/preload/index.ts +1047 -0
  209. package/src/renderer/App.tsx +515 -0
  210. package/src/renderer/AppWrapper.tsx +28 -0
  211. package/src/renderer/assets/logo-dark.svg +7 -0
  212. package/src/renderer/assets/logo.svg +7 -0
  213. package/src/renderer/audio/AudioCaptureRenderer.ts +454 -0
  214. package/src/renderer/capture/ScreenRecordingRenderer.ts +492 -0
  215. package/src/renderer/components/AnnotationOverlay.tsx +836 -0
  216. package/src/renderer/components/AudioWaveform.tsx +811 -0
  217. package/src/renderer/components/ClarificationQuestions.tsx +656 -0
  218. package/src/renderer/components/CountdownTimer.tsx +495 -0
  219. package/src/renderer/components/CrashRecoveryDialog.tsx +632 -0
  220. package/src/renderer/components/DonateButton.tsx +127 -0
  221. package/src/renderer/components/ErrorBoundary.tsx +308 -0
  222. package/src/renderer/components/ExportDialog.tsx +872 -0
  223. package/src/renderer/components/HotkeyHint.tsx +261 -0
  224. package/src/renderer/components/KeyboardShortcuts.tsx +787 -0
  225. package/src/renderer/components/ModelDownloadDialog.tsx +844 -0
  226. package/src/renderer/components/Onboarding.tsx +1830 -0
  227. package/src/renderer/components/ProcessingOverlay.tsx +157 -0
  228. package/src/renderer/components/RecordingOverlay.tsx +423 -0
  229. package/src/renderer/components/SessionHistory.tsx +1746 -0
  230. package/src/renderer/components/SessionReview.tsx +1321 -0
  231. package/src/renderer/components/SettingsPanel.tsx +217 -0
  232. package/src/renderer/components/Skeleton.tsx +347 -0
  233. package/src/renderer/components/StatusIndicator.tsx +86 -0
  234. package/src/renderer/components/ThemeProvider.tsx +429 -0
  235. package/src/renderer/components/Tooltip.tsx +370 -0
  236. package/src/renderer/components/TranscriptionPreview.tsx +183 -0
  237. package/src/renderer/components/TranscriptionTierSelector.tsx +640 -0
  238. package/src/renderer/components/UpdateNotification.tsx +377 -0
  239. package/src/renderer/components/WindowSelector.tsx +947 -0
  240. package/src/renderer/components/index.ts +99 -0
  241. package/src/renderer/components/primitives/ApiKeyInput.tsx +98 -0
  242. package/src/renderer/components/primitives/ColorPicker.tsx +65 -0
  243. package/src/renderer/components/primitives/DangerButton.tsx +45 -0
  244. package/src/renderer/components/primitives/DirectoryPicker.tsx +41 -0
  245. package/src/renderer/components/primitives/Dropdown.tsx +34 -0
  246. package/src/renderer/components/primitives/KeyRecorder.tsx +117 -0
  247. package/src/renderer/components/primitives/SettingsSection.tsx +32 -0
  248. package/src/renderer/components/primitives/Slider.tsx +43 -0
  249. package/src/renderer/components/primitives/Toggle.tsx +36 -0
  250. package/src/renderer/components/primitives/index.ts +10 -0
  251. package/src/renderer/components/settings/AdvancedTab.tsx +174 -0
  252. package/src/renderer/components/settings/AppearanceTab.tsx +77 -0
  253. package/src/renderer/components/settings/GeneralTab.tsx +40 -0
  254. package/src/renderer/components/settings/HotkeysTab.tsx +79 -0
  255. package/src/renderer/components/settings/RecordingTab.tsx +84 -0
  256. package/src/renderer/components/settings/index.ts +9 -0
  257. package/src/renderer/components/settings/settingsStyles.ts +673 -0
  258. package/src/renderer/components/settings/tabConfig.tsx +85 -0
  259. package/src/renderer/components/settings/useSettingsPanel.ts +447 -0
  260. package/src/renderer/contexts/ProcessingContext.tsx +227 -0
  261. package/src/renderer/contexts/RecordingContext.tsx +683 -0
  262. package/src/renderer/contexts/UIContext.tsx +326 -0
  263. package/src/renderer/contexts/index.ts +24 -0
  264. package/src/renderer/donateMessages.ts +69 -0
  265. package/src/renderer/hooks/index.ts +75 -0
  266. package/src/renderer/hooks/useAnimation.tsx +544 -0
  267. package/src/renderer/hooks/useTheme.ts +313 -0
  268. package/src/renderer/index.html +26 -0
  269. package/src/renderer/main.tsx +52 -0
  270. package/src/renderer/styles/animations.css +1093 -0
  271. package/src/renderer/styles/app-shell.css +662 -0
  272. package/src/renderer/styles/globals.css +515 -0
  273. package/src/renderer/styles/theme.ts +578 -0
  274. package/src/renderer/types/electron.d.ts +385 -0
  275. package/src/shared/hotkeys.ts +283 -0
  276. package/src/shared/types.ts +809 -0
  277. package/tests/clipboard.test.ts +228 -0
  278. package/tests/e2e/criticalPaths.test.ts +594 -0
  279. package/tests/feedbackAnalyzer.test.ts +303 -0
  280. package/tests/integration/sessionFlow.test.ts +583 -0
  281. package/tests/markdownGenerator.test.ts +418 -0
  282. package/tests/output.test.ts +96 -0
  283. package/tests/setup.ts +486 -0
  284. package/tests/unit/appIntegration.test.ts +676 -0
  285. package/tests/unit/appViewState.test.ts +281 -0
  286. package/tests/unit/audioIpcChannels.test.ts +17 -0
  287. package/tests/unit/exportService.test.ts +492 -0
  288. package/tests/unit/hotkeys.test.ts +92 -0
  289. package/tests/unit/navigationPreload.test.ts +94 -0
  290. package/tests/unit/onboardingFlow.test.ts +345 -0
  291. package/tests/unit/permissionManager.test.ts +175 -0
  292. package/tests/unit/permissionManagerExpanded.test.ts +296 -0
  293. package/tests/unit/screenRecordingRenderer.test.ts +368 -0
  294. package/tests/unit/sessionController.test.ts +515 -0
  295. package/tests/unit/tierManager.test.ts +61 -0
  296. package/tests/unit/tierManagerExpanded.test.ts +142 -0
  297. package/tests/unit/transcriptAnalyzer.test.ts +64 -0
  298. package/tsconfig.json +25 -0
  299. package/vitest.config.ts +46 -0
@@ -0,0 +1,288 @@
1
+ # =============================================================================
2
+ # markupr Nightly Builds
3
+ # =============================================================================
4
+ # Runs every day at 2am UTC
5
+ # Builds beta versions for testing
6
+ # Uploads to a separate "nightly" release
7
+ # =============================================================================
8
+
9
+ name: Nightly
10
+
11
+ on:
12
+ schedule:
13
+ # Run at 2am UTC every day
14
+ - cron: '0 2 * * *'
15
+ # Allow manual trigger
16
+ workflow_dispatch:
17
+ inputs:
18
+ force-build:
19
+ description: 'Force build even if no changes'
20
+ required: false
21
+ default: 'false'
22
+ type: boolean
23
+
24
+ env:
25
+ NODE_VERSION: '20'
26
+
27
+ jobs:
28
+ # ===========================================================================
29
+ # Check for Changes
30
+ # ===========================================================================
31
+ check-changes:
32
+ name: Check for Changes
33
+ runs-on: ubuntu-latest
34
+ outputs:
35
+ should-build: ${{ steps.check.outputs.should-build }}
36
+ nightly-version: ${{ steps.version.outputs.nightly-version }}
37
+ steps:
38
+ - name: Checkout repository
39
+ uses: actions/checkout@v6
40
+ with:
41
+ fetch-depth: 2
42
+
43
+ - name: Check for changes in last 24 hours
44
+ id: check
45
+ run: |
46
+ # Check if there are commits in the last 24 hours
47
+ COMMITS=$(git log --since="24 hours ago" --oneline | wc -l)
48
+
49
+ if [ "$COMMITS" -gt 0 ] || [ "${{ github.event.inputs.force-build }}" = "true" ]; then
50
+ echo "should-build=true" >> $GITHUB_OUTPUT
51
+ echo "Found $COMMITS commits in last 24 hours, building nightly"
52
+ else
53
+ echo "should-build=false" >> $GITHUB_OUTPUT
54
+ echo "No commits in last 24 hours, skipping nightly build"
55
+ fi
56
+
57
+ - name: Generate nightly version
58
+ id: version
59
+ if: steps.check.outputs.should-build == 'true'
60
+ run: |
61
+ BASE_VERSION=$(node -p "require('./package.json').version")
62
+ DATE=$(date +%Y%m%d)
63
+ SHORT_SHA=$(git rev-parse --short HEAD)
64
+ NIGHTLY_VERSION="${BASE_VERSION}-nightly.${DATE}.${SHORT_SHA}"
65
+
66
+ echo "nightly-version=$NIGHTLY_VERSION" >> $GITHUB_OUTPUT
67
+ echo "Nightly version: $NIGHTLY_VERSION"
68
+
69
+ # ===========================================================================
70
+ # Build macOS Nightly
71
+ # ===========================================================================
72
+ build-macos:
73
+ name: Build macOS Nightly
74
+ runs-on: macos-latest
75
+ needs: check-changes
76
+ if: needs.check-changes.outputs.should-build == 'true'
77
+ steps:
78
+ - name: Checkout repository
79
+ uses: actions/checkout@v6
80
+
81
+ - name: Setup Node.js
82
+ uses: actions/setup-node@v6
83
+ with:
84
+ node-version: ${{ env.NODE_VERSION }}
85
+ cache: 'npm'
86
+
87
+ - name: Install dependencies
88
+ run: npm ci
89
+
90
+ - name: Update version for nightly
91
+ run: |
92
+ npm version ${{ needs.check-changes.outputs.nightly-version }} --no-git-tag-version
93
+
94
+ - name: Build application
95
+ run: npm run build
96
+
97
+ # Build unsigned for nightly (no code signing)
98
+ - name: Package macOS (unsigned)
99
+ run: npm run package:mac:unsigned
100
+ env:
101
+ CSC_IDENTITY_AUTO_DISCOVERY: false
102
+
103
+ - name: Rename artifacts with nightly suffix
104
+ run: |
105
+ cd release
106
+ for f in *.dmg *.zip; do
107
+ if [ -f "$f" ]; then
108
+ mv "$f" "${f%.*}-nightly.${f##*.}"
109
+ fi
110
+ done
111
+ ls -la
112
+
113
+ - name: Upload macOS nightly artifacts
114
+ uses: actions/upload-artifact@v6
115
+ with:
116
+ name: nightly-macos
117
+ path: |
118
+ release/*-nightly.dmg
119
+ release/*-nightly.zip
120
+ if-no-files-found: error
121
+ retention-days: 7
122
+
123
+ # ===========================================================================
124
+ # Build Windows Nightly
125
+ # ===========================================================================
126
+ build-windows:
127
+ name: Build Windows Nightly
128
+ runs-on: windows-latest
129
+ needs: check-changes
130
+ if: needs.check-changes.outputs.should-build == 'true'
131
+ steps:
132
+ - name: Checkout repository
133
+ uses: actions/checkout@v6
134
+
135
+ - name: Setup Node.js
136
+ uses: actions/setup-node@v6
137
+ with:
138
+ node-version: ${{ env.NODE_VERSION }}
139
+ cache: 'npm'
140
+
141
+ - name: Install dependencies
142
+ run: npm ci
143
+
144
+ - name: Update version for nightly
145
+ run: |
146
+ npm version ${{ needs.check-changes.outputs.nightly-version }} --no-git-tag-version
147
+
148
+ - name: Build application
149
+ run: npm run build
150
+
151
+ # Build unsigned for nightly
152
+ - name: Package Windows (unsigned)
153
+ run: npm run package:win
154
+ env:
155
+ WIN_CSC_LINK: ''
156
+
157
+ - name: Rename artifacts with nightly suffix
158
+ shell: pwsh
159
+ run: |
160
+ cd release
161
+ Get-ChildItem -Filter "*.exe" | ForEach-Object {
162
+ $newName = $_.BaseName + "-nightly" + $_.Extension
163
+ Rename-Item $_.FullName $newName
164
+ }
165
+ Get-ChildItem
166
+
167
+ - name: Upload Windows nightly artifacts
168
+ uses: actions/upload-artifact@v6
169
+ with:
170
+ name: nightly-windows
171
+ path: |
172
+ release/*-nightly.exe
173
+ release/*-nightly.zip
174
+ if-no-files-found: error
175
+ retention-days: 7
176
+
177
+ # ===========================================================================
178
+ # Create/Update Nightly Release
179
+ # ===========================================================================
180
+ publish-nightly:
181
+ name: Publish Nightly Release
182
+ runs-on: ubuntu-latest
183
+ needs: [check-changes, build-macos, build-windows]
184
+ if: needs.check-changes.outputs.should-build == 'true'
185
+ permissions:
186
+ contents: write
187
+ steps:
188
+ - name: Checkout repository
189
+ uses: actions/checkout@v6
190
+
191
+ - name: Download all artifacts
192
+ uses: actions/download-artifact@v7
193
+ with:
194
+ path: artifacts
195
+
196
+ - name: Display artifact structure
197
+ run: find artifacts -type f
198
+
199
+ - name: Generate nightly release notes
200
+ run: |
201
+ cat > NIGHTLY_NOTES.md << 'EOF'
202
+ ## Nightly Build
203
+
204
+ **Version:** ${{ needs.check-changes.outputs.nightly-version }}
205
+ **Built:** $(date -u +"%Y-%m-%d %H:%M UTC")
206
+ **Commit:** ${{ github.sha }}
207
+
208
+ > **Warning**: Nightly builds are automatically generated from the latest code and may be unstable. Use at your own risk.
209
+
210
+ ### Recent Changes
211
+
212
+ EOF
213
+
214
+ git log --since="24 hours ago" --pretty=format:"- %s (%h)" >> NIGHTLY_NOTES.md || echo "- No changes in last 24 hours" >> NIGHTLY_NOTES.md
215
+
216
+ cat >> NIGHTLY_NOTES.md << 'EOF'
217
+
218
+ ### Downloads
219
+
220
+ | Platform | Download |
221
+ |----------|----------|
222
+ | macOS | See assets below |
223
+ | Windows | See assets below |
224
+
225
+ ### Checksums
226
+
227
+ ```
228
+ EOF
229
+
230
+ find artifacts -type f \( -name "*.dmg" -o -name "*.exe" -o -name "*.zip" \) -exec sha256sum {} \; >> NIGHTLY_NOTES.md
231
+
232
+ echo '```' >> NIGHTLY_NOTES.md
233
+
234
+ cat NIGHTLY_NOTES.md
235
+
236
+ # Delete existing nightly release if it exists
237
+ - name: Delete existing nightly release
238
+ uses: dev-drprasad/delete-tag-and-release@v1.1
239
+ with:
240
+ tag_name: nightly
241
+ delete_release: true
242
+ github_token: ${{ secrets.GITHUB_TOKEN }}
243
+ continue-on-error: true
244
+
245
+ - name: Create nightly release
246
+ uses: softprops/action-gh-release@v2
247
+ with:
248
+ tag_name: nightly
249
+ name: markupr Nightly (${{ needs.check-changes.outputs.nightly-version }})
250
+ body_path: NIGHTLY_NOTES.md
251
+ draft: false
252
+ prerelease: true
253
+ files: |
254
+ artifacts/nightly-macos/*
255
+ artifacts/nightly-windows/*
256
+ fail_on_unmatched_files: false
257
+ env:
258
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
259
+
260
+ - name: Nightly Summary
261
+ run: |
262
+ echo "## Nightly Build Summary" >> $GITHUB_STEP_SUMMARY
263
+ echo "" >> $GITHUB_STEP_SUMMARY
264
+ echo "**Version:** ${{ needs.check-changes.outputs.nightly-version }}" >> $GITHUB_STEP_SUMMARY
265
+ echo "**Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
266
+ echo "" >> $GITHUB_STEP_SUMMARY
267
+ echo "### Artifacts Published" >> $GITHUB_STEP_SUMMARY
268
+ find artifacts -type f \( -name "*.dmg" -o -name "*.exe" -o -name "*.zip" \) | while read f; do
269
+ echo "- $(basename $f)" >> $GITHUB_STEP_SUMMARY
270
+ done
271
+
272
+ # ===========================================================================
273
+ # Notify on Failure
274
+ # ===========================================================================
275
+ notify-failure:
276
+ name: Notify on Failure
277
+ runs-on: ubuntu-latest
278
+ needs: [build-macos, build-windows, publish-nightly]
279
+ if: failure()
280
+ steps:
281
+ - name: Create failure summary
282
+ run: |
283
+ echo "## Nightly Build Failed" >> $GITHUB_STEP_SUMMARY
284
+ echo "" >> $GITHUB_STEP_SUMMARY
285
+ echo "The nightly build failed. Please check the logs for details." >> $GITHUB_STEP_SUMMARY
286
+ echo "" >> $GITHUB_STEP_SUMMARY
287
+ echo "**Run:** ${{ github.run_id }}" >> $GITHUB_STEP_SUMMARY
288
+ echo "**Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
@@ -0,0 +1,318 @@
1
+ # =============================================================================
2
+ # markupr Release Pipeline
3
+ # =============================================================================
4
+ # Triggered on version tags (v*)
5
+ # Builds signed installers for macOS and Windows
6
+ # Creates GitHub Release with changelog and assets
7
+ # =============================================================================
8
+
9
+ name: Release
10
+
11
+ on:
12
+ push:
13
+ tags:
14
+ - 'v*'
15
+
16
+ # Only one release at a time
17
+ concurrency:
18
+ group: release
19
+ cancel-in-progress: false
20
+
21
+ env:
22
+ NODE_VERSION: '20'
23
+
24
+ jobs:
25
+ # ===========================================================================
26
+ # Validate Release Tag
27
+ # ===========================================================================
28
+ validate-tag:
29
+ name: Validate Release Tag
30
+ runs-on: ubuntu-latest
31
+ outputs:
32
+ version: ${{ steps.version.outputs.version }}
33
+ is-prerelease: ${{ steps.version.outputs.is-prerelease }}
34
+ steps:
35
+ - name: Checkout repository
36
+ uses: actions/checkout@v6
37
+
38
+ - name: Extract version from tag
39
+ id: version
40
+ run: |
41
+ TAG_VERSION=${GITHUB_REF#refs/tags/v}
42
+ echo "version=$TAG_VERSION" >> $GITHUB_OUTPUT
43
+
44
+ # Check if this is a prerelease (alpha, beta, rc)
45
+ if [[ "$TAG_VERSION" =~ (alpha|beta|rc) ]]; then
46
+ echo "is-prerelease=true" >> $GITHUB_OUTPUT
47
+ else
48
+ echo "is-prerelease=false" >> $GITHUB_OUTPUT
49
+ fi
50
+
51
+ echo "Release version: $TAG_VERSION"
52
+
53
+ - name: Validate version matches package.json
54
+ run: |
55
+ PACKAGE_VERSION=$(node -p "require('./package.json').version")
56
+ TAG_VERSION=${{ steps.version.outputs.version }}
57
+
58
+ if [ "$PACKAGE_VERSION" != "$TAG_VERSION" ]; then
59
+ echo "Error: Tag version ($TAG_VERSION) does not match package.json version ($PACKAGE_VERSION)"
60
+ exit 1
61
+ fi
62
+ echo "Version validated: $TAG_VERSION"
63
+
64
+ # ===========================================================================
65
+ # Build macOS (Intel + Apple Silicon)
66
+ # ===========================================================================
67
+ build-macos:
68
+ name: Build macOS
69
+ runs-on: macos-latest
70
+ needs: validate-tag
71
+ env:
72
+ APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
73
+ APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
74
+ KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
75
+ APPLE_ID: ${{ secrets.APPLE_ID }}
76
+ APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
77
+ APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
78
+ steps:
79
+ - name: Checkout repository
80
+ uses: actions/checkout@v6
81
+
82
+ - name: Setup Node.js
83
+ uses: actions/setup-node@v6
84
+ with:
85
+ node-version: ${{ env.NODE_VERSION }}
86
+ cache: 'npm'
87
+
88
+ - name: Install dependencies
89
+ run: npm ci
90
+
91
+ # Cache Electron binaries
92
+ - name: Cache Electron
93
+ uses: actions/cache@v5
94
+ with:
95
+ path: ~/Library/Caches/electron
96
+ key: macos-electron-${{ hashFiles('package-lock.json') }}
97
+ restore-keys: |
98
+ macos-electron-
99
+
100
+ - name: Build application
101
+ run: npm run build
102
+
103
+ # Install certificates for code signing
104
+ - name: Install Apple certificates
105
+ if: ${{ env.APPLE_CERTIFICATE != '' }}
106
+ run: |
107
+ # Create variables
108
+ CERTIFICATE_PATH=$RUNNER_TEMP/certificate.p12
109
+ KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
110
+
111
+ # Import certificate
112
+ echo -n "$APPLE_CERTIFICATE" | base64 --decode -o $CERTIFICATE_PATH
113
+
114
+ # Create temporary keychain
115
+ security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
116
+ security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
117
+ security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
118
+
119
+ # Import certificate to keychain
120
+ security import $CERTIFICATE_PATH -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
121
+ security list-keychain -d user -s $KEYCHAIN_PATH
122
+
123
+ # Allow codesign to access keychain
124
+ security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
125
+
126
+ # Build and sign for macOS
127
+ - name: Package macOS (signed)
128
+ if: ${{ env.APPLE_ID != '' && env.APPLE_CERTIFICATE != '' }}
129
+ run: npx electron-builder --mac --publish never --config electron-builder.yml
130
+ env:
131
+ # Code signing
132
+ APPLE_ID: ${{ secrets.APPLE_ID }}
133
+ APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
134
+ APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
135
+ # Notarization
136
+ APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
137
+ CSC_LINK: ${{ secrets.APPLE_CERTIFICATE }}
138
+ CSC_KEY_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
139
+
140
+ # Build unsigned if no signing credentials
141
+ - name: Package macOS (unsigned)
142
+ if: ${{ env.APPLE_ID == '' || env.APPLE_CERTIFICATE == '' }}
143
+ run: CSC_IDENTITY_AUTO_DISCOVERY=false npx electron-builder --mac --publish never --config electron-builder.yml
144
+ env:
145
+ CSC_IDENTITY_AUTO_DISCOVERY: false
146
+
147
+ - name: List build artifacts
148
+ run: ls -la release/
149
+
150
+ - name: Upload macOS artifacts
151
+ uses: actions/upload-artifact@v6
152
+ with:
153
+ name: release-macos
154
+ path: |
155
+ release/*.dmg
156
+ release/*.zip
157
+ release/*.blockmap
158
+ release/latest-mac.yml
159
+ if-no-files-found: error
160
+ retention-days: 30
161
+
162
+ # ===========================================================================
163
+ # Build Windows
164
+ # ===========================================================================
165
+ build-windows:
166
+ name: Build Windows
167
+ runs-on: windows-latest
168
+ needs: validate-tag
169
+ env:
170
+ WIN_SIGNING_AVAILABLE: ${{ secrets.WIN_CSC_LINK != '' }}
171
+ steps:
172
+ - name: Checkout repository
173
+ uses: actions/checkout@v6
174
+
175
+ - name: Setup Node.js
176
+ uses: actions/setup-node@v6
177
+ with:
178
+ node-version: ${{ env.NODE_VERSION }}
179
+ cache: 'npm'
180
+
181
+ - name: Install dependencies
182
+ run: npm ci
183
+
184
+ # Cache Electron binaries
185
+ - name: Cache Electron
186
+ uses: actions/cache@v5
187
+ with:
188
+ path: ~/AppData/Local/electron/Cache
189
+ key: windows-electron-${{ hashFiles('package-lock.json') }}
190
+ restore-keys: |
191
+ windows-electron-
192
+
193
+ - name: Build application
194
+ run: npm run build
195
+
196
+ # Build and sign for Windows
197
+ - name: Package Windows (signed)
198
+ if: ${{ env.WIN_SIGNING_AVAILABLE == 'true' }}
199
+ run: npx electron-builder --win --x64 --publish never --config electron-builder.yml
200
+ env:
201
+ WIN_CSC_LINK: ${{ secrets.WIN_CSC_LINK }}
202
+ WIN_CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD }}
203
+
204
+ # Build unsigned if no signing credentials
205
+ - name: Package Windows (unsigned)
206
+ if: ${{ env.WIN_SIGNING_AVAILABLE != 'true' }}
207
+ run: npx electron-builder --win --x64 --publish never --config electron-builder.yml
208
+ env:
209
+ CSC_IDENTITY_AUTO_DISCOVERY: false
210
+
211
+ - name: List build artifacts
212
+ run: dir release
213
+
214
+ - name: Upload Windows artifacts
215
+ uses: actions/upload-artifact@v6
216
+ with:
217
+ name: release-windows
218
+ path: |
219
+ release/*.exe
220
+ release/*.msi
221
+ release/*.zip
222
+ release/*.blockmap
223
+ release/latest.yml
224
+ if-no-files-found: error
225
+ retention-days: 30
226
+
227
+ # ===========================================================================
228
+ # Create GitHub Release
229
+ # ===========================================================================
230
+ create-release:
231
+ name: Create GitHub Release
232
+ runs-on: ubuntu-latest
233
+ needs: [validate-tag, build-macos, build-windows]
234
+ permissions:
235
+ contents: write
236
+ steps:
237
+ - name: Checkout repository
238
+ uses: actions/checkout@v6
239
+ with:
240
+ fetch-depth: 0
241
+
242
+ - name: Download all artifacts
243
+ uses: actions/download-artifact@v7
244
+ with:
245
+ path: artifacts
246
+
247
+ - name: Display artifact structure
248
+ run: find artifacts -type f | head -50
249
+
250
+ - name: Generate changelog
251
+ id: changelog
252
+ run: |
253
+ # Get previous tag
254
+ PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
255
+ CURRENT_TAG=${{ github.ref_name }}
256
+
257
+ echo "## What's Changed" > CHANGELOG.md
258
+ echo "" >> CHANGELOG.md
259
+
260
+ if [ -n "$PREVIOUS_TAG" ]; then
261
+ echo "Changes since $PREVIOUS_TAG:" >> CHANGELOG.md
262
+ echo "" >> CHANGELOG.md
263
+ git log $PREVIOUS_TAG..$CURRENT_TAG --pretty=format:"- %s (%h)" >> CHANGELOG.md
264
+ else
265
+ echo "Initial release" >> CHANGELOG.md
266
+ fi
267
+
268
+ echo "" >> CHANGELOG.md
269
+ echo "" >> CHANGELOG.md
270
+ echo "## Downloads" >> CHANGELOG.md
271
+ echo "" >> CHANGELOG.md
272
+ echo "| Platform | Download |" >> CHANGELOG.md
273
+ echo "|----------|----------|" >> CHANGELOG.md
274
+ echo "| macOS (Apple Silicon) | \`markupr-${{ needs.validate-tag.outputs.version }}-arm64.dmg\` |" >> CHANGELOG.md
275
+ echo "| macOS (Intel) | \`markupr-${{ needs.validate-tag.outputs.version }}-x64.dmg\` |" >> CHANGELOG.md
276
+ echo "| Windows | \`markupr-Setup-${{ needs.validate-tag.outputs.version }}.exe\` |" >> CHANGELOG.md
277
+ echo "" >> CHANGELOG.md
278
+ echo "## Checksums" >> CHANGELOG.md
279
+ echo "" >> CHANGELOG.md
280
+ echo "\`\`\`" >> CHANGELOG.md
281
+ find artifacts -type f \( -name "*.dmg" -o -name "*.exe" -o -name "*.zip" \) -exec sha256sum {} \; >> CHANGELOG.md
282
+ echo "\`\`\`" >> CHANGELOG.md
283
+
284
+ cat CHANGELOG.md
285
+
286
+ - name: Create GitHub Release
287
+ uses: softprops/action-gh-release@v2
288
+ with:
289
+ tag_name: ${{ github.ref_name }}
290
+ name: markupr v${{ needs.validate-tag.outputs.version }}
291
+ body_path: CHANGELOG.md
292
+ draft: false
293
+ prerelease: ${{ needs.validate-tag.outputs.is-prerelease == 'true' }}
294
+ files: |
295
+ artifacts/release-macos/*.dmg
296
+ artifacts/release-macos/*.zip
297
+ artifacts/release-macos/*.blockmap
298
+ artifacts/release-macos/*.yml
299
+ artifacts/release-windows/*.exe
300
+ artifacts/release-windows/*.msi
301
+ artifacts/release-windows/*.zip
302
+ artifacts/release-windows/*.blockmap
303
+ artifacts/release-windows/*.yml
304
+ fail_on_unmatched_files: false
305
+ env:
306
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
307
+
308
+ - name: Release Summary
309
+ run: |
310
+ echo "## Release Summary" >> $GITHUB_STEP_SUMMARY
311
+ echo "" >> $GITHUB_STEP_SUMMARY
312
+ echo "**Version:** v${{ needs.validate-tag.outputs.version }}" >> $GITHUB_STEP_SUMMARY
313
+ echo "**Prerelease:** ${{ needs.validate-tag.outputs.is-prerelease }}" >> $GITHUB_STEP_SUMMARY
314
+ echo "" >> $GITHUB_STEP_SUMMARY
315
+ echo "### Artifacts" >> $GITHUB_STEP_SUMMARY
316
+ find artifacts -type f \( -name "*.dmg" -o -name "*.exe" -o -name "*.zip" \) | while read f; do
317
+ echo "- $(basename $f)" >> $GITHUB_STEP_SUMMARY
318
+ done