win-exe.yml 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. name: Build Windows Installer
  2. on:
  3. release:
  4. types: [published]
  5. workflow_dispatch:
  6. inputs:
  7. version:
  8. description: 'Version'
  9. required: false
  10. env:
  11. JAVA_VERSION: 19
  12. JAVA_DIST: 'temurin'
  13. JAVA_CACHE: 'maven'
  14. JFX_JMODS_URL: 'https://download2.gluonhq.com/openjfx/19.0.2.1/openjfx-19.0.2.1_windows-x64_bin-jmods.zip'
  15. JFX_JMODS_HASH: 'B7CF2CAD2468842B3B78D99F6C0555771499A36FA1F1EE3DD1B9A4597F1FAB86'
  16. defaults:
  17. run:
  18. shell: bash
  19. jobs:
  20. get-version:
  21. uses: ./.github/workflows/get-version.yml
  22. with:
  23. version: ${{ inputs.version }}
  24. build-msi:
  25. name: Build .msi Installer
  26. runs-on: windows-latest
  27. needs: [get-version]
  28. env:
  29. LOOPBACK_ALIAS: 'cryptomator-vault'
  30. steps:
  31. - uses: actions/checkout@v3
  32. - name: Setup Java
  33. uses: actions/setup-java@v3
  34. with:
  35. distribution: ${{ env.JAVA_DIST }}
  36. java-version: ${{ env.JAVA_VERSION }}
  37. java-package: 'jdk+fx'
  38. cache: ${{ env.JAVA_CACHE }}
  39. - name: Download and extract JavaFX jmods from Gluon
  40. #In the last step we move all jmods files a dir level up because jmods are placed inside a directory in the zip
  41. run: |
  42. curl --output jfxjmods.zip -L "${{ env.JFX_JMODS_URL }}"
  43. if(!(Get-FileHash -Path jfxjmods.zip -Algorithm SHA256).Hash.equals("${{ env.JFX_JMODS_HASH }}")) {
  44. exit 1;
  45. }
  46. Expand-Archive -Path jfxjmods.zip -DestinationPath jfxjmods
  47. Get-ChildItem -Path jfxjmods -Recurse -Filter "*.jmod" | ForEach-Object { Move-Item -Path $_ -Destination $_.Directory.Parent}
  48. shell: pwsh
  49. - name: Ensure major jfx version in pom and in jmods is the same
  50. run: |
  51. JMOD_VERSION_AMD64=$(jmod describe jfxjmods/javafx.base.jmod | head -1)
  52. JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64#*@}
  53. JMOD_VERSION_AMD64=${JMOD_VERSION_AMD64%%.*}
  54. POM_JFX_VERSION=$(mvn help:evaluate "-Dexpression=javafx.version" -q -DforceStdout)
  55. POM_JFX_VERSION=${POM_JFX_VERSION#*@}
  56. POM_JFX_VERSION=${POM_JFX_VERSION%%.*}
  57. if [ $POM_JFX_VERSION -ne $JMOD_VERSION_AMD64 ]; then
  58. >&2 echo "Major JavaFX version in pom.xml (${POM_JFX_VERSION}) != amd64 jmod version (${JMOD_VERSION_AMD64})"
  59. exit 1
  60. fi
  61. - name: Set version
  62. run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }}
  63. - name: Run maven
  64. run: mvn -B clean package -Pdependency-check,win -DskipTests
  65. - name: Patch target dir
  66. run: |
  67. cp LICENSE.txt target
  68. cp target/cryptomator-*.jar target/mods
  69. - name: Run jlink
  70. run: >
  71. ${JAVA_HOME}/bin/jlink
  72. --verbose
  73. --output runtime
  74. --module-path "jfxjmods;${JAVA_HOME}/jmods"
  75. --add-modules java.base,java.desktop,java.instrument,java.logging,java.naming,java.net.http,java.scripting,java.sql,java.xml,javafx.base,javafx.graphics,javafx.controls,javafx.fxml,jdk.unsupported,jdk.crypto.ec,jdk.accessibility,jdk.management.jfr
  76. --strip-native-commands
  77. --no-header-files
  78. --no-man-pages
  79. --strip-debug
  80. --compress=1
  81. - name: Run jpackage
  82. run: >
  83. ${JAVA_HOME}/bin/jpackage
  84. --verbose
  85. --type app-image
  86. --runtime-image runtime
  87. --input target/libs
  88. --module-path target/mods
  89. --module org.cryptomator.desktop/org.cryptomator.launcher.Cryptomator
  90. --dest appdir
  91. --name Cryptomator
  92. --vendor "Skymatic GmbH"
  93. --copyright "(C) 2016 - 2023 Skymatic GmbH"
  94. --app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
  95. --java-options "--enable-preview"
  96. --java-options "--enable-native-access=org.cryptomator.jfuse.win"
  97. --java-options "-Xss5m"
  98. --java-options "-Xmx256m"
  99. --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\""
  100. --java-options "-Dfile.encoding=\"utf-8\""
  101. --java-options "-Dcryptomator.logDir=\"~/AppData/Roaming/Cryptomator\""
  102. --java-options "-Dcryptomator.pluginDir=\"~/AppData/Roaming/Cryptomator/Plugins\""
  103. --java-options "-Dcryptomator.settingsPath=\"~/AppData/Roaming/Cryptomator/settings.json\""
  104. --java-options "-Dcryptomator.p12Path=\"~/AppData/Roaming/Cryptomator/key.p12\""
  105. --java-options "-Dcryptomator.ipcSocketPath=\"~/AppData/Roaming/Cryptomator/ipc.socket\""
  106. --java-options "-Dcryptomator.mountPointsDir=\"~/Cryptomator\""
  107. --java-options "-Dcryptomator.loopbackAlias=\"${{ env.LOOPBACK_ALIAS }}\""
  108. --java-options "-Dcryptomator.showTrayIcon=true"
  109. --java-options "-Dcryptomator.buildNumber=\"msi-${{ needs.get-version.outputs.revNum }}\""
  110. --java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=\"Cryptomator\""
  111. --java-options "-Dcryptomator.integrationsWin.keychainPaths=\"~/AppData/Roaming/Cryptomator/keychain.json\""
  112. --resource-dir dist/win/resources
  113. --icon dist/win/resources/Cryptomator.ico
  114. - name: Patch Application Directory
  115. run: |
  116. cp dist/win/contrib/* appdir/Cryptomator
  117. - name: Set LOOPBACK_ALIAS in patchWebDAV.bat
  118. shell: pwsh
  119. run: |
  120. $patchScript = "appdir\Cryptomator\patchWebDAV.bat"
  121. try {
  122. (Get-Content $patchScript ) -replace '::REPLACE ME', "SET LOOPBACK_ALIAS=`"${{ env.LOOPBACK_ALIAS}}`"" | Set-Content $patchScript
  123. } catch {
  124. Write-Host "Failed to set LOOPBACK_ALIAS for patchWebDAV.bat"
  125. exit 1
  126. }
  127. - name: Fix permissions
  128. run: attrib -r appdir/Cryptomator/Cryptomator.exe
  129. shell: pwsh
  130. - name: Extract integrations DLL for code signing
  131. shell: pwsh
  132. run: gci ./appdir/Cryptomator/app/mods/ -File integrations-win-*.jar | ForEach-Object {Set-Location -Path $_.Directory; jar --file=$($_.FullName) --extract integrations.dll }
  133. - name: Codesign
  134. uses: skymatic/code-sign-action@v2
  135. with:
  136. certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
  137. password: ${{ secrets.WIN_CODESIGN_P12_PW }}
  138. certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A
  139. description: Cryptomator
  140. timestampUrl: 'http://timestamp.digicert.com'
  141. folder: appdir/Cryptomator
  142. recursive: true
  143. - name: Repack signed DLL into jar
  144. shell: pwsh
  145. run: |
  146. gci ./appdir/Cryptomator/app/mods/ -File integrations-win-*.jar | ForEach-Object {Set-Location -Path $_.Directory; jar --file=$($_.FullName) --update integrations.dll; Remove-Item integrations.dll}
  147. - name: Generate license for MSI
  148. run: >
  149. mvn -B license:add-third-party
  150. "-Dlicense.thirdPartyFilename=license.rtf"
  151. "-Dlicense.outputDirectory=dist/win/resources"
  152. "-Dlicense.fileTemplate=dist/win/resources/licenseTemplate.ftl"
  153. "-Dlicense.includedScopes=compile"
  154. "-Dlicense.excludedGroups=^org\.cryptomator"
  155. "-Dlicense.failOnMissing=true"
  156. "-Dlicense.licenseMergesUrl=file:///${{ github.workspace }}/license/merges"
  157. shell: pwsh
  158. - name: Create MSI
  159. run: >
  160. ${JAVA_HOME}/bin/jpackage
  161. --verbose
  162. --type msi
  163. --win-upgrade-uuid bda45523-42b1-4cae-9354-a45475ed4775
  164. --app-image appdir/Cryptomator
  165. --dest installer
  166. --name Cryptomator
  167. --vendor "Skymatic GmbH"
  168. --copyright "(C) 2016 - 2023 Skymatic GmbH"
  169. --app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum}}"
  170. --win-menu
  171. --win-dir-chooser
  172. --win-shortcut-prompt
  173. --win-update-url "https:\\cryptomator.org"
  174. --win-menu-group Cryptomator
  175. --resource-dir dist/win/resources
  176. --license-file dist/win/resources/license.rtf
  177. --file-associations dist/win/resources/FAvaultFile.properties
  178. env:
  179. JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources # requires abs path, used in resources/main.wxs
  180. - name: Codesign MSI
  181. uses: skymatic/code-sign-action@v2
  182. with:
  183. certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
  184. password: ${{ secrets.WIN_CODESIGN_P12_PW }}
  185. certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A
  186. description: Cryptomator Installer
  187. timestampUrl: 'http://timestamp.digicert.com'
  188. folder: installer
  189. - name: Add possible alpha/beta tags to installer name
  190. run: mv installer/Cryptomator-*.msi Cryptomator-${{ needs.get-version.outputs.semVerStr }}-x64.msi
  191. - name: Create detached GPG signature with key 615D449FE6E6A235
  192. run: |
  193. echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
  194. echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a Cryptomator-*.msi
  195. env:
  196. GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
  197. GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
  198. - name: Upload artifacts
  199. uses: actions/upload-artifact@v3
  200. with:
  201. name: msi
  202. path: |
  203. Cryptomator-*.msi
  204. Cryptomator-*.asc
  205. if-no-files-found: error
  206. - name: Publish .msi on GitHub Releases
  207. if: startsWith(github.ref, 'refs/tags/')
  208. uses: softprops/action-gh-release@v1
  209. with:
  210. fail_on_unmatched_files: true
  211. token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
  212. files: |
  213. *.msi
  214. *.asc
  215. build-exe:
  216. name: Build .exe installer
  217. runs-on: windows-latest
  218. needs: [get-version, build-msi]
  219. steps:
  220. - uses: actions/checkout@v3
  221. - name: Download .msi
  222. uses: actions/download-artifact@v3
  223. with:
  224. name: msi
  225. path: dist/win/bundle/resources
  226. - name: Strip version info from msi file name
  227. run: mv dist/win/bundle/resources/Cryptomator*.msi dist/win/bundle/resources/Cryptomator.msi
  228. - uses: actions/setup-java@v3
  229. with:
  230. distribution: ${{ env.JAVA_DIST }}
  231. java-version: ${{ env.JAVA_VERSION }}
  232. cache: ${{ env.JAVA_CACHE }}
  233. - name: Generate license for exe
  234. run: >
  235. mvn -B license:add-third-party
  236. "-Dlicense.thirdPartyFilename=license.rtf"
  237. "-Dlicense.fileTemplate=dist/win/bundle/resources/licenseTemplate.ftl"
  238. "-Dlicense.outputDirectory=dist/win/bundle/resources"
  239. "-Dlicense.includedScopes=compile"
  240. "-Dlicense.excludedGroups=^org\.cryptomator"
  241. "-Dlicense.failOnMissing=true"
  242. "-Dlicense.licenseMergesUrl=file:///${{ github.workspace }}/license/merges"
  243. shell: pwsh
  244. - name: Download WinFsp
  245. run: |
  246. $winfspUrl = (Select-String -Path ".\dist\win\bundle\resources\winFspMetaData.wxi" -Pattern '<\?define BundledWinFspDownloadLink="(.+)".*?>').Matches.Groups[1].Value
  247. curl --output dist/win/bundle/resources/winfsp.msi -L $winfspUrl
  248. shell: pwsh
  249. - name: Compile to wixObj file
  250. run: >
  251. "${WIX}/bin/candle.exe" dist/win/bundle/bundleWithWinfsp.wxs
  252. -ext WixBalExtension
  253. -ext WixUtilExtension
  254. -out dist/win/bundle/
  255. -dBundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}"
  256. -dBundleVendor="Skymatic GmbH"
  257. -dBundleCopyright="(C) 2016 - 2023 Skymatic GmbH"
  258. -dAboutUrl="https://cryptomator.org"
  259. -dHelpUrl="https://cryptomator.org/contact"
  260. -dUpdateUrl="https://cryptomator.org/downloads/"
  261. - name: Create executable with linker
  262. run: >
  263. "${WIX}/bin/light.exe" -b dist/win/ dist/win/bundle/bundleWithWinfsp.wixobj
  264. -ext WixBalExtension
  265. -ext WixUtilExtension
  266. -out installer/unsigned/Cryptomator-Installer.exe
  267. - name: Detach burn engine in preparation to sign
  268. run: >
  269. "${WIX}/bin/insignia.exe"
  270. -ib installer/unsigned/Cryptomator-Installer.exe
  271. -o tmp/engine.exe
  272. - name: Codesign burn engine
  273. uses: skymatic/code-sign-action@v2
  274. with:
  275. certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
  276. password: ${{ secrets.WIN_CODESIGN_P12_PW }}
  277. certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A
  278. description: Cryptomator Installer
  279. timestampUrl: 'http://timestamp.digicert.com'
  280. folder: tmp
  281. - name: Reattach signed burn engine to installer
  282. run : >
  283. "${WIX}/bin/insignia.exe"
  284. -ab tmp/engine.exe installer/unsigned/Cryptomator-Installer.exe
  285. -o installer/Cryptomator-Installer.exe
  286. - name: Codesign EXE
  287. uses: skymatic/code-sign-action@v2
  288. with:
  289. certificate: ${{ secrets.WIN_CODESIGN_P12_BASE64 }}
  290. password: ${{ secrets.WIN_CODESIGN_P12_PW }}
  291. certificatesha1: 5FC94CE149E5B511E621F53A060AC67CBD446B3A
  292. description: Cryptomator Installer
  293. timestampUrl: 'http://timestamp.digicert.com'
  294. folder: installer
  295. - name: Add possible alpha/beta tags to installer name
  296. run: mv installer/Cryptomator-Installer.exe Cryptomator-${{ needs.get-version.outputs.semVerStr }}-x64.exe
  297. - name: Create detached GPG signature with key 615D449FE6E6A235
  298. run: |
  299. echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import
  300. echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a Cryptomator-*.exe
  301. env:
  302. GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }}
  303. GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }}
  304. - name: Upload artifacts
  305. uses: actions/upload-artifact@v3
  306. with:
  307. name: exe
  308. path: |
  309. Cryptomator-*.exe
  310. Cryptomator-*.asc
  311. if-no-files-found: error
  312. - name: Publish .msi on GitHub Releases
  313. if: startsWith(github.ref, 'refs/tags/')
  314. uses: softprops/action-gh-release@v1
  315. with:
  316. fail_on_unmatched_files: true
  317. token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }}
  318. files: |
  319. Cryptomator-*.exe
  320. Cryptomator-*.asc
  321. allowlist:
  322. name: Anti Virus Allowlisting
  323. if: startsWith(github.ref, 'refs/tags/')
  324. runs-on: ubuntu-latest
  325. needs: [build-msi, build-exe]
  326. steps:
  327. - name: Download .msi
  328. uses: actions/download-artifact@v3
  329. with:
  330. name: msi
  331. path: msi
  332. - name: Download .exe
  333. uses: actions/download-artifact@v3
  334. with:
  335. name: exe
  336. path: exe
  337. - name: Collect files
  338. run: |
  339. mkdir files
  340. cp msi/*.msi files
  341. cp exe/*.exe files
  342. - name: Upload to Kaspersky
  343. uses: SamKirkland/FTP-Deploy-Action@4.3.3
  344. with:
  345. protocol: ftps
  346. server: allowlist.kaspersky-labs.com
  347. port: 990
  348. username: ${{ secrets.ALLOWLIST_KASPERSKY_USERNAME }}
  349. password: ${{ secrets.ALLOWLIST_KASPERSKY_PASSWORD }}
  350. local-dir: files/
  351. - name: Upload to Avast
  352. uses: SamKirkland/FTP-Deploy-Action@4.3.0
  353. with:
  354. protocol: ftp
  355. server: whitelisting.avast.com
  356. port: 21
  357. username: ${{ secrets.ALLOWLIST_AVAST_USERNAME }}
  358. password: ${{ secrets.ALLOWLIST_AVAST_PASSWORD }}
  359. local-dir: files/