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
7 changes: 0 additions & 7 deletions .github/macos-test-quarantine.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ MCPBridgeIntegrationTests
# host (only plugin metadata loads), so driver-backed SQL generation returns empty.
TableOperationsPluginTests
TableQueryBuilderFilteredQueryTests
FilterSQLGeneratorTests
SQLCompletionProviderTests
SQLStatementGeneratorPKRegressionTests
SQLStatementGeneratorCompositePKTests
Expand All @@ -31,15 +30,13 @@ ValidateDriverDescriptorTests
PluginCapabilityTests
FreeTDSClassifierTests
DatabaseTypeCassandraTests
RowOperationsManagerBinaryCopyTests
RowOperationsManagerTests
StructureGridDelegateAddRowTests
SaveCompletionTests
ChangeReapplyVersionTests

# --- Persistence-entangled: tests assume lowercase enum values but rawValues are
# display-style ("Red"/"Private Key"); changing them needs a Codable migration.
ConnectionSharingTests
ConnectionURLFormatterSSHProfileTests
DatabaseConnectionExternalAccessTests
DataGridSettingsDefaultSortDecoderTests
Expand All @@ -50,8 +47,6 @@ MCPPairingServiceTests
MCPBearerTokenAuthenticatorTests
TablePlusImporterTests
SequelAceImporterTests
DBeaverImporterTests
ForeignAppImporterRegistryTests
HostKeyStoreTests
KeychainHelperTests

Expand All @@ -60,8 +55,6 @@ StructureChangeManagerUndoTests
DataChangeManagerExtendedTests
DataChangeManagerTests
CoordinatorEditorLoadTests
CoordinatorColumnVisibilityTests
CommandActionsDispatchTests
SidebarViewModelTests
ChatToolSpecCopilotTests
SQLStatementScannerLocatedTests
50 changes: 2 additions & 48 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,54 +32,8 @@ jobs:

test:
name: macOS Tests
runs-on: macos-26
timeout-minutes: 40

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Select Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '26.4.1'

- name: Install xcbeautify
run: brew list xcbeautify &>/dev/null || brew install xcbeautify

- name: Download static libraries
env:
GH_TOKEN: ${{ github.token }}
run: scripts/download-libs.sh --force

- name: Create Secrets.xcconfig
env:
ANALYTICS_HMAC_SECRET: ${{ secrets.ANALYTICS_HMAC_SECRET }}
run: echo "ANALYTICS_HMAC_SECRET = ${ANALYTICS_HMAC_SECRET}" > Secrets.xcconfig

- name: Run package tests
run: swift test --package-path Packages/TableProCore

- name: Run app tests
run: |
set -o pipefail
SKIP_ARGS=()
while IFS= read -r line; do
suite="${line%%#*}"
suite="$(echo "$suite" | xargs)"
[ -z "$suite" ] && continue
SKIP_ARGS+=("-skip-testing:TableProTests/$suite")
done < .github/macos-test-quarantine.txt
xcodebuild test \
-project "$XCODE_PROJECT" \
-scheme "$XCODE_SCHEME" \
-destination "platform=macOS" \
-only-testing:TableProTests \
"${SKIP_ARGS[@]}" \
-parallel-testing-enabled NO \
-skipPackagePluginValidation \
CODE_SIGNING_ALLOWED=NO \
| xcbeautify --renderer github-actions
uses: ./.github/workflows/macos-tests.yml

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restrict release downloads to build artifacts

