Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/actions/linux-package-disk/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Disk for a Linux package build
description: Removes the preinstalled toolchains a package build never uses, and moves Docker to the larger disk.

runs:
using: composite
steps:
- name: Make room for the package build
shell: bash
# A package build peaks at about 46 GB, its tests building the workspace and DuckDB a second time,
# and some hosted runners have less left on the root disk beside the toolchains removed here.
run: |
set -euo pipefail
df -h / /mnt 2> /dev/null || true
sudo docker image prune --all --force > /dev/null
sudo rm -rf /usr/local/lib/android /usr/share/dotnet /opt/ghc /usr/local/.ghcup /usr/share/swift \
/opt/hostedtoolcache /usr/local/share/boost /usr/local/share/powershell /usr/local/share/chromium \
/usr/lib/jvm /opt/microsoft /opt/google /opt/az
available() { df -Pk "$1" | awk 'NR == 2 { print $4 }'; }
if [ -d /mnt ] && [ "$(available /mnt)" -gt "$(available /)" ]; then
sudo systemctl stop docker.socket docker.service
sudo mkdir -p /mnt/docker /etc/docker
if [ -s /etc/docker/daemon.json ]; then
jq '. + {"data-root": "/mnt/docker"}' /etc/docker/daemon.json > "$RUNNER_TEMP/daemon.json"
else
echo '{"data-root": "/mnt/docker"}' > "$RUNNER_TEMP/daemon.json"
fi
sudo cp "$RUNNER_TEMP/daemon.json" /etc/docker/daemon.json
sudo systemctl start docker.service
echo "Docker keeps its data on /mnt"
fi
df -h / /mnt 2> /dev/null || true
docker info --format 'Docker root: {{.DockerRootDir}}'
45 changes: 45 additions & 0 deletions .github/workflows/build-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,48 @@ jobs:
"cargo-$RUST_VERSION" check --workspace --all-targets --locked
"cargo-$RUST_VERSION" check --workspace --all-targets --locked --no-default-features

# Every other job builds from paths without a space. Meson hands each path
# to the build as one argument (build-aux/cargo-build.sh), and this checks
# it with a source, build and install directory that each hold one.
spaced-paths:
name: Build from paths with spaces
# Only in this workflow's own nightly or manual run, to keep a CI run under GitHub Free's 20
# concurrent jobs. A called workflow sees the caller's github context, so from CI this is "CI".
if: ${{ github.workflow == 'Build Linux' }}
runs-on: ubuntu-24.04
timeout-minutes: 120
container:
image: ubuntu:26.04
env:
DEBIAN_FRONTEND: noninteractive
# The runner passes a step's working directory to docker exec unquoted,
# so each step changes into the source tree itself.
steps:
- name: Install git and the build dependencies
run: |
apt-get update
apt-get install -y --no-install-recommends \
ca-certificates git curl build-essential pkgconf meson ninja-build gettext \
desktop-file-utils appstream libglib2.0-bin libxml2-utils \
libgtk-4-dev libadwaita-1-dev libgtksourceview-5-dev \
libsqlite3-dev libkrb5-dev liblcms2-dev libseccomp-dev clang libclang-dev
git config --global --add safe.directory "$GITHUB_WORKSPACE/source tree"
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
path: source tree
- uses: dtolnay/rust-toolchain@683b588c487a69d01f6c6ddf40f036ff682cc2c8 # master
with:
toolchain: "1.98"
- name: Build and install both executables
run: |
cd "source tree/linux"
meson setup "build dir" -Dprofile=development
meson compile -C "build dir"
DESTDIR="$PWD/install root" meson install -C "build dir" --no-rebuild
test -x "install root/usr/local/bin/tablepro"
test -x "install root/usr/local/libexec/tablepro-askpass"

