forked from github-mirrorer/taskchampion-sync-server
Compare commits
2 Commits
v0.7.1
...
issue135-d
| Author | SHA1 | Date | |
|---|---|---|---|
| 48f7698271 | |||
| b2331350f3 |
@ -6,4 +6,3 @@
|
||||
!sqlite/
|
||||
!postgres/
|
||||
!entrypoint-*
|
||||
!Dockerfile*
|
||||
|
||||
13
.github/workflows/checks.yml
vendored
13
.github/workflows/checks.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
name: "Check & Clippy"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v4
|
||||
@ -48,7 +48,7 @@ jobs:
|
||||
name: "Rustdoc"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v4
|
||||
@ -96,7 +96,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Formatting"
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
@ -114,18 +114,19 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: "Cargo Semver Checks"
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: obi1kenobi/cargo-semver-checks-action@v2
|
||||
with:
|
||||
# exclude the binary package from semver checks, since it is not published as a crate.
|
||||
exclude: taskchampion-sync-server
|
||||
# exclude postgres temporarily until it is released
|
||||
exclude: taskchampion-sync-server,taskchampion-sync-server-storage-postgres
|
||||
|
||||
mdbook:
|
||||
runs-on: ubuntu-latest
|
||||
name: "mdBook Documentation"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup mdBook
|
||||
uses: peaceiris/actions-mdbook@v2
|
||||
|
||||
6
.github/workflows/docker.yml
vendored
6
.github/workflows/docker.yml
vendored
@ -33,7 +33,8 @@ jobs:
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
file: "./Dockerfile-sqlite"
|
||||
context: .
|
||||
path: "{context}/Dockerfile-sqlite"
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta-sqlite.outputs.tags }}
|
||||
@ -63,7 +64,8 @@ jobs:
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
file: "./Dockerfile-postgres"
|
||||
context: .
|
||||
path: "{context}/Dockerfile-postgres"
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta-postgres.outputs.tags }}
|
||||
|
||||
2
.github/workflows/publish-docs.yml
vendored
2
.github/workflows/publish-docs.yml
vendored
@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup mdBook
|
||||
uses: peaceiris/actions-mdbook@v2
|
||||
|
||||
2
.github/workflows/rust-tests.yml
vendored
2
.github/workflows/rust-tests.yml
vendored
@ -39,7 +39,7 @@ jobs:
|
||||
--health-retries 5
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v4
|
||||
|
||||
2
.github/workflows/security.yml
vendored
2
.github/workflows/security.yml
vendored
@ -14,7 +14,7 @@ jobs:
|
||||
permissions: write-all
|
||||
name: "Audit Rust Dependencies"
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
- uses: rustsec/audit-check@v2.0.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
24
Cargo.lock
generated
24
Cargo.lock
generated
@ -85,9 +85,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "actix-rt"
|
||||
version = "2.11.0"
|
||||
version = "2.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92589714878ca59a7626ea19734f0e07a6a875197eec751bb5d3f99e64998c63"
|
||||
checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208"
|
||||
dependencies = [
|
||||
"actix-macros",
|
||||
"futures-core",
|
||||
@ -1776,9 +1776,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.11"
|
||||
version = "0.4.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
|
||||
checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
@ -1859,7 +1859,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "taskchampion-sync-server"
|
||||
version = "0.7.1"
|
||||
version = "0.7.0"
|
||||
dependencies = [
|
||||
"actix-rt",
|
||||
"actix-web",
|
||||
@ -1883,7 +1883,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "taskchampion-sync-server-core"
|
||||
version = "0.7.1"
|
||||
version = "0.7.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -1898,7 +1898,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "taskchampion-sync-server-storage-postgres"
|
||||
version = "0.7.1"
|
||||
version = "0.7.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -1921,7 +1921,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "taskchampion-sync-server-storage-sqlite"
|
||||
version = "0.7.1"
|
||||
version = "0.7.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-trait",
|
||||
@ -1946,9 +1946,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.23.0"
|
||||
version = "3.20.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
|
||||
checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"getrandom",
|
||||
@ -2209,9 +2209,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.18.0"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be"
|
||||
checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"js-sys",
|
||||
|
||||
@ -10,7 +10,7 @@ rust-version = "1.85.0" # MSRV
|
||||
|
||||
[workspace.dependencies]
|
||||
async-trait = "0.1.88"
|
||||
uuid = { version = "^1.18.0", features = ["serde", "v4"] }
|
||||
uuid = { version = "^1.17.0", features = ["serde", "v4"] }
|
||||
actix-web = "^4.11.0"
|
||||
anyhow = "1.0"
|
||||
thiserror = "2.0"
|
||||
@ -26,7 +26,7 @@ actix-rt = "2"
|
||||
tempfile = "3"
|
||||
pretty_assertions = "1"
|
||||
temp-env = "0.3"
|
||||
tokio = { version = "1.47", features = ["rt", "macros"] }
|
||||
tokio = { version = "*", features = ["rt", "macros"] }
|
||||
tokio-postgres = { version = "0.7.13", features = ["with-uuid-1"] }
|
||||
bb8 = "0.9.0"
|
||||
bb8-postgres = { version = "0.9.0", features = ["with-uuid-1"] }
|
||||
|
||||
@ -13,8 +13,7 @@
|
||||
1. Run `git push upstream`
|
||||
1. Run `git push upstream --tag vX.Y.Z`
|
||||
1. Run `cargo publish -p taskchampion-sync-server-core`
|
||||
1. Run `cargo publish -p taskchampion-sync-server-storage-sqlite`
|
||||
1. Run `cargo publish -p taskchampion-sync-server-storage-postgres` (and add any other new published packages here)
|
||||
1. Run `cargo publish -p taskchampion-sync-server-storage-sqlite` (and add any other new published packages here)
|
||||
1. Bump the patch version in `*/Cargo.toml` and add the `-pre` suffix. This allows `cargo-semver-checks` to check for changes not accounted for in the version delta.
|
||||
1. Run `cargo build --release` again to update `Cargo.lock`
|
||||
1. Commit that change with comment "Bump to -pre version".
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "taskchampion-sync-server-core"
|
||||
version = "0.7.1"
|
||||
version = "0.7.0"
|
||||
authors = ["Dustin J. Mitchell <dustin@mozilla.com>"]
|
||||
edition = "2021"
|
||||
description = "Core of sync protocol for TaskChampion"
|
||||
|
||||
@ -43,7 +43,7 @@ services:
|
||||
condition: service_completed_successfully
|
||||
|
||||
tss:
|
||||
image: ghcr.io/gothenburgbitfactory/taskchampion-sync-server:0.7.1
|
||||
image: ghcr.io/gothenburgbitfactory/taskchampion-sync-server:0.7.0
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- "RUST_LOG=info"
|
||||
|
||||
@ -10,38 +10,16 @@ One binary is provided for each storage backend:
|
||||
- `taskchampion-sync-server` (SQLite)
|
||||
- `taskchampion-sync-server-postgres` (Postgres)
|
||||
|
||||
### Building the Binary
|
||||
|
||||
This is a standard Rust project, and can be built with `cargo build --release`.
|
||||
|
||||
By default, only the SQLite binary is built. To also build the Postgres binary,
|
||||
use
|
||||
```none
|
||||
cargo build --release --features postgres
|
||||
```
|
||||
|
||||
To disable building the SQLite binary and build only the Postgres binary, use
|
||||
|
||||
```none
|
||||
cargo build --release --no-default-features --features postgres
|
||||
```
|
||||
|
||||
### Running the Binary
|
||||
|
||||
The server is configured with command-line options or environment variables.
|
||||
See the `--help` output for full details.
|
||||
|
||||
For the SQLite binary, the `--data-dir` option or `DATA_DIR` environment
|
||||
variable specifies where the server should store its data.
|
||||
|
||||
For the Postgres binary, the `--connection` option or `CONNECTION` environment
|
||||
variable specifies the connection information, in the form of a [LibPQ-style
|
||||
connection
|
||||
variable specifies where the server should store its data. For the Postgres
|
||||
binary, the `--connection` option or `CONNECTION` environment variable
|
||||
specifies the connection information, in the form of a [LibPQ-style connection
|
||||
URI](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS).
|
||||
Note that unlike LibPQ, the Rust client only supports `sslmode` values
|
||||
`disable`, `prefer`, and `require`, and will always validate CA hostnames and
|
||||
certificates when using TLS.
|
||||
|
||||
The remaining options are common to all binaries.
|
||||
|
||||
The `--listen` option specifies the interface and port the server listens on.
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
# Docker Compose
|
||||
|
||||
The
|
||||
[`docker-compose.yml`](https://raw.githubusercontent.com/GothenburgBitFactory/taskchampion-sync-server/refs/tags/v0.7.1/docker-compose.yml)
|
||||
[`docker-compose.yml`](https://raw.githubusercontent.com/GothenburgBitFactory/taskchampion-sync-server/refs/tags/v0.7.0/docker-compose.yml)
|
||||
file in this repository is sufficient to run taskchampion-sync-server,
|
||||
including setting up TLS certificates using Lets Encrypt, thanks to
|
||||
[Caddy](https://caddyserver.com/). This setup uses the SQLite backend, which is
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "taskchampion-sync-server-storage-postgres"
|
||||
version = "0.7.1"
|
||||
version = "0.7.0"
|
||||
authors = ["Dustin J. Mitchell <dustin@v.igoro.us>"]
|
||||
edition = "2021"
|
||||
description = "Postgres backend for TaskChampion-sync-server"
|
||||
@ -16,7 +16,7 @@ bb8.workspace = true
|
||||
chrono.workspace = true
|
||||
env_logger.workspace = true
|
||||
log.workspace = true
|
||||
taskchampion-sync-server-core = { path = "../core", version = "0.7.1" }
|
||||
taskchampion-sync-server-core = { path = "../core", version = "0.7.0" }
|
||||
thiserror.workspace = true
|
||||
tokio-postgres.workspace = true
|
||||
tokio.workspace = true
|
||||
|
||||
@ -39,26 +39,6 @@ use uuid::Uuid;
|
||||
#[cfg(test)]
|
||||
mod testing;
|
||||
|
||||
/// An `ErrorSink` implementation that logs errors to the Rust log.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct LogErrorSink;
|
||||
|
||||
impl LogErrorSink {
|
||||
fn new() -> Box<Self> {
|
||||
Box::new(Self)
|
||||
}
|
||||
}
|
||||
|
||||
impl bb8::ErrorSink<tokio_postgres::Error> for LogErrorSink {
|
||||
fn sink(&self, e: tokio_postgres::Error) {
|
||||
log::error!("Postgres connection error: {e}");
|
||||
}
|
||||
|
||||
fn boxed_clone(&self) -> Box<dyn bb8::ErrorSink<tokio_postgres::Error>> {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// A storage backend which uses Postgres.
|
||||
pub struct PostgresStorage {
|
||||
pool: bb8::Pool<PostgresConnectionManager<MakeTlsConnector>>,
|
||||
@ -69,10 +49,7 @@ impl PostgresStorage {
|
||||
let connector = native_tls::TlsConnector::new()?;
|
||||
let connector = postgres_native_tls::MakeTlsConnector::new(connector);
|
||||
let manager = PostgresConnectionManager::new_from_stringlike(connection_string, connector)?;
|
||||
let pool = bb8::Pool::builder()
|
||||
.error_sink(LogErrorSink::new())
|
||||
.build(manager)
|
||||
.await?;
|
||||
let pool = bb8::Pool::builder().build(manager).await?;
|
||||
Ok(Self { pool })
|
||||
}
|
||||
}
|
||||
@ -272,13 +249,8 @@ impl StorageTxn for Txn {
|
||||
"UPDATE clients
|
||||
SET latest_version_id = $1,
|
||||
versions_since_snapshot = versions_since_snapshot + 1
|
||||
WHERE client_id = $2 and (latest_version_id = $3 or latest_version_id = $4)",
|
||||
&[
|
||||
&version_id,
|
||||
&self.client_id,
|
||||
&parent_version_id,
|
||||
&Uuid::nil(),
|
||||
],
|
||||
WHERE client_id = $2 and latest_version_id = $3",
|
||||
&[&version_id, &self.client_id, &parent_version_id],
|
||||
)
|
||||
.await
|
||||
.context("error updating latest_version_id")?;
|
||||
@ -694,22 +666,4 @@ mod test {
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
/// When an add_version call specifies a `parent_version_id` that does not exist in the
|
||||
/// DB, but no other versions exist, the call succeeds.
|
||||
async fn test_add_version_no_history() -> anyhow::Result<()> {
|
||||
with_db(async |connection_string, db_client| {
|
||||
let storage = PostgresStorage::new(connection_string).await?;
|
||||
let client_id = make_client(&db_client).await?;
|
||||
|
||||
let mut txn = storage.txn(client_id).await?;
|
||||
let version_id = Uuid::new_v4();
|
||||
let parent_version_id = Uuid::new_v4();
|
||||
txn.add_version(version_id, parent_version_id, b"v1".to_vec())
|
||||
.await?;
|
||||
Ok(())
|
||||
})
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "taskchampion-sync-server"
|
||||
version = "0.7.1"
|
||||
version = "0.7.0"
|
||||
authors = ["Dustin J. Mitchell <dustin@mozilla.com>"]
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "taskchampion-sync-server-storage-sqlite"
|
||||
version = "0.7.1"
|
||||
version = "0.7.0"
|
||||
authors = ["Dustin J. Mitchell <dustin@mozilla.com>"]
|
||||
edition = "2021"
|
||||
description = "SQLite backend for TaskChampion-sync-server"
|
||||
@ -9,7 +9,7 @@ repository = "https://github.com/GothenburgBitFactory/taskchampion-sync-server"
|
||||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
taskchampion-sync-server-core = { path = "../core", version = "0.7.1" }
|
||||
taskchampion-sync-server-core = { path = "../core", version = "0.7.0" }
|
||||
async-trait.workspace = true
|
||||
uuid.workspace = true
|
||||
anyhow.workspace = true
|
||||
|
||||
@ -276,12 +276,11 @@ impl StorageTxn for Txn {
|
||||
SET
|
||||
latest_version_id = ?,
|
||||
versions_since_snapshot = versions_since_snapshot + 1
|
||||
WHERE client_id = ? and (latest_version_id = ? or latest_version_id = ?)",
|
||||
WHERE client_id = ? and latest_version_id = ?",
|
||||
params![
|
||||
StoredUuid(version_id),
|
||||
StoredUuid(self.client_id),
|
||||
StoredUuid(parent_version_id),
|
||||
StoredUuid(Uuid::nil())
|
||||
StoredUuid(parent_version_id)
|
||||
],
|
||||
)
|
||||
.context("Error updating client for new version")?;
|
||||
@ -490,21 +489,4 @@ mod test {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
/// When an add_version call specifies a `parent_version_id` that does not exist in the
|
||||
/// DB, but no other versions exist, the call succeeds.
|
||||
async fn test_add_version_no_history() -> anyhow::Result<()> {
|
||||
let tmp_dir = TempDir::new()?;
|
||||
let storage = SqliteStorage::new(tmp_dir.path())?;
|
||||
let client_id = Uuid::new_v4();
|
||||
let mut txn = storage.txn(client_id).await?;
|
||||
txn.new_client(Uuid::nil()).await?;
|
||||
|
||||
let version_id = Uuid::new_v4();
|
||||
let parent_version_id = Uuid::new_v4();
|
||||
txn.add_version(version_id, parent_version_id, b"v1".to_vec())
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user