chore: add release infrastructure and packaging support
Rust / build (macos-latest, stable) (push) Canceled after 0s
Rust / build (ubuntu-latest, stable) (push) Canceled after 0s
Rust / build (windows-latest, stable) (push) Canceled after 0s

Add GitHub Actions workflows for CI and release builds, packaging
scripts for Windows, macOS, Linux, and Flatpak/Snap distribution,
application icons, desktop files, and release metadata resources.
This commit is contained in:
2026-09-07 12:44:35 +07:00
parent 02a0134164
commit 1af4c66566
31 changed files with 1508 additions and 2 deletions
Vendored
BIN
View File
Binary file not shown.
+173
View File
@@ -0,0 +1,173 @@
name: Build and Release
on:
workflow_dispatch:
push:
tags:
- "v*"
jobs:
build:
name: Build ${{ matrix.platform }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- platform: windows-x64
os: windows-latest
target: x86_64-pc-windows-msvc
- platform: windows-arm64
os: windows-11-arm
target: aarch64-pc-windows-msvc
- platform: macos-x64
os: macos-15-intel
target: x86_64-apple-darwin
- platform: macos-arm64
os: macos-latest
target: aarch64-apple-darwin
- platform: linux-x64
os: ubuntu-latest
target: x86_64-unknown-linux-gnu
- platform: linux-arm64
os: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
# Windows and macOS builds using cargo-packager
- name: Build with cargo-packager (Windows/macOS)
if: runner.os != 'Linux'
working-directory: desktop
run: |
cargo install cargo-packager --locked
cargo packager --release
- name: Upload Windows/macOS artifacts
if: runner.os != 'Linux'
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.platform }}-artifacts
path: |
dist/*.dmg
dist/*.msi
dist/*.exe
if-no-files-found: error
# Linux builds using custom scripts
- name: Install Linux build dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y flatpak flatpak-builder snapd squashfs-tools jq gettext-base
- name: Install Snapcraft
if: runner.os == 'Linux'
run: sudo snap install snapcraft --classic
- name: Make scripts executable
if: runner.os == 'Linux'
run: |
chmod +x script/get-crate-version
chmod +x script/linux
chmod +x script/bundle-snap
chmod +x script/bundle-linux
chmod +x script/flatpak/deps
chmod +x script/flatpak/bundle-flatpak
- name: Install required dependencies
if: runner.os == 'Linux'
run: ./script/linux
# Build the release tarball on every Linux architecture
- name: Build release tarball
if: runner.os == 'Linux'
run: ./script/bundle-linux
# Only build Flatpak and Snap for x86_64 (most common use case)
- name: Build Flatpak
if: runner.os == 'Linux' && matrix.target == 'x86_64-unknown-linux-gnu'
run: |
./script/flatpak/deps
./script/flatpak/bundle-flatpak
- name: Build Snap
if: runner.os == 'Linux' && matrix.target == 'x86_64-unknown-linux-gnu'
run: |
VERSION=$(script/get-crate-version signed)
./script/bundle-snap $VERSION
- name: Collect Linux artifacts
if: runner.os == 'Linux'
working-directory: ${{ github.workspace }}
run: |
mkdir -p linux-artifacts
# Copy the tarball created by bundle-linux
find target/release -name "*.tar.gz" -exec cp {} linux-artifacts/ \;
# Find and copy flatpak files (if they exist)
find . -name "*.flatpak" -exec cp {} linux-artifacts/ \; || true
# Find and copy snap files (if they exist)
find . -name "*.snap" -exec cp {} linux-artifacts/ \; || true
ls -la linux-artifacts/
- name: Upload Linux artifacts
if: runner.os == 'Linux'
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.platform }}-artifacts
path: linux-artifacts/**/*
if-no-files-found: error
release:
name: Create Release
needs: build
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') || github.event_name == 'workflow_dispatch'
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Make get-crate-version executable
run: chmod +x script/get-crate-version
- name: Get version
id: version
run: |
VERSION=$(script/get-crate-version signed)
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=v$VERSION" >> $GITHUB_OUTPUT
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Display artifacts structure
run: |
echo "Artifacts structure:"
find artifacts -type f -exec ls -la {} \;
- name: Create draft release
id: create_release
uses: akkuman/gitea-release-action@v1
with:
server_url: "https://git.reya.su/"
repository: "reya/signed"
token: ${{ secrets.GITEA_TOKEN }}
draft: true
prerelease: false
files: |
artifacts/**/*
- name: Output release info
run: |
echo "Created draft release: ${{ steps.create_release.outputs.url }}"
echo "Release ID: ${{ steps.create_release.outputs.id }}"
+32
View File
@@ -0,0 +1,32 @@
name: Rust
on:
push:
branches: ["**"]
pull_request:
branches: ["m**"]
env:
CARGO_TERM_COLOR: always
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
rustup: [stable]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Install Linux build dependencies
run: chmod +x ./script/linux && ./script/linux
if: matrix.os == 'ubuntu-latest'
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose
+20 -1
View File
@@ -1 +1,20 @@
/target
# Generated by Cargo
# will have compiled files and executables
debug/
target/
dist/
# Snap and Flatpak local build output
/snap
/su.reya.signed.json
/linux-artifacts
# Vendored dependencies + cargo config generated by script/prepare-flathub
.cargo/
vendor/
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
# macOS
.DS_Store
+1 -1
View File
@@ -57,7 +57,7 @@ strip = true
opt-level = "z"
lto = true
codegen-units = 1
panic = "abort"
panic = "unwind"
[profile.profiling]
inherits = "release"
+18
View File
@@ -8,6 +8,24 @@ publish.workspace = true
name = "signed"
path = "src/main.rs"
[package.metadata.packager]
name = "Signed"
product-name = "Signed"
description = "Nostr Git client for browsing repositories and collaborating"
identifier = "su.reya.signed"
category = "DeveloperTool"
version = "0.1.0-alpha"
out-dir = "../dist"
before-packaging-command = "cargo build --release"
resources = ["Cargo.toml", "src"]
icons = [
"resources/32x32.png",
"resources/128x128.png",
"resources/128x128@2x.png",
"resources/icon.icns",
"resources/icon.ico",
]
[dependencies]
assets = { path = "../crates/assets" }
paths = { path = "../crates/paths" }
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,58 @@
{
"id": "$APP_ID",
"runtime": "org.freedesktop.Platform",
"runtime-version": "24.08",
"sdk": "org.freedesktop.Sdk",
"sdk-extensions": ["org.freedesktop.Sdk.Extension.rust-stable"],
"command": "signed",
"finish-args": [
"--talk-name=org.freedesktop.Flatpak",
"--device=dri",
"--share=ipc",
"--share=network",
"--socket=wayland",
"--socket=fallback-x11",
"--socket=pulseaudio",
"--filesystem=host"
],
"build-options": {
"append-path": "/usr/lib/sdk/rust-stable/bin"
},
"modules": [
{
"name": "signed",
"buildsystem": "simple",
"build-options": {
"env": {
"APP_ID": "$APP_ID",
"APP_ICON": "$APP_ID",
"APP_NAME": "$APP_NAME",
"BRANDING_LIGHT": "$BRANDING_LIGHT",
"BRANDING_DARK": "$BRANDING_DARK",
"APP_CLI": "signed",
"APP_ARGS": "--foreground %U",
"DO_STARTUP_NOTIFY": "false"
}
},
"build-commands": [
"install -Dm644 $ICON_FILE.png /app/share/icons/hicolor/512x512/apps/$APP_ID.png",
"envsubst < signed.desktop.in > signed.desktop && install -Dm644 signed.desktop /app/share/applications/$APP_ID.desktop",
"envsubst < flatpak/signed.metainfo.xml.in > signed.metainfo.xml && install -Dm644 signed.metainfo.xml /app/share/metainfo/$APP_ID.metainfo.xml",
"sed -i -e '/@release_info@/{r flatpak/release-info/$CHANNEL' -e 'd}' /app/share/metainfo/$APP_ID.metainfo.xml",
"install -Dm755 bin/signed /app/bin/signed",
"install -Dm755 libexec/signed /app/libexec/signed",
"install -Dm755 lib/* -t /app/lib"
],
"sources": [
{
"type": "archive",
"path": "./target/release/$ARCHIVE"
},
{
"type": "dir",
"path": "./desktop/resources"
}
]
}
]
}
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>$APP_ID</id>
<metadata_license>MIT</metadata_license>
<project_license>GPL-3.0-or-later</project_license>
<name>$APP_NAME</name>
<summary>GPUI desktop Git client</summary>
<developer id="su.reya">
<name translate="no">Ren Amamiya</name>
</developer>
<description>
<p>
Signed is a desktop Git client built with GPUI.
</p>
<p>
Browse repositories and their history, review commits and diffs, and
collaborate through issues, pull requests, and patches.
</p>
</description>
<launchable type="desktop-id">$APP_ID.desktop</launchable>
<branding>
<color type="primary" scheme_preference="light">$BRANDING_LIGHT</color>
<color type="primary" scheme_preference="dark">$BRANDING_DARK</color>
</branding>
<content_rating type="oars-1.1"/>
<url type="homepage">https://git.reya.su/reya/signed</url>
<url type="bugtracker">https://git.reya.su/reya/signed/issues</url>
<url type="faq">https://git.reya.su/reya/signed</url>
<url type="help">https://git.reya.su/reya/signed/issues</url>
<url type="contact">https://reya.su/</url>
<url type="vcs-browser">https://git.reya.su/reya/signed</url>
<recommends>
<control>pointing</control>
<control>keyboard</control>
<display_length compare="ge">768</display_length>
</recommends>
<releases>
@release_info@
<release version="0.0.0" date="1970-01-01">
<description>
<p>Dummy release to keep flatpak-builder AppStream metadata validation from complaining</p>
</description>
</release>
</releases>
</component>
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 258 KiB