supply-chain:
name: Supply chain
if: ${{ !inputs.docs-only }}
Expand Down Expand Up @@ -458,6 +500,9 @@ jobs:
- package: tablepro-driver-postgres
release: postgres-14
postgres: "14"
- package: tablepro-driver-postgres
release: postgres-15
postgres: "15"
- package: tablepro-driver-postgres
release: postgres-18
postgres: "18"
Expand Down
37 changes: 25 additions & 12 deletions .github/workflows/linux-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ name: Linux packages
# The Debian source package is built once for each Ubuntu series the PPA
# builds for, and its binaries are built from it the way Launchpad builds
# them: offline, in a fresh container with only the declared build
# dependencies, then checked with lintian. The .rpm is built in a fresh
# fedora:44 with only its BuildRequires. Each package is then installed in
# another fresh container with only its runtime dependencies and started.
# dependencies, then checked with lintian. The .rpm is built in Mock, as
# COPR builds it, for each Fedora release COPR builds for: the BuildRequires
# go into a fresh chroot, then the build runs there with no network, then
# rpmlint. Each package is then installed in another fresh container of its
# release with only its runtime dependencies and started.
# release-linux.yml calls this workflow and uploads the source packages.
# A run by hand can add arm64, which the nightly and pull requests leave out.
# Given a release tag, it packages that release's tarballs instead, with
Expand All @@ -28,6 +30,7 @@ on:
- "linux/po/meson.build"
- "linux/po/LINGUAS"
- ".github/workflows/linux-packages.yml"
- ".github/actions/linux-package-disk/**"
# Nightly on main, so a failure only one distribution's build shows turns
# up before tag time. Three hours after build-linux.yml's nightly, so the
# two do not share the account's 20 concurrent jobs.
Expand Down Expand Up @@ -158,6 +161,7 @@ jobs:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/linux-package-disk
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: linux-source-package
Expand Down Expand Up @@ -196,65 +200,74 @@ jobs:
if-no-files-found: error

rpm:
name: RPM package (${{ matrix.runner }})
name: RPM package (Fedora ${{ matrix.fedora }}, ${{ matrix.runner }})
needs: sources
if: inputs.release-tag == ''
strategy:
fail-fast: false
matrix:
runner: ${{ fromJSON(inputs.rpm-runners || (inputs.arm64 && '["ubuntu-24.04", "ubuntu-24.04-arm"]') || '["ubuntu-24.04"]') }}
# Every Fedora release the COPR project builds for.
fedora: ["44", "45"]
runs-on: ${{ matrix.runner }}
timeout-minutes: 300
container:
image: fedora:44
# On the runner itself, so the build's container can go on the larger
# disk. It is privileged, since Mock mounts the chroot's filesystems and
# build-rpm.sh unshares the network for the build.
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: ./.github/actions/linux-package-disk
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: linux-sources
path: _packages/sources
- name: Build, test and lint the package
env:
FEDORA: ${{ matrix.fedora }}
run: |
dist="$(find _packages/sources -name 'tablepro-*.tar.xz' ! -name '*-vendor.tar.xz')"
vendor="$(find _packages/sources -name 'tablepro-*-vendor.tar.xz')"
linux/build-aux/packaging/build-rpm.sh "$dist" "$vendor" _packages/rpm
docker run --rm --privileged -v "$PWD:$PWD" -w "$PWD" "fedora:$FEDORA" \
linux/build-aux/packaging/build-rpm.sh "$dist" "$vendor" _packages/rpm
- name: Keep the RPM failure logs
if: failure()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: linux-rpm-testlog-${{ runner.arch }}
name: linux-rpm-testlog-${{ matrix.fedora }}-${{ runner.arch }}
path: |
_packages/rpm/testlog.txt
_packages/rpm/build.log
_packages/rpm/disk-usage.tsv
_packages/rpm/disk-usage.txt
if-no-files-found: ignore
retention-days: 7
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: linux-rpm-${{ runner.arch }}
name: linux-rpm-${{ matrix.fedora }}-${{ runner.arch }}
path: _packages/rpm
if-no-files-found: error