On tag builds this newly called reusable workflow uploads macos-test-results (TestResults.xcresult), and the release job later calls actions/download-artifact without a name/pattern; GitHub documents that omitting a name downloads all artifacts in the run (https://docs.github.com/en/actions/tutorials/store-and-share-data#downloading-artifacts-during-a-workflow-run). That means releases now pull the full xcresult bundle into artifacts-raw even though only artifacts-arm64/artifacts-x86_64 are needed, which can make release jobs slow or fail on large test logs; restrict the release download to artifacts-* or skip the test-results upload when invoked from build.yml.

Useful? React with 👍 / 👎.

secrets: inherit

build-arm64:
name: Build ARM64
Expand Down
39 changes: 0 additions & 39 deletions .github/workflows/contract-drift.yml

This file was deleted.

1 change: 1 addition & 0 deletions .github/workflows/macos-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ on:
- "Libs/**"
- ".github/workflows/macos-tests.yml"
workflow_dispatch:
workflow_call:

# Only one run per PR/branch at a time; new pushes cancel pending older ones.
concurrency:
Expand Down
35 changes: 0 additions & 35 deletions .github/workflows/pluginkit-abi.yml

This file was deleted.

4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ When adding a new method to the driver protocol: add to `PluginDatabaseDriver` (

**Additive changes are binary-compatible and need NO version bump**: adding a requirement to `DriverPlugin` / `PluginDatabaseDriver` that has a default implementation, reordering requirements, adding a field to a non-`@frozen` transfer struct, or removing a requirement that defaulted to `nil`.

**Adding a field to a transfer struct is additive ONLY if every existing public initializer keeps its exact signature.** Adding a parameter to an existing public init or function, even with a default value, replaces its mangled symbol and breaks every already-built plugin (this shipped in 0.49.0: `PluginQueryResult` gained `columnMeta:` on its init and every registry plugin failed to load with "Bundle failed to load executable"). Add a NEW overload for the new field and keep the old signature; mark the old overload `@_disfavoredOverload` so new code resolves to the full init while old binaries keep their symbol. A red PluginKit ABI Gate is a merge blocker, never something to merge over: either the diff is additive (verify no symbol disappeared, then add the `abi-additive` label) or it is breaking (bump and re-release).
**Adding a field to a transfer struct is additive ONLY if every existing public initializer keeps its exact signature.** Adding a parameter to an existing public init or function, even with a default value, replaces its mangled symbol and breaks every already-built plugin (this shipped in 0.49.0: `PluginQueryResult` gained `columnMeta:` on its init and every registry plugin failed to load with "Bundle failed to load executable"). Add a NEW overload for the new field and keep the old signature; mark the old overload `@_disfavoredOverload` so new code resolves to the full init while old binaries keep their symbol. Before any PluginKit change run `scripts/check-pluginkit-abi.sh` (see below) and act on the result: either the diff is additive (verify no symbol disappeared) or it is breaking (bump and re-release).

**Bump `currentPluginKitVersion` (in `PluginManager.swift`) and `TableProPluginKitVersion` in every plugin `Info.plist` ONLY for a breaking change**: changing or removing an existing requirement's signature, adding a requirement without a default, adding a case to a `@frozen` enum, or changing a frozen type's layout. Mark a public enum `@frozen` only when an exhaustive switch over it forces it (the compiler flags the switch) and its case set is genuinely closed; leave the rest non-frozen so they can gain cases. `PluginCapability` stays non-frozen with `@unknown default` because it is a growing capability set, not a closed vocabulary. The driver protocols and transfer structs stay non-frozen so they can grow. The strict version gate in `validateBundleVersions` still rejects a stale plugin cleanly after a breaking bump (no `EXC_BAD_INSTRUCTION`).

**ABI gate**: `scripts/check-pluginkit-abi.sh [base-ref]` builds TableProPluginKit at the current tree and at the base ref with the same toolchain, then diffs their public interfaces. There is no committed baseline, so a Swift version difference between a dev machine and CI never produces a false diff. CI (`.github/workflows/pluginkit-abi.yml`) runs it on every PR that touches `Plugins/TableProPluginKit/**`, comparing against the PR base. A reported diff is a real ABI change: additive needs no bump; breaking needs the version bump above plus `release-all-plugins.sh`. After reviewing a diff as additive, add the `abi-additive` label to the PR; the gate then passes and records the decision. Remove the label if later commits add a breaking change. (Until Library Evolution is on the base too, the base emits no interface and the gate passes as a bootstrap.)
**ABI check** (manual): `scripts/check-pluginkit-abi.sh [base-ref]` builds TableProPluginKit at the current tree and at the base ref with the same toolchain, then diffs their public interfaces. There is no committed baseline, so a Swift version difference between machines never produces a false diff. Run it before merging any change under `Plugins/TableProPluginKit/**`, comparing against the merge base. A reported diff is a real ABI change: additive needs no bump; breaking needs the version bump above plus `release-all-plugins.sh`. (Until Library Evolution is on the base too, the base emits no interface and the check passes as a bootstrap.)

**Post-ABI-bump checklist (mandatory, breaking bumps only)**: Bumps are now rare (only the breaking changes listed above). After one, every registry-published plugin must be rebuilt against the new ABI. Run `release-all-plugins.sh` for the new version BEFORE or WITH the app release, never after, or users on the new app hit `noCompatibleBinary` until the registry catches up. App auto-update reconciliation handles the user-facing recovery, but the registry has to carry binaries for the new PluginKit version first.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// documented value. If a requirement is ever added without a default, this file
// (and FakeMSSQLPluginDriver) stops compiling, flagging a breaking change that
// needs a currentPluginKitVersion bump. Cross-binary load compatibility itself
// is enforced by scripts/check-pluginkit-abi.sh in CI.
// is checked by scripts/check-pluginkit-abi.sh, run manually before merging.
//

import Foundation
Expand Down
Loading