mirror of
https://github.com/narrrl/proton-drive-linux.git
synced 2026-11-12 17:27:03 +01:00
`pdfs completions <shell>` prints a completion script for bash, zsh, fish, elvish or PowerShell, built on clap_complete's dynamic engine: on Tab the shell calls `pdfs` back, which completes commands and options and also the values the running service knows, each with a description: paths in My files, synced-folder and queue ids, computers, trash, albums, items shared with me, invitations, bookmarks, conflict copies, and a file's versions or a share's members and public link once its path is typed. A completer that gets no answer from the service within two seconds offers nothing rather than hanging the prompt. Listings that ask Proton are kept for 30 s in $XDG_RUNTIME_DIR (0600), so repeated Tabs do not wait again. Completion is triggered by PDFS_COMPLETE rather than clap's generic COMPLETE, because the same binary runs the daemon. Share roles are now checked by the CLI before the request. The package recipes install the bash, zsh and fish scripts via packaging/completions.sh.
344 lines
11 KiB
YAML
344 lines
11 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)"
|
|
spec_version="$(sed -n 's/^%{!?version: %global version \([^}]*\)}/\1/p' packaging/proton-drive-linux.spec)"
|
|
test "$tag_version" = "$manifest_version"
|
|
test "$tag_version" = "$pkgbuild_version"
|
|
test "$tag_version" = "$spec_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 .
|
|
|
|
# Every crate the build needs, so COPR can build the spec without network.
|
|
- name: Package vendored crates (.tar.xz)
|
|
run: |
|
|
cargo vendor --locked dist/vendor > /dev/null
|
|
tar -cJf proton-drive-linux-vendor-${{ env.VERSION }}.tar.xz -C dist vendor
|
|
|
|
- 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
|
|
packaging/completions.sh target/release/pdfs deb/usr/share
|
|
|
|
# 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
|
|
*.tar.xz
|
|
*.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
|
|
*.tar.xz
|
|
*.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 }}
|
|
|
|
copr:
|
|
name: Build COPR packages
|
|
needs: publish
|
|
if: startsWith(github.ref, 'refs/tags/')
|
|
uses: ./.github/workflows/copr.yml
|
|
with:
|
|
version: ${{ github.ref_name }}
|
|
secrets:
|
|
COPR_CONFIG: ${{ secrets.COPR_CONFIG }}
|
|
|
|
wiki:
|
|
name: Publish the wiki
|
|
needs: publish
|
|
if: startsWith(github.ref, 'refs/tags/')
|
|
uses: ./.github/workflows/wiki.yml
|
|
with:
|
|
ref: ${{ github.ref_name }}
|