+12
View File
@@ -0,0 +1,12 @@
[Desktop Entry]
Version=1.0
Type=Application
Name=$APP_NAME
GenericName=Nostr Git Client
Comment=Nostr Git client for browsing repositories and collaborating
TryExec=$APP_CLI
StartupNotify=$DO_STARTUP_NOTIFY
Exec=$APP_CLI $APP_ARGS
Icon=$APP_ICON
Categories=Development;RevisionControl;
Keywords=git;repository;diff;commit;pull-request;patch;
+57
View File
@@ -0,0 +1,57 @@
name: signed
title: Signed
base: core24
version: "$RELEASE_VERSION"
summary: GPUI desktop Git client for browsing repositories and collaborating
description: |
Browse repositories and their history, review commits and diffs, and
collaborate through issues, pull requests, and patches.
grade: stable
confinement: classic
compression: lzo
website: https://git.reya.su/reya/signed
source-code: https://git.reya.su/reya/signed
issues: https://git.reya.su/reya/signed/issues
contact: https://reya.su
parts:
signed:
plugin: dump
source: target/release/signed-linux-$ARCH_SUFFIX.tar.gz
organize:
# These renames seem to not be necessary, but it's tidier.
bin: usr/bin
libexec: usr/libexec
stage-packages:
- libasound2t64
# snapcraft has a lint that this is unused, but without it Signed exits with
# "Missing Vulkan entry points: LibraryLoadFailure" in blade_graphics.
- libvulkan1
# snapcraft has a lint that this is unused, but without it Signed exits with
# "NoWaylandLib" when run with Wayland.
- libwayland-client0
- libxcb1
- libxkbcommon-x11-0
- libxkbcommon0
build-attributes:
- enable-patchelf
prime:
# Omit unneeded files from the tarball
- -lib
- -licenses.md
- -share
# Omit unneeded files from stage-packages
- -etc
- -usr/share/doc
- -usr/share/lintian
- -usr/share/man
apps:
signed:
command: usr/bin/signed
common-id: su.reya.signed
+14
View File
@@ -0,0 +1,14 @@
# Generated files - do not commit to main repo
# These are generated by script/prepare-flathub
vendor/
vendor.tar.gz
su.reya.signed.yml
su.reya.signed.metainfo.xml
release-info.xml
cargo-config.toml
build/
repo/
# Keep the README and this .gitignore
!README.md
!.gitignore
+129
View File
@@ -0,0 +1,129 @@
# Flathub Submission for Signed
This directory contains the files needed to submit Signed to Flathub.
## Prerequisites
- Flatpak installed
- `flatpak-builder` installed
- Rust/Cargo installed (for vendoring)
## Quick Start
Run the preparation script from the repo root:
```bash
./script/prepare-flathub
```
This will:
1. Vendor all Rust dependencies (crates.io + git)
2. Generate the metainfo.xml with proper release info
3. Create `su.reya.signed.yml` - the Flatpak manifest for Flathub
## Files Generated
| File | Purpose |
|------|---------|
| `su.reya.signed.yml` | Main Flatpak manifest (submit this to Flathub) |
| `su.reya.signed.metainfo.xml` | AppStream metadata with release info |
| `vendor.tar.gz` | Vendored Rust dependencies |
| `cargo-config.toml` | Cargo configuration for offline builds |
| `release-info.xml` | Release info snippet for metainfo |
## Testing Locally
Before submitting to Flathub, test the build:
```bash
cd flathub
# Build and install locally
flatpak-builder --user --install --force-clean build su.reya.signed.yml
# Test the app
flatpak run su.reya.signed
# Run the Flathub linter (must pass!)
flatpak run --command=flatpak-builder-lint org.flatpak.Builder manifest su.reya.signed.yml
flatpak run --command=flatpak-builder-lint org.flatpak.Builder repo repo
```
## Submitting to Flathub
### 1. Prepare Your Release
Ensure you have:
- [ ] Committed all changes
- [ ] Tagged the release: `git tag -a v0.1.0 -m "Release v0.1.0"`
- [ ] Pushed the tag: `git push origin v0.1.0`
- [ ] Run `./script/prepare-flathub` to regenerate files
### 2. Fork and Submit
```bash
# Fork https://github.com/flathub/flathub on GitHub first
# Clone your fork (use the new-pr branch!)
git clone --branch=new-pr git@github.com:YOUR_USERNAME/flathub.git
cd flathub
# Create a new branch
git checkout -b su.reya.signed
# Copy ONLY the manifest file from your project
cp /path/to/signed/flathub/su.reya.signed.yml .
# Commit and push
git add su.reya.signed.yml
git commit -m "Add su.reya.signed"
git push origin su.reya.signed
```
### 3. Open Pull Request
1. Go to your fork on GitHub
2. Click "Compare & pull request"
3. **Important:** Set base branch to `new-pr` (not `master`!)
4. Fill in the PR template
5. Submit and wait for review
## What Happens Next?
1. Flathub's automated CI will build your app
2. A maintainer will review your submission
3. Once approved, a new repo `flathub/su.reya.signed` will be created
4. You'll get write access to maintain the app
5. Future updates: Push new commits to `flathub/su.reya.signed`
## Updating the App
To release a new version:
1. Update version in workspace `Cargo.toml`
2. Tag the new release: `git tag -a v0.1.0 -m "Release v0.1.0"`
3. Push the tag: `git push origin v0.1.0`
4. Run `./script/prepare-flathub` to regenerate
5. Clone the flathub repo: `git clone https://github.com/flathub/su.reya.signed.git`
6. Update the manifest with new commit/tag and hashes
7. Submit PR to `flathub/su.reya.signed`
## Troubleshooting
### Build fails with "network access not allowed"
- Make sure `CARGO_NET_OFFLINE=true` is set in the manifest
- Ensure `vendor.tar.gz` is properly extracted before building
### Linter complains about metainfo
- Ensure `su.reya.signed.metainfo.xml` has at least one `<release>` entry
- Add accessible screenshot URLs if required
### Missing dependencies
- If new git dependencies are added, re-run `script/prepare-flathub`
- The script vendors all dependencies from `Cargo.lock`
## Resources
- [Flathub Submission Docs](https://docs.flathub.org/docs/for-app-authors/submission)
- [Flatpak Manifest Reference](https://docs.flatpak.org/en/latest/manifests.html)
- [AppStream Metainfo Guide](https://www.freedesktop.org/software/appstream/docs/chap-Metadata.html)
+106
View File
@@ -0,0 +1,106 @@
#!/usr/bin/env bash
set -euxo pipefail
# Function for displaying help info
help_info() {
echo "
Usage: ${0##*/}
Build a release .tar.gz for Linux.
"
}
# Parse all arguments manually
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
help_info
exit 0
;;
--)
shift
break
;;
-*)
echo "Unknown option: $1" >&2
help_info
exit 1
;;
*)
echo "Error: Unexpected argument: $1" >&2
help_info
exit 1
;;
esac
done
target_dir="${CARGO_TARGET_DIR:-target}"
version="$(script/get-crate-version signed)"
# Set RELEASE_VERSION so it's compiled into the app and it knows about the version.
export RELEASE_VERSION="${version}"
commit=$(git rev-parse HEAD | cut -c 1-7)
version_info=$(rustc --version --verbose)
host_line=$(echo "$version_info" | grep host)
target_triple=${host_line#*: }
export CC=$(which clang)
# Build binary in release mode
export RUSTFLAGS="${RUSTFLAGS:-} -C link-args=-Wl,--disable-new-dtags,-rpath,\$ORIGIN/../lib"
cargo build --release --target "${target_triple}" --package signed
# Strip debug symbols and save them
objcopy --only-keep-debug "${target_dir}/${target_triple}/release/signed" "${target_dir}/${target_triple}/release/signed.dbg"
objcopy --strip-debug "${target_dir}/${target_triple}/release/signed"
gzip -f "${target_dir}/${target_triple}/release/signed.dbg"
# Move everything that should end up in the final package
# into a temp directory.
temp_dir=$(mktemp -d)
signed_dir="${temp_dir}/signed.app"
# Binary
mkdir -p "${signed_dir}/bin" "${signed_dir}/libexec"
cp "${target_dir}/${target_triple}/release/signed" "${signed_dir}/libexec/signed"
cp "${target_dir}/${target_triple}/release/signed" "${signed_dir}/bin/signed"
# Libs
find_libs() {
ldd ${target_dir}/${target_triple}/release/signed |\
cut -d' ' -f3 |\
grep -v '\<\(libstdc++.so\|libc.so\|libgcc_s.so\|libm.so\|libpthread.so\|libdl.so\|libasound.so\)'
}
mkdir -p "${signed_dir}/lib"
rm -rf "${signed_dir}/lib/*"
cp $(find_libs) "${signed_dir}/lib"
# Icons
mkdir -p "${signed_dir}/share/icons/hicolor/512x512/apps"
cp "desktop/resources/icon.png" "${signed_dir}/share/icons/hicolor/512x512/apps/signed.png"
mkdir -p "${signed_dir}/share/icons/hicolor/1024x1024/apps"
cp "desktop/resources/icon@2x.png" "${signed_dir}/share/icons/hicolor/1024x1024/apps/signed.png"
# .desktop
export DO_STARTUP_NOTIFY="true"
export APP_CLI="signed"
export APP_ICON="signed"
export APP_ARGS="%U"
export APP_NAME="Signed"
mkdir -p "${signed_dir}/share/applications"
envsubst < "desktop/resources/signed.desktop.in" > "${signed_dir}/share/applications/signed.desktop"
# Create archive out of everything that's in the temp directory
arch=$(uname -m)
target="linux-${arch}"
archive="signed-${target}.tar.gz"
rm -rf "${archive}"
remove_match="signed(-[a-zA-Z0-9]+)?-linux-$(uname -m)\.tar\.gz"
ls "${target_dir}/release" | grep -E ${remove_match} | xargs -d "\n" -I {} rm -f "${target_dir}/release/{}" || true
tar -czvf "${target_dir}/release/$archive" -C ${temp_dir} "signed.app"
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# Build the macOS .app/.dmg bundle with cargo-packager.
# Requires macOS. Linux/macOS users building on Windows are unsupported here.
set -euxo pipefail
cd "$(dirname "$0")/../desktop"
if ! command -v cargo-packager >/dev/null 2>&1; then
cargo install cargo-packager --locked
fi
cargo packager --release
+54
View File
@@ -0,0 +1,54 @@
#!/usr/bin/env bash
set -euxo pipefail
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <release_version>"
exit 1
fi
ARCH=$(uname -m)
# Snap uses its own architecture names, which must match the file name and
# the architecture asserted inside the .snap. `x86_64`/`aarch64` here would
# produce a file like signed_1.0.0_x86_64.snap that snapd cannot match.
case "$ARCH" in
x86_64|amd64) ARCH_SUFFIX="amd64" ;;
aarch64|arm64) ARCH_SUFFIX="arm64" ;;
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
esac
# Setup GUI files
mkdir -p snap/gui
export DO_STARTUP_NOTIFY="true"
export APP_NAME="Signed"
export APP_ICON="\${SNAP}/meta/gui/signed.png"
export APP_ARGS="%U"
envsubst < "desktop/resources/signed.desktop.in" > "snap/gui/signed.desktop"
cp "desktop/resources/icon.png" "snap/gui/signed.png"
# Generate snapcraft.yaml with version and architecture
RELEASE_VERSION="$1" ARCH_SUFFIX="$ARCH_SUFFIX" envsubst < desktop/resources/snap/snapcraft.yaml.in > snap/snapcraft.yaml
# Clean previous builds
snapcraft clean
# Build snap with architecture in filename
SNAP_NAME="signed_${1}_${ARCH_SUFFIX}.snap"
snapcraft --destructive-mode --output "$SNAP_NAME"
echo "Created snap package: $SNAP_NAME"
cat <<'EOF'
Install locally (local builds are unsigned, so snapd requires --dangerous; a
plain `snap install ./file.snap` fails with "cannot find signatures with
metadata for snap/component ..."):
sudo snap install --dangerous ./signed_<version>_amd64.snap
Distribute publicly via the Snap Store (signs the snap, users can then run
plain `snap install signed`):
snapcraft login
snapcraft upload ./signed_<version>_amd64.snap
snapcraft release signed <uploaded-revision> stable
EOF
+13
View File
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# Build the Windows .msi/.exe bundles with cargo-packager.
# Requires Windows (MSVC toolchain) - run from Git Bash or MSYS2.
set -euxo pipefail
cd "$(dirname "$0")/../desktop"
if ! command -v cargo-packager >/dev/null 2>&1; then
cargo install cargo-packager --locked
fi
cargo packager --release
+35
View File
@@ -0,0 +1,35 @@
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")/../.."
shopt -s extglob
# Get system architecture
ARCH=$(uname -m)
case "$ARCH" in
x86_64) ARCH_SUFFIX="x86_64" ;;
aarch64) ARCH_SUFFIX="aarch64" ;;
*) echo "Unsupported architecture: $ARCH"; exit 1 ;;
esac
archive_match="signed(-[a-zA-Z0-9]+)?-linux-${ARCH_SUFFIX}\.tar\.gz"
archive=$(ls "target/release" | grep -E ${archive_match})
export ARCHIVE="$archive"
export APP_ID="su.reya.signed"
export APP_NAME="Signed"
export BRANDING_LIGHT="#C6FF4D"
export BRANDING_DARK="#C6FF4D"
export ICON_FILE="icon"
export CHANNEL="stable"
# Generate manifest
envsubst < "desktop/resources/flatpak/manifest-template.json" > "$APP_ID.json"
# Build Flatpak
flatpak-builder --user --install --force-clean build "$APP_ID.json"
# Create bundle with architecture suffix
OUTPUT_FILE="target/release/${APP_ID}_${ARCH_SUFFIX}.flatpak"
flatpak build-bundle ~/.local/share/flatpak/repo "$OUTPUT_FILE" "$APP_ID"
echo "Created '$OUTPUT_FILE'"
+9
View File
@@ -0,0 +1,9 @@
#!/bin/sh
flatpak remote-add --if-not-exists --user flathub https://dl.flathub.org/repo/flathub.flatpakrepo
arch=$(arch)
fd_version=24.08
flatpak install -y --user org.freedesktop.Platform/${arch}/${fd_version}
flatpak install -y --user org.freedesktop.Sdk/${arch}/${fd_version}
flatpak install -y --user org.freedesktop.Sdk.Extension.rust-stable/${arch}/${fd_version}
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -eu
if [[ $# -ne 1 ]]; then
echo "Usage: $0 <crate_name>" >&2
exit 1
fi
CRATE_NAME=$1
cargo metadata \
--no-deps \
--format-version=1 \
| jq \
--raw-output \
".packages[] | select(.name == \"${CRATE_NAME}\") | .version"
Executable
+238
View File
@@ -0,0 +1,238 @@
#!/usr/bin/env bash
set -xeuo pipefail
# if root or if sudo/unavailable, define an empty variable
if [ "$(id -u)" -eq 0 ]
then maysudo=''
else maysudo="$(command -v sudo || command -v doas || true)"
fi
function finalize {
# after packages install (curl, etc), get the rust toolchain
which rustup > /dev/null 2>&1 || curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
# verify the mold situation
if ! command -v mold >/dev/null 2>&1; then
echo "Warning: Mold binaries are unavailable on your system." >&2
echo " Builds will be slower without mold. Try: script/install-mold" >&2
fi
echo "Finished installing Linux dependencies with script/linux"
}
# Ubuntu, Debian, Mint, Kali, Pop!_OS, Raspbian, etc.
apt=$(command -v apt-get || true)
if [[ -n $apt ]]; then
deps=(
gcc
g++
libasound2-dev
libfontconfig-dev
libwayland-dev
libx11-xcb-dev
libxkbcommon-x11-dev
libssl-dev
libzstd-dev
libvulkan1
libgit2-dev
libx11-dev
make
cmake
clang
jq
git
curl
gettext-base
elfutils
musl-tools
musl-dev
build-essential
)
if (grep -qP 'PRETTY_NAME="(Linux Mint 22|.+24\.(04|10))' /etc/os-release); then
deps+=( mold libstdc++-14-dev )
elif (grep -qP 'PRETTY_NAME="((Debian|Raspbian).+12|Linux Mint 21|.+22\.04)' /etc/os-release); then
deps+=( mold libstdc++-12-dev )
elif (grep -qP 'PRETTY_NAME="((Debian|Raspbian).+11|Linux Mint 20|.+20\.04)' /etc/os-release); then
deps+=( libstdc++-10-dev )
fi
$maysudo "$apt" update
$maysudo "$apt" install -y "${deps[@]}"
finalize
exit 0
fi
# Fedora, CentOS, RHEL, Alma, Amazon 2023, Oracle, etc.
dnf=$(command -v dnf || true)
# Old Redhat (yum only): Amazon Linux 2, Oracle Linux 7, etc.
yum=$(command -v yum || true)
if [[ -n $dnf ]] || [[ -n $yum ]]; then
pkg_cmd="${dnf:-${yum}}"
deps=(
musl-gcc
gcc
clang
cmake
alsa-lib-devel
fontconfig-devel
wayland-devel
libxcb-devel
libxkbcommon-x11-devel
openssl-devel
libzstd-devel
vulkan-loader
jq
git
tar
)
# perl used for building openssl-sys crate. See: https://docs.rs/openssl/latest/openssl/
if grep -qP '^ID="?(fedora)' /etc/os-release; then
deps+=(
perl-FindBin
perl-IPC-Cmd
perl-File-Compare
perl-File-Copy
mold
)
elif grep -qP '^ID="?(rhel|rocky|alma|centos|ol)' /etc/os-release; then
deps+=( perl-interpreter )
fi
# gcc-c++ is g++ on RHEL8 and 8.x clones
if grep -qP '^ID="?(rhel|rocky|alma|centos|ol)' /etc/os-release \
&& grep -qP '^VERSION_ID="?(8)' /etc/os-release; then
deps+=( gcc-c++ )
else
deps+=( g++ )
fi
# libxkbcommon-x11-devel is in a non-default repo on RHEL 8.x/9.x (except on AmazonLinux)
if grep -qP '^VERSION_ID="?(8|9)' /etc/os-release && grep -qP '^ID="?(rhel|rocky|centos|alma|ol)' /etc/os-release; then
$maysudo dnf install -y 'dnf-command(config-manager)'
if grep -qP '^PRETTY_NAME="(AlmaLinux 8|Rocky Linux 8)' /etc/os-release; then
$maysudo dnf config-manager --set-enabled powertools
elif grep -qP '^PRETTY_NAME="((AlmaLinux|Rocky|CentOS Stream) 9|Red Hat.+(8|9))' /etc/os-release; then
$maysudo dnf config-manager --set-enabled crb
elif grep -qP '^PRETTY_NAME="Oracle Linux Server 8' /etc/os-release; then
$maysudo dnf config-manager --set-enabled ol8_codeready_builder
elif grep -qP '^PRETTY_NAME="Oracle Linux Server 9' /etc/os-release; then
$maysudo dnf config-manager --set-enabled ol9_codeready_builder
else
echo "Unexpected distro" && grep 'PRETTY_NAME' /etc/os-release && exit 1
fi
fi
$maysudo "$pkg_cmd" install -y "${deps[@]}"
finalize
exit 0
fi
# openSUSE
# https://software.opensuse.org/
zyp=$(command -v zypper || true)
if [[ -n $zyp ]]; then
deps=(
alsa-devel
clang
cmake
fontconfig-devel
gcc
gcc-c++
git
gzip
jq
libvulkan1
libx11-devel
libxcb-devel
libxkbcommon-devel
libxkbcommon-x11-devel
libzstd-devel
make
mold
openssl-devel
tar
wayland-devel
xcb-util-devel
)
$maysudo "$zyp" install -y "${deps[@]}"
finalize
exit 0
fi
# Arch, Manjaro, etc.
# https://archlinux.org/packages
pacman=$(command -v pacman || true)
if [[ -n $pacman ]]; then
deps=(
gcc
clang
musl
cmake
alsa-lib
fontconfig
wayland
libgit2
libxcb
libxkbcommon-x11
openssl
zstd
pkgconf
mold
jq
git
)
$maysudo "$pacman" -Syu --needed --noconfirm "${deps[@]}"
finalize
exit 0
fi
# Void
# https://voidlinux.org/packages/
xbps=$(command -v xbps-install || true)
if [[ -n $xbps ]]; then
deps=(
gettext-devel
clang
cmake
jq
elfutils-devel
gcc
alsa-lib-devel
fontconfig-devel
libxcb-devel
libxkbcommon-devel
libzstd-devel
openssl-devel
wayland-devel
vulkan-loader
mold
)
$maysudo "$xbps" -Syu "${deps[@]}"
finalize
exit 0
fi
# Gentoo
# https://packages.gentoo.org/
emerge=$(command -v emerge || true)
if [[ -n $emerge ]]; then
deps=(
app-arch/zstd
app-misc/jq
dev-libs/openssl
dev-libs/wayland
dev-util/cmake
media-libs/alsa-lib
media-libs/fontconfig
media-libs/vulkan-loader
x11-libs/libxcb
x11-libs/libxkbcommon
sys-devel/mold
)
$maysudo "$emerge" -u "${deps[@]}"
finalize
exit 0
fi
echo "Unsupported Linux distribution in script/linux"
exit 1
Executable
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env bash
set -xeuo pipefail
export HOMEBREW_NO_INSTALL_CLEANUP=1
# if root or if sudo/unavailable, define an empty variable
if [ "$(id -u)" -eq 0 ]
then maysudo=''
else maysudo="$(command -v sudo || command -v doas || true)"
fi
function finalize {
# after packages install (curl, etc), get the rust toolchain
which rustup > /dev/null 2>&1 || curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
# verify the mold situation
if ! command -v mold >/dev/null 2>&1; then
echo "Warning: Mold binaries are unavailable on your system." >&2
echo " Builds will be slower without mold. Try: script/install-mold" >&2
fi
echo "Finished installing MacOS dependencies with script/macos"
}
# MacOS
brew=$(command -v brew || true)
if [[ -n $brew ]]; then
deps=(
gcc
libx11
libxkbcommon
openssl
zstd
vulkan-headers
libgit2
libx11
make
cmake
jq
git
curl
gettext
)
$brew update
for dep in "${deps[@]}";do
$brew search "$dep";
done
$brew install "${deps[@]}"
finalize
exit 0
fi
+246
View File
@@ -0,0 +1,246 @@
#!/usr/bin/env bash
#
# Prepare Flathub submission for Signed
# This script:
# 1. Vendors all Rust dependencies (crates.io + git)
# 2. Generates release info for metainfo.xml
# 3. Creates the Flathub manifest (su.reya.signed.yml)
#
# Usage: ./script/prepare-flathub [--release-date YYYY-MM-DD]
set -euo pipefail
cd "$(dirname "$0")/.."
# Configuration
APP_ID="su.reya.signed"
APP_NAME="Signed"
REPO_URL="https://git.reya.su/reya/signed"
BRANDING_LIGHT="#C6FF4D"
BRANDING_DARK="#C6FF4D"
# Parse arguments
RELEASE_DATE=""
while [[ $# -gt 0 ]]; do
case $1 in
--release-date)
RELEASE_DATE="$2"
shift 2
;;
-h|--help)
echo "Usage: ${0##*/} [options]"
echo ""
echo "Options:"
echo " --release-date DATE Release date in YYYY-MM-DD format (default: today)"
echo " -h, --help Display this help and exit"
exit 0
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done
# Get version from workspace
VERSION=$(script/get-crate-version signed)
if [[ -z "$RELEASE_DATE" ]]; then
RELEASE_DATE=$(date +%Y-%m-%d)
fi
echo "=== Preparing Flathub submission for $APP_NAME v$VERSION ==="
echo ""
# Create flathub directory
mkdir -p flathub
echo "[1/5] Created flathub/ directory"
# Step 2: Vendor all dependencies
echo "[2/5] Vendoring Rust dependencies..."
if [[ -d vendor ]]; then
echo " Removing old vendor directory..."
rm -rf vendor
fi
# Create cargo config for vendoring
mkdir -p .cargo
cat > .cargo/config.toml << 'EOF'
[source.crates-io]
replace-with = "vendored"
[source.vendored]
directory = "vendor"
EOF
# Vendor all dependencies (crates.io + git)
cargo vendor --locked vendor/
echo " Vendored dependencies to vendor/"
# Create tarball of vendored deps
tar -czf flathub/vendor.tar.gz vendor/
echo " Created flathub/vendor.tar.gz"
# Step 3: Generate release info for metainfo
echo "[3/5] Generating release info..."
cat > flathub/release-info.xml << EOF
<release version="${VERSION}" date="${RELEASE_DATE}">
<description>
<p>Release version ${VERSION}</p>
</description>
</release>
EOF
echo " Created flathub/release-info.xml"
# Step 4: Generate the metainfo file with release info
echo "[4/5] Generating metainfo.xml..."
export APP_ID APP_NAME BRANDING_LIGHT BRANDING_DARK
cat desktop/resources/flatpak/signed.metainfo.xml.in | \
sed -e "/@release_info@/r flathub/release-info.xml" -e '/@release_info@/d' \
> flathub/${APP_ID}.metainfo.xml
echo " Created flathub/${APP_ID}.metainfo.xml"
# Step 5: Generate the Flatpak manifest
echo "[5/5] Generating Flatpak manifest..."
# Get current commit hash
COMMIT=$(git rev-parse HEAD)
# Generate the YAML manifest
cat > flathub/${APP_ID}.yml << 'MANIFEST_EOF'
id: su.reya.signed
runtime: org.freedesktop.Platform
runtime-version: "24.08"
sdk: org.freedesktop.Sdk
sdk-extensions:
- org.freedesktop.Sdk.Extension.rust-stable
- org.freedesktop.Sdk.Extension.llvm18
command: signed
finish-args:
- --talk-name=org.freedesktop.Flatpak
- --device=dri
- --share=ipc
- --share=network
- --socket=wayland
- --socket=fallback-x11
- --socket=pulseaudio
- --filesystem=host
build-options:
append-path: /usr/lib/sdk/rust-stable/bin:/usr/lib/sdk/llvm18/bin
env:
CC: clang
CXX: clang++
modules:
- name: signed
buildsystem: simple
build-options:
env:
CARGO_HOME: /run/build/signed/cargo
CARGO_NET_OFFLINE: "true"
RELEASE_VERSION: "@VERSION@"
build-commands:
# Setup vendored dependencies
- mkdir -p .cargo
- cp cargo-config.toml .cargo/config.toml
# Extract vendored deps
- tar -xzf vendor.tar.gz
# Build the project (entire workspace, then install signed binary)
- cargo build --release --offline --package signed
# Install binary
- install -Dm755 target/release/signed /app/bin/signed
# Install icons
- install -Dm644 desktop/resources/icon.png /app/share/icons/hicolor/512x512/apps/su.reya.signed.png
- install -Dm644 desktop/resources/icon@2x.png /app/share/icons/hicolor/1024x1024/apps/su.reya.signed.png
# Install desktop file
- |
export APP_ID="su.reya.signed"
export APP_ICON="su.reya.signed"
export APP_NAME="Signed"
export APP_CLI="signed"
export APP_ARGS="%U"
export DO_STARTUP_NOTIFY="true"
envsubst < desktop/resources/signed.desktop.in > signed.desktop
install -Dm644 signed.desktop /app/share/applications/su.reya.signed.desktop
# Install metainfo (use pre-generated one with release info)
- install -Dm644 su.reya.signed.metainfo.xml /app/share/metainfo/su.reya.signed.metainfo.xml
sources:
# Main source code - specific commit
- type: git
url: https://git.reya.su/reya/signed.git
commit: "@COMMIT@"
tag: "v@VERSION@"
# Vendored dependencies tarball (generated by this script)
- type: file
path: vendor.tar.gz
sha256: "@VENDOR_SHA256@"
# Pre-generated metainfo with release info
- type: file
path: su.reya.signed.metainfo.xml
sha256: "@METAINFO_SHA256@"
# Cargo config for vendoring
- type: file
path: cargo-config.toml
sha256: "@CARGO_CONFIG_SHA256@"
MANIFEST_EOF
# Calculate SHA256 hashes
VENDOR_SHA256=$(sha256sum flathub/vendor.tar.gz | cut -d' ' -f1)
METAINFO_SHA256=$(sha256sum flathub/${APP_ID}.metainfo.xml | cut -d' ' -f1)
# Create cargo-config.toml
mkdir -p flathub
cat > flathub/cargo-config.toml << 'EOF'
[source.crates-io]
replace-with = "vendored"
[source.vendored]
directory = "vendor"
EOF
CARGO_CONFIG_SHA256=$(sha256sum flathub/cargo-config.toml | cut -d' ' -f1)
# Substitute values into the manifest
sed -i.bak \
-e "s/@VERSION@/${VERSION}/g" \
-e "s/@COMMIT@/${COMMIT}/g" \
-e "s/@VENDOR_SHA256@/${VENDOR_SHA256}/g" \
-e "s/@METAINFO_SHA256@/${METAINFO_SHA256}/g" \
-e "s/@CARGO_CONFIG_SHA256@/${CARGO_CONFIG_SHA256}/g" \
flathub/${APP_ID}.yml
rm -f flathub/${APP_ID}.yml.bak
echo " Created flathub/${APP_ID}.yml"
echo ""
echo "=== Flathub preparation complete! ==="
echo ""
echo "Files generated in flathub/:"
echo " - ${APP_ID}.yml # Main Flatpak manifest (submit this to Flathub)"
echo " - ${APP_ID}.metainfo.xml # AppStream metadata with release info"
echo " - vendor.tar.gz # Vendored Rust dependencies"
echo " - cargo-config.toml # Cargo configuration for vendoring"
echo " - release-info.xml # Release info snippet"
echo ""
echo "Next steps:"
echo " 1. Test the build locally:"
echo " cd flathub && flatpak-builder --user --install --force-clean build ${APP_ID}.yml"
echo ""
echo " 2. If build succeeds, submit to Flathub:"
echo " - Fork https://github.com/flathub/flathub"
echo " - Clone: git clone --branch=new-pr git@github.com:YOUR_USERNAME/flathub.git"
echo " - Copy ONLY ${APP_ID}.yml to the repo"
echo " - Submit PR against flathub/flathub:new-pr"
echo ""
echo "Note: Make sure you have:"
echo " - Committed all changes (commit: ${COMMIT})"
echo " - Tagged the release (tag: v${VERSION})"
echo " - Pushed the tag"
Executable
+132
View File
@@ -0,0 +1,132 @@
#!/bin/bash
# Script to release a new version of the application
# Usage: ./release <new_version>
set -e # Exit on any error
if [ $# -ne 1 ]; then
echo "Usage: $0 <new_version>"
echo "Example: $0 1.0.0"
exit 1
fi
NEW_VERSION="$1"
WORKSPACE_CARGO="Cargo.toml"
CRATE_CARGO="desktop/Cargo.toml"
# Check if both Cargo.toml files exist
if [ ! -f "$WORKSPACE_CARGO" ]; then
echo "Error: $WORKSPACE_CARGO not found in current directory"
exit 1
fi
if [ ! -f "$CRATE_CARGO" ]; then
echo "Error: $CRATE_CARGO not found"
exit 1
fi
# Function to update version in a Cargo.toml file
update_version() {
local file="$1"
local backup="${file}.bak"
# Backup the original file
cp "$file" "$backup"
# More flexible regex that handles various version formats and whitespace.
# Note: -i.bak works on both GNU and BSD sed.
if sed -i.bak -E "s/^[[:space:]]*version[[:space:]]*=[[:space:]]*\"[^\"]+\"/version = \"$NEW_VERSION\"/" "$file"; then
echo "✓ Updated version to $NEW_VERSION in $file"
else
echo "Error: Failed to update version in $file"
# Restore original backup
mv "$backup" "$file"
exit 1
fi
# Remove the backup file
rm -f "$backup"
}
# Update both Cargo.toml files
echo "Updating versions..."
update_version "$WORKSPACE_CARGO"
update_version "$CRATE_CARGO"
# Check git status before committing
echo "Checking git status..."
if git status --porcelain | grep -q .; then
echo "Current uncommitted changes:"
git status --short
# Ask user if they want to commit all changes or just version files
echo ""
echo "Do you want to:"
echo "1) Commit all current changes (including the version updates)"
echo "2) Commit only the version file changes"
echo "3) Abort the release"
read -p "Enter choice (1/2/3): " choice
case $choice in
1)
echo "Committing all changes..."
git add .
;;
2)
echo "Committing only version file changes..."
git add "$WORKSPACE_CARGO" "$CRATE_CARGO"
;;
3)
echo "Release aborted by user"
exit 0
;;
*)
echo "Invalid choice. Release aborted."
exit 1
;;
esac
else
# Only version files were modified, add them specifically
echo "Only version files were modified, adding them for commit..."
git add "$WORKSPACE_CARGO" "$CRATE_CARGO"
fi
# Commit the changes
COMMIT_MSG="chore: release version $NEW_VERSION"
if git commit -m "$COMMIT_MSG"; then
echo "✓ Committed version changes"
else
echo "Error: Failed to commit version changes"
exit 1
fi
# Push version changes to origin
echo "Pushing version changes to origin..."
if git push origin master; then
echo "✓ Successfully pushed version changes to origin"
else
echo "Error: Failed to push version changes to origin"
exit 1
fi
# Create git tag
TAG_NAME="v$NEW_VERSION"
if git tag -a "$TAG_NAME" -m "$COMMIT_MSG"; then
echo "✓ Created git tag: $TAG_NAME"
else
echo "Error: Failed to create git tag"
exit 1
fi
# Push tag to origin
echo "Pushing tag to origin..."
if git push origin "$TAG_NAME"; then
echo "✓ Successfully pushed tag to origin"
echo "✓ Release $NEW_VERSION completed successfully!"
else
echo "Error: Failed to push tag to origin"
exit 1
fi
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
# This script is intended to be run after `script/bundle-snap`.
#
# It expects a version to be passed as the first argument, and expects the
# built `.snap` for that version to be in the current directory. bundle-snap
# names it `signed_<version>_amd64.snap` (Snap's canonical amd64/arm64 naming).
#
# This will uninstall the current `signed` snap, replacing it with a snap
# that directly uses the `snap/unpacked` directory.
set -euxo pipefail
if [ "$#" -ne 1 ]; then
echo "Usage: $0 <release_version>"
exit 1
fi
# Rerun as root
[ "$UID" -eq 0 ] || exec sudo bash -e "$0" "$@"
snap remove signed || true
mkdir -p snap
rm -rf snap/unpacked
unsquashfs -dest snap/unpacked "signed_$1_amd64.snap"
snap try --classic snap/unpacked