rpm-install:
name: Install the RPM package (${{ matrix.runner }})
name: Install the RPM package (Fedora ${{ matrix.fedora }}, ${{ matrix.runner }})
needs: rpm
strategy:
fail-fast: false
matrix:
runner: ${{ fromJSON(inputs.rpm-runners || (inputs.arm64 && '["ubuntu-24.04", "ubuntu-24.04-arm"]') || '["ubuntu-24.04"]') }}
fedora: ["44", "45"]
runs-on: ${{ matrix.runner }}
timeout-minutes: 20
container:
image: fedora:44
image: fedora:${{ matrix.fedora }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: linux-rpm-${{ runner.arch }}
name: linux-rpm-${{ matrix.fedora }}-${{ runner.arch }}
path: _packages/rpm
- name: Install, start and validate
run: |
Expand Down
4 changes: 4 additions & 0 deletions core/crates/test-fixtures/src/fixture_image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ impl FixtureImage {
name: "postgres",
tag: "14-alpine",
};
pub const POSTGRES_15: Self = Self {
name: "postgres",
tag: "15-alpine",
};
pub const POSTGRES_18: Self = Self {
name: "postgres",
tag: "18-alpine",
Expand Down
6 changes: 5 additions & 1 deletion core/crates/test-fixtures/src/postgres_version.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::{FixtureImage, ServerVersion};
pub enum PostgresVersion {
V13,
V14,
V15,
#[default]
V17,
V18,
Expand All @@ -18,6 +19,7 @@ impl PostgresVersion {
match self {
Self::V13 => 13,
Self::V14 => 14,
Self::V15 => 15,
Self::V17 => 17,
Self::V18 => 18,
}
Expand All @@ -26,12 +28,13 @@ impl PostgresVersion {

impl ServerVersion for PostgresVersion {
const VARIABLE: &'static str = "TABLEPRO_TEST_POSTGRES";
const ALL: &'static [Self] = &[Self::V13, Self::V14, Self::V17, Self::V18];
const ALL: &'static [Self] = &[Self::V13, Self::V14, Self::V15, Self::V17, Self::V18];

fn name(self) -> &'static str {
match self {
Self::V13 => "13",
Self::V14 => "14",
Self::V15 => "15",
Self::V17 => "17",
Self::V18 => "18",
}
Expand All @@ -41,6 +44,7 @@ impl ServerVersion for PostgresVersion {
match self {
Self::V13 => FixtureImage::POSTGRES_13,
Self::V14 => FixtureImage::POSTGRES_14,
Self::V15 => FixtureImage::POSTGRES_15,
Self::V17 => FixtureImage::POSTGRES,
Self::V18 => FixtureImage::POSTGRES_18,
}
Expand Down
2 changes: 1 addition & 1 deletion linux/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ meson setup _build -Dprofile=development
meson compile -C _build # builds tablepro and tablepro-askpass
meson test -C _build # unit, gtk, data and packaging suites
meson devenv -C _build ./crates/app/tablepro # run the app
meson devenv -C _build cargo test --workspace --exclude tablepro --exclude tablepro-ffi # the unit suite
meson devenv -C _build cargo test --workspace --exclude tablepro --exclude tablepro-ffi --exclude tablepro-bindgen # the unit suite
GTK_A11Y=test GSK_RENDERER=cairo GDK_BACKEND=x11 meson devenv -C _build cargo test -p tablepro # the app's tests
cargo fmt --all # format
```
Expand Down
26 changes: 14 additions & 12 deletions linux/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ TablePro supports the server releases their vendors still support. CI runs each

| Engine | Tested releases | Not supported |
|---|---|---|
| PostgreSQL | 14, 17 and 18 | 13 and older, past end of life (13 on 2025-11-13). 19 until it is released |
| PostgreSQL | 14, 15, 17 and 18 | 13 and older, past end of life (13 on 2025-11-13). 19 until it is released |
| MySQL | 8.0, 8.4 and 9.7 | 8.1 to 9.6, innovation releases past end of life. 5.7 and older |
| MariaDB | 10.11, 11.4 and 12.3 | 10.6 and older, past end of life (10.6 on 2026-07-06). Rolling releases such as 13.0 |
| SQL Server | 2017, 2019, 2022 and 2025 | 2016 and older, past extended support (2016 on 2026-07-14) |
Expand All @@ -24,9 +24,9 @@ TablePro supports the server releases their vendors still support. CI runs each
| Redis | 7.4 and 8.10 | 7.2 and older, past end of life. Cluster and Sentinel deployments. Valkey answers the same commands and is not tested |
| MongoDB | 7.0 and 8.0 | 6.0 and older, past end of life (6.0 on 2025-07-31). Minor releases between major ones, such as 8.2, are not tested. A sharded cluster is reached through `mongos` and is not tested |

- PostgreSQL 14 reaches end of life on 2026-11-12.
- PostgreSQL 14 reaches end of life on 2026-11-12, and 15, the oldest release after it, is tested already.
- MySQL 8.0 reached end of life on 2026-04-30, but Amazon RDS keeps 8.0 instances under paid Extended Support until 2029-07-31, so it stays tested.
- MariaDB 11.8, PostgreSQL 15 and 16, and Cassandra 4.1 are supported between the tested releases, which bound them.
- MariaDB 11.8, PostgreSQL 16 and Cassandra 4.1 are supported between the tested releases, which bound them.

## Install

Expand Down Expand Up @@ -84,10 +84,10 @@ TablePro makes no network requests of its own: no telemetry, no update check and
System dependencies:

```bash
# Ubuntu 26.04
# Ubuntu 26.04 and 26.10
sudo apt install -y build-essential pkgconf meson ninja-build gettext desktop-file-utils appstream libglib2.0-bin libxml2-utils libgtk-4-dev libadwaita-1-dev libgtksourceview-5-dev libsqlite3-dev libkrb5-dev liblcms2-dev libseccomp-dev clang libclang-dev openssh-client

# Fedora 44
# Fedora 44 and 45
sudo dnf install -y gcc gcc-c++ pkgconf meson ninja-build gettext desktop-file-utils appstream glib2-devel libxml2 gtk4-devel libadwaita-devel gtksourceview5-devel sqlite-devel krb5-devel lcms2-devel libseccomp-devel clang-devel openssh-clients

# Arch (not covered by CI)
Expand All @@ -102,11 +102,11 @@ test, gnome-keyring for the Secret Service tests and the glycin loaders
for the Row Details picture tests.

```bash
# Ubuntu 26.04
# Ubuntu 26.04 and 26.10
sudo apt install -y xvfb xauth dbus-daemon adwaita-icon-theme locales gnome-keyring glycin-loaders
sudo localedef -i en_US -f UTF-8 en_US.UTF-8

# Fedora 44
# Fedora 44 and 45
sudo dnf install -y xorg-x11-server-Xvfb xorg-x11-xauth dbus-daemon adwaita-icon-theme glibc-langpack-en gnome-keyring glycin-loaders
```

Expand Down Expand Up @@ -227,11 +227,13 @@ build-aux/packaging/build-packages.sh all _packages

It writes the source and vendor tarballs, the Debian source package and
its .deb built offline as Launchpad builds it (checked by lintian), and
the RPMs (checked by rpmlint) under `_packages`, then installs each
package in a fresh container and starts it. `deb` or `rpm` in place of
`all` builds one, and Ubuntu series names after the output directory
replace the default `resolute`. The source tarball archives `HEAD`, so
commit first.
the RPMs built offline in Mock as COPR builds them (checked by rpmlint)
under `_packages`, then installs each package in a fresh container and
starts it. `deb` or `rpm` in place of `all` builds one, Ubuntu series
names after the output directory replace the default `resolute`, and
`FEDORA` picks the Fedora release, 44 by default. The RPM build runs in a
privileged container, since Mock mounts filesystems. The source tarball
archives `HEAD`, so commit first.

After a change to `Cargo.lock`, `build-aux/update-third-party-licenses.sh`
rewrites `debian/copyright` and the spec's `License` tag along with
Expand Down
2 changes: 1 addition & 1 deletion linux/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ The app runs on GNOME 50 ([ADR 0015](docs/decisions/0015-gnome-50-platform-floor
| Capability | Detail |
|---|---|
| Flatpak | The Devel manifest builds on GNOME 51 for x86_64 and aarch64 with every Meson suite in the sandbox, and is linted, in the nightly Linux run |
| .deb and .rpm | Ubuntu 26.04 and 26.10 and Fedora 44, built offline in CI the way Launchpad and COPR build them, linted, then installed and started in fresh containers; a `linux-v*` tag uploads to the PPA and starts the COPR build ([ADR 0018](docs/decisions/0018-ppa-copr-and-flathub-later.md)) |
| .deb and .rpm | Ubuntu 26.04 and 26.10 and Fedora 44 and 45, built offline in CI the way Launchpad and COPR build them, linted, then installed and started in fresh containers; a `linux-v*` tag uploads to the PPA and starts the COPR build ([ADR 0018](docs/decisions/0018-ppa-copr-and-flathub-later.md)) |
| Desktop integration | Desktop file with Open With for SQLite files, D-Bus activation, a man page, metainfo with screenshots, and SVG icons |
| Translations | Vietnamese ships. The app's own strings go through gettext, and CI fails when `POTFILES.in` is stale or a translation loses a placeholder. CI builds the template with gettext 1.0 and publishes it from main and with each release; translators send pull requests against `po/*.po` ([po/README.md](po/README.md#where-translators-work)) |
| Logs | stderr, which the session journals, with JSON lines on request. A panic also writes a crash report under `$XDG_STATE_HOME`, offered with Show Report on the next launch |
Expand Down
25 changes: 25 additions & 0 deletions linux/build-aux/cargo-build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/sh
# Runs Cargo, then copies each file it built to the output Meson declared.
# Every path is one argument, so a source or build directory may hold spaces.
# Usage: cargo-build.sh <built file> <output> [<built file> <output>]... -- <cargo> <argument>...
set -eu

skip=0
found=false
for argument in "$@"; do
skip=$((skip + 1))
if [ "$argument" = -- ]; then
found=true
break
fi
done
if [ "$found" = false ] || [ $(((skip - 1) % 2)) -ne 0 ]; then
echo "usage: cargo-build.sh <built file> <output>... -- <cargo> <argument>..." >&2
exit 2
fi

(shift "$skip" && exec "$@")
while [ "$1" != -- ]; do
cp "$1" "$2"
shift 2
done
5 changes: 5 additions & 0 deletions linux/build-aux/debian/rules
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ export CARGO_PROFILE_RELEASE_DEBUG = line-tables-only
# what DuckDB's C++ build writes and the memory each of its translation
# units takes; rustc links without -flto, so their GIMPLE half goes unused.
export DEB_BUILD_MAINT_OPTIONS = hardening=+all optimize=-lto
# DuckDB's C++ builds once for the package and once for its tests, and
# with full DWARF its objects and archives filled the builder's disk. -g1
# keeps the line tables the dbgsym package needs, as the .rpm does.
export DEB_CFLAGS_MAINT_APPEND = -g1
export DEB_CXXFLAGS_MAINT_APPEND = -g1

# The tarball holds the repository's layout: the Meson project is linux/,
# and the Cargo workspace and vendor/ are at the top.
Expand Down
Loading
Loading