mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-03 16:41:26 +01:00
Removing the package left the user service running from the deleted binary, with ~/ProtonDrive still mounted. A user who then deleted the folder to clean up had every file in it moved to the Proton Drive trash, as any delete through the mount is. The .deb (prerm on remove), the .rpm (%preun on erase) and the Arch packages (pre_remove) now stop proton-drive.service for every user with a running user manager, through runuser with that user's XDG_RUNTIME_DIR, so no systemd-machined is needed. Upgrades are left alone. Queued writes stay in the state directory for a later install. The pacman install script lives once in packaging/ and the AUR directories link it; push.sh copies its content into each AUR repository. The uninstall guide now warns not to delete the mount point while the service runs. Reported on Reddit by a user who restored the files from the trash.
315 lines
10 KiB
YAML
315 lines
10 KiB
YAML
name: Release
|
|
|
|
on:
|
|
push:
|
|
tags:
|
|
- 'v*'
|
|
workflow_dispatch:
|
|
|
|
permissions:
|
|
contents: write
|
|
|
|
jobs:
|
|
checks:
|
|
name: Release quality gates
|
|
runs-on: ubuntu-24.04
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v7
|
|
|
|
- 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
|
|
|
|
- name: Set up Rust
|
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
with:
|
|
toolchain: '1.96'
|
|
components: rustfmt, clippy
|
|
cache: false
|
|
|
|
# A tag can read the caches of main but its own caches are useless to the next
|
|
# tag, so this only restores what CI saved on main.
|
|
- name: Cache Cargo target
|
|
uses: swatinem/rust-cache@v2
|
|
with:
|
|
shared-key: debug
|
|
save-if: false
|
|
|
|
- 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
|
|
|
|
build-release:
|
|
name: Build packages
|
|
runs-on: ubuntu-24.04
|
|
environment: 'rpm signing'
|
|
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v7
|
|
|
|
- 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 \
|
|
gettext \
|
|
rpm
|
|
|
|
- name: Set up Rust
|
|
uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
with:
|
|
toolchain: '1.96'
|
|
cache: false
|
|
|
|
# Restores the release-profile dependencies that CI builds on main.
|
|
- name: Cache Cargo target
|
|
uses: swatinem/rust-cache@v2
|
|
with:
|
|
shared-key: release
|
|
save-if: false
|
|
|
|
- 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/
|
|
po/build.sh dist/binaries/locale
|
|
|
|
# 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/
|
|
po/build.sh deb/usr/share/locale
|
|
|
|
# Stops the running daemon before removal, so the mount stops mirroring deletes
|
|
install -m755 packaging/deb/prerm deb/DEBIAN/prerm
|
|
|
|
# Calculate Installed-Size in KB for the control file
|
|
INSTALLED_SIZE=$(du -sk deb | cut -f1)
|
|
|
|
# Write DEBIAN/control file
|
|
cat <<EOF > deb/DEBIAN/control
|
|
Package: proton-drive-linux
|
|
Version: ${{ env.VERSION }}
|
|
Section: utils
|
|
Priority: optional
|
|
Architecture: amd64
|
|
Maintainer: Nils Pukropp <contact@narl.io>
|
|
Depends: fuse3, libgtk-4-1 (>= 4.12.0), libadwaita-1-0 (>= 1.5.0), libsecret-1-0, libwebkitgtk-6.0-4, libimage-exiftool-perl
|
|
Installed-Size: ${INSTALLED_SIZE}
|
|
Homepage: https://proton-drive.narl.io
|
|
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 "prebuilt 1" \
|
|
--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 <<EOF > ~/.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@v7
|
|
with:
|
|
name: proton-drive-linux-builds
|
|
path: |
|
|
*.deb
|
|
*.tar.gz
|
|
*.rpm
|
|
if-no-files-found: error
|
|
|
|
# The flake is the Nix release: a tag is what `github:narrrl/proton-drive-linux/vX.Y.Z`
|
|
# pins, so it has to build before the release is announced.
|
|
nix:
|
|
name: Build the Nix package
|
|
runs-on: ubuntu-24.04
|
|
steps:
|
|
- uses: actions/checkout@v7
|
|
|
|
- uses: cachix/install-nix-action@v31
|
|
|
|
# Pulls from the project's binary cache, and pushes what this run built
|
|
# when the token is there; a fork's pull request has none and only pulls.
|
|
- uses: cachix/cachix-action@v17
|
|
with:
|
|
name: proton-drive-linux
|
|
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
|
|
|
- name: Build the flake
|
|
run: nix build --print-build-logs .#proton-drive-linux
|
|
|
|
- name: Check the version
|
|
run: |
|
|
built="$(./result/bin/pdfs --version)"
|
|
echo "$built"
|
|
case "$GITHUB_REF" in
|
|
refs/tags/v*) grep -qF "${GITHUB_REF_NAME#v}" <<< "$built" ;;
|
|
esac
|
|
|
|
publish:
|
|
name: Create GitHub Release
|
|
needs: [checks, build-release, nix]
|
|
if: startsWith(github.ref, 'refs/tags/')
|
|
runs-on: ubuntu-24.04
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v7
|
|
|
|
- name: Download packages
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
name: proton-drive-linux-builds
|
|
|
|
# The release notes are this version's section of the changelog, from its
|
|
# heading up to the next one.
|
|
- name: Extract release notes
|
|
run: |
|
|
version="${GITHUB_REF_NAME#v}"
|
|
awk -v heading="## [$version]" \
|
|
'index($0, heading) == 1 { found = 1; print; next }
|
|
found && /^## \[/ { exit }
|
|
found' docs/CHANGELOG.md > release-notes.md
|
|
if [ ! -s release-notes.md ]; then
|
|
echo "::error::docs/CHANGELOG.md has no section for $version"
|
|
exit 1
|
|
fi
|
|
|
|
- name: Create GitHub Release
|
|
uses: softprops/action-gh-release@v3
|
|
with:
|
|
body_path: release-notes.md
|
|
files: |
|
|
*.deb
|
|
*.tar.gz
|
|
*.rpm
|
|
draft: false
|
|
prerelease: false
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
aur:
|
|
name: Publish AUR packages
|
|
needs: publish
|
|
if: startsWith(github.ref, 'refs/tags/')
|
|
uses: ./.github/workflows/aur.yml
|
|
with:
|
|
version: ${{ github.ref_name }}
|
|
secrets:
|
|
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
|