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
2 changes: 1 addition & 1 deletion .claude/rules/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
paths:
- "**/CHANGELOG.md"
- "**/changelog.d/**/*"
- "towncrier.toml"
- "**/towncrier.toml"
---

# Changelog
Expand Down
2 changes: 1 addition & 1 deletion .claude/rules/ci.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ The required check names are in `AGENTS.md` (CI). Reading a red check: `.claude/
- `shellcheck --severity=warning` on every `*.sh` under `scripts` and `.claude/skills`;
- the tooling tests: `scripts/ci/test_*.py`, `scripts/lib/test_*.py`, `scripts/test_localization.py` and `scripts/ci/test_libs_release.sh`;
- `scripts/release/test_*.py` on Python 3.9 from `actions/setup-python`, in a venv that installs `scripts/release/requirements.txt` with `pip --require-hashes`;
- in the same venv, `check-changelog.py` and `towncrier build --draft --version 0.0.0`, which fails on a fragment name it cannot parse;
- in the same venv, `check-changelog.py` and `towncrier build --draft --version 0.0.0` for the root and `--dir linux`, which fails on a fragment name it cannot parse;
- `check-lib-sourcing.py`, `check-plugin-manifest.py`, `check-plugin-provides.py`, `check-deployment-target.sh`, `check-ios-shared-isolation.py`;
- `localization.py plugins` and `plugins --target ios`;
- `check-string-catalogs.py`, `check-license-inventory.py`, `check-entitlements.py`, `check-test-plans.py`;
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/fix-issue/references/platform-linux.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ Run the app from the tree with `meson devenv -C _build ./crates/app/tablepro` in

## Ship

- A user-visible change gets one fragment under `[Unreleased]` in `linux/CHANGELOG.md`, never in the root `CHANGELOG.md`, which is the macOS release notes.
- A user-visible change gets one fragment in `linux/changelog.d/` (`.claude/rules/changelog.md`), never in the root `changelog.d/`, which is the macOS release notes.
- Commit scope `linux`, or `linux-<area>` for one area of the app.
- A probe worth keeping becomes a test in the crate it measures; the Linux workspace keeps no separate probe directory.
2 changes: 1 addition & 1 deletion .github/workflows/build-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ jobs:
run: |
# The $0 in the awk program is awk's record, not a shell variable.
# shellcheck disable=SC2016
found=$(find crates/app/src/ui -name '*.rs' ! -name tests.rs -print0 \
found=$(find crates/app/src/ui -name '*.rs' ! -name tests.rs ! -path '*/tests/*' -print0 \
| xargs -0 awk '/^mod tests \{/ { nextfile } /std::fs::/ || /\.(exists|try_exists|is_dir|is_file|is_symlink|canonicalize|read_dir|read_link|symlink_metadata)\(/ || (/_blocking\(/ && !/spawn_blocking_task\(/) { print FILENAME ":" FNR ": " $0 }')
if [ -n "$found" ]; then
echo "$found"
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/repo-hygiene.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ jobs:
set -euo pipefail
"$RUNNER_TEMP/release-venv/bin/python" scripts/ci/check-changelog.py
"$RUNNER_TEMP/release-venv/bin/towncrier" build --draft --version 0.0.0
"$RUNNER_TEMP/release-venv/bin/towncrier" build --draft --dir linux --version 0.0.0

# shellcheck cannot tell a library function from a command, so a missing source is exit 127
# at release time (v0.67.1).
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ Derived/

# towncrier venv for scripts/release/notes.py (RELEASING.md, Notes)
/.venv/
__pycache__/

# Static libraries (downloaded from GitHub Releases via scripts/download-libs.sh)
Libs/*.a
Expand Down
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Every capability is core, a module or a plugin. The first rule that fits decides
- Tests: `TableProTests/`, `TableProUITests/`, `Plugins/*Tests/`, `Packages/*/Tests/`, `TableProMobile/TableProMobileTests/`; plans in `TestPlans/`. Which holds what: `.claude/rules/tests.md`.
- `Native/`: first-party Rust and Go bridges (`.claude/rules/native-bridges.md`).
- `Libs/`: static libraries and iOS xcframeworks from `scripts/download-libs.sh`, not in git.
- `linux/`: the Linux app, a GTK 4 app built with Meson and Cargo.
- `linux/`: the GTK 4 Linux app, built with Meson and Cargo.
- Docs site: TableProApp/docs, cloned beside this repo as `../tablepro-docs`, under its own `AGENTS.md` and `STYLE.md`.
- `TablePro.xcodeproj` and `TableProMobile/TableProMobile.xcodeproj` are generated by XcodeGen from their `project.yml`, gitignored except their `Package.resolved`; never hand-edit them. Signing overrides go in `Configs/Secrets.xcconfig`.

Expand Down Expand Up @@ -130,7 +130,7 @@ Claude Code loads a rule when it reads or edits a file the rule covers. Under Co
| Rule | Read before editing |
| --- | --- |
| `ai-mcp-security.md` | `TablePro/Core/AI`, `TablePro/Core/MCP`, `Packages/TableProMacCore/Sources/TableProMCP` |
| `changelog.md` | `**/CHANGELOG.md`, `**/changelog.d`, `towncrier.toml` |
| `changelog.md` | `**/CHANGELOG.md`, `**/changelog.d`, `**/towncrier.toml` |
| `ci.md` | `.github/workflows`, `.github/actions`, `.github/actionlint.yaml`, `.github/*baseline*`, `scripts/ci`, `scripts/release`, `.swiftlint.yml`, `**/.swiftlint.yml` |
| `connection-window.md` | `TablePro/Core/Services/Infrastructure`, `TablePro/Models/Connection`, `TablePro/Core/Database/DatabaseManager*.swift`, `Packages/TableProCore/Sources/TableProDatabase`, `TablePro/Views/Main` |
| `data-grid.md` | `TablePro/Views/Results`, `TablePro/Core/DataGrid`, `TableProTests/Views/Results` |
Expand Down
4 changes: 2 additions & 2 deletions linux/build-aux/debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ Build-Depends:
Standards-Version: 4.7.3
Rules-Requires-Root: no
Homepage: https://tablepro.app
Vcs-Browser: https://github.com/TableProApp/TablePro/tree/linux/linux/build-aux/debian
Vcs-Git: https://github.com/TableProApp/TablePro.git -b linux [linux/build-aux]
Vcs-Browser: https://github.com/TableProApp/TablePro/tree/main/linux/build-aux/debian
Vcs-Git: https://github.com/TableProApp/TablePro.git -b main [linux/build-aux]

Package: tablepro
Architecture: amd64 arm64
Expand Down
2 changes: 2 additions & 0 deletions linux/build-aux/flatpak/app.tablepro.TablePro.Devel.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
"skip": [
".flatpak-builder",
"_build",
"_flatpak",
"_packages",
"flatpak_app",
"repo",
"target",
Expand Down
4 changes: 0 additions & 4 deletions linux/crates/app/src/ui/browse_tab/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ mod edit_input;
mod fetch;
mod imp;
mod layout;
#[cfg(test)]
mod load_tests;
mod page_label;
mod page_reply;
mod page_state;
Expand All @@ -49,8 +47,6 @@ mod selection_input;
mod selection_snapshot;
#[cfg(test)]
mod tests;
#[cfg(test)]
mod total_tests;

use std::cell::Cell;
use std::collections::{BTreeSet, VecDeque};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ use libadwaita as adw;
use tablepro_core::{ColumnInfo, DriverError, LossPhase, QueryResult, Value};
use tablepro_test_support::{CallCounters, FakeReply};

use super::tests::{
use super::super::{ClipboardInput, PagingInput};
use super::{
Harness, Shown, WAIT, column, column_view, delete_action, full_page, header_titles, key, not_null_name, rows,
serving_table, text, toasts,
};
use super::{ClipboardInput, PagingInput};
use crate::test_support::{after_next_frame, drain_main_context, wait_until};
use crate::ui::grid::GridCell;

Expand Down Expand Up @@ -245,7 +245,7 @@ fn a_selection_is_not_put_back_after_a_failed_refresh() {
/// follows it hands the focus the rows had to Try Again.
#[gtk4::test]
fn a_failed_page_turn_hands_the_focus_to_try_again() {
let mut script = super::tests::paging(full_page(0), rows(&["unused"]));
let mut script = super::paging(full_page(0), rows(&["unused"]));
script.query_bound = Default::default();
script
.query_bound
Expand Down Expand Up @@ -531,7 +531,7 @@ fn a_failed_column_read_leaves_no_read_for_a_later_one_to_start() {
);
}

fn copy_rows_action(tab: &super::BrowseTab) -> gtk4::gio::SimpleAction {
fn copy_rows_action(tab: &super::super::BrowseTab) -> gtk4::gio::SimpleAction {
use gtk4::subclass::prelude::ObjectSubclassIsExt;
tab.imp()
.model
Expand All @@ -554,8 +554,8 @@ fn the_loading_page_names_a_table_with_an_ampersand() {
outcome: Ok(rows(&["late"])),
});
let fake = crate::test_support::FakeSession::start(script, [], runtime.tasks());
let stores = super::tests::TabStores::new();
let tab = super::tests::table_tab(
let stores = super::TabStores::new();
let tab = super::table_tab(
&fake.session,
&runtime,
&stores,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
mod load;
mod total;

use std::sync::Arc;
use std::time::Duration;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ use tablepro_core::{DriverError, TimeoutPhase};
use tablepro_session::fakes::FakeEstablish;
use tablepro_test_support::{CallCounters, ConnectionScript, FakeReply};

use super::tests::{
use super::super::{PagingInput, SaveInput};
use super::{
Harness, LogLines, WAIT, estimate, full_page, not_null, not_null_name, paging, rows, rows_from, serving_table, text,
};
use super::{PagingInput, SaveInput};
use crate::services::change_origins::ChangeOrigins;
use crate::test_support::{drain_main_context, wait_until};

Expand Down
4 changes: 0 additions & 4 deletions linux/crates/app/src/ui/session_window/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@ mod imp;
mod locate_file;
mod notification_request;
mod notification_sink;
#[cfg(test)]
mod notification_tests;
mod notifications;
#[cfg(test)]
mod open_file_tests;
mod picker_page;
mod resolve_file_identity;
mod secret_retry;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
mod notification;
mod open_file;

use std::rc::Rc;
use std::sync::Arc;
use std::time::Duration;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ use tablepro_core::{DriverError, EditorSession, Value, WriteKind, WriteReport};
use tablepro_test_support::{FakeEditorSession, FakeReply, FakeRun, Replies};
use uuid::Uuid;

use super::SessionWindowInput;
use super::application_notification_sink::ApplicationNotificationSink;
use super::notification_request::NotificationRequest;
use super::tests::{TestWindow, WAIT, editors};
use super::work_notifier::tests::{Notice, RecordingNotificationSink};
use super::super::SessionWindowInput;
use super::super::application_notification_sink::ApplicationNotificationSink;
use super::super::notification_request::NotificationRequest;
use super::super::work_notifier::tests::{Notice, RecordingNotificationSink};
use super::{TestWindow, WAIT, editors};
use crate::runtime::DeliverInput;
use crate::services::change_origins::ChangeOrigins;
use crate::services::change_tracker::RowKey;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

use gtk4::prelude::*;

use super::tests::{TestWindow, WAIT};
use super::*;
use super::super::*;
use super::{TestWindow, WAIT};
use crate::test_support::wait_until;

/// An empty file, which SQLite reads as an empty database.
Expand Down
12 changes: 6 additions & 6 deletions linux/docs/regression-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ Kinds: `unit` runs in the Meson unit suite, `gtk` in the gtk suite, `docker` in
| F-001 | docker | `f001_read_only_insert_164` | [crates/drivers/clickhouse/tests/integration/writes.rs](../crates/drivers/clickhouse/tests/integration/writes.rs) |
| F-002 | unit | `f002_accepts_only_latest_generation` | [crates/session/src/connect/connect_attempts.rs](../crates/session/src/connect/connect_attempts.rs) |
| F-002 | unit | `f002_late_reconnect_after_cancel_is_discarded_and_closed` | [crates/session/src/health/health_monitor.rs](../crates/session/src/health/health_monitor.rs) |
| F-002 | gtk | `f002_cancel_connect_discards_late_attempt` | [crates/app/src/ui/session_window/tests.rs](../crates/app/src/ui/session_window/tests.rs) |
| F-002 | gtk | `f002_late_show_create_reply_after_disconnect_is_dropped` | [crates/app/src/ui/session_window/tests.rs](../crates/app/src/ui/session_window/tests.rs) |
| F-002 | gtk | `f002_cancel_connect_discards_late_attempt` | [crates/app/src/ui/session_window/tests/mod.rs](../crates/app/src/ui/session_window/tests/mod.rs) |
| F-002 | gtk | `f002_late_show_create_reply_after_disconnect_is_dropped` | [crates/app/src/ui/session_window/tests/mod.rs](../crates/app/src/ui/session_window/tests/mod.rs) |
| F-002 | gtk | `f002_a_late_catalog_commit_after_the_watch_drops_is_not_delivered` | [crates/app/src/ui/workspace/sidebar/catalog_watch.rs](../crates/app/src/ui/workspace/sidebar/catalog_watch.rs) |
| F-003 | unit | `f003_truncated_file_is_unavailable_and_upsert_leaves_bytes_identical` | [crates/storage/src/connections.rs](../crates/storage/src/connections.rs) |
| F-003 | unit | `f003_version_2_is_newer_and_never_written` | [crates/storage/src/connections.rs](../crates/storage/src/connections.rs) |
| F-004 | gtk | `f004_edit_after_draft_insert_targets_edited_row` | [crates/app/src/ui/grid/column_factory.rs](../crates/app/src/ui/grid/column_factory.rs) |
| F-004 | gtk | `f004_menu_set_null_after_draft_removal_targets_clicked_row` | [crates/app/src/ui/grid/column_factory.rs](../crates/app/src/ui/grid/column_factory.rs) |
| F-004 | gtk | `f004_copy_row_as_insert_uses_row_below_draft` | [crates/app/src/ui/browse_tab/tests.rs](../crates/app/src/ui/browse_tab/tests.rs) |
| F-005 | gtk | `f005_unchanged_40kb_multiline_text_records_no_edit` | [crates/app/src/ui/browse_tab/tests.rs](../crates/app/src/ui/browse_tab/tests.rs) |
| F-005 | gtk | `f005_pasted_newlines_in_text_cell_are_kept` | [crates/app/src/ui/browse_tab/tests.rs](../crates/app/src/ui/browse_tab/tests.rs) |
| F-005 | gtk | `f005_pressing_enter_on_float_keeps_full_precision` | [crates/app/src/ui/browse_tab/tests.rs](../crates/app/src/ui/browse_tab/tests.rs) |
| F-004 | gtk | `f004_copy_row_as_insert_uses_row_below_draft` | [crates/app/src/ui/browse_tab/tests/mod.rs](../crates/app/src/ui/browse_tab/tests/mod.rs) |
| F-005 | gtk | `f005_unchanged_40kb_multiline_text_records_no_edit` | [crates/app/src/ui/browse_tab/tests/mod.rs](../crates/app/src/ui/browse_tab/tests/mod.rs) |
| F-005 | gtk | `f005_pasted_newlines_in_text_cell_are_kept` | [crates/app/src/ui/browse_tab/tests/mod.rs](../crates/app/src/ui/browse_tab/tests/mod.rs) |
| F-005 | gtk | `f005_pressing_enter_on_float_keeps_full_precision` | [crates/app/src/ui/browse_tab/tests/mod.rs](../crates/app/src/ui/browse_tab/tests/mod.rs) |
| F-006 | conformance | `f006_unsupported_types_never_decode_as_null` | [crates/test-support/src/conformance/cases/type_fallback.rs](../crates/test-support/src/conformance/cases/type_fallback.rs) |
| F-006 | docker | `f006_round_trip_matrix` | [crates/drivers/postgres/tests/integration/decode.rs](../crates/drivers/postgres/tests/integration/decode.rs) |
| F-006 | unit | `f006_count_sum_and_expression_columns_are_typed` | [crates/drivers/sqlite/tests/integration/decode.rs](../crates/drivers/sqlite/tests/integration/decode.rs) |
Expand Down
17 changes: 8 additions & 9 deletions linux/docs/releasing.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@

A repository admin does these once. The workflow's header names the same secrets and variables.

1. **Environment** `linux-release`: a required reviewer, and deployments from `linux-v*` tags and the `linux` branch only. The branch is for a [packaging fix](#a-packaging-fix). Two secrets in it:
1. **Environment** `linux-release`: a required reviewer, and deployments from `linux-v*` tags and the `main` branch only. The branch is for a [packaging fix](#a-packaging-fix). Two secrets in it:
- `LINUX_PPA_SIGNING_KEY`: the ASCII-armored OpenPGP secret key, with no passphrase, that signs the uploads.
- `LINUX_COPR_WEBHOOK`: the custom webhook URL from the COPR project's Integrations page, ending in `/tablepro/`.
2. **Variables**: `LINUX_PPA`, the PPA as `owner/name`. `LINUX_BRANCH` stays unset unless a release comes from a [maintenance branch](#a-fix-release).
3. **Tag ruleset**: add `refs/tags/linux-v*` to the ruleset that lets only admins create release tags. Today it covers `refs/tags/v*` alone, so anyone with write access could start a release.
4. **Workflows on `main`**: copy `linux-packages.yml` and `release-linux.yml` to `main`, as `build-linux.yml` already is. GitHub offers Run workflow only for a workflow on the default branch, and the arm64 build and the packaging fix both start that way.
5. **Launchpad**: a team that owns the PPA, and the PPA with a dependency on `~rust-toolchain/staging`, amd64 and arm64 turned on under its processors, and debug symbol publishing on (Launchpad's admins turn it on when the PPA's settings do not offer it). Register the signing key's public half on an account in the team. Launchpad mails a failed build to the owner of the key that signed the upload, so that account's mail has to reach someone.
6. **COPR**: a project with the Fedora 44 x86_64 and aarch64 chroots, following Fedora branching, with AppStream metadata generation on, and a package named `tablepro` with the custom source method from `build-aux/rpm/copr-sources.sh` (the command is in its header). Turn on build failure emails for the project's admins.
4. **Launchpad**: a team that owns the PPA, and the PPA with a dependency on `~rust-toolchain/staging`, amd64 and arm64 turned on under its processors, and debug symbol publishing on (Launchpad's admins turn it on when the PPA's settings do not offer it). Register the signing key's public half on an account in the team. Launchpad mails a failed build to the owner of the key that signed the upload, so that account's mail has to reach someone.
5. **COPR**: a project with the Fedora 44 x86_64 and aarch64 chroots, following Fedora branching, with AppStream metadata generation on, and a package named `tablepro` with the custom source method from `build-aux/rpm/copr-sources.sh` (the command is in its header). Turn on build failure emails for the project's admins.

[README.md](../README.md#install) gives users `ppa:tablepro/tablepro` and `@tablepro/tablepro`; change it if the PPA or the COPR project gets another name.

Expand All @@ -37,15 +36,15 @@ A tag such as `linux-v0.2.0-rc.1` publishes a GitHub pre-release with the tarbal

A fix to `build-aux/debian` or `build-aux/rpm` that needs no new version, such as a missing dependency.

**PPA.** Merge the fix to `linux`, then run the workflow by hand on `linux`:
**PPA.** Merge the fix to `main`, then run the workflow by hand on `main`:

```sh
gh workflow run release-linux.yml --ref linux -f tag=linux-v0.1.0 -f revision=2
gh workflow run release-linux.yml --ref main -f tag=linux-v0.1.0 -f revision=2
```

It downloads that release's two tarballs, checks them against its `SHA256SUMS`, builds the source package with the packaging from `linux` as `0.1.0-0ppa2~YY.MM`, builds and tests the .deb on both architectures, and uploads it once a reviewer approves. Launchpad accepts the release's own orig tarballs again, and would refuse new ones whose bytes differ. Count the revision up for each further upload of the same version.
It downloads that release's two tarballs, checks them against its `SHA256SUMS`, builds the source package with the packaging from `main` as `0.1.0-0ppa2~YY.MM`, builds and tests the .deb on both architectures, and uploads it once a reviewer approves. Launchpad accepts the release's own orig tarballs again, and would refuse new ones whose bytes differ. Count the revision up for each further upload of the same version.

**COPR.** COPR builds the spec at the tag, so a fix to it goes in by hand. Raise `Release` in `build-aux/rpm/tablepro.spec` on `linux` with a `%changelog` entry, then, on Fedora with `copr-cli` signed in, build the source RPM from that spec and submit it:
**COPR.** COPR builds the spec at the tag, so a fix to it goes in by hand. Raise `Release` in `build-aux/rpm/tablepro.spec` on `main` with a `%changelog` entry, then, on Fedora with `copr-cli` signed in, build the source RPM from that spec and submit it:

```sh
spectool --get-files --sources build-aux/rpm/tablepro.spec
Expand All @@ -57,7 +56,7 @@ The next version's release commit sets `Release` back to 1.

## A fix release

0.1.1 is a release like any other, from `linux`. When `linux` already holds work that should wait for 0.2.0, branch `linux-0.1` from the `linux-v0.1.0` tag, cherry-pick the fixes onto it with their fragments, and open the release pull request into `linux-0.1`, so towncrier builds the section from those fragments only. Set `LINUX_BRANCH` to `linux-0.1` and allow that branch in the environment, push the tag, then set both back. Afterwards cherry-pick the release commit onto `linux` in a pull request with the same title: it brings the version, the dates and the section, and deletes the fragments 0.1.1 shipped.
0.1.1 is a release like any other, from `main`. When `main` already holds work that should wait for 0.2.0, branch `linux-0.1` from the `linux-v0.1.0` tag, cherry-pick the fixes onto it with their fragments, and open the release pull request into `linux-0.1`, so towncrier builds the section from those fragments only. Set `LINUX_BRANCH` to `linux-0.1` and allow that branch in the environment, push the tag, then set both back. Afterwards cherry-pick the release commit onto `main` in a pull request with the same title: it brings the version, the dates and the section, and deletes the fragments 0.1.1 shipped.

## Downgrades

Expand Down
Loading
Loading