name: Release on: push: tags: - 'v*' workflow_dispatch: permissions: contents: write jobs: build-release: name: Build and Release runs-on: ubuntu-24.04 environment: 'rpm signing' steps: - name: Checkout repository uses: actions/checkout@v4 - name: Install system dependencies run: | sudo apt-get update sudo apt-get install -y \ pkg-config \ libfuse3-dev \ libgtk-4-dev \ libadwaita-1-dev \ libwebkitgtk-6.0-dev \ libsecret-1-dev \ libdbus-1-dev \ desktop-file-utils \ rpm - name: Set up Rust uses: actions-rust-lang/setup-rust-toolchain@v1 with: toolchain: '1.96' components: rustfmt, clippy - name: Cache Cargo target uses: swatinem/rust-cache@v2 - name: Verify tag and manifest versions if: startsWith(github.ref, 'refs/tags/') shell: bash run: | tag_version="${GITHUB_REF_NAME#v}" manifest_version="$(sed -n 's/^version = "\([^"]*\)"/\1/p' Cargo.toml | head -n1)" pkgbuild_version="$(sed -n 's/^pkgver=//p' packaging/PKGBUILD | head -n1)" test "$tag_version" = "$manifest_version" test "$tag_version" = "$pkgbuild_version" - name: Release quality gates run: | cargo fmt --all -- --check cargo clippy --workspace --all-targets -- -D warnings cargo test --workspace --locked scripts/fuse-acceptance.sh --offline-only - name: Build release binaries run: | cargo build --release --locked - name: Determine version run: | if [[ $GITHUB_REF == refs/tags/* ]]; then # Extract version from tag (e.g. v0.1.0 -> 0.1.0) VERSION=${GITHUB_REF#refs/tags/} VERSION=${VERSION#v} else # Fallback for manual workflow runs: extract version from Cargo.toml VERSION=$(grep -m1 '^version' Cargo.toml | cut -d'"' -f2) VERSION="${VERSION}-dev-${GITHUB_SHA::7}" fi echo "VERSION=$VERSION" >> $GITHUB_ENV echo "Building version: $VERSION" - name: Package raw binaries (.tar.gz) run: | mkdir -p dist/binaries cp target/release/pdfs dist/binaries/ cp target/release/pdfs-tray dist/binaries/ cp target/release/pdfs-app dist/binaries/ cp target/release/pdfs-prompt dist/binaries/ # Create tarball tar -czf proton-drive-linux-${{ env.VERSION }}-x86_64.tar.gz -C dist/binaries . - name: Package Debian package (.deb) run: | mkdir -p deb/DEBIAN mkdir -p deb/usr/bin mkdir -p deb/usr/share/applications mkdir -p deb/usr/share/icons/hicolor/scalable/apps mkdir -p deb/usr/share/licenses/proton-drive-linux mkdir -p deb/usr/lib/systemd/user mkdir -p deb/etc/xdg/autostart # Copy binaries cp target/release/pdfs deb/usr/bin/ cp target/release/pdfs-tray deb/usr/bin/ cp target/release/pdfs-app deb/usr/bin/ cp target/release/pdfs-prompt deb/usr/bin/ # Copy desktop integration files cp packaging/io.narl.proton-drive-linux.desktop deb/usr/share/applications/ cp packaging/io.narl.proton-drive-linux-tray.desktop deb/etc/xdg/autostart/ cp packaging/io.narl.proton-drive-linux.svg deb/usr/share/icons/hicolor/scalable/apps/ cp packaging/proton-drive.service deb/usr/lib/systemd/user/ cp LICENSE deb/usr/share/licenses/proton-drive-linux/ # Calculate Installed-Size in KB for the control file INSTALLED_SIZE=$(du -sk deb | cut -f1) # Write DEBIAN/control file cat < deb/DEBIAN/control Package: proton-drive-linux Version: ${{ env.VERSION }} Section: utils Priority: optional Architecture: amd64 Maintainer: Nils Pukropp Depends: fuse3, libgtk-4-1 (>= 4.12.0), libadwaita-1-0 (>= 1.5.0), libsecret-1-0, libwebkitgtk-6.0-4 Installed-Size: ${INSTALLED_SIZE} Homepage: https://github.com/narrrl/proton-drive-linux Description: Unofficial Proton Drive client for Linux Files-on-demand Proton Drive for the Linux desktop, unaffiliated with Proton AG: - FUSE virtual mount with block-level caching - Scriptable command-line interface (pdfs) - GTK4 desktop application, system tray, and search launcher EOF # Build Debian package dpkg-deb --build deb proton-drive-linux_${{ env.VERSION }}_amd64.deb - name: Package Fedora package (.rpm) run: | # Sanitize version (replace hyphens with dots for RPM compatibility) RPM_VERSION=$(echo "${{ env.VERSION }}" | tr '-' '.') # Create RPM build directories mkdir -p rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS,BUILDROOT,db} # Build RPM package rpmbuild -bb \ --nodeps \ --define "_topdir $PWD/rpmbuild" \ --define "_sourcedir $PWD" \ --define "git_dir $PWD" \ --define "version ${RPM_VERSION}" \ --define "_dbpath $PWD/rpmbuild/db" \ packaging/proton-drive-linux.spec # Copy built RPM to root directory cp rpmbuild/RPMS/x86_64/*.rpm . - name: Sign Fedora package (.rpm) env: GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} GPG_KEY_NAME: ${{ secrets.GPG_KEY_NAME }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} run: | if [ -n "$GPG_PRIVATE_KEY" ] && [ -n "$GPG_KEY_NAME" ]; then echo "$GPG_PRIVATE_KEY" | gpg --batch --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" --import cat < ~/.rpmmacros %_signature gpg %_gpg_name ${GPG_KEY_NAME} %__gpg_sign_cmd %{__gpg} gpg --batch --verbose --no-armor --pinentry-mode loopback --passphrase %{_gpg_passphrase} --no-secmem-warning -u "%{_gpg_name}" -sbo %{__signature_filename} --digest-algo sha256 %{__plaintext_filename} EOF rpm --addsign --define "_gpg_passphrase $GPG_PASSPHRASE" *.rpm else echo "Skipping RPM signing: GPG_PRIVATE_KEY or GPG_KEY_NAME secret is not set." fi - name: Upload Workflow Artifacts uses: actions/upload-artifact@v4 with: name: proton-drive-linux-builds path: | *.deb *.tar.gz *.rpm if-no-files-found: error - name: Create GitHub Release if: startsWith(github.ref, 'refs/tags/') uses: softprops/action-gh-release@v2 with: files: | *.deb *.tar.gz *.rpm draft: false prerelease: false env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}