From d9134b49adc27863a76d5151c1004ff52f135204 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Fri, 6 Mar 2026 17:11:11 +0100 Subject: [PATCH 01/44] add workflow_call to release artifact workflows --- .github/workflows/appimage.yml | 25 ++++++++++++++++++++++--- .github/workflows/mac-dmg-x64.yml | 23 +++++++++++++++++++---- .github/workflows/mac-dmg.yml | 21 ++++++++++++++++++--- .github/workflows/win-exe.yml | 30 +++++++++++++++++++++++++++--- 4 files changed, 86 insertions(+), 13 deletions(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index d3da01b7b..2ecef5f22 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -1,8 +1,19 @@ name: Build AppImage on: - release: - types: [published] + workflow_call: + inputs: + is-release: + description: "Workflow is called by a release" + type: boolean + default: false + outputs: + sha256-appimage-x64: + description: "SHA256 sum of the x64 appimage" + value: ${{ jobs.build.outputs.x64-sha256sum}} + sha256-appimage-aarch64: + description: "SHA256 sum of the aarch64 appimage" + value: ${{ jobs.build.outputs.x64-sha256sum}} workflow_dispatch: inputs: version: @@ -35,6 +46,9 @@ jobs: name: Build AppImage runs-on: ${{ matrix.os }} needs: [get-version] + outputs: + x64-sha256sum: ${{ steps.sha256sum.outputs.value-x86_64 }} + aarch64-sha256sum: ${{ steps.sha256sum.outputs.value-aarch64 }} env: SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }} SEMVER_NUM: ${{ needs.get-version.outputs.semVerNum }} @@ -180,6 +194,10 @@ jobs: ./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${SEMVER_STR}-${{ matrix.arch }}.AppImage -u "gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${{ matrix.arch }}.AppImage.zsync" --sign --sign-key=615D449FE6E6A235 + - id: sha256sum + run: | + read -ra CMD_OUTPUT < <(sha256sum cryptomator-*.AppImage) + echo "value-${{matrix.arch}}=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT - name: Create detached GPG signatures run: | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage @@ -194,9 +212,10 @@ jobs: cryptomator-*.asc if-no-files-found: error - name: Publish AppImage on GitHub Releases - if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published' + if: github.ref_type == 'tag' && inputs.is-release uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 with: + draft: true fail_on_unmatched_files: true token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} files: | diff --git a/.github/workflows/mac-dmg-x64.yml b/.github/workflows/mac-dmg-x64.yml index bdb66d667..6c42b43a0 100644 --- a/.github/workflows/mac-dmg-x64.yml +++ b/.github/workflows/mac-dmg-x64.yml @@ -9,8 +9,16 @@ name: Build macOS .dmg for x64 ####################################### on: - release: - types: [published] + workflow_call: + inputs: + is-release: + description: "Workflow is called by a release" + type: boolean + default: false + outputs: + sha256-dmg: + description: "SHA256 sum of the x64 dmg" + value: ${{ jobs.build.outputs.sha256sum}} workflow_dispatch: inputs: version: @@ -32,10 +40,12 @@ jobs: with: version: ${{ inputs.version }} - build-arm: + build: name: Build Cryptomator.app for ${{ matrix.output-suffix }} runs-on: ${{ matrix.os }} needs: [get-version] + outputs: + sha256sum: ${{ steps.sha256sum.outputs.value }} strategy: fail-fast: false matrix: @@ -256,6 +266,10 @@ jobs: password: ${{ secrets.MACOS_NOTARIZATION_PW }} team-id: ${{ secrets.MACOS_NOTARIZATION_TEAM_ID }} xcode-path: '/Applications/Xcode_16.app' + - id: sha256sum + run: | + read -ra CMD_OUTPUT < <(sha -a256 Cryptomator-*.dmg) + echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT - name: Add possible alpha/beta tags to installer name run: mv Cryptomator-*.dmg Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.output-suffix }}.dmg - name: Create detached GPG signature with key 615D449FE6E6A235 @@ -278,9 +292,10 @@ jobs: Cryptomator-*.asc if-no-files-found: error - name: Publish dmg on GitHub Releases - if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published' + if: github.ref_type == 'tag' && inputs.is-release uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 with: + draft: true fail_on_unmatched_files: true token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} files: | diff --git a/.github/workflows/mac-dmg.yml b/.github/workflows/mac-dmg.yml index 743586153..ca9c13199 100644 --- a/.github/workflows/mac-dmg.yml +++ b/.github/workflows/mac-dmg.yml @@ -1,8 +1,16 @@ name: Build macOS .dmg for arm64 on: - release: - types: [published] + workflow_call: + inputs: + is-release: + description: "Workflow is called by a release" + type: boolean + default: false + outputs: + sha256-dmg: + description: "SHA256 sum of the arm64 dmg" + value: ${{ jobs.build.outputs.sha256sum}} workflow_dispatch: inputs: version: @@ -34,6 +42,8 @@ jobs: name: Build Cryptomator.app for ${{ matrix.output-suffix }} runs-on: ${{ matrix.os }} needs: [get-version] + outputs: + sha256sum: ${{ steps.sha256sum.outputs.value }} strategy: fail-fast: false matrix: @@ -255,6 +265,10 @@ jobs: password: ${{ secrets.MACOS_NOTARIZATION_PW }} team-id: ${{ secrets.MACOS_NOTARIZATION_TEAM_ID }} xcode-path: '/Applications/Xcode_16.app' + - id: sha256sum + run: | + read -ra CMD_OUTPUT < <(sha -a256 Cryptomator-*.dmg) + echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT - name: Add possible alpha/beta tags to installer name run: mv Cryptomator-*.dmg Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.output-suffix }}.dmg - name: Create detached GPG signature with key 615D449FE6E6A235 @@ -277,9 +291,10 @@ jobs: Cryptomator-*.asc if-no-files-found: error - name: Publish dmg on GitHub Releases - if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published' + if: github.ref_type == 'tag' && inputs.is-release uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 with: + draft: true fail_on_unmatched_files: true token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} files: | diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml index 1e36d0af4..536083d72 100644 --- a/.github/workflows/win-exe.yml +++ b/.github/workflows/win-exe.yml @@ -1,8 +1,19 @@ name: Build Windows Installer on: - release: - types: [published] + workflow_call: + inputs: + is-release: + description: "Workflow is called by a release" + type: boolean + default: false + outputs: + sha256-msi: + description: "SHA256 sum of the x64 msi" + value: ${{ jobs.build-msi.outputs.sha256sum}} + sha256-exe: + description: "SHA256 sum of the x64 exe" + value: ${{ jobs.build-exe.outputs.sha256sum}} workflow_dispatch: inputs: version: @@ -43,6 +54,8 @@ jobs: name: Build .msi Installer runs-on: ${{ matrix.os }} needs: [ get-version ] + outputs: + sha256sum: ${{ steps.sha256sum.outputs.value }} strategy: matrix: include: @@ -270,6 +283,10 @@ jobs: tenant-id: ${{ secrets.AZURE_TENANT_ID }} client-id: ${{ secrets.AZURE_CLIENT_ID }} client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} + - id: sha256sum + run: | + read -ra CMD_OUTPUT < <(sha256sum installer/Cryptomator-*.msi) + echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT - name: Add possible alpha/beta tags and architecture to installer name run: mv installer/Cryptomator-*.msi Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.arch }}.msi - name: Create detached GPG signature with key 615D449FE6E6A235 @@ -292,6 +309,8 @@ jobs: name: Build .exe installer runs-on: ${{ matrix.os }} needs: [ get-version, build-msi ] + outputs: + sha256sum: ${{ steps.sha256sum.outputs.value }} strategy: matrix: include: @@ -413,6 +432,10 @@ jobs: sign-url: 'https://cryptomator.org' username: ${{ secrets.WIN_CODESIGN_USERNAME }} password: ${{ secrets.WIN_CODESIGN_PW }} + - id: sha256sum + run: | + read -ra CMD_OUTPUT < <(sha256sum installer/Cryptomator-*.exe) + echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT - name: Add possible alpha/beta tags to installer name run: mv installer/Cryptomator-Installer.exe Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.executable-suffix }}.exe - name: Create detached GPG signature with key 615D449FE6E6A235 @@ -433,7 +456,7 @@ jobs: publish: name: Publish installers to the github release - if: startsWith(github.ref, 'refs/tags/') && github.event.action == 'published' + if: github.ref_type == 'tag' && inputs.is-release runs-on: ubuntu-latest needs: [ build-msi, build-exe ] outputs: @@ -448,6 +471,7 @@ jobs: id: publish uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 with: + draft: true fail_on_unmatched_files: true token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} # do not change ordering of filelist, required for correct job output From 81b20810334cde6e65527618a9009f63acb92f41 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 25 Mar 2026 11:41:38 +0100 Subject: [PATCH 02/44] fix outputs typo in appimage flow --- .github/workflows/appimage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index 2ecef5f22..7093650a6 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -13,7 +13,7 @@ on: value: ${{ jobs.build.outputs.x64-sha256sum}} sha256-appimage-aarch64: description: "SHA256 sum of the aarch64 appimage" - value: ${{ jobs.build.outputs.x64-sha256sum}} + value: ${{ jobs.build.outputs.aarch64-sha256sum}} workflow_dispatch: inputs: version: From 4e5eef5a169528f9f74dcf3b76737d5c7b36b7c4 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 25 Mar 2026 11:41:54 +0100 Subject: [PATCH 03/44] remove release drafting from build flow --- .github/workflows/build.yml | 39 +------------------------------------ 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 218b1caae..3b4bb03b4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,41 +46,4 @@ jobs: -Dsonar.host.url=https://sonarcloud.io env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - - name: Draft a release - if: startsWith(github.ref, 'refs/tags/') - uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 - with: - draft: true - discussion_category_name: releases - token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} - generate_release_notes: true - body: |- - > [!NOTE] - > 🚧 Work in Progress 🚧 - > - > Please be patient, the [builds are still running](https://github.com/cryptomator/cryptomator/actions). Binary packages can be found here in a few moments. - - - - For a comprehensive view of changes, read the [CHANGELOG](https://github.com/cryptomator/cryptomator/blob/develop/CHANGELOG.md). - - --- - - - - - > [!TIP] - > You can verify the GPG signature of all assets using our public key: [`5811 7AFA 1F85 B3EE C154 677D 615D 449F E6E6 A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a). - - - - + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file From d9c0c4980b963a2fd6c0811019ffdedac0e77af1 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 25 Mar 2026 11:42:26 +0100 Subject: [PATCH 04/44] add release flow to create releases --- .github/workflows/release.yml | 158 ++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..98993193c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,158 @@ +name: Create a Cryptomator Release + +on: + workflow_dispatch: + push: + tags: + - '*' + +env: + JAVA_DIST: 'temurin' + JAVA_VERSION: 25 + +defaults: + run: + shell: bash + +jobs: + get-version: + uses: ./.github/workflows/get-version.yml + with: + version: '' + + create-release: + name: Compile and Test + runs-on: ubuntu-latest + needs: get-version + if: github.ref_type == 'tag' && needs.get-version.outputs.versionType != 'unknown' + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 + with: + distribution: ${{ env.JAVA_DIST }} + java-version: ${{ env.JAVA_VERSION }} + cache: 'maven' + - name: Build and Test + run: xvfb-run mvn -B verify -Plinux + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + - name: Draft a release + uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 + with: + draft: true + discussion_category_name: releases + token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} + generate_release_notes: true + body: |- + > [!WARN] + > 🚧 DO NOT EDIT 🚧 + > + > The [builds are still running](https://github.com/cryptomator/cryptomator/actions/workflows/release.yml). + + + + For a comprehensive view of changes, read the [CHANGELOG](https://github.com/cryptomator/cryptomator/blob/develop/CHANGELOG.md). + + --- + + 💾 SHA-256 checksums of release artifacts: + ``` + ``` + + > [!TIP] + > You can verify the GPG signature of all assets using our public key: [`5811 7AFA 1F85 B3EE C154 677D 615D 449F E6E6 A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a). + + + + - name: Download source tarball + run: | + curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" https://github.com/cryptomator/cryptomator/archive/${{ github.ref }}.tar.gz --output cryptomator-${{ github.ref_name }}.tar.gz + - name: Sign source tarball with key 615D449FE6E6A235 + run: | + echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import + echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.tar.gz + env: + GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }} + GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }} + - name: Publish asc on GitHub Releases + uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 + with: + draft: true + fail_on_unmatched_files: true + token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} + files: | + cryptomator-*.tar.gz.asc + + build-exe-and-msi: + needs: create-release + uses: ./.github/workflows/win-exe.yml + with: + is-release: true + secrets: inherit + + build-dmg-arm64: + needs: create-release + uses: ./.github/workflows/mac-dmg.yml + with: + is-release: true + secrets: inherit + + build-dmg-x64: + needs: create-release + uses: ./.github/workflows/mac-dmg-x64.yml + with: + is-release: true + secrets: inherit + + build-appimages: + needs: create-release + uses: ./.github/workflows/appimage.yml + with: + is-release: true + secrets: inherit + + update-sha256sums: + runs-on: ubuntu-latest + needs: [get-version, build-exe-and-msi, build-dmg-arm64, build-dmg-x64, build-appimages] + env: + TAG: ${{ github.ref_name }} + SEMVER: ${{ needs.get-version.outputs.semVerStr }} + GH_TOKEN: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} + steps: + - name: Compute source tarball SHA256 + id: src-sha256 + run: | + curl --silent --fail-with-body --proto "=https" -L \ + -H "Accept: application/vnd.github+json" \ + "https://github.com/cryptomator/cryptomator/archive/refs/tags/${TAG}.tar.gz" \ + --output "cryptomator-${SEMVER}.tar.gz" + read -ra CMD_OUTPUT < <(sha256sum "cryptomator-${SEMVER}.tar.gz") + echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT + - name: Update release body with checksums + run: | + CHECKSUMS="${SRC_SHA} cryptomator-${SEMVER}.tar.gz + ${MSI_SHA} Cryptomator-${SEMVER}-x64.msi + ${EXE_SHA} Cryptomator-${SEMVER}-x64.exe + ${DMG_ARM64_SHA} Cryptomator-${SEMVER}-arm64.dmg + ${DMG_X64_SHA} Cryptomator-${SEMVER}-x64.dmg + ${APPIMAGE_X64_SHA} cryptomator-${SEMVER}-x86_64.AppImage + ${APPIMAGE_AARCH64_SHA} cryptomator-${SEMVER}-aarch64.AppImage" + + CURRENT_BODY=$(gh release view "${TAG}" --json body --jq .body) + UPDATED_BODY=$(echo "$CURRENT_BODY" | awk -v sums="$CHECKSUMS" ' + /^```$/ && !done { print; print sums; done=1; next } + 1 + ') + gh release edit "${TAG}" --draft --notes "$UPDATED_BODY" + env: + SRC_SHA: ${{ steps.src-sha256.outputs.value }} + MSI_SHA: ${{ needs.build-exe-and-msi.outputs.sha256-msi }} + EXE_SHA: ${{ needs.build-exe-and-msi.outputs.sha256-exe }} + DMG_ARM64_SHA: ${{ needs.build-dmg-arm64.outputs.sha256-dmg }} + DMG_X64_SHA: ${{ needs.build-dmg-x64.outputs.sha256-dmg }} + APPIMAGE_X64_SHA: ${{ needs.build-appimages.outputs.sha256-appimage-x64 }} + APPIMAGE_AARCH64_SHA: ${{ needs.build-appimages.outputs.sha256-appimage-aarch64 }} From 690726efc3723fd8035e4bb61f2d8c609e7c494a Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 25 Mar 2026 11:43:58 +0100 Subject: [PATCH 05/44] adjust post-publish * run av-whitelist after publish * notify winget * remove gpg signature creation --- .github/workflows/post-publish.yml | 78 +++++++++++++++++++++++------- .github/workflows/win-exe.yml | 37 -------------- 2 files changed, 60 insertions(+), 55 deletions(-) diff --git a/.github/workflows/post-publish.yml b/.github/workflows/post-publish.yml index 619f0f607..94e782cb6 100644 --- a/.github/workflows/post-publish.yml +++ b/.github/workflows/post-publish.yml @@ -6,25 +6,13 @@ on: jobs: get-version: + uses: ./.github/workflows/get-version.yml + with: + version: ${{ github.event.release.tag_name }} + + notify: runs-on: ubuntu-latest steps: - - name: Download source tarball - run: | - curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" https://github.com/cryptomator/cryptomator/archive/refs/tags/${{ github.event.release.tag_name }}.tar.gz --output cryptomator-${{ github.event.release.tag_name }}.tar.gz - - name: Sign source tarball with key 615D449FE6E6A235 - run: | - echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import - echo "${GPG_PASSPHRASE}" | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.tar.gz - env: - GPG_PRIVATE_KEY: ${{ secrets.RELEASES_GPG_PRIVATE_KEY }} - GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }} - - name: Publish asc on GitHub Releases - uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0 - with: - fail_on_unmatched_files: true - token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} - files: | - cryptomator-*.tar.gz.asc - name: Slack Notification uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 env: @@ -36,4 +24,58 @@ jobs: SLACK_TITLE: "Release ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} published." SLACK_MESSAGE: "Ready to ." SLACK_FOOTER: false - MSG_MINIMAL: true \ No newline at end of file + MSG_MINIMAL: true + + get-asset-urls: + name: Get release asset URLs + runs-on: ubuntu-latest + outputs: + msi-url: ${{ steps.urls.outputs.msi }} + exe-url: ${{ steps.urls.outputs.exe }} + steps: + - name: Extract MSI and EXE download URLs + id: urls + run: | + MSI_URL=$(gh api "repos/${{ github.repository }}/releases/${{ github.event.release.id }}/assets" \ + --jq '[.[] | select(.name | endswith("-x64.msi"))][0].browser_download_url') + EXE_URL=$(gh api "repos/${{ github.repository }}/releases/${{ github.event.release.id }}/assets" \ + --jq '[.[] | select(.name | endswith("-x64.exe"))][0].browser_download_url') + echo "msi=${MSI_URL}" >> $GITHUB_OUTPUT + echo "exe=${EXE_URL}" >> $GITHUB_OUTPUT + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + allowlist-msi-x64: + needs: [get-asset-urls] + if: needs.get-asset-urls.outputs.msi-url != 'null' && needs.get-asset-urls.outputs.msi-url != '' + uses: ./.github/workflows/av-whitelist.yml + with: + url: ${{ needs.get-asset-urls.outputs.msi-url }} + secrets: inherit + + allowlist-exe-x64: + needs: [get-asset-urls, allowlist-msi-x64] + if: needs.get-asset-urls.outputs.exe-url != 'null' && needs.get-asset-urls.outputs.exe-url != '' + uses: ./.github/workflows/av-whitelist.yml + with: + url: ${{ needs.get-asset-urls.outputs.exe-url }} + secrets: inherit + + notify-winget: + name: Notify for winget-release + if: needs.get-version.outputs.versionType == 'stable' + needs: [get-version, get-asset-urls] + runs-on: ubuntu-latest + steps: + - name: Slack Notification + uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_USERNAME: 'Cryptobot' + SLACK_ICON: false + SLACK_ICON_EMOJI: ':bot:' + SLACK_CHANNEL: 'cryptomator-desktop' + SLACK_TITLE: "Release ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} published." + SLACK_MESSAGE: "Ready to ." + SLACK_FOOTER: false + MSG_MINIMAL: true diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml index 536083d72..0c242016e 100644 --- a/.github/workflows/win-exe.yml +++ b/.github/workflows/win-exe.yml @@ -459,9 +459,6 @@ jobs: if: github.ref_type == 'tag' && inputs.is-release runs-on: ubuntu-latest needs: [ build-msi, build-exe ] - outputs: - download-url-msi-x64: ${{ fromJSON(steps.publish.outputs.assets)[0].browser_download_url }} - download-url-exe-x64: ${{ fromJSON(steps.publish.outputs.assets)[2].browser_download_url }} steps: - name: Download installers uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 @@ -474,41 +471,7 @@ jobs: draft: true fail_on_unmatched_files: true token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} - # do not change ordering of filelist, required for correct job output files: | *x64.msi *x64.exe *.asc - - allowlist-msi-x64: - uses: ./.github/workflows/av-whitelist.yml - needs: [ publish ] - with: - url: ${{ needs.publish.outputs.download-url-msi-x64 }} - secrets: inherit - - allowlist-exe-x64: - uses: ./.github/workflows/av-whitelist.yml - needs: [ publish, allowlist-msi-x64 ] - with: - url: ${{ needs.publish.outputs.download-url-exe-x64 }} - secrets: inherit - - notify-winget: - name: Notify for winget-release - if: needs.get-version.outputs.versionType == 'stable' - needs: [publish, get-version] - runs-on: ubuntu-latest - steps: - - name: Slack Notification - uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 - env: - SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} - SLACK_USERNAME: 'Cryptobot' - SLACK_ICON: false - SLACK_ICON_EMOJI: ':bot:' - SLACK_CHANNEL: 'cryptomator-desktop' - SLACK_TITLE: "MSI packages of ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} published." - SLACK_MESSAGE: "Ready to ." - SLACK_FOOTER: false - MSG_MINIMAL: true From d22e912ca46e961de3671800f6a4b0774aface45 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 25 Mar 2026 15:14:35 +0100 Subject: [PATCH 06/44] fix wrong webhook --- .github/workflows/post-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/post-publish.yml b/.github/workflows/post-publish.yml index 94e782cb6..3ff434a67 100644 --- a/.github/workflows/post-publish.yml +++ b/.github/workflows/post-publish.yml @@ -70,7 +70,7 @@ jobs: - name: Slack Notification uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 env: - SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }} SLACK_USERNAME: 'Cryptobot' SLACK_ICON: false SLACK_ICON_EMOJI: ':bot:' From 0b77e6ce0441d5b61c600ef311ef94199a1abc1d Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 25 Mar 2026 23:15:13 +0100 Subject: [PATCH 07/44] use release object in event payload --- .github/workflows/post-publish.yml | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/.github/workflows/post-publish.yml b/.github/workflows/post-publish.yml index 3ff434a67..24e76cd60 100644 --- a/.github/workflows/post-publish.yml +++ b/.github/workflows/post-publish.yml @@ -36,18 +36,16 @@ jobs: - name: Extract MSI and EXE download URLs id: urls run: | - MSI_URL=$(gh api "repos/${{ github.repository }}/releases/${{ github.event.release.id }}/assets" \ - --jq '[.[] | select(.name | endswith("-x64.msi"))][0].browser_download_url') - EXE_URL=$(gh api "repos/${{ github.repository }}/releases/${{ github.event.release.id }}/assets" \ - --jq '[.[] | select(.name | endswith("-x64.exe"))][0].browser_download_url') + MSI_URL=$(jq -r '[.[] | select(.name | endswith("-x64.msi"))][0].browser_download_url // "null"' <<< "$RELEASE_ASSETS") + EXE_URL=$(jq -r '[.[] | select(.name | endswith("-x64.exe"))][0].browser_download_url // "null"' <<< "$RELEASE_ASSETS") echo "msi=${MSI_URL}" >> $GITHUB_OUTPUT echo "exe=${EXE_URL}" >> $GITHUB_OUTPUT env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + RELEASE_ASSETS: ${{ toJson(github.event.release.assets) }} allowlist-msi-x64: needs: [get-asset-urls] - if: needs.get-asset-urls.outputs.msi-url != 'null' && needs.get-asset-urls.outputs.msi-url != '' + if: needs.get-asset-urls.outputs.msi-url != 'null' uses: ./.github/workflows/av-whitelist.yml with: url: ${{ needs.get-asset-urls.outputs.msi-url }} @@ -55,7 +53,7 @@ jobs: allowlist-exe-x64: needs: [get-asset-urls, allowlist-msi-x64] - if: needs.get-asset-urls.outputs.exe-url != 'null' && needs.get-asset-urls.outputs.exe-url != '' + if: needs.get-asset-urls.outputs.exe-url != 'null' uses: ./.github/workflows/av-whitelist.yml with: url: ${{ needs.get-asset-urls.outputs.exe-url }} @@ -79,3 +77,16 @@ jobs: SLACK_MESSAGE: "Ready to ." SLACK_FOOTER: false MSG_MINIMAL: true + + notify-website-repo: + if: needs.get-version.outputs.versionType == 'stable' + needs: [get-version] + runs-on: ubuntu-latest + steps: + - name: Notify website repo about desktop update + uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1 + with: + event-type: desktop-update + token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} + repository: cryptomator/cryptomator.github.io + From 309a8fc705da45f59ebb090b60076bf131577004 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 26 Mar 2026 10:48:47 +0100 Subject: [PATCH 08/44] adjust repository dispatch for website update * change event type to desktop-release * add client payload --- .github/workflows/post-publish.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/post-publish.yml b/.github/workflows/post-publish.yml index 24e76cd60..3680c385a 100644 --- a/.github/workflows/post-publish.yml +++ b/.github/workflows/post-publish.yml @@ -79,14 +79,15 @@ jobs: MSG_MINIMAL: true notify-website-repo: - if: needs.get-version.outputs.versionType == 'stable' needs: [get-version] runs-on: ubuntu-latest + if: needs.get-version.outputs.versionType == 'stable' steps: - name: Notify website repo about desktop update uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1 with: - event-type: desktop-update - token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} + event-type: desktop-release + token: ${{ secrets.CRYPTOBOT_WORKFLOW_DISPATCH_TOKEN }} repository: cryptomator/cryptomator.github.io + client-payload: '{ "version": "${{needs.get-version.outputs.semVerStr}}", "release": ${{ toJson(github.event.release.assets) }} }' From 57c84627f9e098d1c71715a8f9877d4f52804945 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 30 Mar 2026 12:07:08 +0200 Subject: [PATCH 09/44] Update release draft with sed and envsubst instead of awk --- .github/release-body.md.template | 34 ++++++++++++++++++ .github/workflows/release.yml | 61 ++++++++++++-------------------- 2 files changed, 57 insertions(+), 38 deletions(-) create mode 100644 .github/release-body.md.template diff --git a/.github/release-body.md.template b/.github/release-body.md.template new file mode 100644 index 000000000..80d063c4a --- /dev/null +++ b/.github/release-body.md.template @@ -0,0 +1,34 @@ + +> [!WARN] +> 🚧 DO NOT EDIT 🚧 +> +> The [builds are still running](https://github.com/cryptomator/cryptomator/actions/workflows/release.yml). +> This banner will be replaced after the builds are finished. + + + + +For a comprehensive view of changes, read the [CHANGELOG](https://github.com/cryptomator/cryptomator/blob/develop/CHANGELOG.md). + +--- + +💾 SHA-256 checksums of release artifacts: +``` +$TARBALL +$EXE +$MSI +$DMG_x64 +$DMG_arm64 +$APPIMAGE_x86_64 +$APPIMAGE_aarch64 +``` + +> [!TIP] +> You can verify the GPG signature of all assets using our public key: [`5811 7AFA 1F85 B3EE C154 677D 615D 449F E6E6 A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a). + + + diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 98993193c..edc90a79e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,31 +43,7 @@ jobs: discussion_category_name: releases token: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} generate_release_notes: true - body: |- - > [!WARN] - > 🚧 DO NOT EDIT 🚧 - > - > The [builds are still running](https://github.com/cryptomator/cryptomator/actions/workflows/release.yml). - - - - For a comprehensive view of changes, read the [CHANGELOG](https://github.com/cryptomator/cryptomator/blob/develop/CHANGELOG.md). - - --- - - 💾 SHA-256 checksums of release artifacts: - ``` - ``` - - > [!TIP] - > You can verify the GPG signature of all assets using our public key: [`5811 7AFA 1F85 B3EE C154 677D 615D 449F E6E6 A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a). - - - + body_path: .github/release-body.md.template - name: Download source tarball run: | curl --silent --fail-with-body --proto "=https" -L -H "Accept: application/vnd.github+json" https://github.com/cryptomator/cryptomator/archive/${{ github.ref }}.tar.gz --output cryptomator-${{ github.ref_name }}.tar.gz @@ -123,6 +99,7 @@ jobs: SEMVER: ${{ needs.get-version.outputs.semVerStr }} GH_TOKEN: ${{ secrets.CRYPTOBOT_RELEASE_TOKEN }} steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Compute source tarball SHA256 id: src-sha256 run: | @@ -134,20 +111,28 @@ jobs: echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT - name: Update release body with checksums run: | - CHECKSUMS="${SRC_SHA} cryptomator-${SEMVER}.tar.gz - ${MSI_SHA} Cryptomator-${SEMVER}-x64.msi - ${EXE_SHA} Cryptomator-${SEMVER}-x64.exe - ${DMG_ARM64_SHA} Cryptomator-${SEMVER}-arm64.dmg - ${DMG_X64_SHA} Cryptomator-${SEMVER}-x64.dmg - ${APPIMAGE_X64_SHA} cryptomator-${SEMVER}-x86_64.AppImage - ${APPIMAGE_AARCH64_SHA} cryptomator-${SEMVER}-aarch64.AppImage" - CURRENT_BODY=$(gh release view "${TAG}" --json body --jq .body) - UPDATED_BODY=$(echo "$CURRENT_BODY" | awk -v sums="$CHECKSUMS" ' - /^```$/ && !done { print; print sums; done=1; next } - 1 - ') - gh release edit "${TAG}" --draft --notes "$UPDATED_BODY" + RELEASE_BODY=$(printf '%s\n' "${CURRENT_BODY}" | sed '//,//c\ + \ + > [!SUCCESS]\ + > Release artifacts finished building successfully.\ + >\ + > SHA-256 checksums have been updated below.\ + ') + + export TARBALL="${SRC_SHA} cryptomator-${SEMVER}.tar.gz" + export MSI="${MSI_SHA} Cryptomator-${SEMVER}-x64.msi" + export EXE="${EXE_SHA} Cryptomator-${SEMVER}-x64.exe" + export DMG_arm64="${DMG_ARM64_SHA} Cryptomator-${SEMVER}-arm64.dmg" + export DMG_x64="${DMG_X64_SHA} Cryptomator-${SEMVER}-x64.dmg" + export APPIMAGE_x86_64="${APPIMAGE_X64_SHA} cryptomator-${SEMVER}-x86_64.AppImage" + export APPIMAGE_aarch64="${APPIMAGE_AARCH64_SHA} cryptomator-${SEMVER}-aarch64.AppImage" + + envsubst '$TARBALL $EXE $MSI $DMG_x64 $DMG_arm64 $APPIMAGE_x86_64 $APPIMAGE_aarch64' \ + <<< "${RELEASE_BODY}" \ + > release-body.md + + gh release edit "${TAG}" --draft --notes-file release-body.md env: SRC_SHA: ${{ steps.src-sha256.outputs.value }} MSI_SHA: ${{ needs.build-exe-and-msi.outputs.sha256-msi }} From ee92cc4e9fa2c4f23a141f23c0f464eb6d71abdc Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 30 Mar 2026 12:22:03 +0200 Subject: [PATCH 10/44] Add docs update workflow --- .github/workflows/post-publish.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/post-publish.yml b/.github/workflows/post-publish.yml index 3680c385a..38015289d 100644 --- a/.github/workflows/post-publish.yml +++ b/.github/workflows/post-publish.yml @@ -78,12 +78,12 @@ jobs: SLACK_FOOTER: false MSG_MINIMAL: true - notify-website-repo: + trigger-website-update: needs: [get-version] runs-on: ubuntu-latest if: needs.get-version.outputs.versionType == 'stable' steps: - - name: Notify website repo about desktop update + - name: Start website update workflow uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1 with: event-type: desktop-release @@ -91,3 +91,15 @@ jobs: repository: cryptomator/cryptomator.github.io client-payload: '{ "version": "${{needs.get-version.outputs.semVerStr}}", "release": ${{ toJson(github.event.release.assets) }} }' + trigger-docs-update: + needs: [get-version] + runs-on: ubuntu-latest + if: needs.get-version.outputs.versionType == 'stable' + steps: + - name: Start docs update workflow + uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1 + with: + event-type: desktop-release + token: ${{ secrets.CRYPTOBOT_WORKFLOW_DISPATCH_TOKEN }} + repository: cryptomator/docs + client-payload: '{ "version": "${{needs.get-version.outputs.semVerStr}}", "release": ${{ toJson(github.event.release.assets) }} }' From e75deb282cfbbfc2ac2ec4ddd4983338989e7cbb Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 30 Mar 2026 15:33:24 +0200 Subject: [PATCH 11/44] use correct cmd for computing sha sum --- .github/workflows/mac-dmg-x64.yml | 2 +- .github/workflows/mac-dmg.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mac-dmg-x64.yml b/.github/workflows/mac-dmg-x64.yml index 6c42b43a0..8ec952df2 100644 --- a/.github/workflows/mac-dmg-x64.yml +++ b/.github/workflows/mac-dmg-x64.yml @@ -268,7 +268,7 @@ jobs: xcode-path: '/Applications/Xcode_16.app' - id: sha256sum run: | - read -ra CMD_OUTPUT < <(sha -a256 Cryptomator-*.dmg) + read -ra CMD_OUTPUT < <(shasum -a256 Cryptomator-*.dmg) echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT - name: Add possible alpha/beta tags to installer name run: mv Cryptomator-*.dmg Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.output-suffix }}.dmg diff --git a/.github/workflows/mac-dmg.yml b/.github/workflows/mac-dmg.yml index ca9c13199..36951ceae 100644 --- a/.github/workflows/mac-dmg.yml +++ b/.github/workflows/mac-dmg.yml @@ -267,7 +267,7 @@ jobs: xcode-path: '/Applications/Xcode_16.app' - id: sha256sum run: | - read -ra CMD_OUTPUT < <(sha -a256 Cryptomator-*.dmg) + read -ra CMD_OUTPUT < <(shasum -a256 Cryptomator-*.dmg) echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT - name: Add possible alpha/beta tags to installer name run: mv Cryptomator-*.dmg Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.output-suffix }}.dmg From 95eed96a37921dc24d427a2ba714a82c4ec181d3 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 31 Mar 2026 16:02:32 +0200 Subject: [PATCH 12/44] gate windows specifc post-publishes task with check for windows artifacts in release --- .github/workflows/post-publish.yml | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/.github/workflows/post-publish.yml b/.github/workflows/post-publish.yml index 38015289d..7809276fa 100644 --- a/.github/workflows/post-publish.yml +++ b/.github/workflows/post-publish.yml @@ -30,6 +30,7 @@ jobs: name: Get release asset URLs runs-on: ubuntu-latest outputs: + is-windows-release: ${{ steps.urls.outputs.urls-present }}) msi-url: ${{ steps.urls.outputs.msi }} exe-url: ${{ steps.urls.outputs.exe }} steps: @@ -38,14 +39,19 @@ jobs: run: | MSI_URL=$(jq -r '[.[] | select(.name | endswith("-x64.msi"))][0].browser_download_url // "null"' <<< "$RELEASE_ASSETS") EXE_URL=$(jq -r '[.[] | select(.name | endswith("-x64.exe"))][0].browser_download_url // "null"' <<< "$RELEASE_ASSETS") - echo "msi=${MSI_URL}" >> $GITHUB_OUTPUT - echo "exe=${EXE_URL}" >> $GITHUB_OUTPUT + if [[ "$MSI_URL" == "null" || -z "$MSI_URL" || "$EXE_URL" == "null" || -z "EXE_URL" ]]; then + echo "urls-present=false" >> $GITHUB_OUTPUT + else + echo "urls-present=true" >> $GITHUB_OUTPUT + echo "msi=${MSI_URL}" >> $GITHUB_OUTPUT + echo "exe=${EXE_URL}" >> $GITHUB_OUTPUT + fi env: RELEASE_ASSETS: ${{ toJson(github.event.release.assets) }} allowlist-msi-x64: needs: [get-asset-urls] - if: needs.get-asset-urls.outputs.msi-url != 'null' + if: needs.get-asset-urls.outputs.is-windows-release == 'true' uses: ./.github/workflows/av-whitelist.yml with: url: ${{ needs.get-asset-urls.outputs.msi-url }} @@ -53,7 +59,7 @@ jobs: allowlist-exe-x64: needs: [get-asset-urls, allowlist-msi-x64] - if: needs.get-asset-urls.outputs.exe-url != 'null' + if: needs.get-asset-urls.outputs.is-windows-release == 'true' uses: ./.github/workflows/av-whitelist.yml with: url: ${{ needs.get-asset-urls.outputs.exe-url }} @@ -61,7 +67,7 @@ jobs: notify-winget: name: Notify for winget-release - if: needs.get-version.outputs.versionType == 'stable' + if: needs.get-asset-urls.outputs.is-windows-release == 'true' && needs.get-version.outputs.versionType == 'stable' needs: [get-version, get-asset-urls] runs-on: ubuntu-latest steps: @@ -92,9 +98,9 @@ jobs: client-payload: '{ "version": "${{needs.get-version.outputs.semVerStr}}", "release": ${{ toJson(github.event.release.assets) }} }' trigger-docs-update: - needs: [get-version] + needs: [get-version, get-asset-urls] runs-on: ubuntu-latest - if: needs.get-version.outputs.versionType == 'stable' + if: needs.get-asset-urls.outputs.is-windows-release == 'true' && needs.get-version.outputs.versionType == 'stable' steps: - name: Start docs update workflow uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1 From f10b28ecb1de412ef5162271f95cfe42d6c25a6e Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 31 Mar 2026 18:11:41 +0200 Subject: [PATCH 13/44] fix typos --- .github/workflows/post-publish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/post-publish.yml b/.github/workflows/post-publish.yml index 7809276fa..b0f01c892 100644 --- a/.github/workflows/post-publish.yml +++ b/.github/workflows/post-publish.yml @@ -30,7 +30,7 @@ jobs: name: Get release asset URLs runs-on: ubuntu-latest outputs: - is-windows-release: ${{ steps.urls.outputs.urls-present }}) + is-windows-release: ${{ steps.urls.outputs.urls-present }} msi-url: ${{ steps.urls.outputs.msi }} exe-url: ${{ steps.urls.outputs.exe }} steps: @@ -39,7 +39,7 @@ jobs: run: | MSI_URL=$(jq -r '[.[] | select(.name | endswith("-x64.msi"))][0].browser_download_url // "null"' <<< "$RELEASE_ASSETS") EXE_URL=$(jq -r '[.[] | select(.name | endswith("-x64.exe"))][0].browser_download_url // "null"' <<< "$RELEASE_ASSETS") - if [[ "$MSI_URL" == "null" || -z "$MSI_URL" || "$EXE_URL" == "null" || -z "EXE_URL" ]]; then + if [[ "$MSI_URL" == "null" || -z "$MSI_URL" || "$EXE_URL" == "null" || -z "$EXE_URL" ]]; then echo "urls-present=false" >> $GITHUB_OUTPUT else echo "urls-present=true" >> $GITHUB_OUTPUT From e341983ffe85d4f4587cdd04a5ae3f46687db40b Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 1 Apr 2026 14:14:33 +0200 Subject: [PATCH 14/44] add update-latest-version job to post-publish --- .github/workflows/post-publish.yml | 40 ++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/.github/workflows/post-publish.yml b/.github/workflows/post-publish.yml index b0f01c892..623243e0f 100644 --- a/.github/workflows/post-publish.yml +++ b/.github/workflows/post-publish.yml @@ -109,3 +109,43 @@ jobs: token: ${{ secrets.CRYPTOBOT_WORKFLOW_DISPATCH_TOKEN }} repository: cryptomator/docs client-payload: '{ "version": "${{needs.get-version.outputs.semVerStr}}", "release": ${{ toJson(github.event.release.assets) }} }' + + update-latest-version: + needs: [get-version] + runs-on: ubuntu-latest + if: needs.get-version.outputs.versionType == 'stable' + steps: + - name: Download + run: > + curl --silent --fail-with-body --proto "=https" + -L -H "Accept: application/json" + https://static.cryptomator.org/desktop/latest-version.json + --output latest-version.json + - name: Update + run: | + update_entry() { + local os="$1" + local file_extension="$2" + + local url=$(jq -r --arg file_extension "$file_extension" '[.[] | select(.name | endswith($file_extension))][0].browser_download_url // "null"' <<< "$RELEASE_ASSETS") + if [[ "$url" != "null" && -n "$url" ]]; then + jq -r --arg os_key "$os" '.[$os_key] = env.NEW_VERSION' latest-version.json > INPUT.tmp + mv INPUT.tmp latest-version.json + fi + } + + update_entry "win" ".msi" + update_entry "mac" ".dmg" + update_entry "linux" ".AppImage" + env: + RELEASE_ASSETS: ${{ toJson(github.event.release.assets) }} + NEW_VERSION: ${{ needs.get-version.outputs.semVerStr }} + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ vars.AWS_REGION || 'nl-ams' }} + - name: Upload + run: aws s3 cp latest-version.json s3://static.cryptomator.org/desktop/latest-version.json --endpoint-url https://s3.nl-ams.scw.cloud/ + From c199561a9e7d5423dd1fd39996ac1ac3dcfec3ca Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 1 Apr 2026 16:10:26 +0200 Subject: [PATCH 15/44] Link to the changelog of the git tag in the release notes --- .github/release-body.md.template | 2 +- .github/workflows/release.yml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/release-body.md.template b/.github/release-body.md.template index 80d063c4a..bc191d48a 100644 --- a/.github/release-body.md.template +++ b/.github/release-body.md.template @@ -12,7 +12,7 @@ ### Other Changes 📎 END REPLACE--> -For a comprehensive view of changes, read the [CHANGELOG](https://github.com/cryptomator/cryptomator/blob/develop/CHANGELOG.md). +For a comprehensive view of changes, read the [CHANGELOG](https://github.com/cryptomator/cryptomator/blob/$VERSION/CHANGELOG.md). --- diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index edc90a79e..ea968810d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -128,12 +128,13 @@ jobs: export APPIMAGE_x86_64="${APPIMAGE_X64_SHA} cryptomator-${SEMVER}-x86_64.AppImage" export APPIMAGE_aarch64="${APPIMAGE_AARCH64_SHA} cryptomator-${SEMVER}-aarch64.AppImage" - envsubst '$TARBALL $EXE $MSI $DMG_x64 $DMG_arm64 $APPIMAGE_x86_64 $APPIMAGE_aarch64' \ + envsubst '$VERSION $TARBALL $EXE $MSI $DMG_x64 $DMG_arm64 $APPIMAGE_x86_64 $APPIMAGE_aarch64' \ <<< "${RELEASE_BODY}" \ > release-body.md gh release edit "${TAG}" --draft --notes-file release-body.md env: + VERSION: ${{ needs.get-version.outputs.semVerStr }} SRC_SHA: ${{ steps.src-sha256.outputs.value }} MSI_SHA: ${{ needs.build-exe-and-msi.outputs.sha256-msi }} EXE_SHA: ${{ needs.build-exe-and-msi.outputs.sha256-exe }} From aa8ccf53df2d88ce02c3f80011f29c3ba22368ce Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 1 Apr 2026 16:16:46 +0200 Subject: [PATCH 16/44] remove manual trigger for workflow --- .github/workflows/release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ea968810d..80a1f9fac 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,7 +1,6 @@ name: Create a Cryptomator Release on: - workflow_dispatch: push: tags: - '*' From ddd8c572e73aad7e46f4bc99b6427923a3c2a543 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 1 Apr 2026 16:27:20 +0200 Subject: [PATCH 17/44] prevent accidental releases of unsigend tags --- .github/workflows/release.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 80a1f9fac..08dec45a2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -26,6 +26,10 @@ jobs: if: github.ref_type == 'tag' && needs.get-version.outputs.versionType != 'unknown' steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + fetch-depth: 0 + - name: Check the git tag is signed + run: git cat-file -p "${GITHUB_REF_NAME}" | grep "BEGIN SSH SIGNATURE" - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: ${{ env.JAVA_DIST }} From 02767b0cafb9747adff82a73c993edd0bfeca82e Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 1 Apr 2026 16:29:59 +0200 Subject: [PATCH 18/44] pin aws-configure action --- .github/workflows/post-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/post-publish.yml b/.github/workflows/post-publish.yml index 623243e0f..2d990bab5 100644 --- a/.github/workflows/post-publish.yml +++ b/.github/workflows/post-publish.yml @@ -141,7 +141,7 @@ jobs: RELEASE_ASSETS: ${{ toJson(github.event.release.assets) }} NEW_VERSION: ${{ needs.get-version.outputs.semVerStr }} - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@v4 + uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} From 5d5b9137cce6391243829fa6e08d80af994d6dcf Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 1 Apr 2026 16:38:07 +0200 Subject: [PATCH 19/44] fix workflows --- .github/workflows/appimage.yml | 32 +++++++++++++++++++++++--------- .github/workflows/win-exe.yml | 4 ++++ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index 3aed30ab4..4b5fb0efa 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -12,10 +12,10 @@ on: outputs: sha256-appimage-x64: description: "SHA256 sum of the x64 appimage" - value: ${{ jobs.build.outputs.x64-sha256sum}} + value: ${{ jobs.collect-sha256sums.outputs.x64-sha256sum}} sha256-appimage-aarch64: description: "SHA256 sum of the aarch64 appimage" - value: ${{ jobs.build.outputs.aarch64-sha256sum}} + value: ${{ jobs.collect-sha256sums.outputs.aarch64-sha256sum}} workflow_dispatch: inputs: version: @@ -48,9 +48,6 @@ jobs: name: Build AppImage runs-on: ${{ matrix.os }} needs: [get-version] - outputs: - x64-sha256sum: ${{ steps.sha256sum.outputs.value-x86_64 }} - aarch64-sha256sum: ${{ steps.sha256sum.outputs.value-aarch64 }} env: SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }} SEMVER_NUM: ${{ needs.get-version.outputs.semVerNum }} @@ -200,10 +197,6 @@ jobs: ./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${SEMVER_STR}-${{ matrix.arch }}.AppImage -u "gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${{ matrix.arch }}.AppImage.zsync" --sign --sign-key=615D449FE6E6A235 - - id: sha256sum - run: | - read -ra CMD_OUTPUT < <(sha256sum cryptomator-*.AppImage) - echo "value-${{matrix.arch}}=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT - name: Create detached GPG signatures run: | gpg --batch --quiet --passphrase-fd 0 --pinentry-mode loopback -u 615D449FE6E6A235 --detach-sign -a cryptomator-*.AppImage @@ -229,6 +222,27 @@ jobs: cryptomator-*.zsync cryptomator-*.asc + collect-sha256sums: + name: Collect AppImage checksums + runs-on: ubuntu-latest + needs: [build] + outputs: + x64-sha256sum: ${{ steps.sha256sum.outputs.x64-sha256sum }} + aarch64-sha256sum: ${{ steps.sha256sum.outputs.aarch64-sha256sum }} + steps: + - name: Download AppImage artifacts + uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 + with: + pattern: appimage-* + path: appimage-artifacts + - name: Compute SHA256 sums + id: sha256sum + run: | + read -ra X64_SUM < <(sha256sum appimage-artifacts/appimage-x86_64/cryptomator-*-x86_64.AppImage) + read -ra AARCH64_SUM < <(sha256sum appimage-artifacts/appimage-aarch64/cryptomator-*-aarch64.AppImage) + echo "x64-sha256sum=${X64_SUM[0]}" >> "$GITHUB_OUTPUT" + echo "aarch64-sha256sum=${AARCH64_SUM[0]}" >> "$GITHUB_OUTPUT" + create-aur-bin-pr: name: Create PR for aur-bin repo if: github.event_name == 'workflow_dispatch' && inputs.create-pr || github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable' diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml index afe71df70..67898e158 100644 --- a/.github/workflows/win-exe.yml +++ b/.github/workflows/win-exe.yml @@ -404,6 +404,10 @@ jobs: tenant-id: ${{ secrets.AZURE_TENANT_ID }} client-id: ${{ secrets.AZURE_CLIENT_ID }} client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} + - id: sha256sum + run: | + read -ra CMD_OUTPUT < <(sha256sum installer/Cryptomator-*.exe) + echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT - name: Add possible alpha/beta tags to installer name run: mv installer/Cryptomator-Installer.exe Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.executable-suffix }}.exe - name: Create detached GPG signature with key 615D449FE6E6A235 From 7dde3896714cbc01e461ad38ab9142995e009866 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 7 Apr 2026 17:04:56 +0200 Subject: [PATCH 20/44] move aur-bin PR creation into own workflow --- .github/workflows/appimage.yml | 77 ---------------------------- .github/workflows/aur-bin.yml | 93 ++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 77 deletions(-) create mode 100644 .github/workflows/aur-bin.yml diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index 4b5fb0efa..091d8722f 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -242,80 +242,3 @@ jobs: read -ra AARCH64_SUM < <(sha256sum appimage-artifacts/appimage-aarch64/cryptomator-*-aarch64.AppImage) echo "x64-sha256sum=${X64_SUM[0]}" >> "$GITHUB_OUTPUT" echo "aarch64-sha256sum=${AARCH64_SUM[0]}" >> "$GITHUB_OUTPUT" - - create-aur-bin-pr: - name: Create PR for aur-bin repo - if: github.event_name == 'workflow_dispatch' && inputs.create-pr || github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable' - runs-on: ubuntu-latest - needs: [build, get-version] - container: - image: archlinux:base-devel - env: - SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }} - PKGDEST: ${{ github.workspace }}/pkgdest - SRCDEST: ${{ github.workspace }}/srcdest - steps: - - name: Prepare pacman - run: | - pacman-key --init - pacman-key --populate archlinux - pacman -Syu --noconfirm --needed git base-devel sudo gnupg maven unzip github-cli curl pacman-contrib - - name: Checkout cryptomator/aur-bin - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - repository: 'cryptomator/aur-bin' - token: ${{ secrets.CRYPTOBOT_PR_TOKEN }} - - name: Create build user - run: | - useradd -m builder - echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/builder - chown -R builder:builder "$GITHUB_WORKSPACE" - install -d -m 0755 -o builder -g builder "$PKGDEST" "$SRCDEST" - - name: Import Cryptomator release signing key - # try first ubuntu. on failure try openpgp keyservers - run: > - sudo -u builder gpg --batch --keyserver hkps://keyserver.ubuntu.com --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235 - || sudo -u builder gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235 - - name: Checkout release branch - run: | - git config --global safe.directory '*' - git checkout -b "release/${SEMVER_STR}" - - name: Update build file - run: | - sed -i -e "s|^pkgver=.*$|pkgver=${SEMVER_STR}|" PKGBUILD - sed -i -e 's|^pkgrel=.*$|pkgrel=1|' PKGBUILD - sudo -u builder updpkgsums - sudo -u builder makepkg --printsrcinfo > .SRCINFO - - name: Build package with makepkg - run: > - sudo -u builder - env PKGDEST="$PKGDEST" SRCDEST="$SRCDEST" - makepkg --syncdeps --cleanbuild --noconfirm --log - - name: Commit and push - run: | - git config user.name "cryptobot" - git config user.email "cryptobot@users.noreply.github.com" - git config push.autoSetupRemote true - git stage PKGBUILD .SRCINFO - git commit -m "Prepare release ${SEMVER_STR}" - git push - - name: Create pull request - id: create-pr - run: | - printf "Created by $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" > pr_body.md - PR_URL=$(gh pr create --title "Release ${SEMVER_STR}" --body-file pr_body.md) - echo "url=$PR_URL" >> "$GITHUB_OUTPUT" - env: - GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }} - - name: Slack Notification - uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 - env: - SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }} - SLACK_USERNAME: 'Cryptobot' - SLACK_ICON: false - SLACK_ICON_EMOJI: ':bot:' - SLACK_CHANNEL: 'cryptomator-desktop' - SLACK_TITLE: "AUR-bin release PR for ${{ github.event.repository.name }} ${{ needs.get-version.outputs.semVerStr }} created." - SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.url }}|PR> on how to proceed." - SLACK_FOOTER: false - MSG_MINIMAL: true diff --git a/.github/workflows/aur-bin.yml b/.github/workflows/aur-bin.yml new file mode 100644 index 000000000..ea892fe0d --- /dev/null +++ b/.github/workflows/aur-bin.yml @@ -0,0 +1,93 @@ +name: PR for aur-bin repo + +on: + release: + types: [published] + workflow_dispatch: + inputs: + src-tag: + description: 'Source or Release tag' + required: false + +jobs: + get-version: + uses: ./.github/workflows/get-version.yml + with: + version: ${{ inputs.src-tag }} + + create-aur-bin-pr: + name: Create PR for aur-bin repo + if: (github.event_name == 'workflow_dispatch') || (github.event_name == 'release' && needs.get-version.outputs.versionType == 'stable') + runs-on: ubuntu-latest + needs: [get-version] + container: + image: archlinux:base-devel + env: + SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }} + PKGDEST: ${{ github.workspace }}/pkgdest + SRCDEST: ${{ github.workspace }}/srcdest + steps: + - name: Prepare pacman + run: | + pacman-key --init + pacman-key --populate archlinux + pacman -Syu --noconfirm --needed git base-devel sudo gnupg maven unzip github-cli curl pacman-contrib + - name: Checkout cryptomator/aur-bin + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: 'cryptomator/aur-bin' + token: ${{ secrets.CRYPTOBOT_PR_TOKEN }} + - name: Create build user + run: | + useradd -m builder + echo 'builder ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers.d/builder + chown -R builder:builder "$GITHUB_WORKSPACE" + install -d -m 0755 -o builder -g builder "$PKGDEST" "$SRCDEST" + - name: Import Cryptomator release signing key + # try first ubuntu. on failure try openpgp keyservers + run: > + sudo -u builder gpg --batch --keyserver hkps://keyserver.ubuntu.com --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235 + || sudo -u builder gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys 58117AFA1F85B3EEC154677D615D449FE6E6A235 + - name: Checkout release branch + run: | + git config --global safe.directory '*' + git checkout -b "release/${SEMVER_STR}" + - name: Update build file + run: | + sed -i -e "s|^pkgver=.*$|pkgver=${SEMVER_STR}|" PKGBUILD + sed -i -e 's|^pkgrel=.*$|pkgrel=1|' PKGBUILD + sudo -u builder updpkgsums + sudo -u builder makepkg --printsrcinfo > .SRCINFO + - name: Build package with makepkg + run: > + sudo -u builder + env PKGDEST="$PKGDEST" SRCDEST="$SRCDEST" + makepkg --syncdeps --cleanbuild --noconfirm --log + - name: Commit and push + run: | + git config user.name "cryptobot" + git config user.email "cryptobot@users.noreply.github.com" + git config push.autoSetupRemote true + git stage PKGBUILD .SRCINFO + git commit -m "Prepare release ${SEMVER_STR}" + git push + - name: Create pull request + id: create-pr + run: | + printf "Created by $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" > pr_body.md + PR_URL=$(gh pr create --title "Release ${SEMVER_STR}" --body-file pr_body.md) + echo "url=$PR_URL" >> "$GITHUB_OUTPUT" + env: + GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }} + - name: Slack Notification + uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }} + SLACK_USERNAME: 'Cryptobot' + SLACK_ICON: false + SLACK_ICON_EMOJI: ':bot:' + SLACK_CHANNEL: 'cryptomator-desktop' + SLACK_TITLE: "AUR-bin release PR for ${{ github.event.repository.name }} ${{ needs.get-version.outputs.semVerStr }} created." + SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.url }}|PR> on how to proceed." + SLACK_FOOTER: false + MSG_MINIMAL: true \ No newline at end of file From 7bffc317ff6dd5868ccffc046b6f6b9766c527d7 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 7 Apr 2026 17:05:30 +0200 Subject: [PATCH 21/44] rename workflow from release to create-release to prevent confusion with github release.yml standard --- .github/workflows/{release.yml => create-release.yml} | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) rename .github/workflows/{release.yml => create-release.yml} (96%) diff --git a/.github/workflows/release.yml b/.github/workflows/create-release.yml similarity index 96% rename from .github/workflows/release.yml rename to .github/workflows/create-release.yml index 08dec45a2..5de755624 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/create-release.yml @@ -23,13 +23,15 @@ jobs: name: Compile and Test runs-on: ubuntu-latest needs: get-version - if: github.ref_type == 'tag' && needs.get-version.outputs.versionType != 'unknown' + if: needs.get-version.outputs.versionType != 'unknown' steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - name: Check the git tag is signed run: git cat-file -p "${GITHUB_REF_NAME}" | grep "BEGIN SSH SIGNATURE" + - name: Check the git tag is on release or main branch + run: git branch --contains "${GITHUB_REF_NAME}" | sed -E "grep -E '^\**\s*(main|release/.*)\s*$' - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: ${{ env.JAVA_DIST }} From 96aa8fe18068bf328b3f7052888939b75547c03d Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 7 Apr 2026 17:20:08 +0200 Subject: [PATCH 22/44] add pkgrel update step for aur-bin --- .github/workflows/aur-bin.yml | 30 +++++++++++++++++++++++++---- .github/workflows/linux-makepkg.yml | 5 ++--- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/.github/workflows/aur-bin.yml b/.github/workflows/aur-bin.yml index ea892fe0d..563ca876f 100644 --- a/.github/workflows/aur-bin.yml +++ b/.github/workflows/aur-bin.yml @@ -52,12 +52,31 @@ jobs: run: | git config --global safe.directory '*' git checkout -b "release/${SEMVER_STR}" + - name: Determine pkgrel + id: pkgrel + run: | + CURRENT_VERSION="$(sed -nE 's/^pkgver=(.*)$/\1/p' PKGBUILD | head -n1)" + CURRENT_REL="$(sed -nE 's/^pkgrel=([0-9]+).*$/\1/p' PKGBUILD | head -n1)" + + if [[ "$CURRENT_VERSION" == "$TARGET_VERSION" && "$CURRENT_REL" =~ ^[0-9]+$ ]]; then + NEXT_REL=$((CURRENT_REL + 1)) + else + NEXT_REL=1 + fi + + echo "value=${NEXT_REL}" >> "$GITHUB_OUTPUT" + echo "dist-version=${TARGET_VERSION}-${NEXT_REL}" >> "$GITHUB_OUTPUT" + env: + TARGET_VERSION: ${{ needs.get-version.outputs.semVerStr }} - name: Update build file run: | - sed -i -e "s|^pkgver=.*$|pkgver=${SEMVER_STR}|" PKGBUILD - sed -i -e 's|^pkgrel=.*$|pkgrel=1|' PKGBUILD + sed -i -e "s|^pkgver=.*$|pkgver=${PKG_VERSION}|" PKGBUILD + sed -i -e "s|^pkgrel=.*$|pkgrel=${PKG_RELEASE}|" PKGBUILD sudo -u builder updpkgsums sudo -u builder makepkg --printsrcinfo > .SRCINFO + env: + PKG_VERSION: ${{ needs.get-version.outputs.semVerNum }} + PKG_RELEASE: ${{ steps.pkgrel.outputs.value }} - name: Build package with makepkg run: > sudo -u builder @@ -69,15 +88,18 @@ jobs: git config user.email "cryptobot@users.noreply.github.com" git config push.autoSetupRemote true git stage PKGBUILD .SRCINFO - git commit -m "Prepare release ${SEMVER_STR}" + git commit -m "Prepare release ${DIST_VERSION}" git push + env: + DIST_VERSION: ${{ steps.pkgrel.outputs.dist-version }} - name: Create pull request id: create-pr run: | printf "Created by $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" > pr_body.md - PR_URL=$(gh pr create --title "Release ${SEMVER_STR}" --body-file pr_body.md) + PR_URL=$(gh pr create --title "Release ${DIST_VERSION}" --body-file pr_body.md) echo "url=$PR_URL" >> "$GITHUB_OUTPUT" env: + DIST_VERSION: ${{ steps.pkgrel.outputs.dist-version }} GH_TOKEN: ${{ secrets.CRYPTOBOT_PR_TOKEN }} - name: Slack Notification uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 diff --git a/.github/workflows/linux-makepkg.yml b/.github/workflows/linux-makepkg.yml index c28597aca..1d9cbaa7a 100644 --- a/.github/workflows/linux-makepkg.yml +++ b/.github/workflows/linux-makepkg.yml @@ -132,7 +132,6 @@ jobs: - name: Determine pkgrel id: pkgrel run: | - TARGET_VERSION='${{ needs.get-version.outputs.semVerStr }}' CURRENT_VERSION="$(sed -nE 's/^pkgver=(.*)$/\1/p' PKGBUILD | head -n1)" CURRENT_REL="$(sed -nE 's/^pkgrel=([0-9]+).*$/\1/p' PKGBUILD | head -n1)" @@ -143,9 +142,9 @@ jobs: fi echo "value=${NEXT_REL}" >> "$GITHUB_OUTPUT" - echo "dist-version=${VERSION}-${NEXT_REL}" >> "$GITHUB_OUTPUT" + echo "dist-version=${TARGET_VERSION}-${NEXT_REL}" >> "$GITHUB_OUTPUT" env: - VERSION: ${{ needs.get-version.outputs.semVerStr }} + TARGET_VERSION: ${{ needs.get-version.outputs.semVerStr }} - name: Download PKGBUILD template uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: From 517e12a58642b19350d96163b3f990a9d6aa8aa2 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 8 Apr 2026 12:35:54 +0200 Subject: [PATCH 23/44] pin jdk version for release --- .github/workflows/create-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 5de755624..98d637b74 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -7,7 +7,7 @@ on: env: JAVA_DIST: 'temurin' - JAVA_VERSION: 25 + JAVA_VERSION: '25.0.2+10.0.LTS' defaults: run: From 357b30684bd5185c97562058d04e38680a83650a Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 8 Apr 2026 12:37:50 +0200 Subject: [PATCH 24/44] point to correct release workflow file in template --- .github/release-body.md.template | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/release-body.md.template b/.github/release-body.md.template index bc191d48a..e0a351603 100644 --- a/.github/release-body.md.template +++ b/.github/release-body.md.template @@ -2,7 +2,7 @@ > [!WARN] > 🚧 DO NOT EDIT 🚧 > -> The [builds are still running](https://github.com/cryptomator/cryptomator/actions/workflows/release.yml). +> The [builds are still running](https://github.com/cryptomator/cryptomator/actions/workflows/create-release.yml). > This banner will be replaced after the builds are finished. From 235a23ce77c3d2d47bb9a409bd8bf5ba0c3a082a Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 8 Apr 2026 12:38:23 +0200 Subject: [PATCH 25/44] fix check for tag belongs to main or release branch --- .github/workflows/create-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 98d637b74..94184b4a3 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -31,7 +31,7 @@ jobs: - name: Check the git tag is signed run: git cat-file -p "${GITHUB_REF_NAME}" | grep "BEGIN SSH SIGNATURE" - name: Check the git tag is on release or main branch - run: git branch --contains "${GITHUB_REF_NAME}" | sed -E "grep -E '^\**\s*(main|release/.*)\s*$' + run: git branch -r --contains "${GITHUB_REF_NAME}" | grep -E '^\s*origin/(main|release/.*)\s*$' - uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0 with: distribution: ${{ env.JAVA_DIST }} From d76dbe0ddb42f094bb5832fad265b507169642f3 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 8 Apr 2026 12:54:27 +0200 Subject: [PATCH 26/44] Replace automatic version file update by simple notification --- .github/workflows/post-publish.yml | 51 +++++++----------------------- 1 file changed, 12 insertions(+), 39 deletions(-) diff --git a/.github/workflows/post-publish.yml b/.github/workflows/post-publish.yml index 2d990bab5..68833f60a 100644 --- a/.github/workflows/post-publish.yml +++ b/.github/workflows/post-publish.yml @@ -25,6 +25,18 @@ jobs: SLACK_MESSAGE: "Ready to ." SLACK_FOOTER: false MSG_MINIMAL: true + - name: Notify about latest-version update + uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 + env: + SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }} + SLACK_USERNAME: 'Cryptobot' + SLACK_ICON: '' + SLACK_ICON_EMOJI: ':bot:' + SLACK_CHANNEL: 'cryptomator-desktop' + SLACK_TITLE: "Requiring version check source update for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }}." + SLACK_MESSAGE: 'Check S3 bucket for .' + SLACK_FOOTER: '' + MSG_MINIMAL: true get-asset-urls: name: Get release asset URLs @@ -110,42 +122,3 @@ jobs: repository: cryptomator/docs client-payload: '{ "version": "${{needs.get-version.outputs.semVerStr}}", "release": ${{ toJson(github.event.release.assets) }} }' - update-latest-version: - needs: [get-version] - runs-on: ubuntu-latest - if: needs.get-version.outputs.versionType == 'stable' - steps: - - name: Download - run: > - curl --silent --fail-with-body --proto "=https" - -L -H "Accept: application/json" - https://static.cryptomator.org/desktop/latest-version.json - --output latest-version.json - - name: Update - run: | - update_entry() { - local os="$1" - local file_extension="$2" - - local url=$(jq -r --arg file_extension "$file_extension" '[.[] | select(.name | endswith($file_extension))][0].browser_download_url // "null"' <<< "$RELEASE_ASSETS") - if [[ "$url" != "null" && -n "$url" ]]; then - jq -r --arg os_key "$os" '.[$os_key] = env.NEW_VERSION' latest-version.json > INPUT.tmp - mv INPUT.tmp latest-version.json - fi - } - - update_entry "win" ".msi" - update_entry "mac" ".dmg" - update_entry "linux" ".AppImage" - env: - RELEASE_ASSETS: ${{ toJson(github.event.release.assets) }} - NEW_VERSION: ${{ needs.get-version.outputs.semVerStr }} - - name: Configure AWS credentials - uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0 - with: - aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws-region: ${{ vars.AWS_REGION || 'nl-ams' }} - - name: Upload - run: aws s3 cp latest-version.json s3://static.cryptomator.org/desktop/latest-version.json --endpoint-url https://s3.nl-ams.scw.cloud/ - From f94d2046045c20f35fc3ce0f6e831e00d5715d87 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 8 Apr 2026 12:57:32 +0200 Subject: [PATCH 27/44] cleanup --- .github/workflows/aur-bin.yml | 4 ++-- .github/workflows/check-jdk-updates.yml | 4 ++-- .github/workflows/linux-flatpak.yml | 4 ++-- .github/workflows/linux-makepkg.yml | 4 ++-- .github/workflows/post-publish.yml | 10 +++++----- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/aur-bin.yml b/.github/workflows/aur-bin.yml index 563ca876f..36865aa26 100644 --- a/.github/workflows/aur-bin.yml +++ b/.github/workflows/aur-bin.yml @@ -106,10 +106,10 @@ jobs: env: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }} SLACK_USERNAME: 'Cryptobot' - SLACK_ICON: false + SLACK_ICON: '' SLACK_ICON_EMOJI: ':bot:' SLACK_CHANNEL: 'cryptomator-desktop' SLACK_TITLE: "AUR-bin release PR for ${{ github.event.repository.name }} ${{ needs.get-version.outputs.semVerStr }} created." SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.url }}|PR> on how to proceed." - SLACK_FOOTER: false + SLACK_FOOTER: '' MSG_MINIMAL: true \ No newline at end of file diff --git a/.github/workflows/check-jdk-updates.yml b/.github/workflows/check-jdk-updates.yml index 9eae6da00..0b0c30db7 100644 --- a/.github/workflows/check-jdk-updates.yml +++ b/.github/workflows/check-jdk-updates.yml @@ -74,10 +74,10 @@ jobs: env: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_URL }} SLACK_USERNAME: 'Cryptobot' - SLACK_ICON: false + SLACK_ICON: '' SLACK_ICON_EMOJI: ':bot:' SLACK_CHANNEL: 'cryptomator-desktop' SLACK_TITLE: "JDK update available" SLACK_MESSAGE: "Cryptomator-CI JDK can be upgraded to ${{ steps.determine.outputs.LATEST_JDK_VERSION }}. Check the Nextcloud collective for instructions." - SLACK_FOOTER: false + SLACK_FOOTER: '' MSG_MINIMAL: true \ No newline at end of file diff --git a/.github/workflows/linux-flatpak.yml b/.github/workflows/linux-flatpak.yml index bd671e6d1..d73d25c11 100644 --- a/.github/workflows/linux-flatpak.yml +++ b/.github/workflows/linux-flatpak.yml @@ -255,10 +255,10 @@ jobs: env: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }} SLACK_USERNAME: 'Cryptobot' - SLACK_ICON: false + SLACK_ICON: '' SLACK_ICON_EMOJI: ':bot:' SLACK_CHANNEL: 'cryptomator-desktop' SLACK_TITLE: "Flathub release PR created for ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} created." SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.FLATHUB_PR_URL }}|PR> on how to proceed." - SLACK_FOOTER: false + SLACK_FOOTER: '' MSG_MINIMAL: true diff --git a/.github/workflows/linux-makepkg.yml b/.github/workflows/linux-makepkg.yml index 1d9cbaa7a..b09ab4381 100644 --- a/.github/workflows/linux-makepkg.yml +++ b/.github/workflows/linux-makepkg.yml @@ -192,10 +192,10 @@ jobs: env: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }} SLACK_USERNAME: 'Cryptobot' - SLACK_ICON: false + SLACK_ICON: '' SLACK_ICON_EMOJI: ':bot:' SLACK_CHANNEL: 'cryptomator-desktop' SLACK_TITLE: "AUR release PR created for ${{ github.event.repository.name }} ${{ steps.pkgrel.outputs.dist-version }} ." SLACK_MESSAGE: "See <${{ steps.create-pr.outputs.url }}|PR> on how to proceed." - SLACK_FOOTER: false + SLACK_FOOTER: '' MSG_MINIMAL: true diff --git a/.github/workflows/post-publish.yml b/.github/workflows/post-publish.yml index 68833f60a..fe6040f93 100644 --- a/.github/workflows/post-publish.yml +++ b/.github/workflows/post-publish.yml @@ -13,17 +13,17 @@ jobs: notify: runs-on: ubuntu-latest steps: - - name: Slack Notification + - name: Notify about DEB build uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 env: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }} SLACK_USERNAME: 'Cryptobot' - SLACK_ICON: false + SLACK_ICON: '' SLACK_ICON_EMOJI: ':bot:' SLACK_CHANNEL: 'cryptomator-desktop' SLACK_TITLE: "Release ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} published." SLACK_MESSAGE: "Ready to ." - SLACK_FOOTER: false + SLACK_FOOTER: '' MSG_MINIMAL: true - name: Notify about latest-version update uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 @@ -88,12 +88,12 @@ jobs: env: SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK_CRYPTOMATOR_DESKTOP }} SLACK_USERNAME: 'Cryptobot' - SLACK_ICON: false + SLACK_ICON: '' SLACK_ICON_EMOJI: ':bot:' SLACK_CHANNEL: 'cryptomator-desktop' SLACK_TITLE: "Release ${{ github.event.repository.name }} ${{ github.event.release.tag_name }} published." SLACK_MESSAGE: "Ready to ." - SLACK_FOOTER: false + SLACK_FOOTER: '' MSG_MINIMAL: true trigger-website-update: From 3a4039d6630d87656ddbcd1ec36eeafa9eb71428 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Wed, 8 Apr 2026 13:00:23 +0200 Subject: [PATCH 28/44] use ubuntu-slim runner for small tasks --- .github/workflows/av-whitelist.yml | 6 +++--- .github/workflows/no-response.yml | 2 +- .github/workflows/post-publish.yml | 10 +++++----- .github/workflows/stale.yml | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/av-whitelist.yml b/.github/workflows/av-whitelist.yml index 0c2bc3d9a..81322eec7 100644 --- a/.github/workflows/av-whitelist.yml +++ b/.github/workflows/av-whitelist.yml @@ -37,7 +37,7 @@ on: jobs: download-file: name: Downloads the file into the VM - runs-on: ubuntu-latest + runs-on: ubuntu-slim outputs: fileName: ${{ steps.extractName.outputs.fileName}} env: @@ -58,7 +58,7 @@ jobs: if-no-files-found: error allowlist-kaspersky: name: Anti Virus Allowlisting Kaspersky - runs-on: ubuntu-latest + runs-on: ubuntu-slim needs: download-file if: inputs.kaspersky steps: @@ -78,7 +78,7 @@ jobs: local-dir: ./upload/ allowlist-avast: name: Anti Virus Allowlisting Avast - runs-on: ubuntu-latest + runs-on: ubuntu-slim needs: download-file if: inputs.avast steps: diff --git a/.github/workflows/no-response.yml b/.github/workflows/no-response.yml index 6585256bb..6cf906950 100644 --- a/.github/workflows/no-response.yml +++ b/.github/workflows/no-response.yml @@ -7,7 +7,7 @@ on: jobs: no-response: - runs-on: ubuntu-latest + runs-on: ubuntu-slim permissions: issues: write pull-requests: write diff --git a/.github/workflows/post-publish.yml b/.github/workflows/post-publish.yml index fe6040f93..8576dd851 100644 --- a/.github/workflows/post-publish.yml +++ b/.github/workflows/post-publish.yml @@ -11,7 +11,7 @@ jobs: version: ${{ github.event.release.tag_name }} notify: - runs-on: ubuntu-latest + runs-on: ubuntu-slim steps: - name: Notify about DEB build uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 @@ -40,7 +40,7 @@ jobs: get-asset-urls: name: Get release asset URLs - runs-on: ubuntu-latest + runs-on: ubuntu-slim outputs: is-windows-release: ${{ steps.urls.outputs.urls-present }} msi-url: ${{ steps.urls.outputs.msi }} @@ -81,7 +81,7 @@ jobs: name: Notify for winget-release if: needs.get-asset-urls.outputs.is-windows-release == 'true' && needs.get-version.outputs.versionType == 'stable' needs: [get-version, get-asset-urls] - runs-on: ubuntu-latest + runs-on: ubuntu-slim steps: - name: Slack Notification uses: rtCamp/action-slack-notify@e31e87e03dd19038e411e38ae27cbad084a90661 # v2.3.3 @@ -98,7 +98,7 @@ jobs: trigger-website-update: needs: [get-version] - runs-on: ubuntu-latest + runs-on: ubuntu-slim if: needs.get-version.outputs.versionType == 'stable' steps: - name: Start website update workflow @@ -111,7 +111,7 @@ jobs: trigger-docs-update: needs: [get-version, get-asset-urls] - runs-on: ubuntu-latest + runs-on: ubuntu-slim if: needs.get-asset-urls.outputs.is-windows-release == 'true' && needs.get-version.outputs.versionType == 'stable' steps: - name: Start docs update workflow diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 9f30d89a5..ed6406551 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -7,7 +7,7 @@ on: jobs: stale: - runs-on: ubuntu-latest + runs-on: ubuntu-slim permissions: issues: write pull-requests: write From 8f0c6eb994a1fba0c086ab76323d9e9e9209022d Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 9 Apr 2026 16:49:37 +0200 Subject: [PATCH 29/44] fix bugs * win-exe still checked for release event * only perform appimage checksum step on release * remove unused input in appimage flow --- .github/workflows/appimage.yml | 5 +---- .github/workflows/win-exe.yml | 10 ++++++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index 59db89176..e9744e838 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -21,10 +21,6 @@ on: version: description: 'Version' required: false - create-pr: - description: 'Create a PR for aur-bin repo' - type: boolean - default: false push: branches-ignore: - 'dependabot/**' @@ -226,6 +222,7 @@ jobs: name: Collect AppImage checksums runs-on: ubuntu-latest needs: [build] + if: inputs.is-release outputs: x64-sha256sum: ${{ steps.sha256sum.outputs.x64-sha256sum }} aarch64-sha256sum: ${{ steps.sha256sum.outputs.aarch64-sha256sum }} diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml index 3d0712000..56ffe9660 100644 --- a/.github/workflows/win-exe.yml +++ b/.github/workflows/win-exe.yml @@ -208,7 +208,7 @@ jobs: & $env:JAVA_HOME\bin\jmod.exe extract --dir jpackage-jmod "${env:JAVA_HOME}\jmods\jdk.jpackage.jmod" Get-ChildItem -Recurse -Path "jpackage-jmod" -File wixhelper.dll | Select-Object -Last 1 | Copy-Item -Destination "appdir" - name: Sign DLLs with Azure Trusted Signing - if: inputs.sign || github.event_name == 'release' || github.event_name == 'schedule' + if: inputs.sign || inputs.is-release || github.event_name == 'schedule' uses: ./.github/actions/win-sign-action with: base-dir: ${{ github.workspace }}\appdir @@ -266,7 +266,7 @@ jobs: JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources # requires abs path, used in resources/main.wxs JP_WIXHELPER_DIR: ${{ github.workspace }}\appdir - name: Sign MSI with Azure Trusted Signing - if: inputs.sign || github.event_name == 'release' || github.event_name == 'schedule' + if: inputs.sign || inputs.is-release || github.event_name == 'schedule' uses: ./.github/actions/win-sign-action with: base-dir: ${{ github.workspace }}\installer @@ -377,10 +377,11 @@ jobs: ./bundle/bundleWithWinfsp.wxs -out "../../installer/unsigned/Cryptomator-Installer.exe" - name: Detach burn engine in preparation to sign + if: inputs.sign || inputs.is-release || github.event_name == 'schedule' run: > wix burn detach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe - name: Sign WiX burn engine with Azure Trusted Signing - if: inputs.sign || github.event_name == 'release' || github.event_name == 'schedule' + if: inputs.sign || inputs.is-release || github.event_name == 'schedule' uses: ./.github/actions/win-sign-action with: base-dir: ${{ github.workspace }}\tmp @@ -391,10 +392,11 @@ jobs: client-id: ${{ secrets.AZURE_CLIENT_ID }} client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} - name: Reattach signed burn engine to installer + if: inputs.sign || inputs.is-release || github.event_name == 'schedule' run: > wix burn reattach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe - name: Sign EXE installer with Azure Trusted Signing - if: inputs.sign || github.event_name == 'release' || github.event_name == 'schedule' + if: inputs.sign || inputs.is-release || github.event_name == 'schedule' uses: ./.github/actions/win-sign-action with: base-dir: ${{ github.workspace }}\installer From aa239418cfde2663bac07cad422c49e802b89e73 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 9 Apr 2026 16:57:30 +0200 Subject: [PATCH 30/44] use more local environment instead of copying data into script --- .github/workflows/win-exe.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml index 56ffe9660..925845b89 100644 --- a/.github/workflows/win-exe.yml +++ b/.github/workflows/win-exe.yml @@ -349,10 +349,10 @@ jobs: shell: pwsh - name: Download WinFsp run: | - curl --silent --fail-with-body --proto "=https" -L ${{ env.WINFSP_MSI }} --output $env:WINFSP_PATH - $computedHash = (Get-FileHash -Path $env:WINFSP_PATH -Algorithm SHA256).Hash.ToLower() - if ($computedHash -ne "${{ env.WINFSP_MSI_HASH }}") { - throw "Checksum mismatch for $env:WINFSP_PATH (expected ${{ env.WINFSP_MSI_HASH }}, got $computedHash)." + curl --silent --fail-with-body --proto "=https" -L "$env:WINFSP_MSI" --output $env:WINFSP_PATH + $computedHash = (Get-FileHash -Path "$env:WINFSP_PATH" -Algorithm SHA256).Hash.ToLower() + if ($computedHash -ne "$env:WINFSP_MSI_HASH") { + throw "Checksum mismatch for ${env:WINFSP_PATH} (expected ${env:WINFSP_MSI_HASH}, got $computedHash)." } env: WINFSP_PATH: 'dist/win/bundle/resources/winfsp.msi' From 54f805a0c942afc123beb776a71d1bbacde81878 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 9 Apr 2026 17:18:07 +0200 Subject: [PATCH 31/44] fix exe installer not found after --- .github/workflows/win-exe.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml index 925845b89..7534e3674 100644 --- a/.github/workflows/win-exe.yml +++ b/.github/workflows/win-exe.yml @@ -375,11 +375,11 @@ jobs: -ext "WixToolset.Util.wixext" -ext "WixToolset.BootstrapperApplications.wixext" ./bundle/bundleWithWinfsp.wxs - -out "../../installer/unsigned/Cryptomator-Installer.exe" + -out "../../installer/Cryptomator-Installer.exe" - name: Detach burn engine in preparation to sign if: inputs.sign || inputs.is-release || github.event_name == 'schedule' run: > - wix burn detach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe + wix burn detach installer/Cryptomator-Installer.exe -engine tmp/engine.exe - name: Sign WiX burn engine with Azure Trusted Signing if: inputs.sign || inputs.is-release || github.event_name == 'schedule' uses: ./.github/actions/win-sign-action @@ -393,8 +393,9 @@ jobs: client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} - name: Reattach signed burn engine to installer if: inputs.sign || inputs.is-release || github.event_name == 'schedule' - run: > - wix burn reattach installer/unsigned/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe + run: | + Move-Item -Path installer/Cryptomator-Installer.exe -Destination tmp/Cryptomator-Installer.exe + wix burn reattach tmp/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe - name: Sign EXE installer with Azure Trusted Signing if: inputs.sign || inputs.is-release || github.event_name == 'schedule' uses: ./.github/actions/win-sign-action From f21ae0e11cd89c8c408b461ff2260b100dd8274f Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 13 Apr 2026 11:37:51 +0200 Subject: [PATCH 32/44] fix notarization of dmg files on workflow calls --- .github/workflows/mac-dmg-x64.yml | 2 +- .github/workflows/mac-dmg.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mac-dmg-x64.yml b/.github/workflows/mac-dmg-x64.yml index 9786b452f..7b6ce4a4c 100644 --- a/.github/workflows/mac-dmg-x64.yml +++ b/.github/workflows/mac-dmg-x64.yml @@ -261,7 +261,7 @@ jobs: env: CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }} - name: Notarize .dmg - if: startsWith(github.ref, 'refs/tags/') || inputs.notarize || github.event_name == 'schedule' + if: inputs.notarize || github.event_name == 'workflow_call' && inputs.is-release || github.event_name == 'schedule' uses: cocoalibs/xcode-notarization-action@5cf433d494b6fa26504b574c591f4dd120388846 # v1.0.3 with: app-path: 'Cryptomator-*.dmg' diff --git a/.github/workflows/mac-dmg.yml b/.github/workflows/mac-dmg.yml index 1aa0654c5..89c784a3b 100644 --- a/.github/workflows/mac-dmg.yml +++ b/.github/workflows/mac-dmg.yml @@ -260,7 +260,7 @@ jobs: env: CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }} - name: Notarize .dmg - if: startsWith(github.ref, 'refs/tags/') || inputs.notarize || github.event_name == 'schedule' + if: inputs.notarize || github.event_name == 'workflow_call' && inputs.is-release || github.event_name == 'schedule' uses: cocoalibs/xcode-notarization-action@5cf433d494b6fa26504b574c591f4dd120388846 # v1.0.3 with: app-path: 'Cryptomator-*.dmg' From 19a9595f2e0b15c3cfdc4d200533f10d82d35db9 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 13 Apr 2026 11:46:03 +0200 Subject: [PATCH 33/44] rename worfklow to clearly indicate what it does --- .github/workflows/{create-release.yml => draft-release.yml} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename .github/workflows/{create-release.yml => draft-release.yml} (99%) diff --git a/.github/workflows/create-release.yml b/.github/workflows/draft-release.yml similarity index 99% rename from .github/workflows/create-release.yml rename to .github/workflows/draft-release.yml index 94184b4a3..354e782ae 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/draft-release.yml @@ -1,4 +1,4 @@ -name: Create a Cryptomator Release +name: Draft a Cryptomator Release on: push: From b6133e481cd5590dc0e4270f03cd66ac7ac0b272 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 13 Apr 2026 16:18:55 +0200 Subject: [PATCH 34/44] Refactor appimage, dmg and msi/exe workflows * unify inputs handling for worklfow dispatch and call * simplify conditions for signing/release steps --- .github/workflows/appimage.yml | 55 ++++++++++++++---------- .github/workflows/mac-dmg-x64.yml | 63 +++++++++++++++++----------- .github/workflows/mac-dmg.yml | 63 +++++++++++++++++----------- .github/workflows/win-exe.yml | 70 +++++++++++++++++++------------ 4 files changed, 151 insertions(+), 100 deletions(-) diff --git a/.github/workflows/appimage.yml b/.github/workflows/appimage.yml index e9744e838..ecb92eb60 100644 --- a/.github/workflows/appimage.yml +++ b/.github/workflows/appimage.yml @@ -5,10 +5,18 @@ on: - cron: '0 23 20 * *' workflow_call: inputs: - is-release: - description: "Workflow is called by a release" - type: boolean - default: false + semVerNum: + type: string + description: 'The Major.Minor.Patch part of the version' + required: true + revisionNum: + type: string + description: 'The revision number' + required: true + semVerSuffix: + type: string + description: 'The suffix of the version, including dash' + required: true outputs: sha256-appimage-x64: description: "SHA256 sum of the x64 appimage" @@ -18,9 +26,16 @@ on: value: ${{ jobs.collect-sha256sums.outputs.aarch64-sha256sum}} workflow_dispatch: inputs: - version: - description: 'Version' + semVerNum: + description: 'The Major.Minor.Patch part of the version' required: false + revisionNum: + description: 'The revision number' + required: false + semVerSuffix: + description: 'The suffix of the version, including dash' + required: false + default: '-SNAPSHOT' push: branches-ignore: - 'dependabot/**' @@ -33,21 +48,15 @@ on: env: JAVA_DIST: 'temurin' JAVA_VERSION: '25.0.2+10.0.LTS' + VERSION_NUM: ${{ inputs.semVerNum || '99.99.99'}} + REVISION_NUM: ${{ inputs.revisionNum || '0' }} + VERSION_SUFFIX: ${{ inputs.semVerSuffix || ''}} + jobs: - get-version: - uses: ./.github/workflows/get-version.yml - with: - version: ${{ inputs.version }} #okay if not defined - build: name: Build AppImage runs-on: ${{ matrix.os }} - needs: [get-version] - env: - SEMVER_STR: ${{ needs.get-version.outputs.semVerStr }} - SEMVER_NUM: ${{ needs.get-version.outputs.semVerNum }} - REV_NUM: ${{ needs.get-version.outputs.revNum }} strategy: fail-fast: false matrix: @@ -92,7 +101,7 @@ jobs: exit 1 fi - name: Set version - run : mvn versions:set -DnewVersion="$SEMVER_STR" + run : mvn versions:set -DnewVersion="${VERSION_NUM}${VERSION_SUFFIX}" - name: Run maven run: mvn -B clean package -Plinux -DskipTests - name: Patch target dir @@ -135,12 +144,12 @@ jobs: --name Cryptomator --vendor "Skymatic GmbH" --copyright "(C) 2016 - 2025 Skymatic GmbH" - --app-version "${SEMVER_NUM}.${REV_NUM}" + --app-version "${VERSION_NUM}.${REVISION_NUM}" --java-options "--enable-preview" --java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.linux.amd64,org.cryptomator.jfuse.linux.aarch64,org.purejava.appindicator" --java-options "-Xss5m" --java-options "-Xmx256m" - --java-options "-Dcryptomator.appVersion=\"${SEMVER_STR}\"" + --java-options "-Dcryptomator.appVersion=\"${VERSION_NUM}${VERSION_SUFFIX}\"" --java-options "-Dfile.encoding=\"utf-8\"" --java-options "-Djava.net.useSystemProxies=true" --java-options "-Dcryptomator.adminConfigPath=\"/etc/cryptomator/config.properties\"" @@ -151,7 +160,7 @@ jobs: --java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/.local/share/Cryptomator/mnt\"" --java-options "-Dcryptomator.showTrayIcon=true" --java-options "-Dcryptomator.integrationsLinux.trayIconsDir=\"@{appdir}/usr/share/icons/hicolor/symbolic/apps\"" - --java-options "-Dcryptomator.buildNumber=\"appimage-${REV_NUM}\"" + --java-options "-Dcryptomator.buildNumber=\"appimage-${REVISION_NUM}\"" --java-options "-Dcryptomator.networking.truststore.p12Path=\"/etc/cryptomator/certs.p12\"" --java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true" --java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log" @@ -190,7 +199,7 @@ jobs: GPG_PASSPHRASE: ${{ secrets.RELEASES_GPG_PASSPHRASE }} - name: Build AppImage run: > - ./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${SEMVER_STR}-${{ matrix.arch }}.AppImage + ./squashfs-root/AppRun Cryptomator.AppDir cryptomator-${VERSION_NUM}${VERSION_SUFFIX}-${{ matrix.arch }}.AppImage -u "gh-releases-zsync|cryptomator|cryptomator|latest|cryptomator-*-${{ matrix.arch }}.AppImage.zsync" --sign --sign-key=615D449FE6E6A235 - name: Create detached GPG signatures @@ -207,7 +216,7 @@ jobs: cryptomator-*.asc if-no-files-found: error - name: Publish AppImage on GitHub Releases - if: github.ref_type == 'tag' && inputs.is-release + if: github.event_name == 'workflow_call' uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1 with: draft: true @@ -222,7 +231,7 @@ jobs: name: Collect AppImage checksums runs-on: ubuntu-latest needs: [build] - if: inputs.is-release + if: github.event_name == 'workflow_call' outputs: x64-sha256sum: ${{ steps.sha256sum.outputs.x64-sha256sum }} aarch64-sha256sum: ${{ steps.sha256sum.outputs.aarch64-sha256sum }} diff --git a/.github/workflows/mac-dmg-x64.yml b/.github/workflows/mac-dmg-x64.yml index 7b6ce4a4c..a440af8c3 100644 --- a/.github/workflows/mac-dmg-x64.yml +++ b/.github/workflows/mac-dmg-x64.yml @@ -13,19 +13,38 @@ on: - cron: '0 20 20 * *' workflow_call: inputs: - is-release: - description: "Workflow is called by a release" + semVerNum: + type: string + description: 'The Major.Minor.Patch part of the version' + required: true + revisionNum: + type: string + description: 'The revision number' + required: true + semVerSuffix: + type: string + description: 'The suffix of the version, including dash' + required: true + notarize: + description: 'Notarize' + default: true type: boolean - default: false outputs: sha256-dmg: description: "SHA256 sum of the x64 dmg" value: ${{ jobs.build.outputs.sha256sum}} workflow_dispatch: inputs: - version: - description: 'Version' + semVerNum: + description: 'The Major.Minor.Patch part of the version' required: false + revisionNum: + description: 'The revision number' + required: false + semVerSuffix: + description: 'The suffix of the version, including dash' + required: false + default: '-SNAPSHOT' notarize: description: 'Notarize' required: true @@ -35,17 +54,15 @@ on: env: JAVA_DIST: 'temurin' JAVA_VERSION: '25.0.2+10.0.LTS' + VERSION_NUM: ${{ inputs.semVerNum || '99.99.99'}} + REVISION_NUM: ${{ inputs.revisionNum || '0' }} + VERSION_SUFFIX: ${{ inputs.semVerSuffix || ''}} + jobs: - get-version: - uses: ./.github/workflows/get-version.yml - with: - version: ${{ inputs.version }} - build: name: Build Cryptomator.app for ${{ matrix.output-suffix }} runs-on: ${{ matrix.os }} - needs: [get-version] outputs: sha256sum: ${{ steps.sha256sum.outputs.value }} strategy: @@ -89,7 +106,7 @@ jobs: exit 1 fi - name: Set version - run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }} + run : mvn versions:set -DnewVersion="${VERSION_NUM}${VERSION_SUFFIX}" - name: Run maven run: mvn -B clean package -Pmac -DskipTests - name: Patch target dir @@ -130,7 +147,7 @@ jobs: --name Cryptomator --vendor "Skymatic GmbH" --copyright "(C) 2016 - 2025 Skymatic GmbH" - --app-version "${{ needs.get-version.outputs.semVerNum }}" + --app-version "${VERSION_NUM}" --java-options "--enable-preview" --java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.mac" --java-options "-Xss5m" @@ -139,7 +156,7 @@ jobs: --java-options "-Djava.net.useSystemProxies=true" --java-options "-Dapple.awt.enableTemplateImages=true" --java-options "-Dsun.java2d.metal=true" - --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" + --java-options "-Dcryptomator.appVersion=\"${VERSION_NUM}${VERSION_SUFFIX}\"" --java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\"" --java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\"" --java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\"" @@ -149,7 +166,7 @@ jobs: --java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Library/Application Support/Cryptomator/mnt\"" --java-options "-Dcryptomator.showTrayIcon=true" --java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism" - --java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\"" + --java-options "-Dcryptomator.buildNumber=\"dmg-${REVISION_NUM}\"" --java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true" --mac-package-identifier org.cryptomator --resource-dir dist/mac/resources @@ -158,12 +175,10 @@ jobs: mv appdir/Cryptomator.app Cryptomator.app mv dist/mac/resources/Cryptomator-Vault.icns Cryptomator.app/Contents/Resources/ cp dist/mac/resources/Assets.car Cryptomator.app/Contents/Resources/ - sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" Cryptomator.app/Contents/Info.plist - sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" Cryptomator.app/Contents/Info.plist + sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NUM}|g" Cryptomator.app/Contents/Info.plist + sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NUM}|g" Cryptomator.app/Contents/Info.plist echo -n "$PROVISIONING_PROFILE_BASE64" | base64 --decode --output Cryptomator.app/Contents/embedded.provisionprofile env: - VERSION_NO: ${{ needs.get-version.outputs.semVerNum }} - REVISION_NO: ${{ needs.get-version.outputs.revNum }} PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }} - name: Generate license for dmg run: > @@ -252,16 +267,14 @@ jobs: --eula "dist/mac/dmg/resources/license.rtf" --icon ".background" 128 758 --icon ".VolumeIcon.icns" 512 758 - Cryptomator-${VERSION_NO}-${{ matrix.output-suffix }}.dmg dmg - env: - VERSION_NO: ${{ needs.get-version.outputs.semVerNum }} + Cryptomator-${VERSION_NUM}-${{ matrix.output-suffix }}.dmg dmg - name: Codesign .dmg run: | codesign -s ${CODESIGN_IDENTITY} --timestamp Cryptomator-*.dmg env: CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }} - name: Notarize .dmg - if: inputs.notarize || github.event_name == 'workflow_call' && inputs.is-release || github.event_name == 'schedule' + if: inputs.notarize || github.event_name == 'schedule' uses: cocoalibs/xcode-notarization-action@5cf433d494b6fa26504b574c591f4dd120388846 # v1.0.3 with: app-path: 'Cryptomator-*.dmg' @@ -274,7 +287,7 @@ jobs: read -ra CMD_OUTPUT < <(shasum -a256 Cryptomator-*.dmg) echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT - name: Add possible alpha/beta tags to installer name - run: mv Cryptomator-*.dmg Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.output-suffix }}.dmg + run: mv Cryptomator-*.dmg "Cryptomator-${VERSION_NUM}${VERSION_SUFFIX}-${{ matrix.output-suffix }}.dmg" - name: Create detached GPG signature with key 615D449FE6E6A235 run: | echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import @@ -295,7 +308,7 @@ jobs: Cryptomator-*.asc if-no-files-found: error - name: Publish dmg on GitHub Releases - if: github.ref_type == 'tag' && inputs.is-release + if: github.event_name == 'workflow_call' uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1 with: draft: true diff --git a/.github/workflows/mac-dmg.yml b/.github/workflows/mac-dmg.yml index 89c784a3b..d4d295104 100644 --- a/.github/workflows/mac-dmg.yml +++ b/.github/workflows/mac-dmg.yml @@ -5,19 +5,38 @@ on: - cron: '0 20 20 * *' workflow_call: inputs: - is-release: - description: "Workflow is called by a release" + semVerNum: + type: string + description: 'The Major.Minor.Patch part of the version' + required: true + revisionNum: + type: string + description: 'The revision number' + required: true + semVerSuffix: + type: string + description: 'The suffix of the version, including dash' + required: true + notarize: + description: 'Notarize' + default: true type: boolean - default: false outputs: sha256-dmg: description: "SHA256 sum of the arm64 dmg" value: ${{ jobs.build.outputs.sha256sum}} workflow_dispatch: inputs: - version: - description: 'Version' + semVerNum: + description: 'The Major.Minor.Patch part of the version' required: false + revisionNum: + description: 'The revision number' + required: false + semVerSuffix: + description: 'The suffix of the version, including dash' + required: false + default: '-SNAPSHOT' notarize: description: 'Notarize' required: true @@ -33,17 +52,15 @@ on: env: JAVA_DIST: 'temurin' JAVA_VERSION: '25.0.2+10.0.LTS' + VERSION_NUM: ${{ inputs.semVerNum || '99.99.99'}} + REVISION_NUM: ${{ inputs.revisionNum || '0' }} + VERSION_SUFFIX: ${{ inputs.semVerSuffix || ''}} + jobs: - get-version: - uses: ./.github/workflows/get-version.yml - with: - version: ${{ inputs.version }} - build: name: Build Cryptomator.app for ${{ matrix.output-suffix }} runs-on: ${{ matrix.os }} - needs: [get-version] outputs: sha256sum: ${{ steps.sha256sum.outputs.value }} strategy: @@ -87,7 +104,7 @@ jobs: exit 1 fi - name: Set version - run : mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }} + run : mvn versions:set -DnewVersion="${VERSION_NUM}${VERSION_SUFFIX}" - name: Run maven run: mvn -B clean package -Pmac -DskipTests - name: Patch target dir @@ -128,7 +145,7 @@ jobs: --name Cryptomator --vendor "Skymatic GmbH" --copyright "(C) 2016 - 2025 Skymatic GmbH" - --app-version "${{ needs.get-version.outputs.semVerNum }}" + --app-version "${VERSION_NUM}" --java-options "--enable-preview" --java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.mac" --java-options "-Xss5m" @@ -137,7 +154,7 @@ jobs: --java-options "-Djava.net.useSystemProxies=true" --java-options "-Dapple.awt.enableTemplateImages=true" --java-options "-Dsun.java2d.metal=true" - --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" + --java-options "-Dcryptomator.appVersion=\"${VERSION_NUM}${VERSION_SUFFIX}\"" --java-options "-Dcryptomator.adminConfigPath=\"/Library/Application Support/Cryptomator/config.properties\"" --java-options "-Dcryptomator.logDir=\"@{userhome}/Library/Logs/Cryptomator\"" --java-options "-Dcryptomator.settingsPath=\"@{userhome}/Library/Application Support/Cryptomator/settings.json\"" @@ -147,7 +164,7 @@ jobs: --java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Library/Application Support/Cryptomator/mnt\"" --java-options "-Dcryptomator.showTrayIcon=true" --java-options "-Dcryptomator.updateMechanism=org.cryptomator.macos.update.DmgUpdateMechanism" - --java-options "-Dcryptomator.buildNumber=\"dmg-${{ needs.get-version.outputs.revNum }}\"" + --java-options "-Dcryptomator.buildNumber=\"dmg-${REVISION_NUM}\"" --java-options "-XX:ErrorFile=/cryptomator/cryptomator_crash.log" --java-options "-Dcryptomator.hub.enableTrustOnFirstUse=true" --mac-package-identifier org.cryptomator @@ -157,12 +174,10 @@ jobs: mv appdir/Cryptomator.app Cryptomator.app mv dist/mac/resources/Cryptomator-Vault.icns Cryptomator.app/Contents/Resources/ cp dist/mac/resources/Assets.car Cryptomator.app/Contents/Resources/ - sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NO}|g" Cryptomator.app/Contents/Info.plist - sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NO}|g" Cryptomator.app/Contents/Info.plist + sed -i '' "s|###BUNDLE_SHORT_VERSION_STRING###|${VERSION_NUM}|g" Cryptomator.app/Contents/Info.plist + sed -i '' "s|###BUNDLE_VERSION###|${REVISION_NUM}|g" Cryptomator.app/Contents/Info.plist echo -n "$PROVISIONING_PROFILE_BASE64" | base64 --decode --output Cryptomator.app/Contents/embedded.provisionprofile env: - VERSION_NO: ${{ needs.get-version.outputs.semVerNum }} - REVISION_NO: ${{ needs.get-version.outputs.revNum }} PROVISIONING_PROFILE_BASE64: ${{ secrets.MACOS_PROVISIONING_PROFILE_BASE64 }} - name: Generate license for dmg run: > @@ -251,16 +266,14 @@ jobs: --eula "dist/mac/dmg/resources/license.rtf" --icon ".background" 128 758 --icon ".VolumeIcon.icns" 512 758 - Cryptomator-${VERSION_NO}-${{ matrix.output-suffix }}.dmg dmg - env: - VERSION_NO: ${{ needs.get-version.outputs.semVerNum }} + Cryptomator-${VERSION_NUM}-${{ matrix.output-suffix }}.dmg dmg - name: Codesign .dmg run: | codesign -s ${CODESIGN_IDENTITY} --timestamp Cryptomator-*.dmg env: CODESIGN_IDENTITY: ${{ secrets.MACOS_CODESIGN_IDENTITY }} - name: Notarize .dmg - if: inputs.notarize || github.event_name == 'workflow_call' && inputs.is-release || github.event_name == 'schedule' + if: inputs.notarize || github.event_name == 'schedule' uses: cocoalibs/xcode-notarization-action@5cf433d494b6fa26504b574c591f4dd120388846 # v1.0.3 with: app-path: 'Cryptomator-*.dmg' @@ -273,7 +286,7 @@ jobs: read -ra CMD_OUTPUT < <(shasum -a256 Cryptomator-*.dmg) echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT - name: Add possible alpha/beta tags to installer name - run: mv Cryptomator-*.dmg Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.output-suffix }}.dmg + run: mv Cryptomator-*.dmg "Cryptomator-${VERSION_NUM}${VERSION_SUFFIX}-${{ matrix.output-suffix }}.dmg" - name: Create detached GPG signature with key 615D449FE6E6A235 run: | echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import @@ -294,7 +307,7 @@ jobs: Cryptomator-*.asc if-no-files-found: error - name: Publish dmg on GitHub Releases - if: github.ref_type == 'tag' && inputs.is-release + if: github.event_name == 'workflow_call' uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2.6.1 with: draft: true diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml index 7534e3674..a85c4207a 100644 --- a/.github/workflows/win-exe.yml +++ b/.github/workflows/win-exe.yml @@ -5,10 +5,22 @@ on: - cron: '0 19 20 * *' workflow_call: inputs: - is-release: - description: "Workflow is called by a release" + semVerNum: + type: string + description: 'The Major.Minor.Patch part of the version' + required: true + revisionNum: + type: string + description: 'The revision number' + required: true + semVerSuffix: + type: string + description: 'The suffix of the version, including dash' + required: true + sign: + description: 'Sign binaries' + default: true type: boolean - default: false outputs: sha256-msi: description: "SHA256 sum of the x64 msi" @@ -18,9 +30,16 @@ on: value: ${{ jobs.build-exe.outputs.sha256sum}} workflow_dispatch: inputs: - version: - description: 'Version' + semVerNum: + description: 'The Major.Minor.Patch part of the version' required: false + revisionNum: + description: 'The revision number' + required: false + semVerSuffix: + description: 'The suffix of the version, including dash' + required: false + default: '-SNAPSHOT' sign: description: 'Sign binaries' required: false @@ -35,6 +54,9 @@ on: env: + VERSION_NUM: ${{ inputs.semVerNum || '99.99.99'}} + REVISION_NUM: ${{ inputs.revisionNum || '0' }} + VERSION_SUFFIX: ${{ inputs.semVerSuffix || ''}} OPENJFX_JMODS_AMD64: 'https://download2.gluonhq.com/openjfx/25.0.2/openjfx-25.0.2_windows-x64_bin-jmods.zip' OPENJFX_JMODS_AMD64_HASH: '33d878dfac85590c4d77c518ed413e512d34a8479d90132b230a7ddd173576b3' WINFSP_MSI: 'https://github.com/winfsp/winfsp/releases/download/v2.1/winfsp-2.1.25156.msi' @@ -47,15 +69,9 @@ defaults: shell: bash jobs: - get-version: - uses: ./.github/workflows/get-version.yml - with: - version: ${{ inputs.version }} - build-msi: name: Build .msi Installer runs-on: ${{ matrix.os }} - needs: [ get-version ] outputs: sha256sum: ${{ steps.sha256sum.outputs.value }} strategy: @@ -109,7 +125,7 @@ jobs: exit 1 fi - name: Set version - run: mvn versions:set -DnewVersion=${{ needs.get-version.outputs.semVerStr }} + run: mvn versions:set -DnewVersion="${VERSION_NUM}${VERSION_SUFFIX}" - name: Run maven run: mvn -B clean package -Pwin -DskipTests - name: Patch target dir @@ -150,12 +166,12 @@ jobs: --name Cryptomator --vendor "Skymatic GmbH" --copyright "(C) 2016 - 2025 Skymatic GmbH" - --app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum }}" + --app-version "${VERSION_NUM}.${REVISION_NUM}" --java-options "--enable-preview" --java-options "--enable-native-access=javafx.graphics,org.cryptomator.jfuse.win,org.cryptomator.integrations.win" --java-options "-Xss5m" --java-options "-Xmx256m" - --java-options "-Dcryptomator.appVersion=\"${{ needs.get-version.outputs.semVerStr }}\"" + --java-options "-Dcryptomator.appVersion=\"${VERSION_NUM}${VERSION_SUFFIX}\"" --java-options "-Dfile.encoding=\"utf-8\"" --java-options "-Djava.net.useSystemProxies=true" --java-options "-Dcryptomator.adminConfigPath=\"C:/ProgramData/Cryptomator/config.properties\"" @@ -166,7 +182,7 @@ jobs: --java-options "-Dcryptomator.mountPointsDir=\"@{userhome}/Cryptomator\"" --java-options "-Dcryptomator.loopbackAlias=\"cryptomator-vault\"" --java-options "-Dcryptomator.showTrayIcon=true" - --java-options "-Dcryptomator.buildNumber=\"msi-${{ needs.get-version.outputs.revNum }}\"" + --java-options "-Dcryptomator.buildNumber=\"msi-${REVISION_NUM}\"" --java-options "-Dcryptomator.integrationsWin.autoStartShellLinkName=\"Cryptomator\"" --java-options "-Dcryptomator.integrationsWin.keychainPaths=\"@{appdata}/Cryptomator/keychain.json;@{userhome}/AppData/Roaming/Cryptomator/keychain.json\"" --java-options "-Dcryptomator.integrationsWin.windowsHelloKeychainPaths=\"@{appdata}/Cryptomator/windowsHelloKeychain.json\"" @@ -208,7 +224,7 @@ jobs: & $env:JAVA_HOME\bin\jmod.exe extract --dir jpackage-jmod "${env:JAVA_HOME}\jmods\jdk.jpackage.jmod" Get-ChildItem -Recurse -Path "jpackage-jmod" -File wixhelper.dll | Select-Object -Last 1 | Copy-Item -Destination "appdir" - name: Sign DLLs with Azure Trusted Signing - if: inputs.sign || inputs.is-release || github.event_name == 'schedule' + if: inputs.sign || github.event_name == 'schedule' uses: ./.github/actions/win-sign-action with: base-dir: ${{ github.workspace }}\appdir @@ -253,7 +269,7 @@ jobs: --name Cryptomator --vendor "Skymatic GmbH" --copyright "(C) 2016 - 2025 Skymatic GmbH" - --app-version "${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum}}" + --app-version "${VERSION_NUM}.${REVISION_NUM}" --win-menu --win-dir-chooser --win-shortcut-prompt @@ -266,7 +282,7 @@ jobs: JP_WIXWIZARD_RESOURCES: ${{ github.workspace }}/dist/win/resources # requires abs path, used in resources/main.wxs JP_WIXHELPER_DIR: ${{ github.workspace }}\appdir - name: Sign MSI with Azure Trusted Signing - if: inputs.sign || inputs.is-release || github.event_name == 'schedule' + if: inputs.sign || github.event_name == 'schedule' uses: ./.github/actions/win-sign-action with: base-dir: ${{ github.workspace }}\installer @@ -280,7 +296,7 @@ jobs: read -ra CMD_OUTPUT < <(sha256sum installer/Cryptomator-*.msi) echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT - name: Add possible alpha/beta tags and architecture to installer name - run: mv installer/Cryptomator-*.msi Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.arch }}.msi + run: mv installer/Cryptomator-*.msi "Cryptomator-${VERSION_NUM}${VERSION_SUFFIX}-${{ matrix.arch }}.msi" - name: Create detached GPG signature with key 615D449FE6E6A235 run: | echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import @@ -300,7 +316,7 @@ jobs: build-exe: name: Build .exe installer runs-on: ${{ matrix.os }} - needs: [ get-version, build-msi ] + needs: [ build-msi ] outputs: sha256sum: ${{ steps.sha256sum.outputs.value }} strategy: @@ -366,7 +382,7 @@ jobs: run: > wix build -define BundleName="Cryptomator" - -define BundleVersion="${{ needs.get-version.outputs.semVerNum }}.${{ needs.get-version.outputs.revNum}}" + -define BundleVersion="${VERSION_NUM}.${REVISION_NUM}" -define BundleVendor="Skymatic GmbH" -define BundleCopyright="(C) 2016 - 2025 Skymatic GmbH" -define AboutUrl="https://cryptomator.org" @@ -377,11 +393,11 @@ jobs: ./bundle/bundleWithWinfsp.wxs -out "../../installer/Cryptomator-Installer.exe" - name: Detach burn engine in preparation to sign - if: inputs.sign || inputs.is-release || github.event_name == 'schedule' + if: inputs.sign || github.event_name == 'schedule' run: > wix burn detach installer/Cryptomator-Installer.exe -engine tmp/engine.exe - name: Sign WiX burn engine with Azure Trusted Signing - if: inputs.sign || inputs.is-release || github.event_name == 'schedule' + if: inputs.sign || github.event_name == 'schedule' uses: ./.github/actions/win-sign-action with: base-dir: ${{ github.workspace }}\tmp @@ -392,12 +408,12 @@ jobs: client-id: ${{ secrets.AZURE_CLIENT_ID }} client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} - name: Reattach signed burn engine to installer - if: inputs.sign || inputs.is-release || github.event_name == 'schedule' + if: inputs.sign || github.event_name == 'schedule' run: | Move-Item -Path installer/Cryptomator-Installer.exe -Destination tmp/Cryptomator-Installer.exe wix burn reattach tmp/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe - name: Sign EXE installer with Azure Trusted Signing - if: inputs.sign || inputs.is-release || github.event_name == 'schedule' + if: inputs.sign || github.event_name == 'schedule' uses: ./.github/actions/win-sign-action with: base-dir: ${{ github.workspace }}\installer @@ -412,7 +428,7 @@ jobs: read -ra CMD_OUTPUT < <(sha256sum installer/Cryptomator-*.exe) echo "value=${CMD_OUTPUT[0]}" >> $GITHUB_OUTPUT - name: Add possible alpha/beta tags to installer name - run: mv installer/Cryptomator-Installer.exe Cryptomator-${{ needs.get-version.outputs.semVerStr }}-${{ matrix.executable-suffix }}.exe + run: mv installer/Cryptomator-Installer.exe "Cryptomator-${VERSION_NUM}${VERSION_SUFFIX}-${{ matrix.executable-suffix }}.exe" - name: Create detached GPG signature with key 615D449FE6E6A235 run: | echo "${GPG_PRIVATE_KEY}" | gpg --batch --quiet --import @@ -431,7 +447,7 @@ jobs: publish: name: Publish installers to the github release - if: github.ref_type == 'tag' && inputs.is-release + if: github.event_name == 'workflow_call' runs-on: ubuntu-latest needs: [ build-msi, build-exe ] steps: From d1fcf528b0792a7f90cd393342019f6027659f0f Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 13 Apr 2026 17:40:43 +0200 Subject: [PATCH 35/44] use pwsh to move reattach burn engine --- .github/workflows/win-exe.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/win-exe.yml b/.github/workflows/win-exe.yml index a85c4207a..0802fb0f0 100644 --- a/.github/workflows/win-exe.yml +++ b/.github/workflows/win-exe.yml @@ -409,6 +409,7 @@ jobs: client-secret: ${{ secrets.AZURE_CLIENT_SECRET }} - name: Reattach signed burn engine to installer if: inputs.sign || github.event_name == 'schedule' + shell: pwsh run: | Move-Item -Path installer/Cryptomator-Installer.exe -Destination tmp/Cryptomator-Installer.exe wix burn reattach tmp/Cryptomator-Installer.exe -engine tmp/engine.exe -o installer/Cryptomator-Installer.exe From c745fca2ea61269ec1431f69e29ce6ab64245c17 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Mon, 13 Apr 2026 17:58:18 +0200 Subject: [PATCH 36/44] update draft-release.yml adhere to new workflow_call api --- .github/workflows/draft-release.yml | 24 ++++++++++++++++-------- .github/workflows/get-version.yml | 7 +++++++ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml index 354e782ae..0749b5c9d 100644 --- a/.github/workflows/draft-release.yml +++ b/.github/workflows/draft-release.yml @@ -69,31 +69,39 @@ jobs: cryptomator-*.tar.gz.asc build-exe-and-msi: - needs: create-release + needs: [get-version, create-release] uses: ./.github/workflows/win-exe.yml with: - is-release: true + semVerNum: ${{needs.get-version.outputs.semVerNum}} + revisionNum: ${{needs.get-version.outputs.revNum}} + semVerSuffix: ${{needs.get-version.outputs.semVerSuffix}} secrets: inherit build-dmg-arm64: - needs: create-release + needs: [get-version, create-release] uses: ./.github/workflows/mac-dmg.yml with: - is-release: true + semVerNum: ${{needs.get-version.outputs.semVerNum}} + revisionNum: ${{needs.get-version.outputs.revNum}} + semVerSuffix: ${{needs.get-version.outputs.semVerSuffix}} secrets: inherit build-dmg-x64: - needs: create-release + needs: [get-version, create-release] uses: ./.github/workflows/mac-dmg-x64.yml with: - is-release: true + semVerNum: ${{needs.get-version.outputs.semVerNum}} + revisionNum: ${{needs.get-version.outputs.revNum}} + semVerSuffix: ${{needs.get-version.outputs.semVerSuffix}} secrets: inherit build-appimages: - needs: create-release + needs: [get-version, create-release] uses: ./.github/workflows/appimage.yml with: - is-release: true + semVerNum: ${{needs.get-version.outputs.semVerNum}} + revisionNum: ${{needs.get-version.outputs.revNum}} + semVerSuffix: ${{needs.get-version.outputs.semVerSuffix}} secrets: inherit update-sha256sums: diff --git a/.github/workflows/get-version.yml b/.github/workflows/get-version.yml index 45056f700..124a3a138 100644 --- a/.github/workflows/get-version.yml +++ b/.github/workflows/get-version.yml @@ -14,6 +14,9 @@ on: semVerNum: description: "The numerical part of the version string" value: ${{ jobs.determine-version.outputs.semVerNum}} + semVerSuffix: + description: "The suffix of the version string" + value: ${{ jobs.determine-version.outputs.semVerSuffix}} revNum: description: "The revision number" value: ${{ jobs.determine-version.outputs.revNum}} @@ -32,6 +35,7 @@ jobs: outputs: semVerNum: ${{ steps.versions.outputs.semVerNum }} semVerStr: ${{ steps.versions.outputs.semVerStr }} + semVerSuffix: ${{ steps.versions.outputs.semVerSuffix }} revNum: ${{ steps.versions.outputs.revNum }} type: ${{ steps.versions.outputs.type}} steps: @@ -55,6 +59,7 @@ jobs: SEM_VER_STR=`mvn help:evaluate -Dexpression=project.version -q -DforceStdout` fi SEM_VER_NUM=`echo ${SEM_VER_STR} | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/'` + SEM_VER_SUFFIX=`echo ${SEM_VER_STR} | sed -E 's/[0-9]+\.[0-9]+\.[0-9]+?(.*)/\1/'` REVCOUNT=`git rev-list --count HEAD` TYPE="unknown" if [[ $SEM_VER_STR =~ [0-9]+\.[0-9]+\.[0-9]+$ ]]; then @@ -68,6 +73,8 @@ jobs: fi echo "semVerStr=${SEM_VER_STR}" >> $GITHUB_OUTPUT echo "semVerNum=${SEM_VER_NUM}" >> $GITHUB_OUTPUT + echo "semVerSuffix=${SEM_VER_SUFFIX}" >> $GITHUB_OUTPUT + echo "revNum=${REVCOUNT}" >> $GITHUB_OUTPUT echo "type=${TYPE}" >> $GITHUB_OUTPUT env: From d27a52752b08e367d70f0e7a0c0920c4f5b9cf38 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 14 Apr 2026 11:40:02 +0200 Subject: [PATCH 37/44] improve readability of version splitting --- .github/workflows/get-version.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/get-version.yml b/.github/workflows/get-version.yml index 124a3a138..def7ed98e 100644 --- a/.github/workflows/get-version.yml +++ b/.github/workflows/get-version.yml @@ -58,23 +58,25 @@ jobs: else SEM_VER_STR=`mvn help:evaluate -Dexpression=project.version -q -DforceStdout` fi - SEM_VER_NUM=`echo ${SEM_VER_STR} | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/'` - SEM_VER_SUFFIX=`echo ${SEM_VER_STR} | sed -E 's/[0-9]+\.[0-9]+\.[0-9]+?(.*)/\1/'` + + SEM_VER_NUM=$(echo ${SEM_VER_STR} | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/') + SEM_VER_SUFFIX="${SEM_VER_STR#"$SEM_VER_NUM"}" REVCOUNT=`git rev-list --count HEAD` + TYPE="unknown" - if [[ $SEM_VER_STR =~ [0-9]+\.[0-9]+\.[0-9]+$ ]]; then + if [[ -z $SEM_VER_SUFFIX ]]; then TYPE="stable" - elif [[ $SEM_VER_STR =~ [0-9]+\.[0-9]+\.[0-9]+-alpha[1-9]+$ ]]; then + elif [[ $SEM_VER_SUFFIX =~ -alpha[1-9]+$ ]]; then TYPE="alpha" - elif [[ $SEM_VER_STR =~ [0-9]+\.[0-9]+\.[0-9]+-beta[1-9]+$ ]]; then + elif [[ $SEM_VER_SUFFIX =~ -beta[1-9]+$ ]]; then TYPE="beta" - elif [[ $SEM_VER_STR =~ [0-9]+\.[0-9]+\.[0-9]+-rc[1-9]$ ]]; then + elif [[ $SEM_VER_SUFFIX =~ -rc[1-9]+$ ]]; then TYPE="rc" fi + echo "semVerStr=${SEM_VER_STR}" >> $GITHUB_OUTPUT echo "semVerNum=${SEM_VER_NUM}" >> $GITHUB_OUTPUT echo "semVerSuffix=${SEM_VER_SUFFIX}" >> $GITHUB_OUTPUT - echo "revNum=${REVCOUNT}" >> $GITHUB_OUTPUT echo "type=${TYPE}" >> $GITHUB_OUTPUT env: From e6cef947c1cd0246cf7ae4d8635ce6dfecc2b03d Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 16 Apr 2026 17:51:06 +0200 Subject: [PATCH 38/44] rename job --- .github/workflows/draft-release.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/draft-release.yml b/.github/workflows/draft-release.yml index 0749b5c9d..0442af4ff 100644 --- a/.github/workflows/draft-release.yml +++ b/.github/workflows/draft-release.yml @@ -19,7 +19,7 @@ jobs: with: version: '' - create-release: + create-release-draft: name: Compile and Test runs-on: ubuntu-latest needs: get-version @@ -69,7 +69,7 @@ jobs: cryptomator-*.tar.gz.asc build-exe-and-msi: - needs: [get-version, create-release] + needs: [get-version, create-release-draft] uses: ./.github/workflows/win-exe.yml with: semVerNum: ${{needs.get-version.outputs.semVerNum}} @@ -78,7 +78,7 @@ jobs: secrets: inherit build-dmg-arm64: - needs: [get-version, create-release] + needs: [get-version, create-release-draft] uses: ./.github/workflows/mac-dmg.yml with: semVerNum: ${{needs.get-version.outputs.semVerNum}} @@ -87,7 +87,7 @@ jobs: secrets: inherit build-dmg-x64: - needs: [get-version, create-release] + needs: [get-version, create-release-draft] uses: ./.github/workflows/mac-dmg-x64.yml with: semVerNum: ${{needs.get-version.outputs.semVerNum}} @@ -96,7 +96,7 @@ jobs: secrets: inherit build-appimages: - needs: [get-version, create-release] + needs: [get-version, create-release-draft] uses: ./.github/workflows/appimage.yml with: semVerNum: ${{needs.get-version.outputs.semVerNum}} From c52ae0120dcde28a91370b72abe37c9d02ec0e7f Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 16 Apr 2026 17:51:15 +0200 Subject: [PATCH 39/44] update changelog --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25b940a11..e6fe7f1f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,10 @@ The changelog starts with version 1.19.0. Changes to prior versions can be found on the [Github release page](https://github.com/cryptomator/cryptomator/releases). -## [Unreleased](https://github.com/cryptomator/cryptomator/compare/1.19.1...HEAD) +## [Unreleased](https://github.com/cryptomator/cryptomator/compare/1.19.2...HEAD) -No changes yet. +### Changed +* Refactored release pipeline to allow immutable releases ([#4205](https://github.com/cryptomator/cryptomator/pull/4205)) ## [1.19.2](https://github.com/cryptomator/cryptomator/releases/1.19.2) - 2026-03-20 From 4a0a4309c21f901faeb00516acf51dfe452f7961 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 16 Apr 2026 17:53:08 +0200 Subject: [PATCH 40/44] Replace get-version workflow call with slim job --- .github/workflows/post-publish.yml | 47 +++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/.github/workflows/post-publish.yml b/.github/workflows/post-publish.yml index 8576dd851..e27820520 100644 --- a/.github/workflows/post-publish.yml +++ b/.github/workflows/post-publish.yml @@ -5,11 +5,6 @@ on: types: [published] jobs: - get-version: - uses: ./.github/workflows/get-version.yml - with: - version: ${{ github.event.release.tag_name }} - notify: runs-on: ubuntu-slim steps: @@ -77,10 +72,36 @@ jobs: url: ${{ needs.get-asset-urls.outputs.exe-url }} secrets: inherit + check-release: + name: Analyzes the release for certain properties + runs-on: ubuntu-slim + outputs: + release-kind: ${{steps.determine-kind.outputs.value}} # Possible values are [alpha, beta, rc, stable, unknown] + steps: + - id: determine-kind + run: | + SEM_VER_NUM=$(echo ${SEM_VER_STR} | sed -E 's/([0-9]+\.[0-9]+\.[0-9]+).*/\1/') + SEM_VER_SUFFIX="${SEM_VER_STR#"$SEM_VER_NUM"}" + + TYPE="unknown" + if [[ -z $SEM_VER_SUFFIX ]]; then + TYPE="stable" + elif [[ $SEM_VER_SUFFIX =~ -alpha[1-9]+$ ]]; then + TYPE="alpha" + elif [[ $SEM_VER_SUFFIX =~ -beta[1-9]+$ ]]; then + TYPE="beta" + elif [[ $SEM_VER_SUFFIX =~ -rc[1-9]+$ ]]; then + TYPE="rc" + fi + echo "value=${TYPE}" >> $GITHUB_OUTPUT + env: + SEM_VER_STR: ${{ github.event.release.tag_name }} + + notify-winget: name: Notify for winget-release - if: needs.get-asset-urls.outputs.is-windows-release == 'true' && needs.get-version.outputs.versionType == 'stable' - needs: [get-version, get-asset-urls] + if: needs.get-asset-urls.outputs.is-windows-release == 'true' && needs.check-release.outputs.release-kind == 'stable' + needs: [check-release, get-asset-urls] runs-on: ubuntu-slim steps: - name: Slack Notification @@ -97,9 +118,9 @@ jobs: MSG_MINIMAL: true trigger-website-update: - needs: [get-version] + needs: [check-release] runs-on: ubuntu-slim - if: needs.get-version.outputs.versionType == 'stable' + if: needs.check-release.outputs.release-kind == 'stable' steps: - name: Start website update workflow uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1 @@ -107,12 +128,12 @@ jobs: event-type: desktop-release token: ${{ secrets.CRYPTOBOT_WORKFLOW_DISPATCH_TOKEN }} repository: cryptomator/cryptomator.github.io - client-payload: '{ "version": "${{needs.get-version.outputs.semVerStr}}", "release": ${{ toJson(github.event.release.assets) }} }' + client-payload: '{ "version": "${{ github.event.release.tag_name }}", "release": ${{ toJson(github.event.release.assets) }} }' trigger-docs-update: - needs: [get-version, get-asset-urls] + needs: [check-release, get-asset-urls] runs-on: ubuntu-slim - if: needs.get-asset-urls.outputs.is-windows-release == 'true' && needs.get-version.outputs.versionType == 'stable' + if: needs.get-asset-urls.outputs.is-windows-release == 'true' && needs.check-release.outputs.release-kind == 'stable' steps: - name: Start docs update workflow uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4.0.1 @@ -120,5 +141,5 @@ jobs: event-type: desktop-release token: ${{ secrets.CRYPTOBOT_WORKFLOW_DISPATCH_TOKEN }} repository: cryptomator/docs - client-payload: '{ "version": "${{needs.get-version.outputs.semVerStr}}", "release": ${{ toJson(github.event.release.assets) }} }' + client-payload: '{ "version": "${{ github.event.release.tag_name }}", "release": ${{ toJson(github.event.release.assets) }} }' From da8493f25f31fa449e2e173674d3531911d42ba8 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Thu, 16 Apr 2026 17:57:39 +0200 Subject: [PATCH 41/44] add release documentation --- .github/workflows/RELEASE.md | 189 +++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 .github/workflows/RELEASE.md diff --git a/.github/workflows/RELEASE.md b/.github/workflows/RELEASE.md new file mode 100644 index 000000000..5020ca997 --- /dev/null +++ b/.github/workflows/RELEASE.md @@ -0,0 +1,189 @@ +# Cryptomator Release Workflow + +This document describes the automated release pipeline defined in [`draft-release.yml`](draft-release.yml) and [`post-publish.yml`](post-publish.yml). + +## Overview + +The release process has two phases: + +1. **Draft phase** (`draft-release.yml`) -- triggered by pushing a signed git tag. Compiles, tests, builds platform installers, and creates a **draft** GitHub Release. +2. **Post-publish phase** (`post-publish.yml`) -- triggered when the draft release is manually **published**. Submits Windows installers for AV whitelisting, notifies the team for DEB build and latest-version update, and triggers downstream updates (website, docs, winget). + +```mermaid +--- +config: + htmlLabels: false +--- +flowchart TD + %% ── Trigger ────────────────────────────────────────────── + push_tag([🏷 Signed tag pushed]) + + %% ── Draft phase ────────────────────────────────────────── + push_tag --> get-version + + subgraph draft["draft-release.yml"] + get-version["get-version + *parse semver from tag*"] + + get-version --> create-release + create-release["create-release + *compile & test (Linux) + create draft release + sign source tarball*"] + + create-release --> build-exe-and-msi + create-release --> build-dmg-arm64 + create-release --> build-dmg-x64 + create-release --> build-appimages + + build-exe-and-msi["build-exe-and-msi + *calls win-exe.yml + MSI + EXE (x64) + code-signed & GPG-signed*"] + build-dmg-arm64["build-dmg-arm64 + *calls mac-dmg.yml + DMG (arm64) + notarized & GPG-signed*"] + build-dmg-x64["build-dmg-x64 + *calls mac-dmg-x64.yml + DMG (x64) + notarized & GPG-signed*"] + build-appimages["build-appimages + *calls appimage.yml + AppImage (x86_64 + aarch64) + GPG-signed*"] + + build-exe-and-msi --> update-sha256sums + build-dmg-arm64 --> update-sha256sums + build-dmg-x64 --> update-sha256sums + build-appimages --> update-sha256sums + + update-sha256sums["update-sha256sums + *compute checksums + update release body*"] + end + + update-sha256sums --> manual_review + + %% ── Manual gate ────────────────────────────────────────── + manual_review{{Manual review + & publish}} + + %% ── Post-publish phase ─────────────────────────────────── + manual_review --> published([📢 Release published]) + published --> post-publish + + subgraph post-publish["post-publish.yml"] + direction TB + + check-release["check-release + *classify release tag + stable, alpha, beta, rc, unknown*"] + notify["notify + *Slack notifications + deb build & version check*"] + get-asset-urls["get-asset-urls + *extract MSI & EXE + download URLs*"] + + check-release --> notify-winget + check-release --> trigger-website + check-release --> trigger-docs + + get-asset-urls --> allowlist-msi + allowlist-msi --> allowlist-exe + + allowlist-msi["allowlist-msi-x64 + *av-whitelist.yml + Kaspersky & Avast*"] + allowlist-exe["allowlist-exe-x64 + *av-whitelist.yml + Kaspersky & Avast*"] + + notify-winget["notify-winget + *Slack: ready for winget + stable only*"] + trigger-website["trigger-website-update + *dispatch to + cryptomator.github.io + stable only*"] + trigger-docs["trigger-docs-update + *dispatch to + cryptomator/docs + stable only, Windows*"] + end +``` + +## Phase 1: Draft Release (`draft-release.yml`) + +**Trigger:** push of any tag (`*`) + +### Jobs + +| Job | Runs on | Description | +|-----|---------|-------------| +| **get-version** | ubuntu | Parses the tag into semver components (`semVerNum`, `semVerSuffix`, `revNum`, `versionType`). Skips remaining jobs if the version format is unknown. | +| **create-release** | ubuntu | Checks out the repo, verifies the tag is **signed** and lives on a `main` or `release/*` branch. Runs `mvn verify` (with `xvfb-run`). Creates a **draft** GitHub Release using the [release body template](../release-body.md.template). Downloads and GPG-signs the source tarball. | +| **build-exe-and-msi** | windows | Calls [`win-exe.yml`](win-exe.yml). Builds the MSI and EXE bundle installer for x64 Windows. Code-signed via Azure Trusted Signing, GPG-signed, and uploaded to the draft release. Outputs SHA-256 checksums. | +| **build-dmg-arm64** | macos-15 | Calls [`mac-dmg.yml`](mac-dmg.yml). Builds the DMG for Apple Silicon. Code-signed, notarized with Apple, GPG-signed, and uploaded. Outputs SHA-256 checksum. | +| **build-dmg-x64** | macos-15-large | Calls [`mac-dmg-x64.yml`](mac-dmg-x64.yml). Same as above but for Intel Macs. Uses macFUSE instead of FUSE-T. | +| **build-appimages** | ubuntu | Calls [`appimage.yml`](appimage.yml). Builds AppImages for x86_64 and aarch64 (matrix). GPG-signed and uploaded with `.zsync` delta-update files. Outputs SHA-256 checksums. | +| **update-sha256sums** | ubuntu | Runs after all builds complete. Computes the source tarball checksum, collects all artifact checksums, and updates the draft release body via `envsubst`. Replaces the "builds still running" banner with a success notice. | + +### Release Artifacts + +After the draft phase, the GitHub Release contains: + +| Artifact | Platform | +|----------|----------| +| `cryptomator-.tar.gz.asc` | Source (GPG signature) | +| `Cryptomator--x64.msi` + `.asc` | Windows | +| `Cryptomator--x64.exe` + `.asc` | Windows | +| `Cryptomator--arm64.dmg` + `.asc` | macOS (Apple Silicon) | +| `Cryptomator--x64.dmg` + `.asc` | macOS (Intel) | +| `cryptomator--x86_64.AppImage` + `.zsync` + `.asc` | Linux (x86_64) | +| `cryptomator--aarch64.AppImage` + `.zsync` + `.asc` | Linux (aarch64) | + +All artifacts are signed with GPG key [`615D449FE6E6A235`](https://gist.github.com/cryptobot/211111cf092037490275f39d408f461a). + +## Manual Review Gate + +After the draft phase completes, a maintainer reviews the draft release on GitHub. This is the point to: + +- Verify all artifacts are present and checksums look correct. +- Edit the auto-generated release notes (What's New, Bugfixes, Other Changes). +- **Publish** the release when ready, which triggers phase 2. + +## Phase 2: Post-Publish (`post-publish.yml`) + +**Trigger:** `release: [published]` + +### Jobs + +| Job | Condition | Description | +|-----|-----------|-------------| +| **notify** | always | Sends Slack notifications to `#cryptomator-desktop`: ready to build `.deb` package, and reminder to update `latest-version.json` on S3. | +| **get-asset-urls** | always | Extracts MSI and EXE download URLs from the release assets. | +| **check-release** | always | Classifies the published release tag as `stable`, `alpha`, `beta`, `rc`, or `unknown`. Stable-only follow-up jobs depend on this output. Unlike `get-version.yml`, this job does not perform semver validation. | +| **allowlist-msi-x64** | Windows release | Calls [`av-whitelist.yml`](av-whitelist.yml). Uploads the MSI to Kaspersky and Avast for whitelisting. | +| **allowlist-exe-x64** | Windows release | Same as above for the EXE. Runs sequentially after MSI. | +| **notify-winget** | stable + Windows | Sends a Slack notification that the release is ready for [winget submission](winget.yml). | +| **trigger-website-update** | stable | Dispatches `desktop-release` event to `cryptomator/cryptomator.github.io`. | +| **trigger-docs-update** | stable + Windows | Dispatches `desktop-release` event to `cryptomator/docs`. | + +### Manual Follow-ups + +These steps are triggered by team members after Slack notifications: + +- **Debian package** -- Run the [`debian.yml`](debian.yml) workflow to build `.deb` and optionally upload to the PPA. +- **winget** -- Run the [`winget.yml`](winget.yml) workflow to submit to the Windows Package Manager. +- **latest-version.json** -- Update the version-check file on S3 (`static.cryptomator.org/desktop/latest-version.json`). + +## Signing & Security + +- **Git tag** must be SSH-signed and reside on `main` or `release/*`. +- **Windows** installers are code-signed using Azure Trusted Signing. +- **macOS** DMGs are code-signed with an Apple Developer certificate and notarized via `notarytool`. +- **All artifacts** receive a detached GPG signature (`.asc`) using key `615D449FE6E6A235`. +- **AV whitelisting** is submitted to Kaspersky and Avast after publish (Windows installers only). +- The draft release is created using `CRYPTOBOT_RELEASE_TOKEN`, not `GITHUB_TOKEN`, to ensure proper permissions and trigger downstream workflows. From 1230e787a9537a44cf92914c98859830beb23b5a Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Tue, 21 Apr 2026 15:36:54 +0200 Subject: [PATCH 42/44] Update RELEASE.md Signed-off-by: Armin Schrenk --- .github/workflows/RELEASE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/RELEASE.md b/.github/workflows/RELEASE.md index 5020ca997..1e4e0be54 100644 --- a/.github/workflows/RELEASE.md +++ b/.github/workflows/RELEASE.md @@ -122,8 +122,8 @@ flowchart TD | Job | Runs on | Description | |-----|---------|-------------| -| **get-version** | ubuntu | Parses the tag into semver components (`semVerNum`, `semVerSuffix`, `revNum`, `versionType`). Skips remaining jobs if the version format is unknown. | -| **create-release** | ubuntu | Checks out the repo, verifies the tag is **signed** and lives on a `main` or `release/*` branch. Runs `mvn verify` (with `xvfb-run`). Creates a **draft** GitHub Release using the [release body template](../release-body.md.template). Downloads and GPG-signs the source tarball. | +| **get-version** | ubuntu | Parses the tag into semver components (`semVerNum`, `semVerSuffix`, `revNum`, `versionType`). The release is aborted if not an alpha, beta, rc or 'stable' release. | +| **create-release-draft** | ubuntu | Checks out the repo, verifies the tag is **signed** and lives on a `main` or `release/*` branch. Runs `mvn verify` (with `xvfb-run`). Creates a GitHub Release **draft** using the [release body template](../release-body.md.template). Downloads and GPG-signs the source tarball. | | **build-exe-and-msi** | windows | Calls [`win-exe.yml`](win-exe.yml). Builds the MSI and EXE bundle installer for x64 Windows. Code-signed via Azure Trusted Signing, GPG-signed, and uploaded to the draft release. Outputs SHA-256 checksums. | | **build-dmg-arm64** | macos-15 | Calls [`mac-dmg.yml`](mac-dmg.yml). Builds the DMG for Apple Silicon. Code-signed, notarized with Apple, GPG-signed, and uploaded. Outputs SHA-256 checksum. | | **build-dmg-x64** | macos-15-large | Calls [`mac-dmg-x64.yml`](mac-dmg-x64.yml). Same as above but for Intel Macs. Uses macFUSE instead of FUSE-T. | @@ -164,7 +164,7 @@ After the draft phase completes, a maintainer reviews the draft release on GitHu |-----|-----------|-------------| | **notify** | always | Sends Slack notifications to `#cryptomator-desktop`: ready to build `.deb` package, and reminder to update `latest-version.json` on S3. | | **get-asset-urls** | always | Extracts MSI and EXE download URLs from the release assets. | -| **check-release** | always | Classifies the published release tag as `stable`, `alpha`, `beta`, `rc`, or `unknown`. Stable-only follow-up jobs depend on this output. Unlike `get-version.yml`, this job does not perform semver validation. | +| **check-release** | always | Classifies the published release tag as `stable`, `alpha`, `beta`, `rc`, or `unknown`. Stable-only follow-up jobs depend on this output. Unlike `get-version.yml`workflow, this job does not perform semver validation. | | **allowlist-msi-x64** | Windows release | Calls [`av-whitelist.yml`](av-whitelist.yml). Uploads the MSI to Kaspersky and Avast for whitelisting. | | **allowlist-exe-x64** | Windows release | Same as above for the EXE. Runs sequentially after MSI. | | **notify-winget** | stable + Windows | Sends a Slack notification that the release is ready for [winget submission](winget.yml). | From 1e6bc1f0430aae676a17f8b45016ad848e9ef551 Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Fri, 24 Apr 2026 15:10:57 +0200 Subject: [PATCH 43/44] Update RELEASE doc Signed-off-by: Armin Schrenk --- .github/workflows/RELEASE.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/RELEASE.md b/.github/workflows/RELEASE.md index 1e4e0be54..d808d48c1 100644 --- a/.github/workflows/RELEASE.md +++ b/.github/workflows/RELEASE.md @@ -25,16 +25,16 @@ flowchart TD get-version["get-version *parse semver from tag*"] - get-version --> create-release - create-release["create-release + get-version --> create-release-draft + create-release-draft["create-release-draft *compile & test (Linux) create draft release sign source tarball*"] - create-release --> build-exe-and-msi - create-release --> build-dmg-arm64 - create-release --> build-dmg-x64 - create-release --> build-appimages + create-release-draft --> build-exe-and-msi + create-release-draft --> build-dmg-arm64 + create-release-draft --> build-dmg-x64 + create-release-draft --> build-appimages build-exe-and-msi["build-exe-and-msi *calls win-exe.yml From 1266926ebb3945f486a0d252bb7e07374b3cc58f Mon Sep 17 00:00:00 2001 From: Armin Schrenk Date: Fri, 24 Apr 2026 15:39:05 +0200 Subject: [PATCH 44/44] fix docs Signed-off-by: Armin Schrenk --- .github/workflows/RELEASE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/RELEASE.md b/.github/workflows/RELEASE.md index d808d48c1..eabf157bf 100644 --- a/.github/workflows/RELEASE.md +++ b/.github/workflows/RELEASE.md @@ -164,7 +164,7 @@ After the draft phase completes, a maintainer reviews the draft release on GitHu |-----|-----------|-------------| | **notify** | always | Sends Slack notifications to `#cryptomator-desktop`: ready to build `.deb` package, and reminder to update `latest-version.json` on S3. | | **get-asset-urls** | always | Extracts MSI and EXE download URLs from the release assets. | -| **check-release** | always | Classifies the published release tag as `stable`, `alpha`, `beta`, `rc`, or `unknown`. Stable-only follow-up jobs depend on this output. Unlike `get-version.yml`workflow, this job does not perform semver validation. | +| **check-release** | always | Classifies the published release tag as `stable`, `alpha`, `beta`, `rc`, or `unknown`. Stable-only follow-up jobs depend on this output. Unlike `get-version.yml` workflow, this job does not perform semver validation. | | **allowlist-msi-x64** | Windows release | Calls [`av-whitelist.yml`](av-whitelist.yml). Uploads the MSI to Kaspersky and Avast for whitelisting. | | **allowlist-exe-x64** | Windows release | Same as above for the EXE. Runs sequentially after MSI. | | **notify-winget** | stable + Windows | Sends a Slack notification that the release is ready for [winget submission](winget.yml). |