From 55975c0119709e50616b51cecc5dcf46163692cb Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Mon, 19 Oct 2026 00:28:38 +0700 Subject: [PATCH 1/2] ci(linux): gate the Linux jobs on main like the Apple suites --- .claude/rules/ci.md | 7 +- .github/workflows/build-linux.yml | 108 ++++++++++-------------- .github/workflows/linux-packages.yml | 2 +- .github/workflows/release-linux.yml | 4 +- linux/docs/testing.md | 2 +- scripts/ci/detect-changed-paths.sh | 9 +- scripts/ci/test_detect_changed_paths.py | 22 ++++- 7 files changed, 82 insertions(+), 72 deletions(-) diff --git a/.claude/rules/ci.md b/.claude/rules/ci.md index 8215631cbc..5517edcc56 100644 --- a/.claude/rules/ci.md +++ b/.claude/rules/ci.md @@ -119,6 +119,7 @@ The required check names are in `AGENTS.md` (CI). Reading a red check: `.claude/ - `ios` watches `TableProMobile/`, `Libs/`, `Plugins/TableProPluginKit/` (the package target is a symlink to it), and every `../` path it reads out of `TableProMobile/project.yml`. - `oracle` watches `Packages/TableProOracle/`; `hana` watches `Native/HanaBridge/`. Each suite also watches its own workflow. - `release` watches what the Release build reads: the app, plugin, package, native, config and libs folders, `project.yml`, the app's `Package.resolved`, `.github/plugin-registry.json`, the release scripts it runs (`build.sh`, `package.sh`, `registry.py`, `version.py`, `notes.py`), the build and CI scripts it runs and the setup actions. It skips `Plugins/*Tests/` and `Packages/*/Tests/`. +- `linux` watches `linux/`, the docs and banned-words scripts the Linux fast job runs, the detector itself and the three Linux workflows. - A path a suite newly reads joins that suite's pattern in the same change, or the suite skips on it. - `CHANGELOG.md` and `changelog.d/` are on no suite's pattern: the What's New phase writes nothing at `0.0.0-dev`, and Repo Hygiene renders every fragment and section instead. @@ -126,16 +127,16 @@ The required check names are in `AGENTS.md` (CI). Reading a red check: `.claude/ - A pull request: both changes jobs; macOS Tests and iOS and Package Tests unless their detector says false (Oracle only when its detector is not false); SwiftLint; Repo Hygiene; PR title. `AllPlugins` only when the `plugins` detector is not false. - A push to main or `release/**`: the same minus PR title, plus Release Build; never cancelled, `AllPlugins` always, the SPM cache saved on a miss. Every code push runs both plans in full; a docs-only or changelog-only push skips the suites through the detector. -- A `v*` tag runs only `release.yml`. The test workflows never run on a tag. +- A `v*` tag runs only `release.yml`, and a `linux-v*` tag only `release-linux.yml`, which calls `linux-packages.yml`. The test workflows never run on a tag. - `workflow_dispatch` exists on every workflow except `pr-title.yml` and `release.yml`. -- `build-linux.yml` is on `main` only for its Monday schedule, which GitHub runs from the default branch. Until the Linux app's directory lands on `main`, every build job skips and `weekly-dispatch` starts the workflow on the branch the `LINUX_BRANCH` variable names (the linux branch when unset), whose testing guide describes the jobs. +- `build-linux.yml` builds and tests the Linux app (`linux/docs/testing.md`, CI). Its `Changes (Linux)` job skips the rest when nothing under `linux/` or the scripts and workflows it reads changed, and its `Linux` job gates on all of them. ## Caches and runner budget - Swift package checkouts live in `~/.spm-cache`, keyed `spm--` with prefix restore. macOS Tests saves it only on a push and only on a miss: a cache saved on a PR ref is visible to that PR alone. - `release.yml` restores that cache and never saves it, since a save in tag scope is unreadable from other refs. - `release-build.yml` restores it and leaves the save to macOS Tests. -- There is no other cache: no libs or DerivedData cache, and none in the iOS, plugin or Ubuntu workflows. +- There is no other Apple cache: no libs or DerivedData cache, and none in the iOS or plugin workflows. The Linux jobs cache Cargo builds through `Swatinem/rust-cache` and the Flatpak build. - CI fits the GitHub Free and Pro plans: no paid larger runner, no self-hosted Mac. At most 5 macOS jobs run at once, and main runs queue behind PR runs for those slots. ## Writing workflow and lint code diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml index 3a430ff54d..63bbff7f3b 100644 --- a/.github/workflows/build-linux.yml +++ b/.github/workflows/build-linux.yml @@ -1,19 +1,9 @@ name: Build Linux on: - push: - branches: [main, linux, "linux/**", "feat/linux-**"] - paths: - - "linux/**" - - ".github/workflows/build-linux.yml" - - ".github/workflows/linux-packages.yml" - - ".github/workflows/release-linux.yml" pull_request: - paths: - - "linux/**" - - ".github/workflows/build-linux.yml" - - ".github/workflows/linux-packages.yml" - - ".github/workflows/release-linux.yml" + push: + branches: [main, "release/**"] schedule: - cron: "13 14 * * 1" workflow_dispatch: @@ -35,51 +25,27 @@ env: LYCHEE_SHA256: 1f4e0ef7f6554a6ed33dd7ac144fb2e1bbed98598e7af973042fc5cd43951c9a jobs: - # The same file runs on main, where linux/ does not exist until the - # first Linux release. Every build job waits for this one and is skipped - # there. - detect: - name: Linux tree + changes: + name: Changes (Linux) runs-on: ubuntu-24.04 timeout-minutes: 5 outputs: - linux: ${{ steps.tree.outputs.linux }} + run: ${{ steps.decide.outputs.run }} steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + fetch-depth: 0 persist-credentials: false - sparse-checkout: linux/meson.build - sparse-checkout-cone-mode: false - - name: Look for linux/meson.build - id: tree - run: | - if [ -f linux/meson.build ]; then - echo "linux=true" >> "$GITHUB_OUTPUT" - else - echo "linux=false" >> "$GITHUB_OUTPUT" - fi - - # GitHub runs a schedule only from the default branch. Until linux/ is - # on main, the weekly run starts this workflow on the Linux branch. - weekly-dispatch: - name: Start the weekly run on the Linux branch - needs: detect - if: github.event_name == 'schedule' && needs.detect.outputs.linux == 'false' - runs-on: ubuntu-24.04 - timeout-minutes: 5 - permissions: - actions: write - steps: - - name: Dispatch this workflow + - name: Decide whether the Linux jobs run + id: decide env: - GH_TOKEN: ${{ github.token }} - LINUX_BRANCH: ${{ vars.LINUX_BRANCH || 'linux' }} - run: gh workflow run build-linux.yml --repo "$GITHUB_REPOSITORY" --ref "$LINUX_BRANCH" + BASE: ${{ github.event.pull_request.base.sha || github.event.before }} + run: echo "run=$(scripts/ci/detect-changed-paths.sh --base "$BASE" linux)" >> "$GITHUB_OUTPUT" fast: name: Fast checks - needs: detect - if: needs.detect.outputs.linux == 'true' + needs: changes + if: ${{ !cancelled() && needs.changes.outputs.run != 'false' }} runs-on: ubuntu-24.04 timeout-minutes: 150 # The host runner ships GLib 2.80, below the GNOME 50 floor. @@ -260,8 +226,8 @@ jobs: # compiler and not with rustup's. msrv: name: Minimum Rust version - needs: detect - if: needs.detect.outputs.linux == 'true' + needs: changes + if: ${{ !cancelled() && needs.changes.outputs.run != 'false' }} runs-on: ubuntu-24.04 timeout-minutes: 60 container: @@ -295,8 +261,8 @@ jobs: docs: name: Documentation links - needs: detect - if: needs.detect.outputs.linux == 'true' + needs: changes + if: ${{ !cancelled() && needs.changes.outputs.run != 'false' }} runs-on: ubuntu-24.04 timeout-minutes: 10 steps: @@ -319,8 +285,8 @@ jobs: supply-chain: name: Supply chain - needs: detect - if: needs.detect.outputs.linux == 'true' + needs: changes + if: ${{ !cancelled() && needs.changes.outputs.run != 'false' }} runs-on: ubuntu-24.04 timeout-minutes: 30 defaults: @@ -365,8 +331,8 @@ jobs: i18n: name: Translations - needs: detect - if: needs.detect.outputs.linux == 'true' + needs: changes + if: ${{ !cancelled() && needs.changes.outputs.run != 'false' }} runs-on: ubuntu-24.04 timeout-minutes: 30 # ubuntu:26.10 ships gettext 1.0, the first release whose xgettext @@ -428,8 +394,8 @@ jobs: flatpak-devel: name: Flatpak Devel (${{ matrix.arch }}) - needs: detect - if: needs.detect.outputs.linux == 'true' + needs: changes + if: ${{ !cancelled() && needs.changes.outputs.run != 'false' }} strategy: fail-fast: false matrix: @@ -467,8 +433,8 @@ jobs: integration: name: Docker tests (${{ matrix.package }}) - needs: [detect, fast] - if: needs.detect.outputs.linux == 'true' + needs: [changes, fast] + if: ${{ !cancelled() && needs.changes.outputs.run != 'false' && needs.fast.result == 'success' }} runs-on: ubuntu-24.04 timeout-minutes: 90 strategy: @@ -530,8 +496,8 @@ jobs: # is mounted; testcontainers sees /.dockerenv and reaches the # containers it starts through the bridge gateway. name: Docker tests (tablepro-session) - needs: [detect, fast] - if: needs.detect.outputs.linux == 'true' + needs: [changes, fast] + if: ${{ !cancelled() && needs.changes.outputs.run != 'false' && needs.fast.result == 'success' }} runs-on: ubuntu-24.04 timeout-minutes: 90 container: @@ -593,8 +559,8 @@ jobs: # session job. Only the named test targets run: the app's startup # test needs Meson and the fast job already covers it. name: Docker tests (tablepro) - needs: [detect, fast] - if: needs.detect.outputs.linux == 'true' + needs: [changes, fast] + if: ${{ !cancelled() && needs.changes.outputs.run != 'false' && needs.fast.result == 'success' }} runs-on: ubuntu-24.04 timeout-minutes: 90 container: @@ -650,3 +616,21 @@ jobs: with: name: junit-tablepro path: linux/target/nextest/ci/junit.xml + + # The one check a branch rule requires: a job skipped by a path decision + # reports success, and this fails when any Linux job failed or was cancelled. + linux: + name: Linux + needs: [changes, fast, msrv, docs, supply-chain, i18n, flatpak-devel, integration, integration-session, integration-app] + if: always() + runs-on: ubuntu-24.04 + timeout-minutes: 5 + steps: + - name: Every Linux job passed or was skipped + env: + RESULTS: ${{ join(needs.*.result, ' ') }} + run: | + echo "$RESULTS" + case " $RESULTS " in + *" failure "* | *" cancelled "*) exit 1 ;; + esac diff --git a/.github/workflows/linux-packages.yml b/.github/workflows/linux-packages.yml index cfd60fbdf0..245750a215 100644 --- a/.github/workflows/linux-packages.yml +++ b/.github/workflows/linux-packages.yml @@ -29,7 +29,7 @@ on: # After a merge every change runs, so a failure only one distribution's # build shows turns up then and not at tag time. push: - branches: [linux] + branches: [main] paths: - "linux/**" - ".github/workflows/linux-packages.yml" diff --git a/.github/workflows/release-linux.yml b/.github/workflows/release-linux.yml index 9f423bf82e..ce9f18d4a0 100644 --- a/.github/workflows/release-linux.yml +++ b/.github/workflows/release-linux.yml @@ -21,7 +21,7 @@ name: Release Linux # LINUX_COPR_WEBHOOK: the custom webhook URL from the COPR project's # Integrations page, ending in the package name: ...//tablepro/. # Variable LINUX_PPA: the PPA, as owner/name. -# Variable LINUX_BRANCH: the branch a release tag must be on, linux when unset. +# Variable LINUX_BRANCH: the branch a release tag must be on, main when unset. on: push: @@ -68,7 +68,7 @@ jobs: working-directory: linux env: TAG: ${{ github.ref_name }} - LINUX_BRANCH: ${{ vars.LINUX_BRANCH || 'linux' }} + LINUX_BRANCH: ${{ vars.LINUX_BRANCH || 'main' }} run: | git config --global --add safe.directory "$GITHUB_WORKSPACE" if ! git merge-base --is-ancestor HEAD "origin/$LINUX_BRANCH"; then diff --git a/linux/docs/testing.md b/linux/docs/testing.md index ff3661aaed..1418a26c71 100644 --- a/linux/docs/testing.md +++ b/linux/docs/testing.md @@ -366,7 +366,7 @@ GitHub Actions (`.github/workflows/build-linux.yml`), Ubuntu runners. It runs on 6. **Flatpak Devel**: the Devel manifest built in the `gnome-51` Flatpak image for x86_64 and aarch64, with every Meson suite run inside the build sandbox from a tree with no `.git`. The x86_64 job lints the manifest with `flatpak-builder-lint` and `build-aux/flatpak/lint-exceptions.json`. The repository holds no Flathub manifest ([ADR 0018](decisions/0018-ppa-copr-and-flathub-later.md)). 7. **Minimum Rust version**: in `ubuntu:26.04`, `build-aux/packaging/add-rust-toolchain-ppa.sh` adds `ppa:rust-toolchain/staging`, `apt-get build-dep -P nocheck` installs the .deb's build dependencies without the test-only ones, and `cargo-1.97 check --workspace --all-targets --locked` runs with and without default features: the compiler the PPA builds with, at the workspace `rust-version`. -A `detect` job first checks that `linux/meson.build` exists, and every other job waits for it and is skipped without it, so the same file can sit on `main` before `linux/` does. GitHub runs a schedule only from the default branch: while `main` has no `linux/`, the Monday run there starts this workflow on the branch the `LINUX_BRANCH` repository variable names, `linux` when it is unset. PRs only merge when every job is green. +A `Changes (Linux)` job runs `scripts/ci/detect-changed-paths.sh linux` and every other job waits for it: a change that touches nothing the Linux jobs read skips them, and a schedule or manual run takes every job. The `Linux` job needs all of them and fails when any failed or was cancelled, so it is the one check a branch rule requires; a skipped job counts as passed. `.github/workflows/linux-packages.yml` builds the packages from the release source and vendor tarballs. For each Ubuntu series the PPA builds for, 26.04 and 26.10, it writes the Debian source package with `build-aux/packaging/build-source.sh`, then `build-deb.sh` builds the binaries from it the way Launchpad does: in a fresh container of that series with only the declared build dependencies, offline, as a user that is not root, running every Meson suite, then lintian. `build-rpm.sh` builds the .rpm in `fedora:44` with only its BuildRequires, running every Meson suite, and checks it with `rpmlint --strict`. Each package is then installed in a fresh container and started. It runs on a pull request that touches the packaging (`build-aux/debian`, `build-aux/rpm`, `build-aux/packaging`), `Cargo.toml`, `Cargo.lock` or a Meson file, and on every push to `linux` that touches `linux/`, on x86_64 only. Run by hand with `arm64` ticked, it builds, tests and installs both packages on an arm64 runner too. `.github/workflows/release-linux.yml` calls it on a `linux-v*` tag before it publishes, on both architectures ([ADR 0018](decisions/0018-ppa-copr-and-flathub-later.md)). Run by hand on a branch with a released tag and a revision, `release-linux.yml` calls it on that release's tarballs with the branch's .deb packaging, then uploads the result to the PPA as a new revision ([releasing.md](releasing.md#a-packaging-fix)). `build-aux/packaging/build-packages.sh` runs the same steps locally. diff --git a/scripts/ci/detect-changed-paths.sh b/scripts/ci/detect-changed-paths.sh index 03c2f64cf4..8bddf3a372 100755 --- a/scripts/ci/detect-changed-paths.sh +++ b/scripts/ci/detect-changed-paths.sh @@ -2,7 +2,7 @@ set -euo pipefail # Prints "true" when a suite has to run for the changes since , "false" when it can skip. -# Usage: detect-changed-paths.sh [--base ] macos|plugins|ios|oracle|hana|release +# Usage: detect-changed-paths.sh [--base ] macos|plugins|ios|oracle|hana|release|linux BASE="" SUITE="" @@ -62,8 +62,13 @@ case "$SUITE" in 'scripts/ci/(detect-changed-paths|verify-plugin-loads)\.sh$' '\.github/actions/(setup-xcode(gen)?|prepare-build)/' '\.github/workflows/release-build\.yml$') SKIP='Plugins/[^/]+Tests/|Packages/[^/]+/Tests/' ;; + linux) + # The fast job checks the Linux docs with the repo's docs and word scripts. + PATTERNS=('linux/' 'scripts/(check-doc-symbols|check-banned-words)\.sh$' 'scripts/banned-words\.txt$' + 'scripts/ci/detect-changed-paths\.sh$' + '\.github/workflows/(build-linux|linux-packages|release-linux)\.yml$') ;; *) - echo "detect-changed-paths.sh: expected macos, plugins, ios, oracle, hana or release, got '$SUITE'" >&2 + echo "detect-changed-paths.sh: expected macos, plugins, ios, oracle, hana, release or linux, got '$SUITE'" >&2 exit 2 ;; esac diff --git a/scripts/ci/test_detect_changed_paths.py b/scripts/ci/test_detect_changed_paths.py index 606f0b0ddd..d564999549 100644 --- a/scripts/ci/test_detect_changed_paths.py +++ b/scripts/ci/test_detect_changed_paths.py @@ -65,7 +65,27 @@ def verdict_after(self, suite, path): return out def test_unknown_suite_exits_2(self): - self.assertEqual(self.detect("linux")[0], 2) + self.assertEqual(self.detect("windows")[0], 2) + + def test_linux_runs_on_the_linux_tree_and_what_its_jobs_read(self): + for path in [ + "linux/crates/app/src/main.rs", + "linux/meson.build", + "scripts/check-doc-symbols.sh", + "scripts/check-banned-words.sh", + "scripts/banned-words.txt", + ".github/workflows/build-linux.yml", + ".github/workflows/linux-packages.yml", + ".github/workflows/release-linux.yml", + ]: + with self.subTest(path=path): + self.assertEqual(self.verdict_after("linux", path), "true") + + def test_linux_skips_the_apple_apps(self): + for path in ["TablePro/App.swift", "TableProMobile/App.swift", "Plugins/Shared/Timeout.swift", + "project.yml", "CHANGELOG.md", ".github/workflows/macos-tests.yml"]: + with self.subTest(path=path): + self.assertEqual(self.verdict_after("linux", path), "false") def test_unknown_flag_exits_2(self): self.assertEqual(self.detect("--head")[0], 2) From f638fb152046da23d23d12a991709ea627997729 Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Mon, 19 Oct 2026 00:30:25 +0700 Subject: [PATCH 2/2] docs: point the root guides at the Linux app on main --- .claude/skills/fix-issue/references/platform-linux.md | 6 ++---- .claude/skills/fix-issue/scripts/lib/platform-linux.sh | 2 +- AGENTS.md | 3 ++- CONTRIBUTING.md | 2 +- README.ko.md | 4 +++- README.md | 4 +++- README.vi.md | 2 +- README.zh.md | 2 +- RELEASING.md | 2 +- linux/AGENTS.md | 4 ---- linux/CONTRIBUTING.md | 2 +- 11 files changed, 16 insertions(+), 17 deletions(-) diff --git a/.claude/skills/fix-issue/references/platform-linux.md b/.claude/skills/fix-issue/references/platform-linux.md index 7a8e7abf7a..137dc25910 100644 --- a/.claude/skills/fix-issue/references/platform-linux.md +++ b/.claude/skills/fix-issue/references/platform-linux.md @@ -6,12 +6,10 @@ The native Linux app. Every profile has these seven sections in this order, so a A report from Linux. The code is `linux/`: a Cargo workspace of crates under `linux/crates/` (the GTK app, the UI-free core, storage, sessions, networking, SSH and one crate per driver), built by Meson. Drivers are linked in at compile time; there are no plugins. A fix lands in one or more crates; name them. -`linux/` exists only on the `linux` branch until the first Linux release, so a checkout of `main` cannot fix it. - ## Base -- Worktree base: `origin/linux`. -- Pull request base: `linux`. +- Worktree base: `origin/main`. +- Pull request base: `main`. ## Done diff --git a/.claude/skills/fix-issue/scripts/lib/platform-linux.sh b/.claude/skills/fix-issue/scripts/lib/platform-linux.sh index 43a6d5c207..15660a1d66 100644 --- a/.claude/skills/fix-issue/scripts/lib/platform-linux.sh +++ b/.claude/skills/fix-issue/scripts/lib/platform-linux.sh @@ -41,7 +41,7 @@ load_rust_environment() { require_linux_tree() { [ -f "$LINUX_DIR/meson.build" ] && return 0 STATUS=INCONCLUSIVE - note "cause: $REPO_ROOT has no linux/. The Linux app is on the linux branch: make the tree from origin/linux." + note "cause: $REPO_ROOT has no linux/. Make the tree from origin/main." emit "" 2 } diff --git a/AGENTS.md b/AGENTS.md index 86364dea00..153adc2a36 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ A native macOS database client (SwiftUI and AppKit), a lightweight alternative to TablePlus. macOS 13.0+, Swift 6 language mode for the app targets (`Configs/Base.xcconfig`), Universal Binary. `TableProMobile/` is the iOS app. -This guide covers the macOS and iOS apps; another platform's app keeps its own guide beside its code. Claude Code loads it through `CLAUDE.md`, Codex directly. +This guide covers the macOS and iOS apps; `linux/AGENTS.md` covers the Linux app. Claude Code loads it through `CLAUDE.md`, Codex directly. ## Principles @@ -36,6 +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. - 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`. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2931b28145..801c841817 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing to TablePro -[`AGENTS.md`](AGENTS.md) holds the invariants and the rules every change meets; where this file and it disagree, it wins. The docs site lives in [TableProApp/docs](https://github.com/TableProApp/docs), and releasing is in [`RELEASING.md`](RELEASING.md). +[`AGENTS.md`](AGENTS.md) holds the invariants and the rules every change meets; where this file and it disagree, it wins. The docs site lives in [TableProApp/docs](https://github.com/TableProApp/docs), and releasing is in [`RELEASING.md`](RELEASING.md). The Linux app has its own setup and rules in [`linux/CONTRIBUTING.md`](linux/CONTRIBUTING.md). ## Setup diff --git a/README.ko.md b/README.ko.md index 2534517d5d..fd8f9ac95e 100644 --- a/README.ko.md +++ b/README.ko.md @@ -65,7 +65,7 @@ TablePro는 네 번째 선택지입니다. 네이티브이고 여러 데이터 |----------|--------| | macOS 13+ | 안정 버전 | | iOS / iPadOS 18+ | 안정 버전 | -| Linux | 프로토타입, 아직 설치할 수 없음 | +| Linux (GNOME 50+) | [`linux/`](linux/README.md)에서 개발 중, 아직 출시 전 | | Windows | 지원하지 않음 | ## 지원 데이터베이스 @@ -104,6 +104,8 @@ brew install --cask tablepro ## 빌드 방법 +아래 단계는 macOS와 iOS 앱을 빌드합니다. Linux 앱은 Meson과 Cargo로 빌드합니다([`linux/README.md`](linux/README.md)). + TablePro를 빌드하려면 Xcode 26 이상과 [XcodeGen](https://github.com/yonaskolb/XcodeGen)이 필요합니다. 저장소 루트에서 최초 설정을 실행하세요. diff --git a/README.md b/README.md index c4ba9e4ccc..a0257cace6 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ TablePro is the missing fourth: native, multi-database, and open source. |----------|--------| | macOS 13+ | Stable | | iOS / iPadOS 18+ | Stable | -| Linux | Prototype, nothing to install yet | +| Linux (GNOME 50+) | In development in [`linux/`](linux/README.md), not released yet | | Windows | No | ## Supported Databases @@ -104,6 +104,8 @@ Or download from [GitHub Releases](https://github.com/TableProApp/TablePro/relea ## How to Build +These steps build the macOS and iOS apps; the Linux app builds with Meson and Cargo ([`linux/README.md`](linux/README.md)). + Building TablePro requires Xcode 26 or later and [XcodeGen](https://github.com/yonaskolb/XcodeGen). diff --git a/README.vi.md b/README.vi.md index c7140b8dcd..0bc23e2e6f 100644 --- a/README.vi.md +++ b/README.vi.md @@ -65,7 +65,7 @@ TablePro là mảnh thứ tư còn thiếu: native, đa database, và mã nguồ |----------|-----------| | macOS 13+ | Ổn định | | iOS / iPadOS 18+ | Ổn định | -| Linux | Bản thử nghiệm, chưa có gì để cài | +| Linux (GNOME 50+) | Đang phát triển trong [`linux/`](linux/README.md), chưa phát hành | | Windows | Không | ## Database hỗ trợ diff --git a/README.zh.md b/README.zh.md index 19b5c929c3..19e3c4d5b7 100644 --- a/README.zh.md +++ b/README.zh.md @@ -65,7 +65,7 @@ TablePro 补上缺失的第四类:原生、多数据库、开源。 |------|------| | macOS 13+ | 稳定版 | | iOS / iPadOS 18+ | 稳定版 | -| Linux | 原型阶段,暂无可安装版本 | +| Linux (GNOME 50+) | 正在 [`linux/`](linux/README.md) 中开发,尚未发布 | | Windows | 无 | ## 支持的数据库 diff --git a/RELEASING.md b/RELEASING.md index 542b2c9479..8f729afc45 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -1,6 +1,6 @@ # Releasing -This runbook covers the macOS app, its registry plugins and the static libraries; the iOS app ships by hand. The `release` skill (`.claude/skills/release/SKILL.md`) decides what ships and points at the sections here. Every command below is the maintainer's to run. +This runbook covers the macOS app, its registry plugins and the static libraries; the iOS app ships by hand, and the Linux app's runbook is `linux/docs/releasing.md`. The `release` skill (`.claude/skills/release/SKILL.md`) decides what ships and points at the sections here. Every command below is the maintainer's to run. ## Channels diff --git a/linux/AGENTS.md b/linux/AGENTS.md index 4c4466e93a..2268c798bb 100644 --- a/linux/AGENTS.md +++ b/linux/AGENTS.md @@ -4,10 +4,6 @@ The native Linux app: Rust, GTK 4 and libadwaita through gtk-rs, built with Meso This is the guide for work under `linux/`. The root `AGENTS.md` describes the macOS and iOS apps; of it, only the principles named below, "Writing style" and the commit rules apply here. Claude Code loads this file through `linux/CLAUDE.md` once a file under `linux/` is read; Codex reads it when started in `linux/`, so otherwise read it yourself. -## Branch - -`linux/` lives on the `linux` branch until the first Linux release, and `main` does not have it. Start work from `origin/linux` and open the pull request against `linux`. - ## Principles 1. **Security first, fix the cause, tests define behavior**, as in the root `AGENTS.md`. diff --git a/linux/CONTRIBUTING.md b/linux/CONTRIBUTING.md index 37d36b48ae..6ca2dc2b5c 100644 --- a/linux/CONTRIBUTING.md +++ b/linux/CONTRIBUTING.md @@ -137,7 +137,7 @@ A user-visible change gets one entry under `[Unreleased]` in [CHANGELOG.md](CHAN ## Pull requests -1. Branch from `linux`, where this subproject lives until the first Linux release, and open the PR against `linux`. Branch name format: `feat/short-slug`, `fix/short-slug`, `refactor/short-slug`. +1. Branch off `main` and open the PR against `main`, as the root [CONTRIBUTING.md](../CONTRIBUTING.md#branch-naming) says. 2. PR title is the conventional commit message you intend to land. 3. The PR description follows the repository's `.github/pull_request_template.md`. 4. Run the [fast-job commands](#fast-job-commands) locally before pushing.